summaryrefslogtreecommitdiffstats
path: root/meta-rcar-gen3-adas/recipes-kernel/linux
diff options
context:
space:
mode:
Diffstat (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux')
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0001-spi-sh-msiof-fixes.patch33
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0002-spi-spidev-add-spi-gpio-into-spidev.patch27
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0003-spi-spi-gpio-fix-CPOL-mode.patch42
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0004-xhci-rcar-add-firmware-for-R-Car-H2-M2-USB-3.0-host-.patch205
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0005-usb-host-xhci-plat-add-support-for-the-R-Car-H3-xHCI.patch174
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0006-spi-spi-gpio-fix-set-CPOL-default-inverted.patch30
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0007-mmc-sh_mobile_sdhi-Add-R-CarGen3-SDHI-SEQUENCER-supp.patch1070
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0008-arm64-do-not-set-dma-masks-that-device-connection-ca.patch132
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0009-swiotlb-ensure-that-page-sized-mappings-are-page-ali.patch38
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0010-can-rcar_can-add-enable-and-standby-control-pins.patch156
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0011-can-rcar_canfd-add-enable-and-standby-control-pins.patch126
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0012-mtd-Add-RPC-HyperFlash-driver.patch1028
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0013-IMR-driver-interim-patch.patch2104
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0014-lib-swiotlb-reduce-verbosity.patch40
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0015-gpio-max732x-fix-gpio-set.patch29
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0016-gpio-gpiolib-suppress-gpiod-warning.patch29
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0017-media-soc_camera-add-legacy-VIN-CSI2.patch5055
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0018-arm64-renesas-r8a7797-Add-Renesas-R8A7797-SoC-suppor.patch5014
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0019-Revert-media-v4l2-async-remove-unneeded-.registered_.patch54
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0020-ti-st-add-device-tree-support.patch236
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0021-btwilink-add-minimal-device-tree-support.patch54
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0022-ASoC-Modify-check-condition-of-multiple-bindings-of-.patch42
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0023-ASoC-add-dummy-Si468x-driver.patch123
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0030-Gen3-LVDS-cameras.patch6491
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0031-arm64-dts-r8a7795-es1-salvator-x-view-add-ADAS-board.patch588
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0032-arm64-dts-r8a7795-es1-h3ulcb-view-add-ADAS-board.patch581
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0033-arm64-dts-r8a7795-es1-h3ulcb-had-add-ADAS-board.patch320
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0034-arm64-dts-r8a7795-es1-h3ulcb-kf-add-ADAS-board.patch1718
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0035-arm64-dts-r8a7796-salvator-x-view-add-ADAS-board.patch353
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0036-arm64-dts-r8a7796-m3ulcb-view-add-ADAS-board.patch322
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0037-arm64-dts-r8a7796-m3ulcb-kf-add-ADAS-board.patch1232
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0038-arm64-dts-r8a7795-salvator-x-view-add-ADAS-board.patch587
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0039-arm64-dts-r8a7795-h3ulcb-view-add-ADAS-board.patch581
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-r8a7795-h3ulcb-had-add-ADAS-board.patch314
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0041-arm64-dts-r8a7795-h3ulcb-kf-add-ADAS-board.patch1714
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0044-arm64-renesas-TTA-R-Drive-board-support.patch1314
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0050-arm64-dts-Gen3-view-boards-TYPE1-first-4-cameras.patch302
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-dts-Gen3-view-boards-TYPE1-second-4-cameras.patch206
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0052-arm64-dts-Gen3-view-boards-TYPE2-first-4-cameras.patch527
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/eagle.cfg26
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/h3ulcb.cfg50
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/hyperflash.cfg2
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/m3ulcb.cfg50
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/salvator-x.cfg29
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/sdhi_seq.cfg2
-rw-r--r--meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas_4.9.bbappend75
46 files changed, 33225 insertions, 0 deletions
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0001-spi-sh-msiof-fixes.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0001-spi-sh-msiof-fixes.patch
new file mode 100644
index 0000000..d8806ba
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0001-spi-sh-msiof-fixes.patch
@@ -0,0 +1,33 @@
+From 32db8cc989d7dfdf0315d286b06234e008e56d7c Mon Sep 17 00:00:00 2001
+From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+Date: Sun, 15 May 2016 21:53:13 +0300
+Subject: [PATCH] spi: sh-msiof: fixes
+
+speed up polling of CTR register
+
+Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+---
+ drivers/spi/spi-sh-msiof.c | 30 ++++++++++++++++++++----------
+ 1 file changed, 20 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c
+index d096f5a..6817304 100644
+--- a/drivers/spi/spi-sh-msiof.c
++++ b/drivers/spi/spi-sh-msiof.c
+@@ -228,11 +228,11 @@ static int sh_msiof_modify_ctr_wait(struct sh_msiof_spi_priv *p,
+ data |= set;
+ sh_msiof_write(p, CTR, data);
+
+- for (k = 100; k > 0; k--) {
++ for (k = 1000; k > 0; k--) {
+ if ((sh_msiof_read(p, CTR) & mask) == set)
+ break;
+
+- udelay(10);
++ udelay(1);
+ }
+
+ return k > 0 ? 0 : -ETIMEDOUT;
+--
+1.9.1
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0002-spi-spidev-add-spi-gpio-into-spidev.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0002-spi-spidev-add-spi-gpio-into-spidev.patch
new file mode 100644
index 0000000..2aec664
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0002-spi-spidev-add-spi-gpio-into-spidev.patch
@@ -0,0 +1,27 @@
+From 4f85719492ae77bc166f90a046e97bb169396062 Mon Sep 17 00:00:00 2001
+From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+Date: Sun, 15 May 2016 21:47:02 +0300
+Subject: [PATCH] spi: spidev: add spi-gpio into spidev
+
+Add spi-gpio to spidev
+
+Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+---
+ drivers/spi/spidev.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
+index b016a5a..bcee148 100644
+--- a/drivers/spi/spidev.c
++++ b/drivers/spi/spidev.c
+@@ -697,6 +697,7 @@ static const struct of_device_id spidev_dt_ids[] = {
+ { .compatible = "rohm,dh2228fv" },
+ { .compatible = "lineartechnology,ltc2488" },
+ { .compatible = "renesas,sh-msiof" },
++ { .compatible = "spi-gpio" },
+ {},
+ };
+ MODULE_DEVICE_TABLE(of, spidev_dt_ids);
+--
+1.9.1
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0003-spi-spi-gpio-fix-CPOL-mode.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0003-spi-spi-gpio-fix-CPOL-mode.patch
new file mode 100644
index 0000000..e802f68
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0003-spi-spi-gpio-fix-CPOL-mode.patch
@@ -0,0 +1,42 @@
+From db37427756bc9e42723f58067a3f387a2861fbbb Mon Sep 17 00:00:00 2001
+From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+Date: Sun, 29 May 2016 23:18:49 +0300
+Subject: [PATCH] spi: spi-gpio: fix CPOL mode
+
+This fixes the SPI SPOL mode, since the cs_gpios is already used
+in generic code spi.c
+
+Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+---
+ drivers/spi/spi-gpio.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c
+index 1c34c93..428417d 100644
+--- a/drivers/spi/spi-gpio.c
++++ b/drivers/spi/spi-gpio.c
+@@ -218,10 +218,6 @@ static void spi_gpio_chipselect(struct spi_device *spi, int is_active)
+ struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
+ unsigned long cs = spi_gpio->cs_gpios[spi->chip_select];
+
+- /* set initial clock polarity */
+- if (is_active)
+- setsck(spi, spi->mode & SPI_CPOL);
+-
+ if (cs != SPI_GPIO_NO_CHIPSELECT) {
+ /* SPI is normally active-low */
+ gpio_set_value_cansleep(cs, (spi->mode & SPI_CS_HIGH) ? is_active : !is_active);
+@@ -257,6 +253,10 @@ static int spi_gpio_setup(struct spi_device *spi)
+ !(spi->mode & SPI_CS_HIGH));
+ }
+ }
++
++ /* set initial clock polarity */
++ setsck(spi, spi->mode & SPI_CPOL);
++
+ if (!status) {
+ /* in case it was initialized from static board data */
+ spi_gpio->cs_gpios[spi->chip_select] = cs;
+--
+1.9.1
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0004-xhci-rcar-add-firmware-for-R-Car-H2-M2-USB-3.0-host-.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0004-xhci-rcar-add-firmware-for-R-Car-H2-M2-USB-3.0-host-.patch
new file mode 100644
index 0000000..8487d5f
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0004-xhci-rcar-add-firmware-for-R-Car-H2-M2-USB-3.0-host-.patch
@@ -0,0 +1,205 @@
+From 63aa7951b66cc771b23a002748a20a5555cf847f Mon Sep 17 00:00:00 2001
+From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Date: Thu, 10 Jul 2014 10:41:55 +0900
+Subject: [PATCH] xhci-rcar: add firmware for R-Car H2/M2 USB 3.0 host
+ controller
+
+This patch adds a firmware for the USB 3.0 host controller of Renesas
+R-Car H2 and M2 SoCs.
+
+Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Signed-off-by: Kyle McMartin <kyle@kernel.org>
+---
+ firmware/LICENCE.r8a779x_usb3 | 26 ++++++++++++++++++++++++++
+ firmware/WHENCE | 8 ++++++++
+ firmware/r8a779x_usb3_v1.dlmem | Bin 0 -> 9452 bytes
+ 3 files changed, 34 insertions(+)
+ create mode 100644 firmware/LICENCE.r8a779x_usb3
+ create mode 100644 firmware/r8a779x_usb3_v1.dlmem
+
+diff --git a/firmware/LICENCE.r8a779x_usb3 b/firmware/LICENCE.r8a779x_usb3
+new file mode 100644
+index 0000000..e2afcc9
+--- /dev/null
++++ b/firmware/LICENCE.r8a779x_usb3
+@@ -0,0 +1,26 @@
++Copyright (c) 2014, Renesas Electronics Corporation
++All rights reserved.
++
++Redistribution and use in binary form, without modification, are permitted
++provided that the following conditions are met:
++
++1. Redistribution in binary form must reproduce the above copyright notice,
++ this list of conditions and the following disclaimer in the documentation
++ and/or other materials provided with the distribution.
++2. The name of Renesas Electronics Corporation may not be used to endorse or
++ promote products derived from this software without specific prior written
++ permission.
++3. Reverse engineering, decompilation, or disassembly of this software is
++ not permitted.
++
++THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS ELECTRONICS CORPORATION DISCLAIMS
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND
++NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL RENESAS ELECTRONICS
++CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
++OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++POSSIBILITY OF SUCH DAMAGE.
+diff --git a/firmware/WHENCE b/firmware/WHENCE
+index 8388f02..4b45ad1 100644
+--- a/firmware/WHENCE
++++ b/firmware/WHENCE
+@@ -852,3 +852,11 @@ Licence:
+ Found in hex form in kernel source.
+
+ --------------------------------------------------------------------------
++
++Driver: xhci-rcar -- Renesas R-Car H2/M2 USB 3.0 host controller driver
++
++File: r8a779x_usb3_v1.dlmem
++
++Licence: Redistributable. See LICENCE.r8a779x_usb3 for details.
++
++--------------------------------------------------------------------------
+diff --git a/firmware/r8a779x_usb3_v1.dlmem b/firmware/r8a779x_usb3_v1.dlmem
+new file mode 100644
+index 0000000000000000000000000000000000000000..d094157084173b3c741d3d3d214bdd83f2c48d6b
+GIT binary patch
+literal 9452
+zcmai44O~=J+J9z-JD0DEGZ$tq5~HKdn7P^_tEi-cgshqM3Mwd?%7<iTW^K8>tsf%}
+zN@k|M>6%}e4VGlBlDK6#(FA717NCr1io*zgj4mLntf_S0|G5L=zU}*4e!u@c=bn4c
+zbDrlp&w0*so}qZ!Zx2LJEwR7LL>5+Z=2=lWvWjeSA9@gFa?}dyZt<$RTWow5S+!gH
+zsEK=o5*e%=WE-U2aF*zWX@j&8=ZFF%(ftS1eFma=8Fd9NV;iZp9@%HINY<t|#nYVG
+zNV;6qEt0|gu6WR7ZMCjW&=!)KRI$s5Vx96PjVIO1v04*qM>tBmY4G>@1ic8o*w~%o
+z=bTesCzMMOZp$voePRTWQ?8z<N=wwPpjQqL)o$xWl%UNGBU(ZEjQ6*C+bk_anwSLb
+z4N!WKtZNLm0orOdcYK02P^G5DWNPC$6*p#iAZeB*8p)<N2!<eorGq+yxW1ysVEv=X
+z_TUH=^$~L={j3D-Sd3akNtl!AM|;^RhYHIwRK&P&^1*_|XqE<PX@{&?tIy^8Nowsi
+z`E|k4VU|?GHC(><w8$A&K%#z9ioV3e+SSv7buO`7pPev73O1@pW3XgAEO}GE;BtAZ
+z1U-UY3;vWo8ABxh%&V2TJ@`IjR`B$d;z7Z4Ws_i$IB4oL=PzqILnbr6hHBl9_UPu<
+z>zd403o0>LsuAq1HA0rJk#h+-z8axjC^gvR6vFzLZ1RqXn}SU?sw(h|SC?`&d9KDL
+zJ0dDL71mBI*%NAn&Qa~>`fEvFT&y0&TI-EB>lg=YPN%#T>szVxZoyl8v{PPvujMSP
+zab$o^-V@L__AB|zU!3xSd*8~SFTtHJUNJc3ACj;(ZZeqD<?9pmDg%?0*_maR%6(!D
+z3|#u$oh!8kI^{w4#@onmPj}URt8>a>_rB#~UUvYj!lDLGmrb73cFfYE?&dVPYwSpk
+z-xfV<=Bk)vuNqWo$r;sxU%JK^#s}5DDeePDjMo}v4GP5f1j{aRpOBcf1}EEOFV#Ko
+zl%pnCq${WFVog`?jhJ&lAB&`NZ-t$gf2DRadfOovY%(Ahb$|bToT}C@@kXpQo98s=
+zsX2n3ai)*8^<aL2wgG&y9mBru8}6y`4QCozDgJD=OaBP;=#N-cJ}c~8-B3<-22;#x
+z@U^!dD=Z9xl|On(g+0_iKut@r>Xlsin$O%t!Z;tZGIiQY5%Z_{uAFLS*79>;`CFlG
+zPt6(3o@utp2Q-OVIYzNAWsffa6}HEn@=K7e!O(374%k_ic*J0rW;A*9?SfNoPqMZ?
+zZ%fc_!wB%ctC#ykU!r8bMzQAt@d{V|P>I_nZ=$;K*4ED<Wx3MRlj_3UeIkp-U_UiM
+z7XtGl4dK?-uhHkS(udi0(Gd2%Q1Kv>`!mn<x>BE{)YmF?x5X*nQe;-e9+jW^g^gGV
+zihgd-z`p!kmA@MbP6jCZy+_t`&Tkz~IUBMrGBQ~eAJp0#a=nbNnwVu>mXv?5?>eJX
+zK4fIx#oB6O^5YBBmqqgXmqx53<6<TBFsjKeevLi1fhxLma9ru_*TLGz&10;sb&%TA
+zMcvw}UzMP}ru1=0|70tV(Q#~tsqJ{r7W1wC_DYjeUN}D3<CMn^wYD~bMt?2i!`gZs
+z^+%MtQ+_Sh)7TDeCyi%5+9}@{jMctR#_8zSBV!)k*xJLQeeg|OIZr;=sFCg6>4wB~
+z9R=%WKvPjtkMvu+X8pJzLF?$MGwqdhQFh8t-Pik=(xclC_Z2~T77x!I0{@MACue{k
+z?Vu~1foG+gGiVL@;zpq_{5a=kr=b7O+N#1F5xiewc0OE#hgai#7}(X;58sC=b-xAo
+zqoZ=w9ka2Tw{(2g%NAivm*tgH^QW$gFdL)E(h(VWAUq)L;1rEm68>qpD)Z3H(kUxv
+znbVI`{#5hq4XRbM%(HXJKC58r>VP!?=JeZCi1xv%*JrIo89{HLZ<%J@R4#4Xl<iZr
+z**kKA7VLa(*UWdP?4I&oPH^U)ndaF#dVi)m(=oGX=HBoR!aoe(H?w%=N8$U!KMwz7
+z%3o$CY7@FVt~rwJ9Bb>7u!UQS3{Lq-<iA>{80cR)2mC{pxE3cj=iVWHXMpDkRCFbF
+z>xyWc_>8!v)8FGDm(2eIem2Sq8-xulvi7WHE@-mV=iG_uq?xF9VXa3-;k`3oZ0y?A
+z8#^}(JtMX#BiMTO?3?{voZ&1O;7MhErfmTH`a?aVs_u=l@%^xK%ny4~OVID)pl%&l
+zTZbavxS{m(Tkeur|2j4<rdsC5rUfeg@P`<Ux?z~cB9;2omn(hSd@f@Gd9S#JpELF)
+zZ(Jyq57kPC-X0Kl;O%;GhnOW^H`Q`E@b4}|k!h6TH#38n->ftEz36=9tyn9|E<sgW
+zBs_X4h!V8Rl~#6oj-_$FbLk0`oN?G!SCNR5A9m`~7%~m_&%gF)R_$%h+Bym=cm!jY
+z!Sl$Andi~A<xbax*Jtj?tQX%Ak3g#`8?+rWQD19i^-6J@sGjUfD^DGifiHPvo0OVw
+z3emR7H8{JjX5dtvGrZ{ucz*RruQ3$+{mFuIz4!Ou^-7LS&<+Up&&AH}MjEZ9{>8<X
+z4hPM>Y}c>|As-RKMxjKgga6*2REL;g7!~2Ugl<Crw~{J2HGJ{4FndA~b&jg#qDQg!
+z<6(AbAHf%$W8Q;F;b<))MsJfLN1<8-dIKM0PxoVtk~z78(_rMDFo!}ZUqF2EI~HFA
+zp!L<TuC*k4>j&hx^Z}W4YVF_U#wU{~oQ%|)qNy+SCo2u4-_Rp8l!nm=il;G@NRQFu
+zlmeRxNG=)!`pGwkJ7q_5#c-Rvl{VvflA4Fu<Oo$Mo*$|T@bswatTy=<brGHixSNQH
+zPI48n{Q1vr#&h(7W<*N?S{5_)(H6ksKU>JO6YxBf=D_nznpYQ9aE$Mhf<55_=tYqx
+znMo6f)?&ed*1MxNF&U?^R&$&V9Bx9CA(KP;fSwgUG9^(kh0+5QMmju2ionx|*mG^N
+zlOH|a$$tnO2Zp6M`KiEx6fV}uXA3L3D15I_FoA{+G>i%b6Gei8@%K)?4VeA7lV3N%
+z$xoi><Q>4<cwhg77F43UsHnA<<eKqG&~FN6H$lh!=s{@tA$k~k9zwr`rhiAn@pS}^
+zqDP_c6iNWbVU}%AIQds6Ir#xkViw>Uu=gn^Kls0#eBNXyuS<3EDS!tUoaW@?r#Shg
+zQ=PmIh)8$x6Mz!H2c%4Q@`q>e;4DA1TfR3G`FcaXFz}}XL?8k)PtSDnZeY<&Cw~$c
+zJ<G|bKMl?E$z7wfaMtD<a>VOgt&l5vIjk8!_GufBRp3+R1fgdXdamXh7u!eZ11&~-
+zzV>p3&vk{J&*Y_AOM`=7g?Pm=;!_^ClZDOmoU*RiB&q1MxKqp(w+ZL|sU<JB^Ab<0
+z+IsK1-Y+D97%l6Mf5Q&nBdDoCd{<PD{BKg>OxsU8!gp#sHThOg;~Bvu8Q>$PUOgx7
+z62B2$*ZYbpoN`5m?w+QM5UNb?OXJdfQW?z=cZOR!4)H2Z!<GMeYFK%%sbP;M2vp8b
+z4b#ByeL#H7*4Xdkx5pogcgnW|EphwFY)m9g8>n(tY3C}-*r{Q`i6Ij>*z!d#Me#fR
+z6f4TYN!o766*pSj4SC{9lULY`-4G9t-@CIy+$<)EE~AE$r3k42yCGJ^_Cf3%<{$Q|
+z*gg=mD!5=+d{waDPb1QqbC9>RICu;ERETb?;<>6)J$h(FdtScI4T28g-E2vSK0;zE
+zo@SmdDb+j86(>`O?t9UC$z<OSy&(b$V_rBpLl?M~g69ibm3)NbVoS$YED&_%`u@^8
+z`7R?*Sz`N`9MLyCSXUsr@-$QlFR#k<&MBkZXL?Jn>`<le<G$QECg}-1yU*T}Y>DQc
+zoJ`6V{kG2XXNTOQTLSwj7Rs{*OON}KX4G<8Mb{Mub6hwbP3VRFJn*?X!G9xJ-^(8-
+zu@!WXJ$zL-+vzOov&?qzh(B?Q7}c~2<wqkhl3%{SF6jd+a9iw_BS&oK*w|GXm1qwy
+zg6HooSu#u#yDj!-9He%0j++hFvo3XlJ;NX|{(bt}+(+Px@rNC`U<DQ8EVVpy&{vzi
+zEj!dG%UR;5kZF_QS+QMsPOKH47fY}zt#ZDgHvS!7zu{)!Jly`IJp+4Uwmm;sS0R3{
+z&&n?0va^o}{u8Lcwm$7N?)Evn3MYgm<N2#O894DWUc9Pl(@eu^KEO@mIblj=x`x)K
+z+vv?HVKe)q$M>^6RJo`x2{YEuJel@R+FMgX5pQLsUErQgb8*4o!pG&qs=poEi|RN_
+z!a-kE{Em1{j8mQ*z$u!afM|&M&VRSJkIi=S4RhcL=7wNzj}7ehA^*RZojey_HOtAD
+z0Ulsdwv%57__9Mm;V$o|kcInSiI6S2xH@={v|RX{c>=zlz3;o1%kJ_pne&`{WS*0^
+z<%OZoXFN_^9lPIG_{y&=<6qBT#=i+{1U3Wj06T&A^0l5d#Mk4De9j~l<UcSnI>zs1
+zDzU>BEiA=z_d?i{4)hlD_1h`1dK(2D*LrqPG-xyL<+@^up?GtO8CIFBjgEO>WK?4B
+z2{@k?M#nI(<$w26UCU0iMa+Noo)DGDW@GaVd!ZT6`7f~97QKMk5S#RH-_2pnV#eW^
+z7JELM!%xo#pD=haqt{Jq`C>-PvzXBmU-WaHMNAXr;MT#pt_+ko;-|ks>dESu>a?wC
+z!DCglhBm}zW$qc0lj$<$W)=@W15cX;&E|;t!aQ*gB9uT_!{CCOR#t|sE>+65)i+J-
+z{qUMnlYc}BH&0{|y;N8PNtYJh6#ljSwL-?-?n1`hvBK`04~t>$=kVLs0Qgl#r$Ont
+z;q_%1oN`-S%QwpAxG$k;_qyQS$c?Pa$zVB$YLo#ee?Y0lE@VB9qaN5*FGoEXZ5=2>
+zQMRBALwOCQuB*>Q)Dfl^(-A76O2g%En7#tAx@~jopDD}n+&FJmM?%_J>r8D~I^QL;
+z`a*_=F3jP`Cz;jrCjZoUHN&hvt9PYdn8Q=9?kZZd>nrsaGJ+`2<5NbvPCMn8b!@Du
+z?We}M)fc1?ij2vr_ntDVaSQiTM$Zcw0x0+DqI~8wqx_RXS>H{$no$m?ym}wTM#i{m
+zaOYjeW;t{E?&tfs=+EvP+{Zm|z|@jR<0{{w+{&+a8jvGXPcBbg@YPWba%F!#rx{ng
+zndTQ?FPMl3n??UxDFC*>){J?ztoVb|Ttjl=YsPpDx$$S7%n}<puaJXhzR*10DMvdh
+z@LcZLjOW~<W<-F|drQaM->Y=EQ?7k~GoHg7%|oDXM=72k78MM+zgL0PDKB}y8S$U*
+z{Zc%)I12DgE2=Zx-;14paqpMnS@wPbo=J{64(C8o5%MYi6R;oIrLTJ-9|CXwS+8ef
+z3N^6R{T4~zX=nH6zJZ-xCuJKuIdF49j9zK*-?ESaEL$mFxkTi@$&^v4DO$<wR2>Vx
+z?732cJdaJ@O=Cu=Xw-R@;R!IR=}(je4|?uL4V56Pv{@MEWmz83L9WW%xTe{ELdBqG
+zBytx~$Rx^bY;P;MAl&Ma3+l=wl~Hq7CTZ5OV2`KKD@0?y7#fZF{CA<3L1iiCEBRF}
+z>Dy+424vl=r~&XdgS09{YdNTWFTNp8)F-BkIG=oiT1=6UVfi<IEO%|`un0Dd*?5*#
+zhO5Q=@Ku^z{$ZgoTqV99?!Uj-TN{HMml}gix@W}g)+7p~5JZQ1M1>MXA%3;Vi*RqV
+z$!ay*`{~s;u||8UEASL+HX~{osb+g$SIhQ(*a>?=V^F6*O3(90>CAs#Q#sJy6}|t_
+z-=2u}lPbH^8068H;Lf*S3t4gRVNq0L5IZH>6+gx17);IRv4z+iEq`;$u3CErxRx#i
+zc~fg)6<-E9!i$h&OHl4j;IGQRUe|~CSLzHj<j=Xhawj-uy;x(iOIfp6^yKRF*BWFm
+z@>s9jIq_SfW}%!<zSG_A>g;YWUz2>tPj6sk_YJTRKF&W^<MS5jy)qVuP1JA0jk6yz
+z1;})6dC*;pj9t&SJx^;`My712VX|SOzGRx8;!;rT=5ReS48P{jhj?e_9hWwgZr`+Q
+zdF4*+Ux>=z$}Ll7c$ct8YH+IF#;*mccuG=FbjrUBRpXRz46;aBW%=TF$VoH?l_IZB
+zWtn5957#9fm4E2881DwMsMc&OLw4P4Br|8QN*}MZ#C;jW;#=NuR6cNff|959uZ&0U
+z<#G{O&BGb88CI~mimiWD6<eFhSepSgJ!?~fn*z%ZK3;Z$hYo(VPVqmo_0JQ}Am)1#
+z88usPrdMlgD(dT$dUsw4S+-icWC(`m5Lj-3`6@R1#acG|p%ZNO^(VXi1#-N>zkxN$
+zGNnDC&&ElYxFv?#^|&o=8H&<Bw*4d<TU*D*UPdmSSr4K+jHNW!Y{br5o9r`e#ff>)
+zz-)1)ut#_S@g1{$qnph>z|APcxfzAgZbrc&^#YG8mHyYk;|qQ*@x$CsJ`=D3+uUsD
+zF|WpEQe&2%1uv)8E|;%#NmZ@T^(b_2D|A_3))V<f-h4`}U7^&HPT|gXs+;ToEb-k_
+zjNeb{8NbKs8NW>bs<b?j(Y;Z>;$Pk~PcuGY-z`*O!U=icv?(qKyVivgCn|16XHe^{
+z)U;<zakwR*?HJkyD7E&}{?+TDa1Gx$P`J_cr4hf9Ee-PDIZB{mmOWkY6Wc2VV$Bd_
+zRtk%Y9jz~hB=d_yvXq=kj?X2`^VJG@KCi$$k?Sm5jfit>H4dL+(uFp#4ANe5B)k~X
+zIm(OdiaE}PyySfB^cO=s`n6s86*l+i|1<ZdpI~QKJ*k`U%fLMzsu&L$p~-xD=)dRT
+zu$S==c!BZYy1;lyZ(=<B0v<9#yLq61qjJ+-yOa^y!$THwGk*v%>7Em}4^P6aycayY
+z0r`dps1LFR7UT>DA!C5d`MJ$jn>>ryS$gdpJ4+)Q*jc)$p$<NINdxoD%Nv+J#Pf_7
+z`+3I8k@Jj~>ho;1AMw}|{s4U_`IC429+*@|<+QuqYvceYSw3dtIlhBJEwt>{u+GCM
+z#(5aUmpqK3%fl$X)adA;_(c~*^--DbQM9+t2>s8p?YYn+TgL?^+tel|+mR+Fo41L{
+z7TnBa>(k6Qxz)@#$-KxoS$vUkqP}ELm;pU2vYqSVB=D%b<W7%lGq83mAr&%d0(@7O
+zY)uy##js0^V$@|ualvIqao1%>55<-)in^n+<sL=mQ&)@c2xg<1a#2^uvi;D};%Kdd
+zrJTNJDPJ2(pvkWVzb?hAY`&3K*?eVJ*?g93Y`#6$90_&Z63AWinUBhcZabvYu$ME+
+zFNF>Gb#}0h5GfMv0;2UqnLrY<@>7AmsJ8%nu{kFLH-IJKM8~U$?gB6Ujp#!l_y?jY
+z;4osO@*jyJtBJCKI7A|k)SwR#P)qbOPz?+_LG%ldeG<Qu0~71e4#eWOg4X~q5Pyp3
+z5HP78rxIX1O*9{90^-gPl>h-hfnUH5IDmSfKYlTv46t9$j{)qL^K4)>um?B-`~Y}?
+zTY%U=G!PgI*nwYwlJi6tfhZ4X0jq&8fp+%ZNVEf}21GA-xB#9}Mxt~8gPMo}kAWB9
+zsc(rE0ILBvkawIY<~yRfz<S^~&;Z;8238U+1U3MBfF_{ud-R8%(|}i-p?e?r0v23F
+zKb&SxpraLYw-Mb&eRPzX`dlYU0di4)8yMRTy#c#`19(6F59l1YhWcG#?G2*P2h{Ww
+zu>2<K9pDdG3+w?(fV04Sd~X60f5tikvwwk3Wax}k<l$7*f@rco@(tO*THqEiD^Nwd
+zfXhMX6QUw}sETd?`GSge17Tq*nhP8PB73PQ4_E{&0S*Hv0e2tB(hqa>2hR^ePe6>7
+zl)sZGCq0C<z%LGmh7nZ`C;B9g=#de?Nbm^gMnN86J#ZJ8A5XLu_yGue6#am?zyhF&
+z(Ls4+G|_}HL?;2;SfT+5m=3=O#3Vv5fN>mtF$J1{fsf%m8GB$n_5<)Ca2J@ILbMKO
+z05<#{^$Ea4qWvfjpuGPtauSgTZS9aT_bJ%VBJj2l<!j&rI0BpjZUOm!BB})vmqJ!x
+zhh9zBfJ{+Mc02ZP0qhZ|1ZJ-$n!W~l1NIbx*6T!5*TU`qT<qyA&<;#mhrI^OeiQZu
+zEL@L0`WD`S8$iki%nw9wL>*WUd;;7Cnl=&b{vYfo!16Ze0);>&5V{$B0;_@jTZlUT
+z%zTNOO148UfVcxZg{!G}Cy{v<_y!IEQSTBh2i!pLZs-+#s!;0QBT5H00bXGJ9?14S
+zXgkms7*s?wcrW%lu=E4`7XZ)%m_Gz<AYvbA0kOr<2XN~ntl!7r0XP7peS$Rt3jac+
+zJ^&ek;)6tOCHVd+{Nf>^#XwXk))#mc*alPq9l(Uc;OVc>A@KHRu(1d=E%^exehEKu
+z6m7s(Cun_zeFd}wbIaf>fazbuUjbp?fCl_%A<F7<yjOrOPzW3cn!@4#BA_2&FVFzA
+z11SdhNr3%#&?F=10_%ZFpbh9FVLgGZfD>o};v-@AKot<*8#Lkb^H8n_Dxu#)F6=wB
+Ty<7#|>98+>v#~@WEkyqdyL9e;
+
+literal 0
+HcmV?d00001
+
+--
+1.9.1
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0005-usb-host-xhci-plat-add-support-for-the-R-Car-H3-xHCI.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0005-usb-host-xhci-plat-add-support-for-the-R-Car-H3-xHCI.patch
new file mode 100644
index 0000000..564d4fe
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0005-usb-host-xhci-plat-add-support-for-the-R-Car-H3-xHCI.patch
@@ -0,0 +1,174 @@
+From 98d922b9bc891f33efd04b9cf8efde22d7949213 Mon Sep 17 00:00:00 2001
+From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Date: Mon, 5 Oct 2015 21:05:56 +0900
+Subject: [PATCH] usb: host: xhci-plat: add support for the R-Car H3 xHCI
+ controllers
+
+This patch adds a firmware for the USB 3.0 host controllers of Renesas
+R-Car H3 SoC.
+This firmware is possible to use on R-Car H2 and M2. However, this
+version causes performance degradation on R-Car H2 and M2. So, we would
+like to keep the v1 firmware.
+
+Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Signed-off-by: Kyle McMartin <kyle@kernel.org>
+---
+ firmware/WHENCE | 3 ++-
+ firmware/r8a779x_usb3_v2.dlmem | Bin 0 -> 9472 bytes
+ 2 files changed, 2 insertions(+), 1 deletion(-)
+ create mode 100644 r8a779x_usb3_v2.dlmem
+
+diff --git a/WHENCE b/WHENCE
+index c310c8b..2890465 100644
+--- a/firmware/WHENCE
++++ b/firmware/WHENCE
+@@ -853,9 +853,10 @@ Licence:
+
+ --------------------------------------------------------------------------
+
+-Driver: xhci-rcar -- Renesas R-Car H2/M2 USB 3.0 host controller driver
++Driver: xhci-rcar -- Renesas R-Car H2/M2/H3 USB 3.0 host controller driver
+
+ File: r8a779x_usb3_v1.dlmem
++File: r8a779x_usb3_v2.dlmem
+
+ Licence: Redistributable. See LICENCE.r8a779x_usb3 for details.
+
+diff --git a/firmware/r8a779x_usb3_v2.dlmem b/firmware/r8a779x_usb3_v2.dlmem
+new file mode 100644
+index 0000000000000000000000000000000000000000..7db71726f45943e7162d8e21ce7d80885bd79184
+GIT binary patch
+literal 9472
+zcmai44O~=J+J9z-JD0DE%!QeY<mgB<W~{cz`bjBB=$cutpn@Ny@*$Ox*>2nRww5Cf
+zN@k|M>6%}e4W?AC61Zi0qY280H9#4W6o(P~7+pbD-BR(s|8ob#ecSi9{C@v?&b{~C
+z=R9BMInQ~9k{Q48Mp8YozY7#;Wv$+l8J(kO$gcFK`_ZOEFQuL*UQN#vJD){1{m1>a
+z#63hw47M9&kJYa|MfAdqSbgMaq5w&B{~mpxk!V3iL!rymL0Y{>@tLiXt@SPOBxf;E
+zcrN-@$>@Gh+;6tE+g2p%i%3hF_}7TyWo5n2lj`MIuNA$69Hm`1`bX`>D8eZA?Kbgq
+zPF7Y6l~SbJx?OS~8$~25wUaezN&2Pq%=KaV&3%Xx^|@h0OR0eI{&rux^$L+LE>V9C
+zlwKs;N~3*{zLw3Mkf;yTXlXH-J2+0mjeR|kbgw0u$ZjwS#vr5h26Y8-14NzC_D8e*
+z{!tq0FXl>y%tZY-e6@&@F(=cH{(`K83a@2oh;bqF!GhIfkz)0<Rne_7<njY0t^Ts|
+zhG4y6ku)Q8T!HwM$QhSHqJh#xL#dfP*UktIcZrpT?8Ko`ut`HYqc!6}$(#BGm&@BE
+z=n?d;;7=WsF;w!;yh5GZgZHyCgJ&)i_Y0nj>jkUCK~pC=e_PiTGL`W)Oz(cUS2w@3
+zYYJa0Xv7q$PH?o>30b}t&L!md>V!_A+-O%O66|BPD|;ia3wFh%slqiuTh7^)`8vCD
+zAhL?nz;;^6kys~mjp;lcqbEa2iFOQo+Gx7oz&K!Y%E~6#w^|*21$PPkWM#$OC#T?z
+zqXX>9&VT{&Un+<0$jZXI?<$}#!CfF;G|I}+WZ1?{MoYSKb+SQYWRfyJvu@Y8kF6w(
+z{M?-@bp*;v?A`C}<oBoBTEExHO4!|ZxtP}-Fi78O)q<xBW>0D-X1Sv6;WVZD+tE6|
+zFM3wa*D%RmF>2CMGHM0CbS-g=52}Al+yjmnuXU;o3dQ#Y>vnP<lbE*#r`Q!QH9RjX
+z(UYvw#S;#(u6y)4%sHsPRnoXO!Ottd)VdkHEszU78IX&<fBYU!Q}35}9c<0!ImvnI
+z4q|0A^|!U}FG$okgHN_%*t<O=JaxViOe4$0pKT85AAugjL7T>BgP&`gE2+U~j#~k~
+zb~VDnLM*)e;qw}-p_l+IErHdmxyqHFxr>GIKIUcGv}GdZPxD<o(Z;;x=fKLhL*1Ub
+zCd@wDVpm+cB)t-+dY8J!7lH~~<FfKQNY`xa@dGFPEK59SbV##WJ%&y}Ryvby?a$j2
+z^_%epc;DW~eQW?x3SX!CbD?;Vt9+o;ZCBP)!vtIV=a8~e9qCDRVebA>#bdFaTA>Sp
+zMUmzRTl-fSb3q-$e7krkdtanRkf|{&GQFYpr>Ol^YTs>@m7i3ZHSvd)C-1N?mVu(5
+z+a~yzpR3CELcz%(b-nk>n$G#XLsqgO>mn1ARgFRIeIeINc&m$ht=p3d?v7n;l9e(O
+zi!QcyGm{^0n7*u%KfbiUj*N?C(8HKkhxirN+*+#Y*1-{Vv|k6SqBe}RwKqU&Pd9a2
+zyJ2~v{<1p8DgBdK9$!zw3M<n(aGxy}*!<6{&9ag|A=o1;<A&MVTR<a5&-k#lUq$~R
+zwJ$5L#(P>iq3z@eEJn-9wIQ(fJu=S3xLz6aaK~&9kM<!pag{vz;G-tCc4r!s(!(j(
+zFbkTBmU^Y%)IIAbg^7A+cb{pmw41W5JbBOPZ`2Vzad?0T%9%VOcL?G)`dyq6ar6dV
+z<cvIP-JDTxED+ZT0}#hKH`@jMf3|iF=7{9|60`l`G9tVd`@`VwX9MwmxZ3x7@IX4O
+z)ZDU|YI*C8&-&OS?dgiLY<j`;<&hRsKeFD43fvbFkhXuCPArZ1G(t1GY)<*KWto=r
+zBUCWmGIy<Jd8TD<E;%v_r>_WD8DL4jNkw=*MDs@GDzuUGCdO9iR!`^BHc#6!O`p9r
+zCurfe=eEyzZ`zJ&@8<;1-Z{rIH=I70qn+)XQ#@x^#D@{PBlgTGne$P^#}S`I?49<P
+zIZ66NHR3{UPm0m9QRzrC6qrae0U8gBVr$9P{sg=uIMDBJyQBWqU#)n~Z0SVA$P!m!
+zFX!A_#qW%WMS-gJ#2)PtjTfI5H+K0)?B`PWe<1P(+TfM&s!Ut2bzfHJV&jt1NjKTx
+z0xyH2ao<%Swsf!abzK{T-Y<5mUoZ>zt|YmeGg+BA$dk$<PxByIiF%;-tLD33+4+H3
+zOJNUsQcE%Jcx;bWZ0*C4f#`#n?0#R)jrUu&Wii#W$TlNTjgUv<blT?OI;&Lf(_X0d
+zZT7iLiR8WL8gbe*fV?9^sdAWJDtl+p$bIiLid)4j@v6C=%R$6<8H>$h)JU3-S(YHq
+z`s3=W>RpLmQCxzizF2tpd=Mq-*Q!t1emaiE`%b4PQcA`FUqe+AasgP-r!&qr-aG%Q
+z!&&t=Ia~V}Sg=Nw0xNMbi$(g5+?l$F#@SnEH;V6y2ccDs9omkYY^b-fezmw+)J}D!
+zRi?&f;7uOcr=%8`L-ZX=9d@%z8Q5p%jc9!wdx3Ve*A$8f@I+yy!Ta0q`lQ4s>PH7N
+zjdg2^9??@wNs0A_ljdJ==vdBBfSh5SP%1PaqHj)aK$b9^igA6Ju0#LllB+l^qH|N2
+zBe9se#?*8D#<2SXVGd~zAv&FA@q|g?Y%eB8Z@n=`rCJPnrbpSe@=-=9ETxLm;mfsQ
+zPL)!DfQ;ieEaM2k)4Z@A4jt_ulJoqBWDeKr|E{z=kxUU}qQ2CR22c#yXfXYX9-?71
+zoJLUsjin@dlpdpr@R`m>i^qa~%JmV*PE)Ez*p*GR0oUWyHq@>}YRYllttrISqiL|&
+zl{?yET=#L;ktH4Hs^IzQ&u+jqc3~UxrvN?6qWbF#;qkljnRYt!nKav<XVT;?s^S>m
+zF2RxbA@rh3lftA4#M4cJ6HjlCS<hsg!Jb-1hJ!;p@(u;-^Fw-8{K%Y4!4yjOQ5c2e
+zDpDk_CS;?pq{w{i1exCm8~|b_%6u}geIgex^HYVT-4wo8DVRYc95hTS1v5o~Lcnij
+zz8RSEn9RRAN#@5*mihHS0q&PPt_PLiZYo;+d8KYbGW0tUvzwvgfpkB#`~W=&JrAW{
+zL({*Z5qLX_#?Zsi_e4qr#$%SE$7Mcmip)nofmwhi;GHLBKKj38e)?3IzXJ?UmHDGU
+zbehZ$o+k4Pr^|dJpiP(gk-!e15g0yG=AE;6aJD$KN4_^z`T9b>Fz^=+h(IJ}o;X|P
+zD}l^8GVcOnGi5&IDQKRL@BTUqyKjLpN4(0_3%R0~gU$FMPuY1`fge6E2qObAas}VA
+z*fGiwXf-(s^cSjpu8VBPCNI@no1Oe}WH8QApYpOI=eI48l{<UPl7>!-+r(UPvvB&K
+zdh&AH&hw<HZ}h(B{X!Cm(X##UH>~h7K}*fzd!lyqf0G8g+{d&vVw=uWS77tBGzn(O
+zh!`>b(rIzK__gS|IzZH5-zzruj5KG2P<8qM8lUEqDrla#Ey8-EjMs2FuJX^*!z%ks
+z4|_OKph|vvm=1C8L*nB$#ebi$CE=R{<idg0ksp)Altj7?P~~jWw&m7w)5C(3LMCzW
+z<>TB$HSP>ly(kNNYo{?+TxaVv=84P9USR`PLjp2@zFk$~1~FN5nRJvQMM{NO4e=Vb
+z4lMIneAuO7>wvPVxL|nv!C-%!M(#6jKX1L_<gJKPA>o_U$W@c-G3*qy`ZLN^E*3gO
+zbh9TT9|?)CdWuE5<W%nr*GPpz!oL@7=gp2S&|9LuGmJ&yl#KAeRTTV;pw}n|IWE3@
+zLe)YcywVUOy<6Zi@suTYj?EE$BZ9*VMOU7VsuATiv%T{wDEH~Uk}Eq@9s8Iscb-{#
+z+`vw_cO`pScUMj(<rTx`uF7YJ-lba#|0xkFvxZ2I`I2YVb9z<RRYuFm2s)hD2kY7N
+zT!Y|0qwMJ8&zzVAo#cpE9>G>R%LA=*ojfv9oGZq(E=T*(D16E1FLX$Tz$%;{d*sLw
+zJ3034a-BwWL=+?P_m!*}W{I62V;BdiJ)GmL!}Z#wL2zUkCC0zcaFhE8d@=s8A{Q>D
+zBJ8Esr}z8nvo~jlniM5V{1h^+H$E$N3eSo4!t-J&tkSL&2wKzM@%C$O7WTs}PdGBL
+zCgwT{g2SuC?+sbmrCfIQLBYQR724ONoy2KBhu2_-ux31eDJKIvUdD@;bRD`Gu;zW-
+z44xCFRj2D{Rl1$tnie)E1|z<o>!IpJ14x*)X3p`nchlaU7K#ikEA1@zY?_M;1{XfA
+z0ABs=xIWatSrhmBY7(|4=;Dyy25_q8Cm}y#vGd=p?XtNtUo#JpV15YJ_K?7y81nx|
+z*>Up`RkLJ%FK`q{$d>upKx1|&DEN3kg)E#1ONDIF#Wf&;B;_LJED-R%`kwb*F1tIz
+zOj;oG`aGFmloy6EyLda_63$NiRldrLukmjbyvDx;tOGUx?*iL^_Y3r%mBcq<k9^K7
+z6&Bn#x?h|>%2Z>8W#*UTx+Wj~6b^ce`Nl02Si6~mj_5sGsUK*w=;gX-j-v$2L<_t!
+zUf(b7zR}T1eJ5dm%I_D)qL%;OPjwaB(H61z)pt^K5}S?96Z1kFuIVqZ*)m_iY{*S|
+zx$ohy|6<1B*ei|#Hiw^{4>2KnF{9T*D}OPgb#yVKMKAg}&myLYN^tAsTo(sR9Pu;X
+zB<)mfTy5H>wBT_XT1ji;vu5ucnlsyF&YfK{q6v{U3!2Rl3xoyYPGl&7@P_EZ>o(Tj
+zE-Y8u<`vh??B2Pu-0c6Nlv^M&iRKp-L(+vs*M)z5{!9_$ZcP#6uB@o13dC}ldpZ2J
+zJpgf)(Wy~KzW&B*8JwC&t>Rl0%g95}bmi*c9kTMx>YNN#g^<w(pgn|Ek5$M<96&#?
+zyI+caFrKxd4MlqjZ5Y}nwBg-jj-!t>y@U=@DODRUe9iO~0PA+lZ+yBU$8+tBMH>Za
+zC$BblWQF_ATeN30baZweM?T4-T`={>mP;8H?J0vR_3S*Ja>Fm-X?A0^;cP|_<#~MS
+z*RGQ|eXnNUnmc}MnO}QW3ZbaDoJQ{nixzb;KV^(On<0R5pKi)cCmH1*Rmz4Q%C(Gg
+z1m!jQ@NHC_t4>zL)ohlglea(L!}a^@*8V-*ef!K;l4yMOyOdk~)ixulX4<KhsSCe6
+ztV8weucvk6OE%CmC07e4Bg1Cdzg`M}FEE?2sFszme}-#lPD0&SuQ4~F>4_|{h4TtI
+zxE2U)6HuLTR^giO+<@zo#cjv{gLjpWy?0dk2wAE4U<0l(&bFb@x3e7Ajm3pS?;TZW
+zla<^L+K~S>eo&69!&!)HQgMUv-cfA-vwl#H>)sCvagB2}aM%Zmi&0_m?|=izA$`>c
+z6%s`A&-y$YSEPfleq@ylT@H4l9uU~oy;F9uodYKq<mji2EJs&sf)&fei|2{_Cz%Q=
+zH}_L(JqN!DzTml7ipq~&*+FARX=uzDR`W5LwDc#+LIgeigN{m3XWAf)_cBVLgX)#H
+zWo4Uxhf2oCD4Y(XQCn0x*xFXBLpbN7I@DcTs-U*++S252f<2xVuh0+k#nB^}&wmzL
+z0V+!{U+FKZOW(E;G@yiMMh`-~iPdY6t>vKiz4)d$*^rbjVt?`pT5+O;n#;fWW7TZy
+z4Xa?+Sxl#BS%g+Bh*+-6<sTG^A~fO~5v&^7LXP&9Am{m(AanTB;uc#n1yTsILj$rx
+ziK3Ce+Lc8(x7ih~maYAi+Uu~<+S)2yscr+ZmeE?a_V3iOwST+bk=PQ{<<HXd{8>7S
+zpG_Jko_A;OfAl|3!gH6#A+-c~45c{peXNJ9;D}{WEkSIT=v3nrn_~#IVZ=sabDa8{
+ztn90IWPoewY>+p#9$s-M$Qe<Ls+<3`5B_TW_PRRMZ>h`BkiQD^hg-pMYs5OUL(0lz
+z*^{fw-)mO9sBHb=*0Em`wF#Ac%B`N~uCAWvl`B(j`ROG@^_&2U5aaxFwLEW?-mhSJ
+z*kr?IoHz%fQh?g$#{1p%sNwa#+xe7^)o3b)8K)X28%k&RDXsy<9uC)_!thJ}e8_jU
+z-E!$e>E?Co#y{Mu{|iy&+qo6$4DS)vNF8?7oA~`elR(MZ$+B{Jm=?QyOORE{swfb@
+zLrtP3s2r7cs+c`?=7{j*!^)v9tLb(i%W5sA3e?*zCbDowoAk*t>&QbvEWhQAhn4L&
+zC#jWdzhyiIFPDqVY613;4e)}OYMA{G)-c<QgKZ+~dTmpRlLD(4K2~vzhYo&Wr@=ok
+z`{#*G$oZZ?jct8jrdL~gD*D^izW)r%>KD({J0xQ;B8R|g3oKT#*^k$=*>@gevoAT`
+z6E9Hp4gM9pNl_^6aYHtCx}=S9)M;3cb{Ja!x1Qtd+lmJEtsB*O<~_*n@GYge<|232
+z+ZCU26L!q~M&^slgq^|*$nTi%2e{enk#0u8>Sh#T-Hd`$>H{8^spGGL#~1us;$z%0
+zKM7a_6uH^TV^NLGq{S>h3tmpEe_grQEtRa&J*v{ZpweYy*+^6z`LGjO{Zh3TcLHa=
+z6Fpr2XNi3$7{6N^8NX$Xj9;dIO<JDF=z1HM{>%NOlZ;RJ_Z6x#V~5;+(mXN<me_|D
+zJ1R~_N6_o5_O79aQv#lqp*KkFc~1JR*Gr)Z?>JEKcE4%C?`BJa{AZ3*XqeSgXa306
+zN}*Uc6qS{tk`ib8iy<le;*c!0rjp}x2@8DnLY~hnut>D;6tjl*G_!{DG?VV;X;wkn
+zMb5+*L%POzQC+c&w4+j)j+Opmh{v$1yS~Eae&qkmZT}H|cFB{v9={db<)Mc0kP(`~
+zr-%M~9-Lmr!woOvVc%KCLrN>-;SPAn2<_p40uC$nw;fVOXfF?0h`zrMF^4}VZW)n`
+zQ+Xdmcq8f!_fdaT4Xmgc#G+y#D^pKzu-TPNVtZ-RX||W@o7rBP+1!AboZHMIbAB_^
+z2c2QO{O%0nW%n7zi+qMzyPwCA_<QI>t)IN>kHDlktR&s;v5^y;Wciqn=lJ#u_0Y0k
+z!*^7QRu7{%-@_>G^Dv6@Tb#WVzv!l@J*-^0)kD$IJ}dM;%eMAxuWYSnnQY0eOt#&v
+zOt#uqCfiS~Ot#QACfm6-#>u2}jFY+N7$+U)9Er1_XH~Y--JAp-R&wuh;shs5wtC3c
+zA|Q5k%T|AmQM`SQQ4GAmD9*gVD6YQX?4@|6n_~E3MZ8Oq#nctzyMo1Jp<MK}@oYV`
+zUU9ZJz*A1%^^~uSrO@P8f?t<(iOo0Y5}R-DB{rXUna#KMvNN%vM*^jLKFeWc=S`<{
+z68_Sp{&q;zj9+YrgcEW_qU}IG1JP_C8I}6!z%KN!0K2d}rvlf2mm`Rd)DYbUe)l(`
+z-9YeBq8i``vZTr%h@xtVvVlp+MINfd7$BgY=p~>Q7=DcC4v>8uznue<8}J;6$L|NP
+z0$w2D1W_3<r4joQU^+?k4A2UUY$7TJ0)7O)fCF#>jX(^3MV|_=U(>$<*stl?zzSd|
+za1b~Oc!8e)v6*NvFb;44cYx9}MCX8L4`=}^fI~nhyKf=d3e*Ck7d)H=&uF92I)T_$
+zqQGy!3-IK(L<@lxfE&m=LKOEM(R^SHa0F-uZUcj>iSmK9z)qkQDEc1bq31N<l{V<!
+z2fl!XmoNtVSuJp*9dmaOg+^=XNud8#qKUxE=<fo?bwY2zcEE-EBmaQTfjj7j-KV8h
+z*NFO~oe#Wz9dvGhKVTKG6DS2v0k7iy4It@fq65I(JJ5*&osot-oQAF-pNv7pAsbi)
+z`~+kMYG^xfAqZnaG~@`?&^4ey(9jMbEKEc5fifVfkB0JqMZn9z0pK{`?hpSQh`C~j
+zF5eG50dY1`|Bj=b@&Ig!-zLh26IG8O+B=fyp;5qS@CbyDfjqz(;5P6~0?{VmC=m8A
+z#sTwzg}@C)2kpT};Jagqjsx~_M1vAxYy2V*mjt~4rt$a{6=($pKZ^Sltbqww55R8V
+zHZXM}(Q2R>So>S_Cjpa*K1RC_?Y)0dQ;0lx)(IJNpM?J`0&n?fUj-k)L7)lv2`Kmz
+zQ9Y2f1hO(1v~&l^7q#SYU=0_-RzNi{cLmYRmCzfovk0`_Aez1keh1)aPp5!RV9IK&
+zHDK;r@Gl^L4c6$}xCgEQ6W3yXpx-+5fi=Kh;3m+zo@mGazy^Tz9nb}efNCIg1Na11
+z03UCJe*aAL8Tc&S0=)p@R;=F$EtPB|vTO(6Kp7DI9?|Q78wlP3AH$d$wBhd)r332$
+zFR*4OWcvWLofr$m784EGh4l_B`4ImZ0JH*@-JlIb?tzVf_!8&?_~|3q?-S?+*axKT
+zg^hrszYuBnK}MitKT$_1-hYa?SVpuMh%SeHfmeXdKn-vMm~;R<{S`U{-uVnRjnvZ1
+zUx3#`h!cnL4A>-t)|XgUKqoN20<i*^`4!?75cW0ni8xw>wzd-YRiFzL0Y`w=2*kfg
+z=m*#ZGy|Q$L?hxP!2V-siV1XqH9$4c0rZz(Phb-u1Fb+p6#O2j0TTLxCSrab+BHBm
+Z^jqe_y2G=VYM{GttV`fjJa~cL{uf;D@)rOA
+
+literal 0
+HcmV?d00001
+
+--
+1.9.1
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0006-spi-spi-gpio-fix-set-CPOL-default-inverted.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0006-spi-spi-gpio-fix-set-CPOL-default-inverted.patch
new file mode 100644
index 0000000..d7b42f3
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0006-spi-spi-gpio-fix-set-CPOL-default-inverted.patch
@@ -0,0 +1,30 @@
+From db37427756bc9e42723f58067a3f387a2861fbbb Mon Sep 17 00:00:00 2001
+From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+Date: Sun, 29 May 2016 23:18:49 +0300
+Subject: [PATCH] spi: spi-gpio: set CPOL default inverted
+
+Workaround:
+ Set default value at probe to 1 due to issue with H3ULCB.HAD FPGA
+ ethernet switch
+
+Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+---
+ drivers/spi/spi-gpio.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c
+index 1c34c93..428417d 100644
+--- a/drivers/spi/spi-gpio.c
++++ b/drivers/spi/spi-gpio.c
+@@ -289,7 +289,7 @@ static int spi_gpio_alloc(unsigned pin, const char *label, bool is_in)
+ if (is_in)
+ value = gpio_direction_input(pin);
+ else
+- value = gpio_direction_output(pin, 0);
++ value = gpio_direction_output(pin, 1);
+ }
+ return value;
+ }
+--
+1.9.1
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0007-mmc-sh_mobile_sdhi-Add-R-CarGen3-SDHI-SEQUENCER-supp.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0007-mmc-sh_mobile_sdhi-Add-R-CarGen3-SDHI-SEQUENCER-supp.patch
new file mode 100644
index 0000000..803c2ed
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0007-mmc-sh_mobile_sdhi-Add-R-CarGen3-SDHI-SEQUENCER-supp.patch
@@ -0,0 +1,1070 @@
+From 3b81bfa8f0dcf10e59172b10efce2c591b35a590 Mon Sep 17 00:00:00 2001
+From: Masaharu Hayakawa <masaharu.hayakawa.ry@renesas.com>
+Date: Wed, 1 Feb 2017 10:59:39 +0900
+Subject: [PATCH] mmc: sh_mobile_sdhi: Add R-CarGen3 SDHI-SEQUENCER support
+
+This is Workaround patch for SDHI-DMAC restriction of R-Car H3(WS1.1)/M3(WS1.0).
+Restriction: Mismatch of the transfer completion interrupt time and data transfer
+completion time.
+Overview: It does not take into account the bus response, the transfer completion
+interrupt IP outputs is in the early out.Therefore, when carrying out the data
+verification data read from the SD card, there is a possibility that the data of
+the last sector might be missing.(MMC Interface is also the same.)
+
+S/W Workaround: The last sector data is preserved by reading data for 2 sectors
+extra in the SDHI Driver of Linux kernel.
+
+The SDHI Driver achieves a dummy read for 2 sectors by the SDHI-SEQ function.
+In case of eMMC: CMD17(MMC_READ_SINGLE_BLOCK) and CMD18(MMC_READ_MULTIPLE_BLOCK)
+ were requested, CMD8(SEND_EXT_CSD) is carried out additionally twice.
+In case of SD card: CMD17(MMC_READ_SINGLE_BLOCK) and CMD18(MMC_READ_MULTIPLE_BLOCK)
+ were requested, 1024 bytes are read additionally by CMD18.
+In other cases: CMD17 and CMD53(SD_IO_RW_EXTENDED) is carried out additionally twice.
+
+Signed-off-by: Kouei Abe <kouei.abe.cp@renesas.com>
+Signed-off-by: Masaharu Hayakawa <masaharu.hayakawa.ry@renesas.com>
+---
+ drivers/mmc/host/Kconfig | 10 +
+ drivers/mmc/host/sh_mobile_sdhi.c | 13 +
+ drivers/mmc/host/tmio_mmc.h | 56 ++++
+ drivers/mmc/host/tmio_mmc_dma_gen3.c | 490 +++++++++++++++++++++++++++++++++++
+ drivers/mmc/host/tmio_mmc_pio.c | 245 ++++++++++++++++++
+ 5 files changed, 814 insertions(+)
+
+diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
+index 7ec33c5..47b29b6 100644
+--- a/drivers/mmc/host/Kconfig
++++ b/drivers/mmc/host/Kconfig
+@@ -568,6 +568,16 @@ config MMC_SDHI_PIO
+ When switching the transfer mode from DMA to PIO, say Y here.
+ When switching the transfer mode from PIO to DMA, say N here.
+
++config MMC_SDHI_PRE_REQ
++ bool "SDHI pre_req/post_req API support"
++ depends on MMC_SDHI && ARM64 && !MMC_SDHI_PIO
++ default y
++
++config MMC_SDHI_SEQ
++ bool "SDHI Sequencer read/write support"
++ depends on MMC_SDHI && ARM64 && !MMC_SDHI_PIO
++ default y
++
+ config MMC_CB710
+ tristate "ENE CB710 MMC/SD Interface support"
+ depends on PCI
+diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
+index ee7b188..35cd37f 100644
+--- a/drivers/mmc/host/sh_mobile_sdhi.c
++++ b/drivers/mmc/host/sh_mobile_sdhi.c
+@@ -114,9 +114,22 @@ struct sh_mobile_sdhi_of_data {
+ .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
+ MMC_CAP_CMD23,
+ .bus_shift = 2,
++#ifdef CONFIG_MMC_SDHI_SEQ
++ /* Gen3 SDHI SEQ can handle 0xffffffff/DM_SEQ_SIZE blk count */
++ .max_blk_count = 0xffffffff / 512,
++ /* Gen3 SDHI SEQ can handle max 8 commands */
++#ifdef CONFIG_MMC_BLOCK_BOUNCE
++ /* (CMD23+CMD18)*1 + (dummy read command) */
++ .max_segs = 1,
++#else
++ /* (CMD23+CMD18)*3 + (dummy read command) */
++ .max_segs = 3,
++#endif
++#else //CONFIG_MMC_SDHI_SEQ
+ /* Gen3 SDHI DMAC can handle 0xffffffff blk count, but seg = 1 */
+ .max_blk_count = 0xffffffff,
+ .max_segs = 1,
++#endif //CONFIG_MMC_SDHI_SEQ
+ .sdbuf_64bit = true,
+ .scc_offset = 0x1000,
+ .taps = rcar_gen3_scc_taps,
+diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h
+index 438e4f8..52191ac 100644
+--- a/drivers/mmc/host/tmio_mmc.h
++++ b/drivers/mmc/host/tmio_mmc.h
+@@ -51,6 +51,29 @@
+ #define CTL_CLK_AND_WAIT_CTL 0x138
+ #define CTL_RESET_SDIO 0x1e0
+
++#ifdef CONFIG_MMC_SDHI_SEQ
++#define DM_CM_SEQ_REGSET 0x800
++#define DM_CM_SEQ_MODE 0x808
++#define DM_CM_SEQ_CTRL 0x810
++#define DM_CM_DTRAN_MODE 0x820
++#define DM_CM_DTRAN_CTRL 0x828
++#define DM_CM_RST 0x830
++#define DM_CM_INFO1 0x840
++#define DM_CM_INFO1_MASK 0x848
++#define DM_CM_INFO2 0x850
++#define DM_CM_INFO2_MASK 0x858
++#define DM_CM_TUNING_STAT 0x860
++#define DM_CM_SEQ_STAT 0x868
++#define DM_DTRAN_ADDR 0x880
++#define DM_SEQ_CMD 0x8a0
++#define DM_SEQ_ARG 0x8a8
++#define DM_SEQ_SIZE 0x8b0
++#define DM_SEQ_SECCNT 0x8b8
++#define DM_SEQ_RSP 0x8c0
++#define DM_SEQ_RSP_CHK 0x8c8
++#define DM_SEQ_ADDR 0x8d0
++#endif
++
+ /* Definitions for values the CTRL_STATUS register can take. */
+ #define TMIO_STAT_CMDRESPEND BIT(0)
+ #define TMIO_STAT_DATAEND BIT(2)
+@@ -78,6 +101,14 @@
+ #define TMIO_STAT_CMD_BUSY BIT(30)
+ #define TMIO_STAT_ILL_ACCESS BIT(31)
+
++#ifdef CONFIG_MMC_SDHI_SEQ
++/* Definitions for values the DM_CM_INFO1 register can take. */
++#define DM_CM_INFO_SEQEND 0x00000001
++#define DM_CM_INFO_SEQSUSPEND 0x00000100
++#define DM_CM_INFO_DTRAEND_CH0 0x00010000
++#define DM_CM_INFO_DTRAEND_CH1 0x00020000
++#endif
++
+ #define CLK_CTL_DIV_MASK 0xff
+ #define CLK_CTL_SCLKEN BIT(8)
+
+@@ -110,6 +141,13 @@
+ struct tmio_mmc_data;
+ struct tmio_mmc_host;
+
++#ifdef CONFIG_MMC_SDHI_PRE_REQ
++enum tmio_cookie {
++ COOKIE_UNMAPPED,
++ COOKIE_PRE_MAPPED,
++};
++#endif
++
+ struct tmio_mmc_dma {
+ enum dma_slave_buswidth dma_buswidth;
+ bool sdbuf_64bit;
+@@ -145,6 +183,9 @@ struct tmio_mmc_host {
+ struct dma_chan *chan_tx;
+ struct tasklet_struct dma_complete;
+ struct tasklet_struct dma_issue;
++#ifdef CONFIG_MMC_SDHI_SEQ
++ struct tasklet_struct seq_complete;
++#endif
+ struct scatterlist bounce_sg;
+ u8 *bounce_buf;
+ u32 dma_tranend1;
+@@ -243,6 +284,9 @@ static inline void tmio_mmc_kunmap_atomic(struct scatterlist *sg,
+ void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdata);
+ void tmio_mmc_release_dma(struct tmio_mmc_host *host);
+ void tmio_mmc_abort_dma(struct tmio_mmc_host *host);
++#ifdef CONFIG_MMC_SDHI_SEQ
++void tmio_mmc_start_sequencer(struct tmio_mmc_host *host);
++#endif
+ #else
+ static inline void tmio_mmc_start_dma(struct tmio_mmc_host *host,
+ struct mmc_data *data)
+@@ -327,4 +371,16 @@ static inline void sd_ctrl_write32_as_16_and_16(struct tmio_mmc_host *host, int
+ writew(val >> 16, host->ctl + ((addr + 2) << host->bus_shift));
+ }
+
++#ifdef CONFIG_MMC_SDHI_SEQ
++static inline u64 tmio_dm_read(struct tmio_mmc_host *host, int addr)
++{
++ return readq(host->ctl + addr);
++}
++
++static inline void tmio_dm_write(struct tmio_mmc_host *host, int addr, u64 val)
++{
++ writeq(val, host->ctl + addr);
++}
++#endif
++
+ #endif
+diff --git a/drivers/mmc/host/tmio_mmc_dma_gen3.c b/drivers/mmc/host/tmio_mmc_dma_gen3.c
+index d1c6c40..faee4ae 100644
+--- a/drivers/mmc/host/tmio_mmc_dma_gen3.c
++++ b/drivers/mmc/host/tmio_mmc_dma_gen3.c
+@@ -19,9 +19,15 @@
+ #include <linux/pagemap.h>
+ #include <linux/scatterlist.h>
+ #include <linux/sys_soc.h>
++#ifdef CONFIG_MMC_SDHI_SEQ
++#include <linux/mmc/mmc.h>
++#include <linux/mmc/sd.h>
++#include <linux/mmc/sdio.h>
++#endif
+
+ #include "tmio_mmc.h"
+
++#if !defined(CONFIG_MMC_SDHI_SEQ)
+ #define DM_CM_DTRAN_MODE 0x820
+ #define DM_CM_DTRAN_CTRL 0x828
+ #define DM_CM_RST 0x830
+@@ -30,6 +36,7 @@
+ #define DM_CM_INFO2 0x850
+ #define DM_CM_INFO2_MASK 0x858
+ #define DM_DTRAN_ADDR 0x880
++#endif
+
+ /* DM_CM_DTRAN_MODE */
+ #define DTRAN_MODE_CH_NUM_CH0 0 /* "downstream" = for write commands */
+@@ -43,6 +50,9 @@
+ /* DM_CM_RST */
+ #define RST_DTRANRST1 BIT(9)
+ #define RST_DTRANRST0 BIT(8)
++#ifdef CONFIG_MMC_SDHI_SEQ
++#define RST_SEQRST BIT(0)
++#endif
+ #define RST_RESERVED_BITS GENMASK_ULL(32, 0)
+
+ /* DM_CM_INFO1 and DM_CM_INFO1_MASK */
+@@ -68,15 +78,17 @@
+ * this driver cannot use original sd_ctrl_{write,read}32 functions.
+ */
+
++#if !defined(CONFIG_MMC_SDHI_SEQ)
+ static void tmio_dm_write(struct tmio_mmc_host *host, int addr, u64 val)
+ {
+ writeq(val, host->ctl + addr);
+ }
+
+ static u32 tmio_dm_read(struct tmio_mmc_host *host, int addr)
+ {
+ return readl(host->ctl + addr);
+ }
++#endif
+
+ void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable)
+ {
+@@ -95,7 +107,11 @@ void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable)
+
+ void tmio_mmc_abort_dma(struct tmio_mmc_host *host)
+ {
++#ifdef CONFIG_MMC_SDHI_SEQ
++ u64 val = RST_SEQRST | RST_DTRANRST1 | RST_DTRANRST0;
++#else
+ u64 val = RST_DTRANRST1 | RST_DTRANRST0;
++#endif
+
+ dev_dbg(&host->pdev->dev, "%s\n", __func__);
+
+@@ -149,11 +165,17 @@ void tmio_mmc_start_dma(struct tmio_mmc_host *host, struct mmc_data *data)
+ irq_mask = TMIO_STAT_TXRQ;
+ }
+
++#ifdef CONFIG_MMC_SDHI_PRE_REQ
++ if (host->data->host_cookie != COOKIE_PRE_MAPPED) {
++#endif
+ ret = dma_map_sg(&host->pdev->dev, sg, host->sg_len, dir);
+ if (ret < 0) {
+ dev_err(&host->pdev->dev, "%s: dma_map_sg failed\n", __func__);
+ return;
+ }
++#ifdef CONFIG_MMC_SDHI_PRE_REQ
++ }
++#endif
+
+ tmio_clear_transtate(host);
+ tmio_mmc_enable_dma(host, true);
+@@ -195,11 +217,450 @@ static void tmio_mmc_complete_tasklet_fn(unsigned long arg)
+ dir = DMA_TO_DEVICE;
+
+ tmio_mmc_enable_dma(host, false);
++#ifdef CONFIG_MMC_SDHI_PRE_REQ
++ if (host->data->host_cookie != COOKIE_PRE_MAPPED)
++#endif
+ dma_unmap_sg(&host->pdev->dev, host->sg_ptr, host->sg_len, dir);
+ tmio_mmc_do_data_irq(host);
+ }
+ #endif
+
++#ifdef CONFIG_MMC_SDHI_SEQ
++/* DM_CM_SEQ_REGSET bits */
++#define DM_CM_SEQ_REGSET_TABLE_NUM BIT(8)
++/* DM_CM_SEQ_CTRL bits */
++#define DM_CM_SEQ_CTRL_SEQ_TABLE BIT(28)
++#define DM_CM_SEQ_CTRL_T_NUM BIT(24)
++#define DM_CM_SEQ_CTRL_SEQ_TYPE_SD BIT(16)
++#define DM_CM_SEQ_CTRL_START_NUM(x) ((x) << 12)
++#define DM_CM_SEQ_CTRL_END_NUM(x) ((x) << 8)
++#define DM_CM_SEQ_CTRL_SEQ_START BIT(0)
++/* DM_SEQ_CMD bits */
++#define DM_SEQ_CMD_MULTI BIT(13)
++#define DM_SEQ_CMD_DIO BIT(12)
++#define DM_SEQ_CMD_CMDTYP BIT(11)
++#define DM_SEQ_CMD_RSP_NONE (BIT(9) | BIT(8))
++#define DM_SEQ_CMD_RSP_R1 BIT(10)
++#define DM_SEQ_CMD_RSP_R1B (BIT(10) | BIT(8))
++#define DM_SEQ_CMD_RSP_R2 (BIT(10) | BIT(9))
++#define DM_SEQ_CMD_RSP_R3 (BIT(10) | BIT(9) | BIT(8))
++#define DM_SEQ_CMD_NONAUTOSTP BIT(7)
++#define DM_SEQ_CMD_APP BIT(6)
++
++#define MAX_CONTEXT_NUM 8
++
++struct tmio_mmc_context {
++ u64 seq_cmd;
++ u64 seq_arg;
++ u64 seq_size;
++ u64 seq_seccnt;
++ u64 seq_rsp;
++ u64 seq_rsp_chk;
++ u64 seq_addr;
++};
++
++static void tmio_mmc_set_seq_context(struct tmio_mmc_host *host, int ctxt_num,
++ struct tmio_mmc_context *ctxt)
++{
++ u64 val;
++
++ WARN_ON(ctxt_num >= MAX_CONTEXT_NUM);
++
++ /* set sequencer table/context number */
++ if (ctxt_num < 4)
++ val = ctxt_num;
++ else
++ val = DM_CM_SEQ_REGSET_TABLE_NUM | (ctxt_num - 4);
++ tmio_dm_write(host, DM_CM_SEQ_REGSET, val);
++
++ /* set command parameter */
++ tmio_dm_write(host, DM_SEQ_CMD, ctxt->seq_cmd);
++ tmio_dm_write(host, DM_SEQ_ARG, ctxt->seq_arg);
++ tmio_dm_write(host, DM_SEQ_SIZE, ctxt->seq_size);
++ tmio_dm_write(host, DM_SEQ_SECCNT, ctxt->seq_seccnt);
++ tmio_dm_write(host, DM_SEQ_RSP, ctxt->seq_rsp);
++ tmio_dm_write(host, DM_SEQ_RSP_CHK, ctxt->seq_rsp_chk);
++ tmio_dm_write(host, DM_SEQ_ADDR, ctxt->seq_addr);
++}
++
++static int tmio_mmc_set_seq_table(struct tmio_mmc_host *host,
++ struct mmc_request *mrq,
++ struct scatterlist *sg,
++ bool ipmmu_on)
++{
++ struct mmc_card *card = host->mmc->card;
++ struct mmc_data *data = mrq->data;
++ struct scatterlist *sg_tmp;
++ struct tmio_mmc_context ctxt;
++ unsigned int blksz, blocks;
++ u32 cmd_opcode, cmd_flag, cmd_arg;
++ u32 sbc_opcode = 0, sbc_arg = 0;
++ int i, ctxt_cnt = 0;
++
++ /* FIXME: SD_COMBO media not tested */
++ cmd_opcode = (mrq->cmd->opcode & 0x3f);
++ cmd_flag = DM_SEQ_CMD_CMDTYP;
++ if (data->flags & MMC_DATA_READ)
++ cmd_flag |= DM_SEQ_CMD_DIO;
++ if (mmc_op_multi(mrq->cmd->opcode) ||
++ (cmd_opcode == SD_IO_RW_EXTENDED && mrq->cmd->arg & 0x08000000)) //FIXME
++ cmd_flag |= DM_SEQ_CMD_MULTI;
++ if (mrq->sbc ||
++ cmd_opcode == SD_IO_RW_EXTENDED) //FIXME
++ cmd_flag |= DM_SEQ_CMD_NONAUTOSTP;
++
++ switch (mmc_resp_type(mrq->cmd)) {
++ case MMC_RSP_NONE:
++ cmd_flag |= DM_SEQ_CMD_RSP_NONE;
++ break;
++ case MMC_RSP_R1:
++ case MMC_RSP_R1 & ~MMC_RSP_CRC:
++ cmd_flag |= DM_SEQ_CMD_RSP_R1;
++ break;
++ case MMC_RSP_R1B:
++ cmd_flag |= DM_SEQ_CMD_RSP_R1B;
++ break;
++ case MMC_RSP_R2:
++ cmd_flag |= DM_SEQ_CMD_RSP_R2;
++ break;
++ case MMC_RSP_R3:
++ cmd_flag |= DM_SEQ_CMD_RSP_R3;
++ break;
++ default:
++ pr_debug("Unknown response type %d\n", mmc_resp_type(mrq->cmd));
++ return -EINVAL;
++ }
++
++ cmd_arg = mrq->cmd->arg;
++ if (cmd_opcode == SD_IO_RW_EXTENDED && cmd_arg & 0x08000000) {
++ /* SDIO CMD53 block mode */
++ cmd_arg &= ~0x1ff;
++ }
++
++ if (mrq->sbc) {
++ sbc_opcode = (mrq->sbc->opcode & 0x3f) | DM_SEQ_CMD_RSP_R1;
++ sbc_arg = mrq->sbc->arg & (MMC_CMD23_ARG_REL_WR |
++ MMC_CMD23_ARG_PACKED | MMC_CMD23_ARG_TAG_REQ);
++ }
++
++ blksz = data->blksz;
++ if (ipmmu_on) {
++ blocks = data->blocks;
++ memset(&ctxt, 0, sizeof(ctxt));
++
++ if (sbc_opcode) {
++ /* set CMD23 */
++ ctxt.seq_cmd = sbc_opcode;
++ ctxt.seq_arg = sbc_arg | blocks;
++ tmio_mmc_set_seq_context(host, ctxt_cnt, &ctxt);
++ ctxt_cnt++;
++ }
++
++ /* set CMD */
++ ctxt.seq_cmd = cmd_opcode | cmd_flag;
++ ctxt.seq_arg = cmd_arg;
++ if (cmd_opcode == SD_IO_RW_EXTENDED && cmd_arg & 0x08000000) {
++ /* SDIO CMD53 block mode */
++ ctxt.seq_arg |= blocks;
++ }
++ ctxt.seq_size = blksz;
++ ctxt.seq_seccnt = blocks;
++ ctxt.seq_addr = sg_dma_address(sg);
++ tmio_mmc_set_seq_context(host, ctxt_cnt, &ctxt);
++ } else {
++ for_each_sg(sg, sg_tmp, host->sg_len, i) {
++ blocks = sg_tmp->length / blksz;
++ memset(&ctxt, 0, sizeof(ctxt));
++
++ if (sbc_opcode) {
++ /* set CMD23 */
++ ctxt.seq_cmd = sbc_opcode;
++ ctxt.seq_arg = sbc_arg | blocks;
++ if (sbc_arg & MMC_CMD23_ARG_TAG_REQ && card &&
++ card->ext_csd.data_tag_unit_size &&
++ blksz * blocks < card->ext_csd.data_tag_unit_size)
++ ctxt.seq_arg &= ~MMC_CMD23_ARG_TAG_REQ;
++ tmio_mmc_set_seq_context(host, ctxt_cnt, &ctxt);
++ ctxt_cnt++;
++ }
++
++ /* set CMD */
++ ctxt.seq_cmd = cmd_opcode | cmd_flag;
++ ctxt.seq_arg = cmd_arg;
++ if (cmd_opcode == SD_IO_RW_EXTENDED &&
++ cmd_arg & 0x08000000) {
++ /* SDIO CMD53 block mode */
++ ctxt.seq_arg |= blocks;
++ }
++ ctxt.seq_size = blksz;
++ ctxt.seq_seccnt = blocks;
++ ctxt.seq_addr = sg_dma_address(sg_tmp);
++ tmio_mmc_set_seq_context(host, ctxt_cnt, &ctxt);
++
++ if (i < (host->sg_len - 1)) {
++ /* increment address */
++ if (cmd_opcode == SD_IO_RW_EXTENDED) {
++ /*
++ * sg_len should be 1 in SDIO CMD53
++ * byte mode
++ */
++ WARN_ON(!(cmd_arg & 0x08000000));
++ if (cmd_arg & 0x04000000) {
++ /*
++ * SDIO CMD53 address
++ * increment mode
++ */
++ cmd_arg += (blocks * blksz) << 9;
++ }
++ } else {
++ if (card && !mmc_card_blockaddr(card))
++ cmd_arg += blocks * blksz;
++ else
++ cmd_arg += blocks;
++ }
++ ctxt_cnt++;
++ }
++ }
++ }
++
++ if (data->flags & MMC_DATA_READ) {
++ /* dummy read */
++ if (cmd_opcode == MMC_READ_MULTIPLE_BLOCK && sbc_opcode &&
++ data->blocks > 1) {
++ memset(&ctxt, 0, sizeof(ctxt));
++ /* set CMD23 */
++ ctxt.seq_cmd = sbc_opcode;
++ ctxt.seq_arg = sbc_arg | 2;
++ if (sbc_arg & MMC_CMD23_ARG_TAG_REQ &&
++ card->ext_csd.data_tag_unit_size &&
++ blksz * 2 < card->ext_csd.data_tag_unit_size)
++ ctxt.seq_arg &= ~MMC_CMD23_ARG_TAG_REQ;
++ ctxt_cnt++;
++ tmio_mmc_set_seq_context(host, ctxt_cnt, &ctxt);
++
++ /* set CMD18 */
++ ctxt.seq_cmd = cmd_opcode | cmd_flag;
++ ctxt.seq_arg = mrq->cmd->arg + data->blocks - 2;
++ ctxt.seq_size = 512;
++ ctxt.seq_seccnt = 2;
++ ctxt.seq_addr = sg_dma_address(&host->bounce_sg);
++ ctxt_cnt++;
++ tmio_mmc_set_seq_context(host, ctxt_cnt, &ctxt);
++ } else {
++ if ((card && mmc_card_mmc(card)) ||
++ cmd_opcode == MMC_SEND_TUNING_BLOCK_HS200) {
++ /* In case of eMMC, set CMD8 twice */
++ memset(&ctxt, 0, sizeof(ctxt));
++ ctxt.seq_cmd = MMC_SEND_EXT_CSD |
++ DM_SEQ_CMD_CMDTYP |
++ DM_SEQ_CMD_DIO |
++ DM_SEQ_CMD_RSP_R1;
++ ctxt.seq_arg = 0;
++ ctxt.seq_size = 512;
++ ctxt.seq_seccnt = 1;
++ ctxt.seq_addr = sg_dma_address(&host->bounce_sg);
++ } else if (cmd_opcode == SD_SWITCH) {
++ /* set SD CMD6 twice */
++ ctxt.seq_addr = sg_dma_address(&host->bounce_sg);
++ } else if ((card && (mmc_card_sdio(card) ||
++ card->type == MMC_TYPE_SD_COMBO)) ||
++ cmd_opcode == SD_IO_RW_EXTENDED) {
++ /* FIXME:
++ * In case of SDIO/SD_COMBO,
++ * read Common I/O Area 0x0-0x1FF twice.
++ */
++ memset(&ctxt, 0, sizeof(ctxt));
++ ctxt.seq_cmd = SD_IO_RW_EXTENDED |
++ DM_SEQ_CMD_CMDTYP |
++ DM_SEQ_CMD_DIO |
++ DM_SEQ_CMD_NONAUTOSTP |
++ DM_SEQ_CMD_RSP_R1;
++ /*
++ * SD_IO_RW_EXTENDED argument format:
++ * [31] R/W flag -> 0
++ * [30:28] Function number -> 0x0 selects
++ * Common I/O Area
++ * [27] Block mode -> 0
++ * [26] Increment address -> 1
++ * [25:9] Regiser address -> 0x0
++ * [8:0] Byte/block count -> 0x0 -> 512Bytes
++ */
++ ctxt.seq_arg = 0x04000000;
++ ctxt.seq_size = 512;
++ ctxt.seq_seccnt = 1;
++ ctxt.seq_addr = sg_dma_address(&host->bounce_sg);
++ } else {
++ /* set CMD17 twice */
++ memset(&ctxt, 0, sizeof(ctxt));
++ ctxt.seq_cmd = MMC_READ_SINGLE_BLOCK |
++ DM_SEQ_CMD_CMDTYP |
++ DM_SEQ_CMD_DIO |
++ DM_SEQ_CMD_RSP_R1;
++ if (cmd_opcode == MMC_READ_SINGLE_BLOCK ||
++ cmd_opcode == MMC_READ_MULTIPLE_BLOCK)
++ ctxt.seq_arg = mrq->cmd->arg;
++ else
++ ctxt.seq_arg = 0; //FIXME
++ ctxt.seq_size = 512;
++ ctxt.seq_seccnt = 1;
++ ctxt.seq_addr = sg_dma_address(&host->bounce_sg);
++ }
++
++ for (i = 0; i < 2; i++) {
++ ctxt_cnt++;
++ tmio_mmc_set_seq_context(host, ctxt_cnt, &ctxt);
++ }
++ }
++ }
++
++ return ctxt_cnt;
++}
++
++void tmio_mmc_start_sequencer(struct tmio_mmc_host *host)
++{
++ struct mmc_card *card = host->mmc->card;
++ struct scatterlist *sg = host->sg_ptr, *sg_tmp;
++ struct mmc_host *mmc = host->mmc;
++ struct mmc_request *mrq = host->mrq;
++ struct mmc_data *data = mrq->data;
++ enum dma_data_direction dir;
++ int ret, i, ctxt_num;
++ u32 val;
++ bool ipmmu_on = false;
++
++ /* This DMAC cannot handle if sg_len larger than max_segs */
++ if (mmc->max_segs == 1 || mmc->max_segs == 3)
++ WARN_ON(host->sg_len > mmc->max_segs);
++ else
++ ipmmu_on = true;
++
++ dev_dbg(&host->pdev->dev, "%s: %d, %x\n", __func__, host->sg_len,
++ data->flags);
++
++ if (!card && host->mrq->cmd->opcode == MMC_SEND_TUNING_BLOCK) {
++ /*
++ * workaround: if card is NULL,
++ * we can not decide a dummy read command to be added
++ * to the CMD19.
++ */
++ host->force_pio = true;
++ tmio_mmc_enable_dma(host, false);
++ return; /* return for PIO */
++ }
++
++ if (ipmmu_on) {
++ if (!IS_ALIGNED(sg->offset, 8) ||
++ ((sg_dma_address(sg) + data->blksz * data->blocks) >
++ GENMASK_ULL(32, 0))) {
++ dev_dbg(&host->pdev->dev, "%s: force pio\n", __func__);
++ host->force_pio = true;
++ tmio_mmc_enable_dma(host, false);
++ return;
++ }
++#if 1 //FIXME
++ /*
++ * workaround: if we use IPMMU, sometimes unhandled error
++ * happened
++ */
++ switch (host->mrq->cmd->opcode) {
++ case MMC_SEND_TUNING_BLOCK_HS200:
++ case MMC_SEND_TUNING_BLOCK:
++ host->force_pio = true;
++ tmio_mmc_enable_dma(host, false);
++ return; /* return for PIO */
++ default:
++ break;
++ }
++#endif
++ } else {
++ for_each_sg(sg, sg_tmp, host->sg_len, i) {
++ /*
++ * This DMAC cannot handle if buffer is not 8-bytes
++ * alignment
++ */
++ if (!IS_ALIGNED(sg_tmp->offset, 8) ||
++ !IS_ALIGNED(sg_tmp->length, data->blksz) ||
++ ((sg_dma_address(sg_tmp) + sg_tmp->length) >
++ GENMASK_ULL(32, 0))) {
++ dev_dbg(&host->pdev->dev, "%s: force pio\n",
++ __func__);
++ host->force_pio = true;
++ tmio_mmc_enable_dma(host, false);
++ return;
++ }
++ }
++ }
++
++#ifdef CONFIG_MMC_SDHI_PRE_REQ
++ if (host->data->host_cookie != COOKIE_PRE_MAPPED) {
++#endif
++ if (data->flags & MMC_DATA_READ)
++ dir = DMA_FROM_DEVICE;
++ else
++ dir = DMA_TO_DEVICE;
++
++ ret = dma_map_sg(&host->pdev->dev, sg, host->sg_len, dir);
++ if (ret <= 0) {
++ dev_err(&host->pdev->dev, "%s: dma_map_sg failed\n", __func__);
++ host->force_pio = true;
++ tmio_mmc_enable_dma(host, false);
++ return;
++ }
++#ifdef CONFIG_MMC_SDHI_PRE_REQ
++ }
++#endif
++
++ tmio_mmc_enable_dma(host, true);
++ /* set context */
++ ctxt_num = tmio_mmc_set_seq_table(host, mrq, sg, ipmmu_on);
++ if (ctxt_num < 0) {
++ host->force_pio = true;
++ tmio_mmc_enable_dma(host, false);
++ return;
++ }
++ /* set dma mode */
++ //FIXME
++ tmio_dm_write(host, DM_CM_DTRAN_MODE,
++ DTRAN_MODE_BUS_WID_TH);
++ //DTRAN_MODE_BUS_WID_TH | DTRAN_MODE_ADDR_MODE);
++ /* enable SEQEND irq */
++ tmio_dm_write(host, DM_CM_INFO1_MASK,
++ GENMASK_ULL(32, 0) & ~DM_CM_INFO_SEQEND);
++
++ if (ctxt_num < 4) {
++ /* issue table0 commands */
++ val = DM_CM_SEQ_CTRL_SEQ_TYPE_SD |
++ DM_CM_SEQ_CTRL_START_NUM(0) |
++ DM_CM_SEQ_CTRL_END_NUM(ctxt_num) |
++ DM_CM_SEQ_CTRL_SEQ_START;
++ tmio_dm_write(host, DM_CM_SEQ_CTRL, val);
++ } else {
++ /* issue table0 commands */
++ val = DM_CM_SEQ_CTRL_SEQ_TYPE_SD |
++ DM_CM_SEQ_CTRL_T_NUM |
++ DM_CM_SEQ_CTRL_START_NUM(0) |
++ DM_CM_SEQ_CTRL_END_NUM(3) |
++ DM_CM_SEQ_CTRL_SEQ_START;
++ tmio_dm_write(host, DM_CM_SEQ_CTRL, val);
++ /* issue table1 commands */
++ val = DM_CM_SEQ_CTRL_SEQ_TABLE |
++ DM_CM_SEQ_CTRL_SEQ_TYPE_SD |
++ DM_CM_SEQ_CTRL_T_NUM |
++ DM_CM_SEQ_CTRL_START_NUM(0) |
++ DM_CM_SEQ_CTRL_END_NUM(ctxt_num - 4) |
++ DM_CM_SEQ_CTRL_SEQ_START;
++ tmio_dm_write(host, DM_CM_SEQ_CTRL, val);
++ }
++
++ return;
++}
++
++static void tmio_mmc_seq_complete_tasklet_fn(unsigned long arg)
++{
++ tmio_mmc_complete_tasklet_fn(arg);
++}
++#endif //CONFIG_MMC_SDHI_SEQ
++
+ bool __tmio_mmc_dma_irq(struct tmio_mmc_host *host)
+ {
+ unsigned int ireg, status;
+@@ -237,6 +698,27 @@ void tmio_mmc_request_dma(struct tmio_mmc_host *host,
+ (unsigned long)host);
+ tasklet_init(&host->dma_issue, tmio_mmc_issue_tasklet_fn,
+ (unsigned long)host);
++#ifdef CONFIG_MMC_SDHI_SEQ
++ tasklet_init(&host->seq_complete, tmio_mmc_seq_complete_tasklet_fn,
++ (unsigned long)host);
++ /* alloc bounce_buf for dummy read */
++ host->bounce_buf = (u8 *)__get_free_page(GFP_KERNEL | GFP_DMA);
++ if (!host->bounce_buf)
++ goto ebouncebuf;
++ /* setup bounce_sg for dummy read */
++ sg_init_one(&host->bounce_sg, host->bounce_buf, 1024);
++ if (dma_map_sg(&host->pdev->dev, &host->bounce_sg, 1, DMA_FROM_DEVICE) <= 0) {
++ free_pages((unsigned long)host->bounce_buf, 0);
++ host->bounce_buf = NULL;
++ goto ebouncebuf;
++ }
++
++ return;
++
++ebouncebuf:
++ host->chan_rx = host->chan_tx = NULL;
++ return;
++#endif
+ #endif
+ }
+
+@@ -244,4 +726,12 @@ void tmio_mmc_release_dma(struct tmio_mmc_host *host)
+ {
+ /* Each value is set to zero to assume "disabling" each DMA */
+ host->chan_rx = host->chan_tx = NULL;
++#ifdef CONFIG_MMC_SDHI_SEQ
++ /* free bounce_buf for dummy read */
++ if (host->bounce_buf) {
++ dma_unmap_sg(&host->pdev->dev, &host->bounce_sg, 1, DMA_FROM_DEVICE);
++ free_pages((unsigned long)host->bounce_buf, 0);
++ host->bounce_buf = NULL;
++ }
++#endif
+ }
+diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
+index 57a954a..e255503 100644
+--- a/drivers/mmc/host/tmio_mmc_pio.c
++++ b/drivers/mmc/host/tmio_mmc_pio.c
+@@ -50,6 +50,9 @@
+ #include <linux/scatterlist.h>
+ #include <linux/spinlock.h>
+ #include <linux/workqueue.h>
++#ifdef CONFIG_MMC_SDHI_PRE_REQ
++#include <linux/dma-mapping.h>
++#endif
+
+ #include "tmio_mmc.h"
+
+@@ -587,6 +590,79 @@ void tmio_mmc_do_data_irq(struct tmio_mmc_host *host)
+ schedule_work(&host->done);
+ }
+
++#ifdef CONFIG_MMC_SDHI_SEQ
++static void tmio_mmc_seq_irq(struct tmio_mmc_host *host, unsigned int stat,
++ u32 seq_stat1, u32 seq_stat2)
++{
++ struct mmc_data *data;
++ struct mmc_command *cmd, *sbc;
++
++ spin_lock(&host->lock);
++ data = host->data;
++ cmd = host->mrq->cmd;
++ sbc = host->mrq->sbc;
++
++ //FIXME: How to get SEQ commands response?
++
++ if (seq_stat2) {
++ //FIXME
++ pr_debug("sequencer error, CMD%d SD_INFO2=0x%x\n",
++ cmd->opcode, stat >> 16);
++ if (stat & TMIO_STAT_CMDTIMEOUT) {
++ cmd->error = -ETIMEDOUT;
++ if (sbc)
++ sbc->error = -ETIMEDOUT;
++ } else if ((stat & TMIO_STAT_CRCFAIL &&
++ cmd->flags & MMC_RSP_CRC) ||
++ stat & TMIO_STAT_STOPBIT_ERR ||
++ stat & TMIO_STAT_CMD_IDX_ERR) {
++ cmd->error = -EILSEQ;
++ if (sbc)
++ sbc->error = -EILSEQ;
++ }
++
++ if (stat & TMIO_STAT_DATATIMEOUT)
++ data->error = -ETIMEDOUT;
++ else if (stat & TMIO_STAT_CRCFAIL ||
++ stat & TMIO_STAT_STOPBIT_ERR ||
++ stat & TMIO_STAT_TXUNDERRUN)
++ data->error = -EILSEQ;
++ }
++
++ if (host->chan_tx && (data->flags & MMC_DATA_WRITE)) {
++ //FIXME
++ u32 status = sd_ctrl_read16_and_16_as_32(host, CTL_STATUS);
++ bool done = false;
++
++ /*
++ * Has all data been written out yet? Testing on SuperH showed,
++ * that in most cases the first interrupt comes already with the
++ * BUSY status bit clear, but on some operations, like mount or
++ * in the beginning of a write / sync / umount, there is one
++ * DATAEND interrupt with the BUSY bit set, in this cases
++ * waiting for one more interrupt fixes the problem.
++ */
++ if (host->pdata->flags & TMIO_MMC_HAS_IDLE_WAIT) {
++ if (status & TMIO_STAT_ILL_FUNC)
++ done = true;
++ } else {
++ if (!(status & TMIO_STAT_CMD_BUSY))
++ done = true;
++ }
++
++ if (!done)
++ goto out;
++ }
++
++ /* mask sequencer irq */
++ tmio_dm_write(host, DM_CM_INFO1_MASK, 0xffffffff);
++ tasklet_schedule(&host->seq_complete);
++
++out:
++ spin_unlock(&host->lock);
++}
++#endif //CONFIG_MMC_SDHI_SEQ
++
+ static void tmio_mmc_data_irq(struct tmio_mmc_host *host, unsigned int stat)
+ {
+ struct mmc_data *data;
+@@ -737,6 +813,22 @@ static bool __tmio_mmc_card_detect_irq(struct tmio_mmc_host *host,
+ static bool __tmio_mmc_sdcard_irq(struct tmio_mmc_host *host,
+ int ireg, int status)
+ {
++#ifdef CONFIG_MMC_SDHI_SEQ
++ u64 dm_cm_info1;
++
++ dm_cm_info1 = tmio_dm_read(host, DM_CM_INFO1);
++ if (dm_cm_info1 & DM_CM_INFO_SEQEND) {
++ u64 dm_cm_info2;
++ dm_cm_info2 = tmio_dm_read(host, DM_CM_INFO2);
++ tmio_dm_write(host, DM_CM_INFO1, 0x0);
++ tmio_dm_write(host, DM_CM_INFO2, 0x0);
++ tmio_mmc_ack_mmc_irqs(host,
++ TMIO_MASK_IRQ & ~(TMIO_STAT_CARD_REMOVE |
++ TMIO_STAT_CARD_INSERT));
++ tmio_mmc_seq_irq(host, status, dm_cm_info1, dm_cm_info2);
++ return true;
++ }
++#endif //CONFIG_MMC_SDHI_SEQ
+ /* Command completion */
+ if (ireg & (TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDTIMEOUT)) {
+ tmio_mmc_ack_mmc_irqs(host,
+@@ -814,6 +906,61 @@ irqreturn_t tmio_mmc_irq(int irq, void *devid)
+ }
+ EXPORT_SYMBOL(tmio_mmc_irq);
+
++#ifdef CONFIG_MMC_SDHI_SEQ
++static int tmio_mmc_start_seq(struct tmio_mmc_host *host,
++ struct mmc_request *mrq)
++{
++ struct tmio_mmc_data *pdata = host->pdata;
++ struct mmc_data *data = mrq->data;
++
++ pr_debug("setup data transfer: blocksize %08x nr_blocks %d\n",
++ data->blksz, data->blocks);
++
++ if (!host->chan_rx || !host->chan_tx) {
++ host->force_pio = true;
++ return 0;
++ }
++
++ /* Some hardware cannot perform 2 byte requests in 4 bit mode */
++ if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_4) {
++ int blksz_2bytes = pdata->flags & TMIO_MMC_BLKSZ_2BYTES;
++
++ if (data->blksz < 2 || (data->blksz < 4 && !blksz_2bytes)) {
++ pr_err("%s: %d byte block unsupported in 4 bit mode\n",
++ mmc_hostname(host->mmc), data->blksz);
++ return -EINVAL;
++ }
++ }
++
++ tmio_mmc_init_sg(host, data);
++ host->cmd = mrq->cmd;
++ host->data = data;
++
++ //FIXME
++ sd_ctrl_write16(host, CTL_STOP_INTERNAL_ACTION, 0x000);
++ //sd_ctrl_write16(host, CTL_STOP_INTERNAL_ACTION, 0x100);
++
++ tmio_mmc_start_sequencer(host);
++
++ if (host->force_pio) {
++ host->cmd = NULL;
++ host->data = NULL;
++ }
++
++ return 0;
++}
++
++static void tmio_mmc_set_blklen_and_blkcnt(struct tmio_mmc_host *host,
++ struct mmc_data *data)
++{
++ host->force_pio = true;
++ tmio_mmc_init_sg(host, data);
++ host->data = data;
++
++ sd_ctrl_write16(host, CTL_SD_XFER_LEN, data->blksz);
++ sd_ctrl_write16(host, CTL_XFER_BLK_COUNT, data->blocks);
++}
++#else
+ static int tmio_mmc_start_data(struct tmio_mmc_host *host,
+ struct mmc_data *data)
+ {
+@@ -845,6 +992,58 @@ static int tmio_mmc_start_data(struct tmio_mmc_host *host,
+
+ return 0;
+ }
++#endif //CONFIG_MMC_SDHI_SEQ
++
++#ifdef CONFIG_MMC_SDHI_PRE_REQ
++static void tmio_mmc_post_req(struct mmc_host *mmc, struct mmc_request *req,
++ int err)
++{
++ struct tmio_mmc_host *host = mmc_priv(mmc);
++ struct mmc_data *data = req->data;
++ enum dma_data_direction dir;
++
++ if (data && data->host_cookie == COOKIE_PRE_MAPPED) {
++ if (req->data->flags & MMC_DATA_READ)
++ dir = DMA_FROM_DEVICE;
++ else
++ dir = DMA_TO_DEVICE;
++
++ dma_unmap_sg(&host->pdev->dev, data->sg, data->sg_len, dir);
++ data->host_cookie = COOKIE_UNMAPPED;
++ }
++}
++
++static void tmio_mmc_pre_req(struct mmc_host *mmc, struct mmc_request *req,
++ bool is_first_req)
++{
++ struct tmio_mmc_host *host = mmc_priv(mmc);
++ struct mmc_data *data = req->data;
++ enum dma_data_direction dir;
++ int ret;
++
++#if 1 //FIXME: IPMMU workaround, skip pre_dma_mapping
++#ifdef CONFIG_MMC_SDHI_SEQ
++ if (mmc->max_segs != 1 && mmc->max_segs != 3)
++#else
++ if (mmc->max_segs != 1)
++#endif
++ return;
++#endif
++
++ if (data && data->host_cookie == COOKIE_UNMAPPED) {
++ if (req->data->flags & MMC_DATA_READ)
++ dir = DMA_FROM_DEVICE;
++ else
++ dir = DMA_TO_DEVICE;
++
++ ret = dma_map_sg(&host->pdev->dev, data->sg, data->sg_len, dir);
++ if (ret <= 0)
++ dev_err(&host->pdev->dev, "%s: dma_map_sg failed\n", __func__);
++ else
++ data->host_cookie = COOKIE_PRE_MAPPED;
++ }
++}
++#endif //CONFIG_MMC_SDHI_PRE_REQ
+
+ static void tmio_mmc_hw_reset(struct mmc_host *mmc)
+ {
+@@ -934,6 +1133,25 @@ static void tmio_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
+
+ spin_unlock_irqrestore(&host->lock, flags);
+
++#ifdef CONFIG_MMC_SDHI_SEQ
++ //FIXME: SD_COMBO media not tested
++ if (mrq->data) {
++ /* Start SEQ */
++ ret = tmio_mmc_start_seq(host, mrq);
++ if (ret)
++ goto fail;
++ else if (!host->force_pio) {
++ /*
++ * Successed to start SEQ
++ * Wait SEQ interrupt
++ */
++ schedule_delayed_work(&host->delayed_reset_work,
++ msecs_to_jiffies(CMDREQ_TIMEOUT));
++ return;
++ }
++ }
++#endif //CONFIG_MMC_SDHI_SEQ
++
+ if (mrq->sbc) {
+ init_completion(&host->completion);
+ ret = tmio_mmc_start_command(host, mrq->sbc);
+@@ -965,9 +1183,32 @@ static void tmio_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
+ }
+
+ if (mrq->data) {
++#ifdef CONFIG_MMC_SDHI_SEQ
++ /*
++ * Failed to start SEQ
++ * Set blklen and blkcnt to transfer in PIO mode
++ */
++ tmio_mmc_set_blklen_and_blkcnt(host, mrq->data);
++#else
+ ret = tmio_mmc_start_data(host, mrq->data);
+ if (ret)
+ goto fail;
++#endif
++
++#ifdef CONFIG_MMC_SDHI_PRE_REQ
++ if (host->force_pio &&
++ mrq->data->host_cookie == COOKIE_PRE_MAPPED) {
++ /* PIO mode, unmap pre_dma_mapped sg */
++ enum dma_data_direction dir;
++ if (mrq->data->flags & MMC_DATA_READ)
++ dir = DMA_FROM_DEVICE;
++ else
++ dir = DMA_TO_DEVICE;
++ dma_unmap_sg(&host->pdev->dev, mrq->data->sg,
++ mrq->data->sg_len, dir);
++ mrq->data->host_cookie = COOKIE_UNMAPPED;
++ }
++#endif
+ }
+
+ ret = tmio_mmc_start_command(host, mrq->cmd);
+@@ -1160,6 +1401,10 @@ static int tmio_multi_io_quirk(struct mmc_card *card,
+ }
+
+ static struct mmc_host_ops tmio_mmc_ops = {
++#ifdef CONFIG_MMC_SDHI_PRE_REQ
++ .post_req = tmio_mmc_post_req,
++ .pre_req = tmio_mmc_pre_req,
++#endif
+ .request = tmio_mmc_request,
+ .set_ios = tmio_mmc_set_ios,
+ .get_ro = tmio_mmc_get_ro,
+--
+1.9.1
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0008-arm64-do-not-set-dma-masks-that-device-connection-ca.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0008-arm64-do-not-set-dma-masks-that-device-connection-ca.patch
new file mode 100644
index 0000000..14612cd
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0008-arm64-do-not-set-dma-masks-that-device-connection-ca.patch
@@ -0,0 +1,132 @@
+From e3218ab51b0bf3f193a9f64e5c0dafe74e292ad2 Mon Sep 17 00:00:00 2001
+From: Nikita Yushchenko <nikita.yoush@cogentembedded.com>
+Date: Fri, 6 Jan 2017 17:12:49 +0300
+Subject: [PATCH] arm64: do not set dma masks that device connection can't
+ handle
+
+It is possible that device is capable of 64-bit DMA addresses, and
+device driver tries to set wide DMA mask, but bridge or bus used to
+connect device to the system can't handle wide addresses.
+
+With swiotlb, memory above 4G still can be used by drivers for streaming
+DMA, but *dev->mask and dev->dma_coherent_mask must still keep values
+that hardware handles physically.
+
+This patch enforces that. Based on original version by
+Arnd Bergmann <arnd@arndb.de>, extended with coherent mask hadnling.
+
+Signed-off-by: Nikita Yushchenko <nikita.yoush@cogentembedded.com>
+CC: Arnd Bergmann <arnd@arndb.de>
+---
+ arch/arm64/Kconfig | 3 +++
+ arch/arm64/include/asm/device.h | 1 +
+ arch/arm64/mm/dma-mapping.c | 51 +++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 55 insertions(+)
+
+diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
+index 76747d92bc72..9513d2eb5c8a 100644
+--- a/arch/arm64/Kconfig
++++ b/arch/arm64/Kconfig
+@@ -191,6 +191,9 @@ config NEED_DMA_MAP_STATE
+ config NEED_SG_DMA_LENGTH
+ def_bool y
+
++config ARCH_HAS_DMA_SET_COHERENT_MASK
++ def_bool y
++
+ config SMP
+ def_bool y
+
+diff --git a/arch/arm64/include/asm/device.h b/arch/arm64/include/asm/device.h
+index 243ef256b8c9..a57e7bb10e71 100644
+--- a/arch/arm64/include/asm/device.h
++++ b/arch/arm64/include/asm/device.h
+@@ -22,6 +22,7 @@ struct dev_archdata {
+ void *iommu; /* private IOMMU data */
+ #endif
+ bool dma_coherent;
++ u64 parent_dma_mask;
+ };
+
+ struct pdev_archdata {
+diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
+index 46a4157adc17..04b9bce96f1b 100644
+--- a/arch/arm64/mm/dma-mapping.c
++++ b/arch/arm64/mm/dma-mapping.c
+@@ -351,6 +351,30 @@ static int __swiotlb_dma_supported(struct device *hwdev, u64 mask)
+ return 1;
+ }
+
++static int __swiotlb_set_dma_mask(struct device *dev, u64 mask)
++{
++ /* device is not DMA capable */
++ if (!dev->dma_mask)
++ return -EIO;
++
++ /* mask is below swiotlb bounce buffer, so fail */
++ if (!swiotlb_dma_supported(dev, mask))
++ return -EIO;
++
++ /*
++ * because of the swiotlb, we can return success for
++ * larger masks, but need to ensure that bounce buffers
++ * are used above parent_dma_mask, so set that as
++ * the effective mask.
++ */
++ if (mask > dev->archdata.parent_dma_mask)
++ mask = dev->archdata.parent_dma_mask;
++
++ *dev->dma_mask = mask;
++
++ return 0;
++}
++
+ static struct dma_map_ops swiotlb_dma_ops = {
+ .alloc = __dma_alloc,
+ .free = __dma_free,
+@@ -366,8 +390,23 @@ static struct dma_map_ops swiotlb_dma_ops = {
+ .sync_sg_for_device = __swiotlb_sync_sg_for_device,
+ .dma_supported = __swiotlb_dma_supported,
+ .mapping_error = swiotlb_dma_mapping_error,
++ .set_dma_mask = __swiotlb_set_dma_mask,
+ };
+
++int dma_set_coherent_mask(struct device *dev, u64 mask)
++{
++ if (!dma_supported(dev, mask))
++ return -EIO;
++
++ if (get_dma_ops(dev) == &swiotlb_dma_ops &&
++ mask > dev->archdata.parent_dma_mask)
++ mask = dev->archdata.parent_dma_mask;
++
++ dev->coherent_dma_mask = mask;
++ return 0;
++}
++EXPORT_SYMBOL(dma_set_coherent_mask);
++
+ static int __init atomic_pool_init(void)
+ {
+ pgprot_t prot = __pgprot(PROT_NORMAL_NC);
+@@ -971,6 +1010,18 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
+ if (!dev->archdata.dma_ops)
+ dev->archdata.dma_ops = &swiotlb_dma_ops;
+
++ /*
++ * we don't yet support buses that have a non-zero mapping.
++ * Let's hope we won't need it
++ */
++ WARN_ON(dma_base != 0);
++
++ /*
++ * Whatever the parent bus can set. A device must not set
++ * a DMA mask larger than this.
++ */
++ dev->archdata.parent_dma_mask = size - 1;
++
+ dev->archdata.dma_coherent = coherent;
+ __iommu_setup_dma_ops(dev, dma_base, size, iommu);
+ }
+--
+2.11.0
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0009-swiotlb-ensure-that-page-sized-mappings-are-page-ali.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0009-swiotlb-ensure-that-page-sized-mappings-are-page-ali.patch
new file mode 100644
index 0000000..cccc80d
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0009-swiotlb-ensure-that-page-sized-mappings-are-page-ali.patch
@@ -0,0 +1,38 @@
+From c92eeec67eb96b79fe3d01b0045789de52fd5af3 Mon Sep 17 00:00:00 2001
+From: Nikita Yushchenko <nikita.yoush@cogentembedded.com>
+Date: Tue, 3 Jan 2017 14:24:58 +0300
+Subject: [PATCH] swiotlb: ensure that page-sized mappings are page-aligned
+
+Some drivers (e.g. nvme) do depend on page mappings to be page
+aligned.
+
+Swiotlb already enforces such alignment for mappings greater than page,
+extend that to page-sized mappings as well.
+
+Signed-off-by: Nikita Yushchenko <nikita.yoush@cogentembedded.com>
+---
+ lib/swiotlb.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/lib/swiotlb.c b/lib/swiotlb.c
+index 76f29ecba8f4..771234d050c7 100644
+--- a/lib/swiotlb.c
++++ b/lib/swiotlb.c
+@@ -452,11 +452,11 @@ phys_addr_t swiotlb_tbl_map_single(struct device *hwdev,
+ : 1UL << (BITS_PER_LONG - IO_TLB_SHIFT);
+
+ /*
+- * For mappings greater than a page, we limit the stride (and
+- * hence alignment) to a page size.
++ * For mappings greater than or equal to a page, we limit the stride
++ * (and hence alignment) to a page size.
+ */
+ nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
+- if (size > PAGE_SIZE)
++ if (size >= PAGE_SIZE)
+ stride = (1 << (PAGE_SHIFT - IO_TLB_SHIFT));
+ else
+ stride = 1;
+--
+2.11.0
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0010-can-rcar_can-add-enable-and-standby-control-pins.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0010-can-rcar_can-add-enable-and-standby-control-pins.patch
new file mode 100644
index 0000000..38d8e09
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0010-can-rcar_can-add-enable-and-standby-control-pins.patch
@@ -0,0 +1,156 @@
+From 5d5eef59a48e3b8e0f67c2ab0963d380c7a7399d Mon Sep 17 00:00:00 2001
+From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+Date: Mon, 2 May 2016 22:05:53 +0300
+Subject: [PATCH] can: rcar_can: add enable and standby control pins
+
+Add enable and standby can transceiver control pins
+
+Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+---
+ .../devicetree/bindings/net/can/rcar_can.txt | 4 ++
+ drivers/net/can/rcar/rcar_can.c | 58 +++++++++++++++++-----
+ include/linux/can/platform/rcar_can.h | 2 +
+ 3 files changed, 51 insertions(+), 13 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/net/can/rcar_can.txt b/Documentation/devicetree/bindings/net/can/rcar_can.txt
+index 8d40ab2..9293cf8 100644
+--- a/Documentation/devicetree/bindings/net/can/rcar_can.txt
++++ b/Documentation/devicetree/bindings/net/can/rcar_can.txt
+@@ -38,6 +38,7 @@ Optional properties:
+ <0x0> (default) : Peripheral clock (clkp1)
+ <0x1> : Peripheral clock (clkp2)
+ <0x3> : Externally input clock
++- gpios: GPIO used for controlling the enable pin and standby pin
+
+ Example
+ -------
+@@ -59,5 +60,8 @@ Board specific .dts file:
+ &can0 {
+ pinctrl-0 = <&can0_pins>;
+ pinctrl-names = "default";
++ gpios = <&gpio5 29 GPIO_ACTIVE_HIGH /* enable */
++ &gpio5 30 GPIO_ACTIVE_LOW /* standby */
++ >;
+ status = "okay";
+ };
+diff --git a/drivers/net/can/rcar/rcar_can.c b/drivers/net/can/rcar/rcar_can.c
+index 788459f..887ca37 100644
+--- a/drivers/net/can/rcar/rcar_can.c
++++ b/drivers/net/can/rcar/rcar_can.c
+@@ -21,6 +21,7 @@
+ #include <linux/clk.h>
+ #include <linux/can/platform/rcar_can.h>
+ #include <linux/of.h>
++#include <linux/of_gpio.h>
+
+ #define RCAR_CAN_DRV_NAME "rcar_can"
+
+@@ -94,6 +95,8 @@ struct rcar_can_priv {
+ u32 tx_tail;
+ u8 clock_select;
+ u8 ier;
++ unsigned int enable_pin; /* transceiver enable */
++ unsigned int standby_pin; /* transceiver standby */
+ };
+
+ static const struct can_bittiming_const rcar_can_bittiming_const = {
+@@ -505,6 +508,10 @@ static int rcar_can_open(struct net_device *ndev)
+ struct rcar_can_priv *priv = netdev_priv(ndev);
+ int err;
+
++ /* transceiver normal mode */
++ if (gpio_is_valid(priv->standby_pin))
++ gpio_set_value(priv->standby_pin, 1);
++
+ err = clk_prepare_enable(priv->clk);
+ if (err) {
+ netdev_err(ndev,
+@@ -581,6 +588,9 @@ static int rcar_can_close(struct net_device *ndev)
+ clk_disable_unprepare(priv->clk);
+ close_candev(ndev);
+ can_led_event(ndev, CAN_LED_EVENT_STOP);
++ /* transceiver stanby mode */
++ if (gpio_is_valid(priv->standby_pin))
++ gpio_set_value(priv->standby_pin, 0);
+ return 0;
+ }
+
+@@ -743,20 +753,9 @@ static int rcar_can_probe(struct platform_device *pdev)
+ struct resource *mem;
+ void __iomem *addr;
+ u32 clock_select = CLKR_CLKP1;
+- int err = -ENODEV;
++ int err = -ENODEV, ret;
+ int irq;
+-
+- if (pdev->dev.of_node) {
+- of_property_read_u32(pdev->dev.of_node,
+- "renesas,can-clock-select", &clock_select);
+- } else {
+- pdata = dev_get_platdata(&pdev->dev);
+- if (!pdata) {
+- dev_err(&pdev->dev, "No platform data provided!\n");
+- goto fail;
+- }
+- clock_select = pdata->clock_select;
+- }
++ enum of_gpio_flags enable_flags, standby_flags;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+@@ -826,6 +825,39 @@ static int rcar_can_probe(struct platform_device *pdev)
+
+ devm_can_led_init(ndev);
+
++ if (pdev->dev.of_node) {
++ of_property_read_u32(pdev->dev.of_node,
++ "renesas,can-clock-select", &clock_select);
++ priv->enable_pin = of_get_gpio_flags(pdev->dev.of_node, 0, &enable_flags);
++ priv->standby_pin = of_get_gpio_flags(pdev->dev.of_node, 1, &standby_flags);
++ } else {
++ pdata = dev_get_platdata(&pdev->dev);
++ if (!pdata) {
++ dev_err(&pdev->dev, "No platform data provided!\n");
++ goto fail;
++ }
++ clock_select = pdata->clock_select;
++ priv->enable_pin = pdata->enable_pin;
++ priv->standby_pin = pdata->standby_pin;
++ }
++
++ if (gpio_is_valid(priv->enable_pin)) {
++ int val = enable_flags & OF_GPIO_ACTIVE_LOW ?
++ GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH;
++ ret = devm_gpio_request_one(&pdev->dev, priv->enable_pin, val, "enable");
++ if (ret)
++ dev_info(&pdev->dev, "Failed to request enable pin\n");
++ }
++
++ if (gpio_is_valid(priv->standby_pin)) {
++ int val = standby_flags & OF_GPIO_ACTIVE_LOW ?
++ GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH;
++ /* transceiver standby mode */
++ ret = devm_gpio_request_one(&pdev->dev, priv->standby_pin, val, "standby");
++ if (ret)
++ dev_info(&pdev->dev, "Failed to request standby pin\n");
++ }
++
+ dev_info(&pdev->dev, "device registered (regs @ %p, IRQ%d)\n",
+ priv->regs, ndev->irq);
+
+diff --git a/include/linux/can/platform/rcar_can.h b/include/linux/can/platform/rcar_can.h
+index 0f4a2f3..7ef810d 100644
+--- a/include/linux/can/platform/rcar_can.h
++++ b/include/linux/can/platform/rcar_can.h
+@@ -12,6 +12,8 @@ enum CLKR {
+
+ struct rcar_can_platform_data {
+ enum CLKR clock_select; /* Clock source select */
++ unsigned int enable_pin;
++ unsigned int standby_pin;
+ };
+
+ #endif /* !_CAN_PLATFORM_RCAR_CAN_H_ */
+--
+1.9.1
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0011-can-rcar_canfd-add-enable-and-standby-control-pins.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0011-can-rcar_canfd-add-enable-and-standby-control-pins.patch
new file mode 100644
index 0000000..c35cacc
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0011-can-rcar_canfd-add-enable-and-standby-control-pins.patch
@@ -0,0 +1,126 @@
+From 0f55d888c83aed7ea5a10761edaff52de8dc06a1 Mon Sep 17 00:00:00 2001
+From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+Date: Mon, 30 May 2016 01:51:47 +0300
+Subject: [PATCH] can: rcar_canfd: add enable and standby control pins
+
+Add enable and standby can transceiver control pins
+
+Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+---
+ .../devicetree/bindings/net/can/rcar_canfd.txt | 5 +++
+ drivers/net/can/rcar/rcar_canfd.c | 48 ++++++++++++++++++----
+ 2 files changed, 44 insertions(+), 9 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/net/can/rcar_canfd.txt b/Documentation/devicetree/bindings/net/can/rcar_canfd.txt
+index 4299bd8..eede77a 100644
+--- a/Documentation/devicetree/bindings/net/can/rcar_canfd.txt
++++ b/Documentation/devicetree/bindings/net/can/rcar_canfd.txt
+@@ -16,6 +16,7 @@ Required properties:
+ - clock-names: 3 clock input name strings: "fck", "canfd", "can_clk".
+ - pinctrl-0: pin control group to be used for this controller.
+ - pinctrl-names: must be "default".
++- gpios: GPIO used for controlling the enable pin and standby pin
+
+ Required child nodes:
+ The controller supports two channels and each is represented as a child node.
+@@ -49,6 +50,10 @@ SoC common .dtsi file:
+ power-domains = <&cpg>;
+ status = "disabled";
+
++ gpios = <&gpio5 29 GPIO_ACTIVE_HIGH /* enable */
++ &gpio5 30 GPIO_ACTIVE_LOW /* standby */
++ >;
++
+ channel0 {
+ status = "disabled";
+ };
+diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c
+index 15a14c5..4aa670d 100644
+--- a/drivers/net/can/rcar/rcar_canfd.c
++++ b/drivers/net/can/rcar/rcar_canfd.c
+@@ -21,6 +21,7 @@
+ #include <linux/clk.h>
+ #include <linux/of.h>
+ #include <linux/of_device.h>
++#include <linux/of_gpio.h>
+ #include <linux/bitmap.h>
+ #include <linux/bitops.h>
+ #include <linux/iopoll.h>
+@@ -386,6 +387,8 @@ struct rcar_canfd_global {
+ enum rcar_canfd_fcanclk fcan; /* CANFD or Ext clock */
+ unsigned long channels_mask; /* Enabled channels mask */
+ bool fdmode; /* CAN FD or Classical CAN only mode */
++ unsigned int enable_pin; /* transceiver enable */
++ unsigned int standby_pin; /* transceiver standby */
+ };
+
+ /* CAN FD mode nominal rate constants */
+@@ -1063,6 +1066,10 @@ static int rcar_canfd_open(struct net_device *ndev)
+ struct rcar_canfd_global *gpriv = priv->gpriv;
+ int err;
+
++ /* transceiver normal mode */
++ if (gpio_is_valid(gpriv->standby_pin))
++ gpio_set_value(gpriv->standby_pin, 1);
++
+ /* Peripheral clock is already enabled in probe */
+ err = clk_prepare_enable(gpriv->can_clk);
+ if (err) {
+@@ -1131,6 +1138,9 @@ static int rcar_canfd_close(struct net_device *ndev)
+ clk_disable_unprepare(gpriv->can_clk);
+ close_candev(ndev);
+ can_led_event(ndev, CAN_LED_EVENT_STOP);
++ /* transceiver stanby mode */
++ if (gpio_is_valid(gpriv->standby_pin))
++ gpio_set_value(gpriv->standby_pin, 0);
+ return 0;
+ }
+
+@@ -1409,8 +1419,9 @@ static int rcar_canfd_probe(struct platform_device *pdev)
+ struct rcar_canfd_global *gpriv;
+ struct device_node *of_child;
+ unsigned long channels_mask = 0;
+- int err, ch_irq, g_irq;
++ int err, ret, ch_irq, g_irq;
+ bool fdmode = true; /* CAN FD only mode - default */
++ enum of_gpio_flags enable_flags, standby_flags;
+
+ if (of_property_read_bool(pdev->dev.of_node, "renesas,no-can-fd"))
+ fdmode = false; /* Classical CAN only mode */
+@@ -1552,6 +1555,33 @@ static int rcar_canfd_probe(struct platform_device *pdev)
+ goto fail_channel;
+ }
+
++ of_property_read_u32(pdev->dev.of_node,
++ "renesas,can-clock-select", &clock_select);
++ if (clock_select >= ARRAY_SIZE(clock_names)) {
++ err = -EINVAL;
++ dev_err(&pdev->dev, "invalid CAN clock selected\n");
++ goto fail_dev;
++ }
++ gpriv->enable_pin = of_get_gpio_flags(pdev->dev.of_node, 0, &enable_flags);
++ gpriv->standby_pin = of_get_gpio_flags(pdev->dev.of_node, 1, &standby_flags);
++
++ if (gpio_is_valid(gpriv->enable_pin)) {
++ int val = enable_flags & OF_GPIO_ACTIVE_LOW ?
++ GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH;
++ ret = devm_gpio_request_one(&pdev->dev, gpriv->enable_pin, val, "enable");
++ if (ret)
++ dev_info(&pdev->dev, "Failed to request enable pin\n");
++ }
++
++ if (gpio_is_valid(gpriv->standby_pin)) {
++ int val = standby_flags & OF_GPIO_ACTIVE_LOW ?
++ GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH;
++ /* transceiver standby mode */
++ ret = devm_gpio_request_one(&pdev->dev, gpriv->standby_pin, val, "standby");
++ if (ret)
++ dev_info(&pdev->dev, "Failed to request standby pin\n");
++ }
++
+ platform_set_drvdata(pdev, gpriv);
+ dev_info(&pdev->dev, "global operational state (clk %d, fdmode %d)\n",
+ gpriv->fcan, gpriv->fdmode);
+--
+1.9.1
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0012-mtd-Add-RPC-HyperFlash-driver.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0012-mtd-Add-RPC-HyperFlash-driver.patch
new file mode 100644
index 0000000..a6d08e7
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0012-mtd-Add-RPC-HyperFlash-driver.patch
@@ -0,0 +1,1028 @@
+From cc3bccbe6c479d8ad76a09b62fb63126403d0bab Mon Sep 17 00:00:00 2001
+From: Valentine Barshak <valentine.barshak@cogentembedded.com>
+Date: Fri, 3 Jun 2016 23:04:20 +0300
+Subject: [PATCH] mtd: Add RPC HyperFlash driver
+
+This adds RPC HyperFlash driver.
+
+Signed-off-by: Valentine Barshak <valentine.barshak@cogentembedded.com>
+---
+ drivers/mtd/Kconfig | 5 +
+ drivers/mtd/Makefile | 1 +
+ drivers/mtd/rpc_hyperflash.c | 976 +++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 982 insertions(+)
+ create mode 100644 drivers/mtd/rpc_hyperflash.c
+
+diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
+index 42cc953..0c58a89 100644
+--- a/drivers/mtd/Kconfig
++++ b/drivers/mtd/Kconfig
+@@ -11,6 +11,11 @@ menuconfig MTD
+ particular hardware and users of MTD devices. If unsure, say N.
+
+ if MTD
++config MTD_RPC_HYPERFLASH
++ tristate "MTD Renesas R-Car Gen3 RPC HyperFlash"
++ depends on ARCH_R8A7795
++ ---help---
++ This option includes Renesas R-Car Gen3 RPC HyperFlash support.
+
+ config MTD_TESTS
+ tristate "MTD tests support (DANGEROUS)"
+diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
+index 99bb9a1..3b81efb 100644
+--- a/drivers/mtd/Makefile
++++ b/drivers/mtd/Makefile
+@@ -13,6 +13,7 @@ obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
+ obj-$(CONFIG_MTD_AR7_PARTS) += ar7part.o
+ obj-$(CONFIG_MTD_BCM63XX_PARTS) += bcm63xxpart.o
+ obj-$(CONFIG_MTD_BCM47XX_PARTS) += bcm47xxpart.o
++obj-$(CONFIG_MTD_RPC_HYPERFLASH) += rpc_hyperflash.o
+
+ # 'Users' - code which presents functionality to userspace.
+ obj-$(CONFIG_MTD_BLKDEVS) += mtd_blkdevs.o
+diff --git a/drivers/mtd/rpc_hyperflash.c b/drivers/mtd/rpc_hyperflash.c
+new file mode 100644
+index 0000000..f8a2c90
+--- /dev/null
++++ b/drivers/mtd/rpc_hyperflash.c
+@@ -0,0 +1,976 @@
++/*
++ * Linux driver for R-Car Gen3 RPC HyperFlash
++ *
++ * Copyright (C) 2016 Renesas Electronics Corporation
++ * Copyright (C) 2016 Cogent Embedded, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/delay.h>
++#include <linux/io.h>
++#include <linux/module.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/partitions.h>
++#include <linux/of.h>
++#include <linux/rwsem.h>
++#include <linux/slab.h>
++
++/* RPC */
++#define RPC_BASE 0xEE200000
++#define RPC_SIZE 0x8100
++#define RPC_FLASH_BASE 0x08000000
++#define RPC_FLASH_SIZE 0x04000000
++
++#define RPC_CMNCR 0x0000 /* R/W */
++#define RPC_CMNCR_MD (0x1 << 31)
++#define RPC_CMNCR_MOIIO0(val) (((val) & 0x3) << 16)
++#define RPC_CMNCR_MOIIO1(val) (((val) & 0x3) << 18)
++#define RPC_CMNCR_MOIIO2(val) (((val) & 0x3) << 20)
++#define RPC_CMNCR_MOIIO3(val) (((val) & 0x3) << 22)
++#define RPC_CMNCR_MOIIO_HIZ (RPC_CMNCR_MOIIO0(3) | RPC_CMNCR_MOIIO1(3) | \
++ RPC_CMNCR_MOIIO2(3) | RPC_CMNCR_MOIIO3(3))
++#define RPC_CMNCR_IO0FV(val) (((val) & 0x3) << 8)
++#define RPC_CMNCR_IO2FV(val) (((val) & 0x3) << 12)
++#define RPC_CMNCR_IO3FV(val) (((val) & 0x3) << 14)
++#define RPC_CMNCR_IOFV_HIZ (RPC_CMNCR_IO0FV(3) | RPC_CMNCR_IO2FV(3) | \
++ RPC_CMNCR_IO3FV(3))
++#define RPC_CMNCR_BSZ(val) (((val) & 0x3) << 0)
++
++#define RPC_SSLDR 0x0004 /* R/W */
++#define RPC_SSLDR_SPNDL(d) (((d) & 0x7) << 16)
++#define RPC_SSLDR_SLNDL(d) (((d) & 0x7) << 8)
++#define RPC_SSLDR_SCKDL(d) (((d) & 0x7) << 0)
++
++#define RPC_DRCR 0x000C /* R/W */
++#define RPC_DRCR_SSLN (0x1 << 24)
++#define RPC_DRCR_RBURST(v) (((v) & 0x1F) << 16)
++#define RPC_DRCR_RCF (0x1 << 9)
++#define RPC_DRCR_RBE (0x1 << 8)
++#define RPC_DRCR_SSLE (0x1 << 0)
++
++#define RPC_DRCMR 0x0010 /* R/W */
++#define RPC_DRCMR_CMD(c) (((c) & 0xFF) << 16)
++#define RPC_DRCMR_OCMD(c) (((c) & 0xFF) << 0)
++
++#define RPC_DREAR 0x0014 /* R/W */
++#define RPC_DREAR_EAV(v) (((v) & 0xFF) << 16)
++#define RPC_DREAR_EAC(v) (((v) & 0x7) << 0)
++
++#define RPC_DROPR 0x0018 /* R/W */
++#define RPC_DROPR_OPD3(o) (((o) & 0xFF) << 24)
++#define RPC_DROPR_OPD2(o) (((o) & 0xFF) << 16)
++#define RPC_DROPR_OPD1(o) (((o) & 0xFF) << 8)
++#define RPC_DROPR_OPD0(o) (((o) & 0xFF) << 0)
++
++#define RPC_DRENR 0x001C /* R/W */
++#define RPC_DRENR_CDB(o) (((o) & 0x3) << 30)
++#define RPC_DRENR_OCDB(o) (((o) & 0x3) << 28)
++#define RPC_DRENR_ADB(o) (((o) & 0x3) << 24)
++#define RPC_DRENR_OPDB(o) (((o) & 0x3) << 20)
++#define RPC_DRENR_SPIDB(o) (((o) & 0x3) << 16)
++#define RPC_DRENR_DME (0x1 << 15)
++#define RPC_DRENR_CDE (0x1 << 14)
++#define RPC_DRENR_OCDE (0x1 << 12)
++#define RPC_DRENR_ADE(v) (((v) & 0xF) << 8)
++#define RPC_DRENR_OPDE(v) (((v) & 0xF) << 4)
++
++#define RPC_SMCR 0x0020 /* R/W */
++#define RPC_SMCR_SSLKP (0x1 << 8)
++#define RPC_SMCR_SPIRE (0x1 << 2)
++#define RPC_SMCR_SPIWE (0x1 << 1)
++#define RPC_SMCR_SPIE (0x1 << 0)
++
++#define RPC_SMCMR 0x0024 /* R/W */
++#define RPC_SMCMR_CMD(c) (((c) & 0xFF) << 16)
++#define RPC_SMCMR_OCMD(c) (((c) & 0xFF) << 0)
++
++#define RPC_SMADR 0x0028 /* R/W */
++#define RPC_SMOPR 0x002C /* R/W */
++#define RPC_SMOPR_OPD0(o) (((o) & 0xFF) << 0)
++#define RPC_SMOPR_OPD1(o) (((o) & 0xFF) << 8)
++#define RPC_SMOPR_OPD2(o) (((o) & 0xFF) << 16)
++#define RPC_SMOPR_OPD3(o) (((o) & 0xFF) << 24)
++
++#define RPC_SMENR 0x0030 /* R/W */
++#define RPC_SMENR_CDB(o) (((o) & 0x3) << 30)
++#define RPC_SMENR_OCDB(o) (((o) & 0x3) << 28)
++#define RPC_SMENR_ADB(o) (((o) & 0x3) << 24)
++#define RPC_SMENR_OPDB(o) (((o) & 0x3) << 20)
++#define RPC_SMENR_SPIDB(o) (((o) & 0x3) << 16)
++#define RPC_SMENR_DME (0x1 << 15)
++#define RPC_SMENR_CDE (0x1 << 14)
++#define RPC_SMENR_OCDE (0x1 << 12)
++#define RPC_SMENR_ADE(v) (((v) & 0xF) << 8)
++#define RPC_SMENR_OPDE(v) (((v) & 0xF) << 4)
++#define RPC_SMENR_SPIDE(v) (((v) & 0xF) << 0)
++
++#define RPC_SMRDR0 0x0038 /* R */
++#define RPC_SMRDR1 0x003C /* R */
++#define RPC_SMWDR0 0x0040 /* R/W */
++#define RPC_SMWDR1 0x0044 /* R/W */
++#define RPC_CMNSR 0x0048 /* R */
++#define RPC_CMNSR_SSLF (0x1 << 1)
++#define RPC_CMNSR_TEND (0x1 << 0)
++
++#define RPC_DRDMCR 0x0058 /* R/W */
++#define RPC_DRDMCR_DMCYC(v) (((v) & 0xF) << 0)
++
++#define RPC_DRDRENR 0x005C /* R/W */
++#define RPC_DRDRENR_HYPE (0x5 << 12)
++#define RPC_DRDRENR_ADDRE (0x1 << 0x8)
++#define RPC_DRDRENR_OPDRE (0x1 << 0x4)
++#define RPC_DRDRENR_DRDRE (0x1 << 0x0)
++
++#define RPC_SMDMCR 0x0060 /* R/W */
++#define RPC_SMDMCR_DMCYC(v) (((v) & 0xF) << 0)
++
++#define RPC_SMDRENR 0x0064 /* R/W */
++#define RPC_SMDRENR_HYPE (0x5 << 12)
++#define RPC_SMDRENR_ADDRE (0x1 << 0x8)
++#define RPC_SMDRENR_OPDRE (0x1 << 0x4)
++#define RPC_SMDRENR_SPIDRE (0x1 << 0x0)
++
++#define RPC_PHYCNT 0x007C /* R/W */
++#define RPC_PHYCNT_CAL (0x1 << 31)
++#define PRC_PHYCNT_OCTA_AA (0x1 << 22)
++#define PRC_PHYCNT_OCTA_SA (0x2 << 22)
++#define PRC_PHYCNT_EXDS (0x1 << 21)
++#define RPC_PHYCNT_OCT (0x1 << 20)
++#define RPC_PHYCNT_WBUF2 (0x1 << 4)
++#define RPC_PHYCNT_WBUF (0x1 << 2)
++#define RPC_PHYCNT_MEM(v) (((v) & 0x3) << 0)
++
++#define RPC_PHYINT 0x0088 /* R/W */
++#define RPC_PHYINT_RSTEN (0x1 << 18)
++#define RPC_PHYINT_WPEN (0x1 << 17)
++#define RPC_PHYINT_INTEN (0x1 << 16)
++#define RPC_PHYINT_RST (0x1 << 2)
++#define RPC_PHYINT_WP (0x1 << 1)
++#define RPC_PHYINT_INT (0x1 << 0)
++
++#define RPC_WBUF 0x8000 /* R/W size=4/8/16/32/64Bytes */
++#define RPC_WBUF_SIZE 0x100
++
++struct rpc_info {
++ struct rw_semaphore lock;
++ void __iomem *rpc_base;
++ void __iomem *flash_base;
++ struct resource *rpc_res;
++ struct resource *flash_res;
++ u32 flash_id;
++ struct mtd_info mtd;
++};
++
++static inline void __iomem *rpc_addr(struct rpc_info *info, u32 offset)
++{
++ return info->rpc_base + offset;
++}
++
++static inline u32 rpc_readl(struct rpc_info *info, u32 offset)
++{
++ u32 val;
++
++ val = readl(rpc_addr(info, offset));
++ return val;
++}
++
++static inline void rpc_writel(struct rpc_info *info, u32 offset, u32 val)
++{
++ writel(val, rpc_addr(info, offset));
++}
++
++static inline void rpc_setl(struct rpc_info *info, u32 offset, u32 mask, u32 set)
++{
++ void __iomem *addr;
++ u32 val;
++
++ addr = rpc_addr(info, offset);
++ val = readl(addr);
++ val &= mask;
++ val |= set;
++ writel(val, addr);
++}
++
++static void rpc_wait_tend(struct rpc_info *info)
++{
++ while (!(rpc_readl(info, RPC_CMNSR) & RPC_CMNSR_TEND))
++ cpu_relax();
++}
++
++/* RPC HyperFlash */
++#define RPC_HF_CMD_CA47 (0x1 << 7) /* Read */
++#define RPC_HF_CMD_CA46 (0x1 << 6) /* Register space */
++#define RPC_HF_CMD_CA45 (0x1 << 5) /* Liner burst */
++
++#define RPC_HF_CMD_READ_REG (RPC_HF_CMD_CA47 | RPC_HF_CMD_CA46)
++#define RPC_HF_CMD_READ_MEM RPC_HF_CMD_CA47
++#define RPC_HF_CMD_WRITE_REG RPC_HF_CMD_CA46
++#define RPC_HF_CMD_WRITE_MEM 0x0
++
++#define RPC_HF_ERASE_SIZE 0x40000
++
++#define RPC_CFI_STATUS_DRB (0x1 << 7)
++#define RPC_CFI_STATUS_ESSB (0x1 << 6)
++#define RPC_CFI_STATUS_ESB (0x1 << 5)
++#define RPC_CFI_STATUS_PSB (0x1 << 4)
++#define RPC_CFI_STATUS_WBASB (0x1 << 3)
++#define RPC_CFI_STATUS_PSSB (0x1 << 2)
++#define RPC_CFI_STATUS_SLSB (0x1 << 1)
++#define RPC_CFI_STATUS_ESTAT (0x1 << 0)
++
++#define RPC_CFI_UNLOCK1 (0x555 << 1)
++#define RPC_CFI_UNLOCK2 (0x2AA << 1)
++
++#define RPC_CFI_CMD_UNLOCK_START 0xAA
++#define RPC_CFI_CMD_UNLOCK_ACK 0x55
++#define RPC_CFI_CMD_RESET 0xF0
++#define RPC_CFI_CMD_READ_STATUS 0x70
++#define RPC_CFI_CMD_READ_ID 0x90
++#define RPC_CFI_CMD_WRITE 0xA0
++#define RPC_CFI_CMD_ERASE_START 0x80
++#define RPC_CFI_CMD_ERASE_SECTOR 0x30
++
++#define RPC_CFI_ID_MASK 0x000F
++#define RPC_CFI_ID_MAN_SPANSION 0x0001
++#define RPC_CFI_ID_TYPE_HYPERFLASH 0x000E
++
++enum rpc_hf_size {
++ RPC_HF_SIZE_16BIT = RPC_SMENR_SPIDE(0x8),
++ RPC_HF_SIZE_32BIT = RPC_SMENR_SPIDE(0xC),
++ RPC_HF_SIZE_64BIT = RPC_SMENR_SPIDE(0xF),
++};
++
++struct rpc_info *rpc_info;
++
++static void rpc_hf_mode_man(struct rpc_info *info)
++{
++ rpc_wait_tend(info);
++
++ /*
++ * RPC_PHYCNT = 0x80000263
++ * bit31 CAL = 1 : PHY calibration
++ * bit1-0 PHYMEM[1:0] = 11 : HyperFlash
++ */
++ rpc_setl(info, RPC_PHYCNT,
++ ~(RPC_PHYCNT_WBUF | RPC_PHYCNT_WBUF2 |
++ RPC_PHYCNT_CAL | RPC_PHYCNT_MEM(3)),
++ RPC_PHYCNT_CAL | RPC_PHYCNT_MEM(3));
++
++ /*
++ * RPC_CMNCR = 0x81FFF301
++ * bit31 MD = 1 : Manual mode
++ * bit1-0 BSZ[1:0] = 01 : QSPI Flash x 2 or HyperFlash
++ */
++ rpc_setl(info, RPC_CMNCR,
++ ~(RPC_CMNCR_MD | RPC_CMNCR_BSZ(3)),
++ RPC_CMNCR_MOIIO_HIZ | RPC_CMNCR_IOFV_HIZ |
++ RPC_CMNCR_MD | RPC_CMNCR_BSZ(1));
++}
++
++static void rpc_hf_mode_ext(struct rpc_info *info)
++{
++ rpc_wait_tend(info);
++
++ /*
++ * RPC_PHYCNT = 0x80000263
++ * bit31 CAL = 1 : PHY calibration
++ * bit1-0 PHYMEM[1:0] = 11 : HyperFlash
++ */
++ rpc_setl(info, RPC_PHYCNT,
++ ~(RPC_PHYCNT_WBUF | RPC_PHYCNT_WBUF2 |
++ RPC_PHYCNT_CAL | RPC_PHYCNT_MEM(3)),
++ RPC_PHYCNT_CAL | RPC_PHYCNT_MEM(3));
++
++ /*
++ * RPC_CMNCR = 0x81FFF301
++ * bit31 MD = 1 : Manual mode
++ * bit1-0 BSZ[1:0] = 01 : QSPI Flash x 2 or HyperFlash
++ */
++ rpc_setl(info, RPC_CMNCR,
++ ~(RPC_CMNCR_MD | RPC_CMNCR_BSZ(3)),
++ RPC_CMNCR_MOIIO_HIZ | RPC_CMNCR_IOFV_HIZ |
++ RPC_CMNCR_BSZ(1));
++
++ /*
++ * RPC_DRCR = 0x001F0100
++ * bit21-16 RBURST[4:0] = 11111 : Read burst 32 64-bit data units
++ * bit9 RCF = 1 : Clear cache
++ * bit8 RBE = 1 : Read burst enable
++ */
++ rpc_writel(info, RPC_DRCR,
++ RPC_DRCR_RBURST(0x1F) | RPC_DRCR_RCF | RPC_DRCR_RBE);
++
++ rpc_writel(info, RPC_DRCMR, RPC_DRCMR_CMD(0xA0));
++ rpc_writel(info, RPC_DRENR,
++ RPC_DRENR_CDB(2) | RPC_DRENR_OCDB(2) |
++ RPC_DRENR_ADB(2) | RPC_DRENR_SPIDB(2) |
++ RPC_DRENR_CDE | RPC_DRENR_OCDE | RPC_DRENR_ADE(4));
++ rpc_writel(info, RPC_DRDMCR, RPC_DRDMCR_DMCYC(0xE));
++ rpc_writel(info, RPC_DRDRENR,
++ RPC_DRDRENR_HYPE | RPC_DRDRENR_ADDRE | RPC_DRDRENR_DRDRE);
++
++ /* Dummy read */
++ rpc_readl(info, RPC_DRCR);
++}
++
++static void rpc_hf_xfer(struct rpc_info *info, u32 addr, u16 *data,
++ enum rpc_hf_size size, u8 cmd)
++{
++ u32 val;
++
++ rpc_hf_mode_man(info);
++
++ /*
++ * bit23-21 CMD[7:5] : CA47-45
++ * CA47 = 0/1 : Write/Read
++ * CA46 = 0/1 : Memory Space/Register Space
++ * CA45 = 0/1 : Wrapped Burst/Linear Burst
++ */
++ rpc_writel(info, RPC_SMCMR, RPC_SMCMR_CMD(cmd));
++
++ rpc_writel(info, RPC_SMADR, addr >> 1);
++
++ rpc_writel(info, RPC_SMOPR, 0x0);
++
++ /*
++ * RPC_SMDRENR = 0x00005101
++ * bit14-12 HYPE = 101: Hyperflash mode
++ * bit8 ADDRE = 1 : Address DDR transfer
++ * bit0 SPIDRE = 1 : DATA DDR transfer
++ */
++ rpc_writel(info, RPC_SMDRENR,
++ RPC_SMDRENR_HYPE | RPC_SMDRENR_ADDRE | RPC_SMDRENR_SPIDRE);
++
++ val = RPC_SMENR_CDB(2) | RPC_SMENR_OCDB(2) |
++ RPC_SMENR_ADB(2) | RPC_SMENR_SPIDB(2) |
++ RPC_SMENR_CDE | RPC_SMENR_OCDE | RPC_SMENR_ADE(4) | size;
++
++ if (cmd & RPC_HF_CMD_CA47)
++ goto read_transfer;
++
++ /*
++ * RPC_SMENR = 0xA222540x
++ * bit31-30 CDB[1:0] = 10 : 4bit width command
++ * bit25-24 ADB[1:0] = 10 : 4bit width address
++ * bit17-16 SPIDB[1:0] = 10 : 4bit width transfer data
++ * bit15 DME = 0 : dummy cycle disable
++ * bit14 CDE = 1 : Command enable
++ * bit12 OCDE = 1 : Option Command enable
++ * bit11-8 ADE[3:0] = 0100 : ADR[23:0] output
++ * bit7-4 OPDE[3:0] = 0000 : Option data disable
++ * bit3-0 SPIDE[3:0] = xxxx : Transfer size
++ */
++ rpc_writel(info, RPC_SMENR, val);
++
++ switch (size) {
++ case RPC_HF_SIZE_64BIT:
++ val = cmd & RPC_HF_CMD_CA46 ?
++ cpu_to_be16(data[0]) | cpu_to_be16(data[1]) << 16 :
++ data[0] | data[1] << 16;
++ rpc_writel(info, RPC_SMWDR1, val);
++ val = cmd & RPC_HF_CMD_CA46 ?
++ cpu_to_be16(data[2]) | cpu_to_be16(data[3]) << 16 :
++ data[2] | data[3] << 16;
++ break;
++ case RPC_HF_SIZE_32BIT:
++ val = cmd & RPC_HF_CMD_CA46 ?
++ cpu_to_be16(data[0]) | cpu_to_be16(data[1]) << 16 :
++ data[0] | data[1] << 16;
++ break;
++ default:
++ val = cmd & RPC_HF_CMD_CA46 ?
++ cpu_to_be16(data[0]) << 16 :
++ data[0] << 16;
++ break;
++ }
++
++ rpc_writel(info, RPC_SMWDR0, val);
++ /*
++ * RPC_SMCR = 0x00000003
++ * bit1 SPIWE = 1 : Data write enable
++ * bit0 SPIE = 1 : SPI transfer start
++ */
++ rpc_writel(info, RPC_SMCR, RPC_SMCR_SPIWE | RPC_SMCR_SPIE);
++ return;
++
++read_transfer:
++ rpc_writel(info, RPC_SMDMCR, RPC_SMDMCR_DMCYC(0xE));
++ val |= RPC_SMENR_DME;
++
++ /*
++ * RPC_SMENR = 0xA222D40x
++ * bit31-30 CDB[1:0] = 10 : 4bit width command
++ * bit25-24 ADB[1:0] = 10 : 4bit width address
++ * bit17-16 SPIDB[1:0] = 10 : 4bit width transfer data
++ * bit15 DME = 1 : dummy cycle disable
++ * bit14 CDE = 1 : Command enable
++ * bit12 OCDE = 1 : Option Command enable
++ * bit11-8 ADE[3:0] = 0100 : ADR[23:0] output (24 Bit Address)
++ * bit7-4 OPDE[3:0] = 0000 : Option data disable
++ * bit3-0 SPIDE[3:0] = xxxx : Transfer size
++ */
++ rpc_writel(info, RPC_SMENR, val);
++
++ /*
++ * RPC_SMCR = 0x00000005
++ * bit2 SPIRE = 1 : Data read disable
++ * bit0 SPIE = 1 : SPI transfer start
++ */
++ rpc_writel(info, RPC_SMCR, RPC_SMCR_SPIRE | RPC_SMCR_SPIE);
++
++ rpc_wait_tend(info);
++ val = rpc_readl(info, RPC_SMRDR0);
++
++ /*
++ * Read data from either register or memory space.
++ * Register space is always big-endian.
++ */
++ switch (size) {
++ case RPC_HF_SIZE_64BIT:
++ if (cmd & RPC_HF_CMD_CA46) {
++ data[3] = be16_to_cpu((val >> 16) & 0xFFFF);
++ data[2] = be16_to_cpu(val & 0xFFFF);
++ } else {
++ data[3] = (val >> 16) & 0xFFFF;
++ data[2] = val & 0xFFFF;
++ }
++ val = rpc_readl(info, RPC_SMRDR1);
++ if (cmd & RPC_HF_CMD_CA46) {
++ data[1] = be16_to_cpu((val >> 16) & 0xFFFF);
++ data[0] = be16_to_cpu(val & 0xFFFF);
++ } else {
++ data[1] = (val >> 16) & 0xFFFF;
++ data[0] = val & 0xFFFF;
++ }
++ break;
++ case RPC_HF_SIZE_32BIT:
++ if (cmd & RPC_HF_CMD_CA46) {
++ data[1] = be16_to_cpu((val >> 16) & 0xFFFF);
++ data[0] = be16_to_cpu(val & 0xFFFF);
++ } else {
++ data[1] = (val >> 16) & 0xFFFF;
++ data[0] = val & 0xFFFF;
++ }
++ break;
++ default:
++ data[0] = cmd & RPC_HF_CMD_CA46 ?
++ be16_to_cpu((val >> 16) & 0xFFFF) :
++ (val >> 16) & 0xFFFF;
++ break;
++ }
++}
++
++static void rpc_hf_wbuf_enable(struct rpc_info *info)
++{
++ rpc_wait_tend(info);
++
++ /*
++ * RPC_PHYCNT = 0x80000277
++ * bit31 CAL = 1 : PHY calibration
++ * bit4 WBUF2 = 1 : Write buffer enable 2
++ * bit2 WBUF = 1 : Write buffer enable
++ * bit1-0 PHYMEM[1:0] = 11 : HyperFlash
++ */
++ rpc_setl(info, RPC_PHYCNT,
++ ~(RPC_PHYCNT_WBUF2 | RPC_PHYCNT_WBUF |
++ RPC_PHYCNT_CAL | RPC_PHYCNT_MEM(3)),
++ RPC_PHYCNT_WBUF2 | RPC_PHYCNT_WBUF |
++ RPC_PHYCNT_CAL | RPC_PHYCNT_MEM(3));
++
++ /*
++ * RPC_DRCR = 0x001F0100
++ * bit21-16 RBURST[4:0] = 11111 : Read burst 32 64-bit data units
++ * bit9 RCF = 1 : Clear cache
++ * bit8 RBE = 1 : Read burst enable
++ */
++ rpc_writel(info, RPC_DRCR,
++ RPC_DRCR_RBURST(0x1F) | RPC_DRCR_RCF | RPC_DRCR_RBE);
++
++ rpc_writel(info, RPC_SMCMR, RPC_SMCMR_CMD(RPC_HF_CMD_WRITE_MEM));
++
++ rpc_writel(info, RPC_SMOPR, 0x0);
++
++ /*
++ * RPC_SMDRENR = 0x00005101
++ * bit14-12 HYPE = 101:Hyperflash mode
++ * bit8 ADDRE = 1 : Address DDR transfer
++ * bit0 SPIDRE = 1 : DATA DDR transfer
++ */
++ rpc_writel(info, RPC_SMDRENR,
++ RPC_SMDRENR_HYPE | RPC_SMDRENR_ADDRE | RPC_SMDRENR_SPIDRE);
++
++ /*
++ * RPC_SMENR = 0xA222540F
++ * bit31-30 CDB[1:0] = 10 : 4bit width command
++ * bit25-24 ADB[1:0] = 10 : 4bit width address
++ * bit17-16 SPIDB[1:0] = 10 : 4bit width transfer data
++ * bit15 DME = 0 : dummy cycle disable
++ * bit14 CDE = 1 : Command enable
++ * bit12 OCDE = 1 : Option Command enable
++ * bit11-8 ADE[3:0] = 0100 : ADR[23:0] output (24 Bit Address)
++ * bit7-4 OPDE[3:0] = 0000 : Option data disable
++ * bit3-0 SPIDE[3:0] = 1111 : 64-bit transfer size
++ */
++ rpc_writel(info, RPC_SMENR,
++ RPC_SMENR_CDB(2) | RPC_SMENR_OCDB(2) |
++ RPC_SMENR_ADB(2) | RPC_SMENR_SPIDB(2) |
++ RPC_SMENR_CDE | RPC_SMENR_OCDE |
++ RPC_SMENR_ADE(4) | RPC_HF_SIZE_64BIT);
++
++ /* Dummy read */
++ rpc_readl(info, RPC_DRCR);
++}
++
++static inline void rpc_hf_write_cmd(struct rpc_info *info, u32 addr, u16 cmd)
++{
++ rpc_hf_xfer(info, addr, &cmd, RPC_HF_SIZE_16BIT, RPC_HF_CMD_WRITE_REG);
++}
++
++static inline void rpc_hf_read_reg(struct rpc_info *info, u32 addr, u16 *data,
++ enum rpc_hf_size size)
++{
++ rpc_hf_xfer(info, addr, data, size, RPC_HF_CMD_READ_REG);
++}
++
++static inline void rpc_hf_write_reg(struct rpc_info *info, u32 addr, u16 *data,
++ enum rpc_hf_size size)
++{
++ rpc_hf_xfer(info, addr, data, size, RPC_HF_CMD_WRITE_REG);
++}
++
++static inline void rpc_hf_read_mem(struct rpc_info *info, u32 addr, u16 *data,
++ enum rpc_hf_size size)
++{
++ rpc_hf_xfer(info, addr, data, size, RPC_HF_CMD_READ_MEM);
++}
++
++static inline void rpc_hf_write_mem(struct rpc_info *info, u32 addr, u16 *data,
++ enum rpc_hf_size size)
++{
++ rpc_hf_xfer(info, addr, data, size, RPC_HF_CMD_WRITE_MEM);
++}
++
++static void rpc_hf_wp(struct rpc_info *info, int enable)
++{
++ rpc_setl(info, RPC_PHYINT, ~RPC_PHYINT_WP, enable ? RPC_PHYINT_WP : 0);
++}
++
++static void rpc_hf_unlock(struct rpc_info *info, u32 addr)
++{
++ rpc_hf_write_cmd(info, addr + RPC_CFI_UNLOCK1,
++ RPC_CFI_CMD_UNLOCK_START);
++ rpc_hf_write_cmd(info, addr + RPC_CFI_UNLOCK2,
++ RPC_CFI_CMD_UNLOCK_ACK);
++}
++
++static inline int rpc_hf_status(struct rpc_info *info, u32 addr,
++ int iterations, int delay)
++{
++ int retval;
++ u16 status = 0;
++
++ while (iterations-- > 0) {
++ rpc_hf_write_cmd(info, addr + RPC_CFI_UNLOCK1, RPC_CFI_CMD_READ_STATUS);
++ rpc_hf_read_reg(info, addr, &status, RPC_HF_SIZE_16BIT);
++
++ if (status & RPC_CFI_STATUS_DRB)
++ break;
++
++ if (delay < 10000)
++ usleep_range(delay, delay * 2);
++ else
++ msleep(delay / 1000);
++ }
++
++ if (!(status & RPC_CFI_STATUS_DRB)) {
++ retval = -ETIMEDOUT;
++ goto out;
++ }
++
++ if (status & (RPC_CFI_STATUS_PSB | RPC_CFI_STATUS_ESB)) {
++ retval = -EIO;
++ goto out;
++ }
++
++ return 0;
++
++out:
++ /* Reset the flash */
++ rpc_hf_write_cmd(info, 0, RPC_CFI_CMD_RESET);
++ return retval;
++}
++
++static int rpc_hf_sector_erase(struct rpc_info *info, u32 addr)
++{
++ rpc_hf_unlock(info, addr);
++ rpc_hf_write_cmd(info, addr + RPC_CFI_UNLOCK1, RPC_CFI_CMD_ERASE_START);
++ rpc_hf_unlock(info, addr);
++ rpc_hf_write_cmd(info, addr, RPC_CFI_CMD_ERASE_SECTOR);
++
++ return rpc_hf_status(info, addr, 1000, 10000);
++}
++
++/* Flash read */
++static int rpc_hf_mtd_read(struct mtd_info *mtd, loff_t from, size_t len,
++ size_t *retlen, u_char *buf)
++{
++ struct rpc_info *info = mtd->priv;
++
++ down_read(&info->lock);
++ memcpy_fromio(buf, info->flash_base + from, len);
++ up_read(&info->lock);
++
++ *retlen = len;
++ return 0;
++}
++
++/* Flash erase */
++static int rpc_hf_mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
++{
++ struct rpc_info *info = mtd->priv;
++ u32 addr, end;
++ int retval = 0;
++
++ if (mtd_mod_by_eb(instr->addr, mtd)) {
++ pr_debug("%s: unaligned address\n", __func__);
++ return -EINVAL;
++ }
++
++ if (mtd_mod_by_eb(instr->len, mtd)) {
++ pr_debug("%s: unaligned length\n", __func__);
++ return -EINVAL;
++ }
++
++ end = instr->addr + instr->len;
++
++ down_write(&info->lock);
++ for (addr = instr->addr; addr < end; addr += mtd->erasesize) {
++ retval = rpc_hf_sector_erase(info, addr);
++
++ if (retval)
++ break;
++ }
++
++ rpc_hf_mode_ext(info);
++ up_write(&info->lock);
++
++ instr->state = retval ? MTD_ERASE_FAILED : MTD_ERASE_DONE;
++ mtd_erase_callback(instr);
++
++ return retval;
++}
++
++/* Copy memory to flash */
++static int rpc_hf_mtd_write(struct mtd_info *mtd, loff_t offset, size_t len,
++ size_t *retlen, const u_char *src)
++{
++ struct rpc_info *info = mtd->priv;
++ union {
++ u8 b[4];
++ u16 w[2];
++ u32 d;
++ } data;
++ loff_t addr;
++ size_t size, cnt;
++ int retval, idx;
++ u8 last;
++
++ retval = 0;
++ *retlen = 0;
++ cnt = len;
++ idx = 0;
++
++ down_write(&info->lock);
++
++ /* Handle unaligned start */
++ if (offset & 0x1) {
++ offset--;
++ data.b[idx] = readb(info->flash_base + offset);
++ idx++;
++ }
++
++ /* Handle unaligned end */
++ addr = offset + idx + len;
++ last = addr & 0x1 ? readb(info->flash_base + addr) : 0xFF;
++
++ addr = offset - mtd_mod_by_eb(offset, mtd);
++ size = mtd->erasesize - (offset - addr);
++
++ while (cnt) {
++ if (size > cnt)
++ size = cnt;
++
++ cnt -= size;
++ while (size) {
++ rpc_hf_unlock(info, addr);
++ rpc_hf_write_cmd(info,
++ addr + RPC_CFI_UNLOCK1,
++ RPC_CFI_CMD_WRITE);
++
++ if (size > 0x7) {
++ u32 wbuf = RPC_WBUF;
++ int block = size >= RPC_WBUF_SIZE ?
++ RPC_WBUF_SIZE : size & ~0x7;
++
++ rpc_hf_wbuf_enable(info);
++
++ rpc_writel(info, RPC_SMADR, offset >> 1);
++ offset += block;
++
++ block >>= 3;
++ while (block--) {
++ while (idx < 4) {
++ data.b[idx++] = *src++;
++ size--;
++ }
++ rpc_writel(info, wbuf, data.d);
++ wbuf += 4;
++
++ idx = 0;
++ while (idx < 4) {
++ data.b[idx++] = *src++;
++ size--;
++ }
++ rpc_writel(info, wbuf, data.d);
++ wbuf += 4;
++
++ idx = 0;
++ }
++
++ rpc_writel(info, RPC_SMCR,
++ RPC_SMCR_SPIWE | RPC_SMCR_SPIE);
++ } else {
++ enum rpc_hf_size bits;
++
++ while (idx < 4) {
++ data.b[idx++] = *src++;
++ size--;
++
++ if (!size)
++ break;
++ }
++
++ if (idx & 0x1)
++ data.b[idx++] = last;
++
++ switch (idx) {
++ case 2:
++ bits = RPC_HF_SIZE_16BIT;
++ break;
++ default:
++ bits = RPC_HF_SIZE_32BIT;
++ break;
++ }
++
++ rpc_hf_write_mem(info, offset, data.w, bits);
++ offset += idx;
++ idx = 0;
++ }
++
++ retval = rpc_hf_status(info, addr, 1000000, 10);
++ if (retval)
++ goto out;
++ }
++
++ size = mtd->erasesize;
++ addr += size;
++ offset = addr;
++ *retlen = len - cnt;
++ }
++
++out:
++ rpc_hf_mode_ext(info);
++ up_write(&info->lock);
++ return retval;
++}
++
++static struct mtd_partition partition_info[]={
++ {
++ .name = "bootparam",
++ .offset = 0,
++ .size = 0x40000,
++ }, {
++ .name = "bl2",
++ .offset = MTDPART_OFS_APPEND,
++ .size = 0x140000
++ }, {
++ .name = "cert_header",
++ .offset = MTDPART_OFS_APPEND,
++ .size = 0x40000,
++ }, {
++ .name = "bl31",
++ .offset = MTDPART_OFS_APPEND,
++ .size = 0x40000,
++ }, {
++ .name = "optee",
++ .offset = MTDPART_OFS_APPEND,
++ .size = 0x440000,
++ }, {
++ .name = "u-boot",
++ .offset = MTDPART_OFS_APPEND,
++ .size = 0x80000,
++ }, {
++ .name = "reserved",
++ .offset = MTDPART_OFS_APPEND,
++ .size = 0x80000,
++ }, {
++ .name = "u-boot-env",
++ .offset = MTDPART_OFS_APPEND,
++ .size = 0x40000,
++ }, {
++ .name = "dtb",
++ .offset = MTDPART_OFS_APPEND,
++ .size = 0x80000,
++ }, {
++ .name = "kernel",
++ .offset = MTDPART_OFS_APPEND,
++ .size = 0x1000000,
++ }, {
++ .name = "user",
++ .offset = MTDPART_OFS_APPEND,
++ .size = MTDPART_SIZ_FULL,
++ },
++};
++
++static int rpc_hf_init_mtd(struct rpc_info *info)
++{
++ struct mtd_info *mtd = &info->mtd;
++ u16 data[2] = { 0, 0 };
++ u32 id, size;
++ int retval;
++
++ rpc_hf_mode_ext(info);
++
++ rpc_hf_wp(info, 0);
++
++ rpc_hf_unlock(info, 0);
++ rpc_hf_write_cmd(info, RPC_CFI_UNLOCK1, RPC_CFI_CMD_READ_ID);
++
++ rpc_hf_read_reg(info, 0x0, data, RPC_HF_SIZE_32BIT);
++ if ((data[0] & RPC_CFI_ID_MASK) != RPC_CFI_ID_MAN_SPANSION ||
++ (data[1] & RPC_CFI_ID_MASK) != RPC_CFI_ID_TYPE_HYPERFLASH) {
++ retval = -ENODEV;
++ goto out;
++ }
++
++ id = data[0] | data[1] << 16;
++
++ rpc_hf_read_reg(info, 0x27 << 1, data, RPC_HF_SIZE_16BIT);
++ size = 1 << data[0];
++
++ if (size > resource_size(info->flash_res))
++ size = resource_size(info->flash_res);
++
++ if (size & (RPC_HF_ERASE_SIZE - 1)) {
++ retval = -EINVAL;
++ goto out;
++ }
++
++ init_rwsem(&info->lock);
++ info->flash_id = id;
++ mtd->name = "HyperFlash";
++ mtd->type = MTD_NORFLASH;
++ mtd->flags = MTD_CAP_NORFLASH;
++ mtd->size = size;
++ mtd->writesize = 1;
++ mtd->writebufsize = RPC_WBUF_SIZE;
++ mtd->erasesize = RPC_HF_ERASE_SIZE;
++ mtd->owner = THIS_MODULE;
++ mtd->priv = info;
++ mtd->_erase = rpc_hf_mtd_erase;
++ mtd->_write = rpc_hf_mtd_write;
++ mtd->_read = rpc_hf_mtd_read;
++ retval = mtd_device_register(mtd, partition_info,
++ ARRAY_SIZE(partition_info));
++out:
++ rpc_hf_write_cmd(info, 0, RPC_CFI_CMD_RESET);
++ rpc_hf_mode_ext(info);
++ return retval;
++}
++
++static int rpc_flash_init(void)
++{
++ struct rpc_info *info;
++ struct resource *res;
++ void __iomem *base;
++ int retval = -ENODEV;
++
++ if (!of_machine_is_compatible("renesas,r8a7795"))
++ return -ENODEV;
++
++ info = kzalloc(sizeof(*info), GFP_KERNEL);
++ if (!info)
++ return -ENOMEM;
++
++ res = request_mem_region(RPC_BASE, RPC_SIZE, "RPC");
++ if (!res)
++ goto out_info;
++
++ info->rpc_res = res;
++ base = ioremap(res->start, resource_size(res));
++ if (!base)
++ goto out_rpc_res;
++
++ info->rpc_base = base;
++ res = request_mem_region(RPC_FLASH_BASE, RPC_FLASH_SIZE, "RPC-ext");
++ if (!res)
++ goto out_rpc_base;
++
++ info->flash_res = res;
++ base = ioremap(res->start, resource_size(res));
++ if (!base)
++ goto out_flash_res;
++
++ info->flash_base = base;
++ retval = rpc_hf_init_mtd(info);
++ if (retval)
++ goto out_flash_base;
++
++ pr_info("HyperFlash Id: %x\n", info->flash_id);
++
++ rpc_info = info;
++ return 0;
++
++out_flash_base:
++ iounmap(info->flash_base);
++out_flash_res:
++ release_mem_region(info->flash_res->start,
++ resource_size(info->flash_res));
++out_rpc_base:
++ iounmap(info->rpc_base);
++out_rpc_res:
++ release_mem_region(info->rpc_res->start,
++ resource_size(info->rpc_res));
++out_info:
++ kfree(info);
++ return retval;
++}
++
++static void rpc_flash_exit(void)
++{
++ struct rpc_info *info = rpc_info;
++
++ if (!info)
++ return;
++
++ rpc_info = NULL;
++
++ mtd_device_unregister(&info->mtd);
++
++ iounmap(info->flash_base);
++ release_mem_region(info->flash_res->start,
++ resource_size(info->flash_res));
++ iounmap(info->rpc_base);
++ release_mem_region(info->rpc_res->start,
++ resource_size(info->rpc_res));
++ kfree(info);
++}
++
++module_init(rpc_flash_init);
++module_exit(rpc_flash_exit);
++
++MODULE_LICENSE("GPL v2");
++MODULE_DESCRIPTION("Renesas RPC HyperFlash MTD driver");
+--
+2.7.4
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0013-IMR-driver-interim-patch.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0013-IMR-driver-interim-patch.patch
new file mode 100644
index 0000000..e863466
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0013-IMR-driver-interim-patch.patch
@@ -0,0 +1,2104 @@
+From 240504b182a2816696c6a02fe37a5048925cc1fb Mon Sep 17 00:00:00 2001
+From: Konstantin Kozhevnikov <Konstantin.Kozhevnikov@cogentembedded.com>
+Date: Wed, 7 Sep 2016 22:55:37 +0300
+Subject: [PATCH] IMR driver - interim patch
+
+Signed-off-by: Konstantin Kozhevnikov <Konstantin.Kozhevnikov@cogentembedded.com>
+---
+ arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi | 32 +
+ arch/arm64/boot/dts/renesas/r8a7795.dtsi | 32 +
+ drivers/clk/renesas/r8a7795-cpg-mssr.c | 4 +
+ drivers/media/platform/Kconfig | 11 +
+ drivers/media/platform/Makefile | 1 +
+ drivers/media/platform/rcar_imr.c | 1840 ++++++++++++++++++++++++++
+ include/uapi/linux/rcar-imr.h | 98 ++
+ 7 files changed, 2018 insertions(+)
+ create mode 100644 drivers/media/platform/rcar_imr.c
+ create mode 100644 include/uapi/linux/rcar-imr.h
+
+diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi b/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi
+index 09e1284..d530100 100644
+--- a/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi
++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi
+@@ -2713,5 +2713,37 @@
+ };
+ };
+ };
++
++ imrlx4_ch0: imr-lx4@fe860000 {
++ compatible = "renesas,imr-lx4";
++ reg = <0 0xfe860000 0 0x2000>;
++ interrupts = <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&cpg CPG_MOD 823>;
++ power-domains = <&sysc R8A7795_PD_A3VC>;
++ };
++
++ imrlx4_ch1: imr-lx4@fe870000 {
++ compatible = "renesas,imr-lx4";
++ reg = <0 0xfe870000 0 0x2000>;
++ interrupts = <GIC_SPI 193 IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&cpg CPG_MOD 822>;
++ power-domains = <&sysc R8A7795_PD_A3VC>;
++ };
++
++ imrlx4_ch2: imr-lx4@fe880000 {
++ compatible = "renesas,imr-lx4";
++ reg = <0 0xfe880000 0 0x2000>;
++ interrupts = <GIC_SPI 194 IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&cpg CPG_MOD 821>;
++ power-domains = <&sysc R8A7795_PD_A3VC>;
++ };
++
++ imrlx4_ch3: imr-lx4@fe890000 {
++ compatible = "renesas,imr-lx4";
++ reg = <0 0xfe890000 0 0x2000>;
++ interrupts = <GIC_SPI 195 IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&cpg CPG_MOD 820>;
++ power-domains = <&sysc R8A7795_PD_A3VC>;
++ };
+ };
+ };
+diff --git a/arch/arm64/boot/dts/renesas/r8a7795.dtsi b/arch/arm64/boot/dts/renesas/r8a7795.dtsi
+index 82ebfd4..9b4ee2f 100644
+--- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi
++++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi
+@@ -2699,5 +2699,37 @@
+ };
+ };
+ };
++
++ imrlx4_ch0: imr-lx4@fe860000 {
++ compatible = "renesas,imr-lx4";
++ reg = <0 0xfe860000 0 0x2000>;
++ interrupts = <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&cpg CPG_MOD 823>;
++ power-domains = <&sysc R8A7795_PD_A3VC>;
++ };
++
++ imrlx4_ch1: imr-lx4@fe870000 {
++ compatible = "renesas,imr-lx4";
++ reg = <0 0xfe870000 0 0x2000>;
++ interrupts = <GIC_SPI 193 IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&cpg CPG_MOD 822>;
++ power-domains = <&sysc R8A7795_PD_A3VC>;
++ };
++
++ imrlx4_ch2: imr-lx4@fe880000 {
++ compatible = "renesas,imr-lx4";
++ reg = <0 0xfe880000 0 0x2000>;
++ interrupts = <GIC_SPI 194 IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&cpg CPG_MOD 821>;
++ power-domains = <&sysc R8A7795_PD_A3VC>;
++ };
++
++ imrlx4_ch3: imr-lx4@fe890000 {
++ compatible = "renesas,imr-lx4";
++ reg = <0 0xfe890000 0 0x2000>;
++ interrupts = <GIC_SPI 195 IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&cpg CPG_MOD 820>;
++ power-domains = <&sysc R8A7795_PD_A3VC>;
++ };
+ };
+ };
+diff --git a/drivers/clk/renesas/r8a7795-cpg-mssr.c b/drivers/clk/renesas/r8a7795-cpg-mssr.c
+index 718afd6..f833031 100644
+--- a/drivers/clk/renesas/r8a7795-cpg-mssr.c
++++ b/drivers/clk/renesas/r8a7795-cpg-mssr.c
+@@ -229,6 +229,10 @@ enum clk_ids {
+ DEF_MOD("vin0", 811, R8A7795_CLK_S0D2),
+ DEF_MOD("etheravb", 812, R8A7795_CLK_S0D6),
+ DEF_MOD("sata0", 815, R8A7795_CLK_S3D2),
++ DEF_MOD("imr3", 820, R8A7795_CLK_S2D1),
++ DEF_MOD("imr2", 821, R8A7795_CLK_S2D1),
++ DEF_MOD("imr1", 822, R8A7795_CLK_S2D1),
++ DEF_MOD("imr0", 823, R8A7795_CLK_S2D1),
+ DEF_MOD("gpio7", 905, R8A7795_CLK_CP),
+ DEF_MOD("gpio6", 906, R8A7795_CLK_CP),
+ DEF_MOD("gpio5", 907, R8A7795_CLK_CP),
+diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
+index ba2b892..f4d12f5 100644
+--- a/drivers/media/platform/Kconfig
++++ b/drivers/media/platform/Kconfig
+@@ -315,6 +315,17 @@ config VIDEO_RENESAS_FCP
+ To compile this driver as a module, choose M here: the module
+ will be called rcar-fcp.
+
++config VIDEO_RENESAS_IMR
++ tristate "Renesas Image Renderer (Distortion Correction) Unit"
++ depends on VIDEO_DEV && VIDEO_V4L2
++ select VIDEOBUF2_DMA_CONTIG
++ select V4L2_MEM2MEM_DEV
++ ---help---
++ This is a V4L2 driver for the Renesas IMR-X2/LX2/LX4 Processing Unit.
++
++ To compile this driver as a module, choose M here: the module
++ will be called rcar_imr.
++
+ config VIDEO_RENESAS_VSP1
+ tristate "Renesas VSP1 Video Processing Engine"
+ depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && HAS_DMA
+diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
+index 40b18d1..9e9464c 100644
+--- a/drivers/media/platform/Makefile
++++ b/drivers/media/platform/Makefile
+@@ -49,6 +49,7 @@ obj-$(CONFIG_SOC_CAMERA) += soc_camera/
+
+ obj-$(CONFIG_VIDEO_RENESAS_FCP) += rcar-fcp.o
+ obj-$(CONFIG_VIDEO_RENESAS_JPU) += rcar_jpu.o
++obj-$(CONFIG_VIDEO_RENESAS_IMR) += rcar_imr.o
+ obj-$(CONFIG_VIDEO_RENESAS_VSP1) += vsp1/
+
+ obj-y += omap/
+diff --git a/drivers/media/platform/rcar_imr.c b/drivers/media/platform/rcar_imr.c
+new file mode 100644
+index 0000000..30c6742
+--- /dev/null
++++ b/drivers/media/platform/rcar_imr.c
+@@ -0,0 +1,1840 @@
++/*
++ * rcar_imr.c -- R-Car IMR-LX4 Driver
++ *
++ * Copyright (C) 2015 Cogent Embedded, Inc. <source@cogentembedded.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/clk.h>
++#include <linux/interrupt.h>
++#include <linux/pm_runtime.h>
++#include <linux/delay.h>
++#include <linux/rcar-imr.h>
++#include <media/v4l2-device.h>
++#include <media/v4l2-ctrls.h>
++#include <media/v4l2-fh.h>
++#include <media/v4l2-mem2mem.h>
++#include <media/v4l2-ioctl.h>
++#include <media/videobuf2-dma-contig.h>
++
++#define DRV_NAME "rcar_imr"
++
++/*******************************************************************************
++ * Module parameters
++ ******************************************************************************/
++
++static int debug;
++module_param(debug, int, 0644);
++MODULE_PARM_DESC(debug, "Debug level (0-4)");
++
++/*******************************************************************************
++ * Local types definitions
++ ******************************************************************************/
++
++/* ...configuration data */
++struct imr_cfg {
++ /* ...display-list main program data */
++ void *dl_vaddr;
++ dma_addr_t dl_dma_addr;
++ u32 dl_size;
++ u32 dl_start_offset;
++
++ /* ...pointers to the source/destination planes */
++ u32 *src_pa_ptr[2];
++ u32 *dst_pa_ptr[2];
++
++ /* ...subpixel destination coordinates space */
++ int dst_subpixel;
++
++ /* ...reference counter */
++ u32 refcount;
++
++ /* ...identifier (for debug output) */
++ u32 id;
++};
++
++struct imr_buffer {
++ /* ...standard M2M buffer descriptor */
++ struct v4l2_m2m_buffer buf;
++
++ /* ...pointer to mesh configuration for processing */
++ struct imr_cfg *cfg;
++};
++
++struct imr_q_data {
++ /* ...latched pixel format */
++ struct v4l2_pix_format fmt;
++
++ /* ...current format flags */
++ u32 flags;
++};
++
++struct imr_format_info {
++ char *name;
++ u32 fourcc;
++ u32 flags;
++};
++
++/* ...per-device data */
++struct imr_device {
++ struct device *dev;
++ struct clk *clock;
++ void __iomem *mmio;
++ int irq;
++ struct mutex mutex;
++ spinlock_t lock;
++
++ struct v4l2_device v4l2_dev;
++ struct video_device video_dev;
++ struct v4l2_m2m_dev *m2m_dev;
++
++ /* ...do we need that counter really? framework counts fh structures for us - tbd */
++ int refcount;
++
++ /* ...should we include media-dev? likely, no - tbd */
++};
++
++/* ...per file-handle context */
++struct imr_ctx {
++ struct v4l2_fh fh;
++ struct imr_device *imr;
++ struct v4l2_m2m_ctx *m2m_ctx;
++ struct imr_q_data queue[2];
++
++ /* ...current job configuration */
++ struct imr_cfg *cfg;
++
++ /* ...frame sequence counter */
++ u32 sequence;
++
++ /* ...cropping parameters (in pixels) */
++ u16 crop[4];
++
++ /* ...number of active configurations (debugging) */
++ u32 cfg_num;
++};
++
++/*******************************************************************************
++ * IMR registers
++ ******************************************************************************/
++
++#define IMR_CR 0x08
++#define IMR_CR_RS (1 << 0)
++#define IMR_CR_SWRST (1 << 15)
++
++#define IMR_SR 0x0C
++#define IMR_SRCR 0x10
++#define IMR_SR_TRA (1 << 0)
++#define IMR_SR_IER (1 << 1)
++#define IMR_SR_INT (1 << 2)
++#define IMR_SR_REN (1 << 5)
++
++#define IMR_ICR 0x14
++#define IMR_IMR 0x18
++#define IMR_ICR_TRAEN (1 << 0)
++#define IMR_ICR_IEREN (1 << 1)
++#define IMR_ICR_INTEN (1 << 2)
++
++#define IMR_DLSP 0x1C
++#define IMR_DLSR 0x20
++#define IMR_DLSAR 0x30
++
++#define IMR_DSAR 0x34
++#define IMR_SSAR 0x38
++#define IMR_DSTR 0x3C
++#define IMR_SSTR 0x40
++#define IMR_DSOR 0x50
++
++#define IMR_CMRCR 0x54
++#define IMR_CMRCSR 0x58
++#define IMR_CMRCCR 0x5C
++#define IMR_CMR_LUCE (1 << 1)
++#define IMR_CMR_CLCE (1 << 2)
++#define IMR_CMR_DUV_SHIFT 3
++#define IMR_CMR_DUV_MASK (3 << IMR_CMR_DUV_SHIFT)
++#define IMR_CMR_SUV_SHIFT 5
++#define IMR_CMR_SUV_MASK (3 << IMR_CMR_SUV_SHIFT)
++#define IMR_CMR_YISM (1 << 7)
++#define IMR_CMR_DY10 (1 << 8)
++#define IMR_CMR_DY12 (1 << 9)
++#define IMR_CMR_SY10 (1 << 11)
++#define IMR_CMR_SY12 (1 << 12)
++#define IMR_CMR_YCM (1 << 14)
++#define IMR_CMR_CP16E (1 << 15)
++
++#define IMR_CMRCR2 0xE4
++#define IMR_CMRCSR2 0xE8
++#define IMR_CMRCCR2 0xEC
++#define IMR_CMR2_LUTE (1 << 0)
++#define IMR_CMR2_YUV422E (1 << 2)
++#define IMR_CMR2_YUV422FORM (1 << 5)
++#define IMR_CMR2_UVFORM (1 << 6)
++#define IMR_CMR2_TCTE (1 << 12)
++#define IMR_CMR2_DCTE (1 << 15)
++
++#define IMR_TRIMR 0x60
++#define IMR_TRIMSR 0x64
++#define IMR_TRIMCR 0x68
++#define IMR_TRIM_TME (1 << 0)
++#define IMR_TRIM_BFE (1 << 1)
++#define IMR_TRIM_AUTODG (1 << 2)
++#define IMR_TRIM_AUTOSG (1 << 3)
++#define IMR_TRIM_DYDXM (1 << 4)
++#define IMR_TRIM_DUDVM (1 << 5)
++#define IMR_TRIM_TCM (1 << 6)
++
++#define IMR_TRICR 0x6C
++#define IMR_TRIC_YCFORM (1 << 31)
++
++#define IMR_UVDPOR 0x70
++#define IMR_SUSR 0x74
++#define IMR_SVSR 0x78
++
++#define IMR_XMINR 0x80
++#define IMR_YMINR 0x84
++#define IMR_XMAXR 0x88
++#define IMR_YMAXR 0x8C
++
++#define IMR_AMXSR 0x90
++#define IMR_AMYSR 0x94
++#define IMR_AMXOR 0x98
++#define IMR_AMYOR 0x9C
++
++#define IMR_CPDPOR 0xD0
++#define IMR_CPDP_YLDPO_SHIFT 8
++#define IMR_CPDP_UBDPO_SHIFT 4
++#define IMR_CPDP_VRDPO_SHIFT 0
++
++/*******************************************************************************
++ * Auxiliary helpers
++ ******************************************************************************/
++
++static inline struct imr_ctx * fh_to_ctx(struct v4l2_fh *fh)
++{
++ return container_of(fh, struct imr_ctx, fh);
++}
++
++static inline struct imr_buffer * to_imr_buffer(struct vb2_v4l2_buffer *vbuf)
++{
++ struct v4l2_m2m_buffer *b = container_of(vbuf, struct v4l2_m2m_buffer, vb);
++
++ return container_of(b, struct imr_buffer, buf);
++}
++
++/*******************************************************************************
++ * Local constants definition
++ ******************************************************************************/
++
++#define IMR_F_Y8 (1 << 0)
++#define IMR_F_Y10 (1 << 1)
++#define IMR_F_Y12 (1 << 2)
++#define IMR_F_UV8 (1 << 3)
++#define IMR_F_UV10 (1 << 4)
++#define IMR_F_UV12 (1 << 5)
++#define IMR_F_PLANAR (1 << 6)
++#define IMR_F_INTERLEAVED (1 << 7)
++#define IMR_F_PLANES_MASK ((1 << 8) - 1)
++#define IMR_F_UV_SWAP (1 << 8)
++#define IMR_F_YUV_SWAP (1 << 9)
++
++/* ...get common planes bits */
++static inline u32 __imr_flags_common(u32 iflags, u32 oflags)
++{
++ return (iflags & oflags) & IMR_F_PLANES_MASK;
++}
++
++static const struct imr_format_info imr_lx4_formats[] = {
++ {
++ .name = "YUV 4:2:2 semiplanar (NV16)",
++ .fourcc = V4L2_PIX_FMT_NV16,
++ .flags = IMR_F_Y8 | IMR_F_UV8 | IMR_F_PLANAR,
++ },
++ {
++ .name = "YVU 4:2:2 semiplanar (NV61)",
++ .fourcc = V4L2_PIX_FMT_NV61,
++ .flags = IMR_F_Y8 | IMR_F_UV8 | IMR_F_PLANAR | IMR_F_UV_SWAP,
++ },
++ {
++ .name = "YUV 4:2:2 interleaved (YUYV)",
++ .fourcc = V4L2_PIX_FMT_YUYV,
++ .flags = IMR_F_Y8 | IMR_F_UV8,
++ },
++ {
++ .name = "YUV 4:2:2 interleaved (UYVY)",
++ .fourcc = V4L2_PIX_FMT_UYVY,
++ .flags = IMR_F_Y8 | IMR_F_UV8 | IMR_F_YUV_SWAP,
++ },
++ {
++ .name = "YUV 4:2:2 interleaved (YVYU)",
++ .fourcc = V4L2_PIX_FMT_YVYU,
++ .flags = IMR_F_Y8 | IMR_F_UV8 | IMR_F_UV_SWAP,
++ },
++ {
++ .name = "YUV 4:2:2 interleaved (UYVY)",
++ .fourcc = V4L2_PIX_FMT_VYUY,
++ .flags = IMR_F_Y8 | IMR_F_UV8 | IMR_F_UV_SWAP | IMR_F_YUV_SWAP,
++ },
++ {
++ .name = "Greyscale 8-bit",
++ .fourcc = V4L2_PIX_FMT_GREY,
++ .flags = IMR_F_Y8 | IMR_F_PLANAR,
++ },
++ {
++ .name = "Greyscale 10-bit",
++ .fourcc = V4L2_PIX_FMT_Y10,
++ .flags = IMR_F_Y8 | IMR_F_Y10 | IMR_F_PLANAR,
++ },
++ {
++ .name = "Greyscale 12-bit",
++ .fourcc = V4L2_PIX_FMT_Y12,
++ .flags = IMR_F_Y8 | IMR_F_Y10 | IMR_F_Y12 | IMR_F_PLANAR,
++ },
++ {
++ .name = "Chrominance UV 8-bit",
++ .fourcc = V4L2_PIX_FMT_UV8,
++ .flags = IMR_F_UV8 | IMR_F_PLANAR,
++ },
++};
++
++/* ...mesh configuration constructor */
++static struct imr_cfg * imr_cfg_create(struct imr_ctx *ctx, u32 dl_size, u32 dl_start)
++{
++ struct imr_device *imr = ctx->imr;
++ struct imr_cfg *cfg;
++
++ /* ...allocate configuration descriptor */
++ cfg = kmalloc(sizeof(*cfg), GFP_KERNEL);
++ if (!cfg) {
++ v4l2_err(&imr->v4l2_dev, "failed to allocate configuration descriptor\n");
++ return ERR_PTR(-ENOMEM);
++ }
++
++ /* ...allocate contiguous memory for a display list */
++ cfg->dl_vaddr = dma_alloc_writecombine(imr->dev, dl_size, &cfg->dl_dma_addr, GFP_KERNEL);
++ if (!cfg->dl_vaddr) {
++ v4l2_err(&imr->v4l2_dev, "failed to allocate %u bytes for a DL\n", dl_size);
++ kfree(cfg);
++ return ERR_PTR(-ENOMEM);
++ }
++
++ cfg->dl_size = dl_size;
++ cfg->dl_start_offset = dl_start;
++ cfg->refcount = 1;
++ cfg->id = ctx->sequence;
++
++ /* ...for debugging purposes, advance number of active configurations */
++ ctx->cfg_num++;
++
++ return cfg;
++}
++
++/* ...add reference to the current configuration */
++static inline struct imr_cfg * imr_cfg_ref(struct imr_ctx *ctx)
++{
++ struct imr_cfg *cfg = ctx->cfg;
++
++ BUG_ON(!cfg);
++ cfg->refcount++;
++ return cfg;
++}
++
++/* ...mesh configuration destructor */
++static void imr_cfg_unref(struct imr_ctx *ctx, struct imr_cfg *cfg)
++{
++ struct imr_device *imr = ctx->imr;
++
++ /* ...no atomicity is required as operation is locked with device mutex */
++ if (!cfg || --cfg->refcount)
++ return;
++
++ /* ...release memory allocated for a display list */
++ if (cfg->dl_vaddr)
++ dma_free_writecombine(imr->dev, cfg->dl_size, cfg->dl_vaddr, cfg->dl_dma_addr);
++
++ /* ...destroy the configuration structure */
++ kfree(cfg);
++
++ /* ...decrement number of active configurations (debugging) */
++ WARN_ON(!ctx->cfg_num--);
++}
++
++
++
++/*******************************************************************************
++ * Context processing queue
++ ******************************************************************************/
++
++static int imr_queue_setup(struct vb2_queue *vq,
++ unsigned int *nbuffers, unsigned int *nplanes,
++ unsigned int sizes[], struct device *alloc_devs[])
++{
++ struct imr_ctx *ctx = vb2_get_drv_priv(vq);
++ struct imr_q_data *q_data = &ctx->queue[V4L2_TYPE_IS_OUTPUT(vq->type) ? 0 : 1];
++ int w = q_data->fmt.width;
++ int h = q_data->fmt.height;
++
++ /* ...we use only single-plane formats */
++ *nplanes = 1;
++
++ /* ...specify plane size */
++ switch (q_data->fmt.pixelformat) {
++ case V4L2_PIX_FMT_UYVY:
++ case V4L2_PIX_FMT_YUYV:
++ case V4L2_PIX_FMT_VYUY:
++ case V4L2_PIX_FMT_YVYU:
++ case V4L2_PIX_FMT_NV16:
++ case V4L2_PIX_FMT_Y10:
++ case V4L2_PIX_FMT_Y16:
++ sizes[0] = w * h * 2;
++ break;
++
++ case V4L2_PIX_FMT_UV8:
++ case V4L2_PIX_FMT_GREY:
++ sizes[0] = w * h;
++ break;
++
++ default:
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++static int imr_buf_prepare(struct vb2_buffer *vb)
++{
++ /* ...unclear yet if we want to prepare a buffer somehow (cache invalidation? - tbd) */
++ return 0;
++}
++
++static void imr_buf_queue(struct vb2_buffer *vb)
++{
++ struct vb2_queue *q = vb->vb2_queue;
++ struct imr_ctx *ctx = vb2_get_drv_priv(q);
++ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
++
++ WARN_ON_ONCE(!mutex_is_locked(&ctx->imr->mutex));
++
++ v4l2_dbg(3, debug, &ctx->imr->v4l2_dev, "%sput buffer <0x%08llx> submitted\n",
++ q->is_output ? "in" : "out",
++ vb2_dma_contig_plane_dma_addr(vb, 0));
++
++ /* ...for input buffer, put current configuration pointer (add reference) */
++ if (q->is_output)
++ to_imr_buffer(vbuf)->cfg = imr_cfg_ref(ctx);
++
++ v4l2_m2m_buf_queue(ctx->m2m_ctx, vbuf);
++}
++
++static void imr_buf_finish(struct vb2_buffer *vb)
++{
++ struct vb2_queue *q = vb->vb2_queue;
++ struct imr_ctx *ctx = vb2_get_drv_priv(q);
++ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
++
++ WARN_ON(!mutex_is_locked(&ctx->imr->mutex));
++
++ /* ...any special processing of completed buffer? - tbd */
++ v4l2_dbg(3, debug, &ctx->imr->v4l2_dev, "%sput buffer <0x%08llx> done\n",
++ q->is_output ? "in" : "out",
++ vb2_dma_contig_plane_dma_addr(vb, 0));
++
++ /* ...unref configuration pointer as needed */
++ if (q->is_output)
++ imr_cfg_unref(ctx, to_imr_buffer(vbuf)->cfg);
++}
++
++static int imr_start_streaming(struct vb2_queue *vq, unsigned int count)
++{
++ struct imr_ctx *ctx = vb2_get_drv_priv(vq);
++ int ret;
++
++ ret = 0;//pm_runtime_get_sync(ctx->imr->dev);
++ if (ret < 0) {
++ v4l2_err(&ctx->imr->v4l2_dev, "failed to start %s streaming: %d\n",
++ (V4L2_TYPE_IS_OUTPUT(vq->type) ? "output" : "capture"), ret);
++ return ret;
++ } else {
++ v4l2_dbg(1, debug, &ctx->imr->v4l2_dev, "%s streaming started\n",
++ (V4L2_TYPE_IS_OUTPUT(vq->type) ? "output" : "capture"));
++ return 0;
++ }
++}
++
++static void imr_stop_streaming(struct vb2_queue *vq)
++{
++ struct imr_ctx *ctx = vb2_get_drv_priv(vq);
++ struct vb2_v4l2_buffer *vb;
++ unsigned long flags;
++
++ spin_lock_irqsave(&ctx->imr->lock, flags);
++
++ /* ...purge all buffers from a queue */
++ if (V4L2_TYPE_IS_OUTPUT(vq->type)) {
++ while ((vb = v4l2_m2m_src_buf_remove(ctx->m2m_ctx)) != NULL)
++ v4l2_m2m_buf_done(vb, VB2_BUF_STATE_ERROR);
++ } else {
++ while ((vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx)) != NULL)
++ v4l2_m2m_buf_done(vb, VB2_BUF_STATE_ERROR);
++ }
++
++ spin_unlock_irqrestore(&ctx->imr->lock, flags);
++
++ v4l2_dbg(1, debug, &ctx->imr->v4l2_dev, "%s streaming stopped\n",
++ (V4L2_TYPE_IS_OUTPUT(vq->type) ? "output" : "capture"));
++
++ //pm_runtime_put(ctx->imr->dev);
++}
++
++/* ...buffer queue operations */
++static struct vb2_ops imr_qops = {
++ .queue_setup = imr_queue_setup,
++ .buf_prepare = imr_buf_prepare,
++ .buf_queue = imr_buf_queue,
++ .buf_finish = imr_buf_finish,
++ .start_streaming = imr_start_streaming,
++ .stop_streaming = imr_stop_streaming,
++ .wait_prepare = vb2_ops_wait_prepare,
++ .wait_finish = vb2_ops_wait_finish,
++};
++
++/* ...M2M device processing queue initialization */
++static int imr_queue_init(void *priv, struct vb2_queue *src_vq,
++ struct vb2_queue *dst_vq)
++{
++ struct imr_ctx *ctx = priv;
++ int ret;
++
++ memset(src_vq, 0, sizeof(*src_vq));
++ src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
++ src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
++ src_vq->drv_priv = ctx;
++ src_vq->buf_struct_size = sizeof(struct imr_buffer);
++ src_vq->ops = &imr_qops;
++ src_vq->mem_ops = &vb2_dma_contig_memops;
++ src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
++ src_vq->lock = &ctx->imr->mutex;
++ src_vq->dev = ctx->imr->v4l2_dev.dev;
++ ret = vb2_queue_init(src_vq);
++ if (ret)
++ return ret;
++
++ memset(dst_vq, 0, sizeof(*dst_vq));
++ dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++ dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
++ dst_vq->drv_priv = ctx;
++ dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
++ dst_vq->ops = &imr_qops;
++ dst_vq->mem_ops = &vb2_dma_contig_memops;
++ dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
++ dst_vq->lock = &ctx->imr->mutex;
++ ret = vb2_queue_init(dst_vq);
++ if (ret)
++ return ret;
++
++ return 0;
++}
++
++/*******************************************************************************
++ * Display list commands
++ ******************************************************************************/
++
++/* ...display list opcodes */
++#define IMR_OP_TRI(n) ((0x8A << 24) | ((n) & 0xFFFF))
++#define IMR_OP_LINE(n) ((0x8B << 24) | ((n) & 0xFFFF))
++#define IMR_OP_NOP(n) ((0x80 << 24) | ((n) & 0xFFFF))
++#define IMR_OP_TRAP ((0x8F << 24))
++#define IMR_OP_WTL(add, n) ((0x81 << 24) | (((add) / 4) << 16) | ((n) & 0xFFFF))
++#define IMR_OP_WTS(add, data) ((0x82 << 24) | (((add) / 4) << 16) | ((data) & 0xFFFF))
++#define IMR_OP_WTL2(add, n) ((0x83 << 24) | (((add) / 4) << 10) | ((n) & 0x3FF))
++#define IMR_OP_INT ((0x88 << 24))
++#define IMR_OP_SYNCM ((0x86 << 24))
++#define IMR_OP_GOSUB ((0x8C << 24))
++#define IMR_OP_RET ((0x8D << 24))
++
++/*******************************************************************************
++ * Operation type decoding helpers
++ ******************************************************************************/
++
++static inline u16 __imr_auto_sg_dg_tcm(u32 type)
++{
++ return (type & IMR_MAP_AUTOSG ? IMR_TRIM_AUTOSG : (type & IMR_MAP_AUTODG ? IMR_TRIM_AUTODG : 0)) |
++ (type & IMR_MAP_TCM ? IMR_TRIM_TCM : 0);
++}
++
++static inline u16 __imr_uvdp(u32 type)
++{
++ return __IMR_MAP_UVDPOR(type) | (type & IMR_MAP_DDP ? (1 << 8) : 0);
++}
++
++static inline u16 __imr_cpdp(u32 type)
++{
++ return (__IMR_MAP_YLDPO(type) << 8) | (__IMR_MAP_UBDPO(type) << 4) | __IMR_MAP_VRDPO(type);
++}
++
++static inline u16 __imr_luce(u32 type)
++{
++ return (type & IMR_MAP_LUCE ? IMR_CMR_LUCE : 0);
++}
++
++static inline u16 __imr_clce(u32 type)
++{
++ return (type & IMR_MAP_CLCE ? IMR_CMR_CLCE : 0);
++}
++
++/*******************************************************************************
++ * Type A (absolute coordinates of source/destination) mapping
++ ******************************************************************************/
++
++/* ...return size of the subroutine for type "a" mapping */
++static inline u32 imr_tri_type_a_get_length(struct imr_mesh *mesh, int item_size)
++{
++ return ((mesh->columns * (item_size / 2) + 1) * (mesh->rows - 1) + 1) * sizeof(u32);
++}
++
++/* ...set a mesh rows * columns using absolute coordinates */
++static inline u32 * imr_tri_set_type_a(u32 *dl, void *map, struct imr_mesh *mesh, int item_size)
++{
++ int rows = mesh->rows;
++ int columns = mesh->columns;
++ u32 stride = item_size * columns;
++ int i, j;
++
++ /* ...convert lattice into set of stripes */
++ for (i = 0; i < rows - 1; i++) {
++ *dl++ = IMR_OP_TRI(columns * 2);
++ for (j = 0; j < columns; j++) {
++ memcpy((void *)dl, map, item_size);
++ memcpy((void *)dl + item_size, map + stride, item_size);
++ dl += item_size / 2;
++ map += item_size;
++ }
++ }
++
++ *dl++ = IMR_OP_RET;
++ return dl;
++}
++
++/*******************************************************************************
++ * Type B mapping (automatically generated source or destination coordinates)
++ ******************************************************************************/
++
++/* ...calculate length of a type "b" mapping */
++static inline u32 imr_tri_type_b_get_length(struct imr_mesh *mesh, int item_size)
++{
++ return ((mesh->columns * (item_size / 2) + 2) * (mesh->rows - 1) + 4) * sizeof(u32);
++}
++
++/* ...set an auto-generated mesh n * m for a source/destination */
++static inline u32 * imr_tri_set_type_b(u32 *dl, void *map, struct imr_mesh *mesh, int item_size)
++{
++ int rows = mesh->rows;
++ int columns = mesh->columns;
++ int x0 = mesh->x0;
++ int y0 = mesh->y0;
++ int dx = mesh->dx;
++ int dy = mesh->dy;
++ int stride = item_size * columns;
++ int i, j;
++
++ /* ...set mesh configuration */
++ *dl++ = IMR_OP_WTS(IMR_AMXSR, dx);
++ *dl++ = IMR_OP_WTS(IMR_AMYSR, dy);
++
++ /* ...origin by "x" coordinate is the same across all rows */
++ *dl++ = IMR_OP_WTS(IMR_AMXOR, x0);
++
++ /* ...convert lattice into set of stripes */
++ for (i = 0; i < rows - 1; i++, y0 += dy) {
++ /* ...set origin by "y" coordinate for a current row */
++ *dl++ = IMR_OP_WTS(IMR_AMYOR, y0);
++ *dl++ = IMR_OP_TRI(2 * columns);
++
++ /* ...fill single row */
++ for (j = 0; j < columns; j++) {
++ memcpy((void *)dl, map, item_size);
++ memcpy((void *)dl + item_size, map + stride, item_size);
++ dl += item_size / 2;
++ map += item_size;
++ }
++ }
++
++ *dl++ = IMR_OP_RET;
++ return dl;
++}
++
++/*******************************************************************************
++ * Type C mapping (vertex-buffer-object)
++ ******************************************************************************/
++
++/* ...calculate length of a type "c" mapping */
++static inline u32 imr_tri_type_c_get_length(struct imr_vbo *vbo, int item_size)
++{
++ return ((4 + 3 * item_size) * vbo->num + 4);
++}
++
++/* ...set a VBO mapping using absolute coordinates */
++static inline u32 * imr_tri_set_type_c(u32 *dl, void *map, struct imr_vbo *vbo, int item_size)
++{
++ int num = vbo->num;
++ int i;
++
++ /* ...prepare list of triangles to draw */
++ for (i = 0; i < num; i++) {
++ *dl++ = IMR_OP_TRI(3);
++ memcpy((void *)dl, map, 3 * item_size);
++ dl += 3 * item_size / 4;
++ map += 3 * item_size;
++ }
++
++ *dl++ = IMR_OP_RET;
++ return dl;
++}
++
++/*******************************************************************************
++ * DL program creation
++ ******************************************************************************/
++
++/* ...return length of a DL main program */
++static inline u32 imr_dl_program_length(struct imr_ctx *ctx)
++{
++ u32 iflags = ctx->queue[0].flags;
++ u32 oflags = ctx->queue[1].flags;
++ u32 cflags = __imr_flags_common(iflags, oflags);
++
++ /* ...check if formats are compatible */
++ if (((iflags & IMR_F_PLANAR) != 0 && (oflags & IMR_F_PLANAR) == 0) || (cflags == 0)) {
++ v4l2_err(&ctx->imr->v4l2_dev, "formats are incompatible: if=%x, of=%x, cf=%x\n", iflags, oflags, cflags);
++ return 0;
++ }
++
++ /* ...maximal possible length of the program is 27 32-bits words; round up to 32 */
++ return 32 << 2;
++}
++
++/* ...setup DL for Y/YUV planar/interleaved processing */
++static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg, u32 type, u32 *dl, u32 subaddr)
++{
++ u32 iflags = ctx->queue[0].flags;
++ u32 oflags = ctx->queue[1].flags;
++ u32 cflags = __imr_flags_common(iflags, oflags);
++ u16 src_y_fmt = (iflags & IMR_F_Y12 ? IMR_CMR_SY12 : (iflags & IMR_F_Y10 ? IMR_CMR_SY10 : 0));
++ u16 src_uv_fmt = (iflags & IMR_F_UV12 ? 2 : (iflags & IMR_F_UV10 ? 1 : 0)) << IMR_CMR_SUV_SHIFT;
++ u16 dst_y_fmt = (cflags & IMR_F_Y12 ? IMR_CMR_DY12 : (cflags & IMR_F_Y10 ? IMR_CMR_DY10 : 0));
++ u16 dst_uv_fmt = (cflags & IMR_F_UV12 ? 2 : (cflags & IMR_F_UV10 ? 1 : 0)) << IMR_CMR_DUV_SHIFT;
++ int w = ctx->queue[0].fmt.width;
++ int h = ctx->queue[0].fmt.height;
++ int W = ctx->queue[1].fmt.width;
++ int H = ctx->queue[1].fmt.height;
++
++ v4l2_dbg(2, debug, &ctx->imr->v4l2_dev, "setup %u*%u -> %u*%u mapping (type=%x)\n", w, h, W, H, type);
++
++ /* ...set triangle mode register from user-supplied descriptor */
++ *dl++ = IMR_OP_WTS(IMR_TRIMCR, 0xFFFF);
++
++ /* ...set automatic source / destination coordinates generation flags */
++ *dl++ = IMR_OP_WTS(IMR_TRIMSR, __imr_auto_sg_dg_tcm(type) | IMR_TRIM_BFE | IMR_TRIM_TME);
++
++ /* ...set source / destination coordinate precision */
++ *dl++ = IMR_OP_WTS(IMR_UVDPOR, __imr_uvdp(type));
++
++ /* ...set luminance/chromacity correction parameters precision */
++ *dl++ = IMR_OP_WTS(IMR_CPDPOR, __imr_cpdp(type));
++
++ /* ...reset rendering mode registers */
++ *dl++ = IMR_OP_WTS(IMR_CMRCCR, 0xFFFF);
++ *dl++ = IMR_OP_WTS(IMR_CMRCCR2, 0xFFFF);
++
++ /* ...set source/destination addresses of Y/UV plane */
++ *dl++ = IMR_OP_WTL(IMR_DSAR, 2);
++ cfg->dst_pa_ptr[0] = dl++;
++ cfg->src_pa_ptr[0] = dl++;
++
++ /* ...select planar/interleaved mode basing on input format */
++ if (iflags & IMR_F_PLANAR) {
++ /* ...planar input means planar output; set Y-plane precision */
++ if (cflags & IMR_F_Y8) {
++ /* ...setup Y-plane processing: YCM=0, SY/DY=xx, SUV/DUV=0 */
++ *dl++ = IMR_OP_WTS(IMR_CMRCSR, src_y_fmt | src_uv_fmt | dst_y_fmt | dst_uv_fmt | __imr_luce(type));
++
++ /* ...set source/destination strides basing on Y-plane precision */
++ *dl++ = IMR_OP_WTS(IMR_DSTR, W << (cflags & IMR_F_Y10 ? 1 : 0));
++ *dl++ = IMR_OP_WTS(IMR_SSTR, w << (iflags & IMR_F_Y10 ? 1 : 0));
++ } else {
++ /* ...setup UV-plane processing only */
++ *dl++ = IMR_OP_WTS(IMR_CMRCSR, IMR_CMR_YCM | src_uv_fmt | dst_uv_fmt | __imr_clce(type));
++
++ /* ...set source/destination strides basing on UV-plane precision */
++ *dl++ = IMR_OP_WTS(IMR_DSTR, W << (cflags & IMR_F_UV10 ? 1 : 0));
++ *dl++ = IMR_OP_WTS(IMR_SSTR, w << (iflags & IMR_F_UV10 ? 1 : 0));
++ }
++ } else {
++ u16 src_fmt = (iflags & IMR_F_UV_SWAP ? IMR_CMR2_UVFORM : 0) | (iflags & IMR_F_YUV_SWAP ? IMR_CMR2_YUV422FORM : 0);
++ u32 dst_fmt = (oflags & IMR_F_YUV_SWAP ? IMR_TRIC_YCFORM : 0);
++
++ /* ...interleaved input; output is either interleaved or planar */
++ *dl++ = IMR_OP_WTS(IMR_CMRCSR2, IMR_CMR2_YUV422E | src_fmt);
++
++ /* ...destination is always YUYV or UYVY */
++ *dl++ = IMR_OP_WTL(IMR_TRICR, 1);
++ *dl++ = dst_fmt;
++
++ /* ...set precision of Y/UV planes and required correction */
++ *dl++ = IMR_OP_WTS(IMR_CMRCSR, src_y_fmt | src_uv_fmt | dst_y_fmt | dst_uv_fmt | __imr_clce(type) | __imr_luce(type));
++
++ /* ...set source stride basing on precision (2 or 4 bytes/pixel) */
++ *dl++ = IMR_OP_WTS(IMR_SSTR, w << (iflags & IMR_F_Y10 ? 2 : 1));
++
++ /* ...if output is planar, put the offset value */
++ if (oflags & IMR_F_PLANAR) {
++ /* ...specify offset of a destination UV plane */
++ *dl++ = IMR_OP_WTL(IMR_DSOR, 1);
++ *dl++ = W * H;
++
++ /* ...destination stride is 1 or 2 bytes/pixel (same for both Y and UV planes) */
++ *dl++ = IMR_OP_WTS(IMR_DSTR, W << (cflags & IMR_F_Y10 ? 1 : 0));
++ } else {
++ /* ...destination stride if 2 or 4 bytes/pixel (Y and UV planes interleaved) */
++ *dl++ = IMR_OP_WTS(IMR_DSTR, W << (cflags & IMR_F_Y10 ? 2 : 1));
++ }
++ }
++
++ /* ...set source width/height of Y/UV plane (for Y plane upper part of SUSR is ignored) */
++ *dl++ = IMR_OP_WTL(IMR_SUSR, 2);
++ *dl++ = ((w - 2) << 16) | (w - 1);
++ *dl++ = h - 1;
++
++ /* ...invoke subroutine for triangles drawing */
++ *dl++ = IMR_OP_GOSUB;
++ *dl++ = subaddr;
++
++ /* ...if we have a planar output with both Y and UV planes available */
++ if ((cflags & (IMR_F_PLANAR | IMR_F_Y8 | IMR_F_UV8)) == (IMR_F_PLANAR | IMR_F_Y8 | IMR_F_UV8)) {
++ /* ...select UV-plane processing mode; put sync before switching */
++ *dl++ = IMR_OP_SYNCM;
++
++ /* ...setup UV-plane source/destination addresses */
++ *dl++ = IMR_OP_WTL(IMR_DSAR, 2);
++ cfg->dst_pa_ptr[1] = dl++;
++ cfg->src_pa_ptr[1] = dl++;
++
++ /* ...select correction mode */
++ *dl++ = IMR_OP_WTS(IMR_CMRCSR, IMR_CMR_YCM | __imr_clce(type));
++
++ /* ...luminance correction bit must be cleared (if it was set) */
++ *dl++ = IMR_OP_WTS(IMR_CMRCCR, IMR_CMR_LUCE);
++
++ /* ...draw triangles */
++ *dl++ = IMR_OP_GOSUB;
++ *dl++ = subaddr;
++ } else {
++ /* ...clear pointers to the source/destination UV-planes addresses */
++ cfg->src_pa_ptr[1] = cfg->dst_pa_ptr[1] = NULL;
++ }
++
++ /* ...signal completion of the operation */
++ *dl++ = IMR_OP_SYNCM;
++ *dl++ = IMR_OP_TRAP;
++}
++
++/*******************************************************************************
++ * Mapping specification processing
++ ******************************************************************************/
++
++/* ...set mapping data (function called with video device lock held) */
++static int imr_ioctl_map(struct imr_ctx *ctx, struct imr_map_desc *desc)
++{
++ struct imr_device *imr = ctx->imr;
++ struct imr_mesh *mesh;
++ struct imr_vbo *vbo;
++ struct imr_cfg *cfg;
++ void *buf, *map;
++ u32 type;
++ u32 length, item_size;
++ u32 tri_length;
++ void *dl_vaddr;
++ u32 dl_size;
++ u32 dl_start_offset;
++ dma_addr_t dl_dma_addr;
++ int ret;
++
++ /* ...read remainder of data into temporary buffer */
++ length = desc->size;
++ buf = kmalloc(length, GFP_KERNEL);
++ if (!buf) {
++ v4l2_err(&imr->v4l2_dev, "failed to allocate %u bytes for mapping reading\n", length);
++ return -ENOMEM;
++ }
++
++ /* ...copy mesh data */
++ if (copy_from_user(buf, (void __user *)desc->data, length)) {
++ v4l2_err(&imr->v4l2_dev, "failed to read %u bytes of mapping specification\n", length);
++ ret = -EFAULT;
++ goto out;
++ }
++
++ type = desc->type;
++
++ /* ...mesh item size calculation */
++ item_size = (type & IMR_MAP_LUCE ? 4 : 0) + (type & IMR_MAP_CLCE ? 4 : 0);
++
++ /* ...calculate the length of a display list */
++ if (type & IMR_MAP_MESH) {
++ /* ...assure we have proper mesh descriptor */
++ if (length < sizeof(struct imr_mesh)) {
++ v4l2_err(&imr->v4l2_dev, "invalid mesh specification size: %u\n", length);
++ ret = -EINVAL;
++ goto out;
++ }
++
++ mesh = (struct imr_mesh *)buf;
++ length -= sizeof(struct imr_mesh);
++ map = buf + sizeof(struct imr_mesh);
++
++ if (type & (IMR_MAP_AUTODG | IMR_MAP_AUTOSG)) {
++ /* ...source / destination vertex size is 4 bytes */
++ item_size += 4;
++
++ /* ...mapping is given using automatic generation pattern; check size */
++ if (mesh->rows * mesh->columns * item_size != length) {
++ v4l2_err(&imr->v4l2_dev, "invalid mesh size: %u*%u*%u != %u\n", mesh->rows, mesh->columns, item_size, length);
++ ret = -EINVAL;
++ goto out;
++ }
++
++ /* ...calculate size of triangles drawing subroutine */
++ tri_length = imr_tri_type_b_get_length(mesh, item_size);
++ } else {
++ /* ...source / destination vertes size if 8 bytes */
++ item_size += 8;
++
++ /* ...mapping is done with absolute coordinates */
++ if (mesh->rows * mesh->columns * item_size != length) {
++ v4l2_err(&imr->v4l2_dev, "invalid mesh size: %u*%u*%u != %u\n", mesh->rows, mesh->columns, item_size, length);
++ ret = -EINVAL;
++ goto out;
++ }
++
++ /* ...calculate size of triangles drawing subroutine */
++ tri_length = imr_tri_type_a_get_length(mesh, item_size);
++ }
++ } else {
++ /* ...assure we have proper VBO descriptor */
++ if (length < sizeof(struct imr_vbo)) {
++ v4l2_err(&imr->v4l2_dev, "invalid vbo specification size: %u\n", length);
++ ret = -EINVAL;
++ goto out;
++ }
++
++ /* ...make sure there is no automatic-generation flags */
++ if (type & (IMR_MAP_AUTODG | IMR_MAP_AUTOSG)) {
++ v4l2_err(&imr->v4l2_dev, "invalid auto-dg/sg flags: 0x%x\n", type);
++ ret = -EINVAL;
++ goto out;
++ }
++
++ vbo = (struct imr_vbo *)buf;
++ length -= sizeof(struct imr_vbo);
++ map = buf + sizeof(struct imr_vbo);
++
++ /* ...vertex is given with absolute coordinates */
++ item_size += 8;
++
++ /* ...check the length is sane */
++ if (length != vbo->num * 3 * item_size) {
++ v4l2_err(&imr->v4l2_dev, "invalid vbo size: %u*%u*3 != %u\n", vbo->num, item_size, length);
++ ret = -EINVAL;
++ goto out;
++ }
++
++ /* ...calculate size of trangles drawing subroutine */
++ tri_length = imr_tri_type_c_get_length(vbo, item_size);
++ }
++
++ /* ...DL main program shall start with 8-byte aligned address */
++ dl_start_offset = (tri_length + 7) & ~7;
++
++ /* ...calculate main routine length */
++ dl_size = imr_dl_program_length(ctx);
++ if (!dl_size) {
++ v4l2_err(&imr->v4l2_dev, "format configuration error\n");
++ ret = -EINVAL;
++ goto out;
++ }
++
++ /* ...we use a single display list, with TRI subroutine prepending MAIN */
++ dl_size += dl_start_offset;
++
++ /* ...unref current configuration (will not be used by subsequent jobs) */
++ imr_cfg_unref(ctx, ctx->cfg);
++
++ /* ...create new configuration */
++ ctx->cfg = cfg = imr_cfg_create(ctx, dl_size, dl_start_offset);
++ if (IS_ERR(cfg)) {
++ ret = PTR_ERR(cfg);
++ v4l2_err(&imr->v4l2_dev, "failed to create configuration: %d\n", ret);
++ goto out;
++ }
++
++ /* ...get pointer to the new display list */
++ dl_vaddr = cfg->dl_vaddr;
++ dl_dma_addr = cfg->dl_dma_addr;
++
++ /* ...prepare a triangles drawing subroutine */
++ if (type & IMR_MAP_MESH) {
++ if (type & (IMR_MAP_AUTOSG | IMR_MAP_AUTODG)) {
++ imr_tri_set_type_b(dl_vaddr, map, mesh, item_size);
++ } else {
++ imr_tri_set_type_a(dl_vaddr, map, mesh, item_size);
++ }
++ } else {
++ imr_tri_set_type_c(dl_vaddr, map, vbo, item_size);
++ }
++
++ /* ...prepare main DL-program */
++ imr_dl_program_setup(ctx, cfg, type, dl_vaddr + dl_start_offset, (u32)dl_dma_addr);
++
++ /* ...update cropping parameters */
++ cfg->dst_subpixel = (type & IMR_MAP_DDP ? 2 : 0);
++
++ /* ...display list updated successfully */
++ v4l2_dbg(2, debug, &ctx->imr->v4l2_dev, "display-list created: #%u[%08X]:%u[%u]\n",
++ cfg->id, (u32)dl_dma_addr, dl_size, dl_start_offset);
++
++ if (debug >= 4)
++ print_hex_dump_bytes("DL-", DUMP_PREFIX_OFFSET, dl_vaddr + dl_start_offset, dl_size - dl_start_offset);
++
++ /* ...success */
++ ret = 0;
++
++out:
++ /* ...release interim buffer */
++ kfree(buf);
++
++ return ret;
++}
++
++/*******************************************************************************
++ * V4L2 I/O controls
++ ******************************************************************************/
++
++/* ...test for a format supported */
++static int __imr_try_fmt(struct imr_ctx *ctx, struct v4l2_format *f)
++{
++ struct v4l2_pix_format *pix = &f->fmt.pix;
++ u32 fourcc = pix->pixelformat;
++ int i;
++
++ /* ...both output and capture interface have the same set of supported formats */
++ for (i = 0; i < ARRAY_SIZE(imr_lx4_formats); i++) {
++ if (fourcc == imr_lx4_formats[i].fourcc) {
++ /* ...fix-up format specification as needed */
++ pix->field = V4L2_FIELD_NONE;
++
++ v4l2_dbg(1, debug, &ctx->imr->v4l2_dev, "format request: '%c%c%c%c', %d*%d\n",
++ (fourcc >> 0) & 0xff, (fourcc >> 8) & 0xff,
++ (fourcc >> 16) & 0xff, (fourcc >> 24) & 0xff,
++ pix->width, pix->height);
++
++ /* ...verify source/destination image dimensions */
++ if (V4L2_TYPE_IS_OUTPUT(f->type))
++ v4l_bound_align_image(&pix->width, 128, 2048, 7, &pix->height, 1, 2048, 0, 0);
++ else
++ v4l_bound_align_image(&pix->width, 64, 2048, 6, &pix->height, 1, 2048, 0, 0);
++
++ return i;
++ }
++ }
++
++ v4l2_err(&ctx->imr->v4l2_dev, "unsupported format request: '%c%c%c%c'\n",
++ (fourcc >> 0) & 0xff, (fourcc >> 8) & 0xff,
++ (fourcc >> 16) & 0xff, (fourcc >> 24) & 0xff);
++
++ return -EINVAL;
++}
++
++/* ...capabilities query */
++static int imr_querycap(struct file *file, void *priv, struct v4l2_capability *cap)
++{
++ strlcpy(cap->driver, DRV_NAME, sizeof(cap->driver));
++ strlcpy(cap->card, DRV_NAME, sizeof(cap->card));
++ strlcpy(cap->bus_info, DRV_NAME, sizeof(cap->bus_info));
++
++ cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT |
++ V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING;
++
++ cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
++
++ return 0;
++}
++
++/* ...enumerate supported formats */
++static int imr_enum_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *f)
++{
++ /* ...no distinction between output/capture formats */
++ if (f->index < ARRAY_SIZE(imr_lx4_formats)) {
++ const struct imr_format_info *fmt = &imr_lx4_formats[f->index];
++ strlcpy(f->description, fmt->name, sizeof(f->description));
++ f->pixelformat = fmt->fourcc;
++ return 0;
++ }
++
++ return -EINVAL;
++}
++
++/* ...retrieve current queue format; operation is locked ? */
++static int imr_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
++{
++ struct imr_ctx *ctx = fh_to_ctx(priv);
++ struct vb2_queue *vq;
++ struct imr_q_data *q_data;
++
++ vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
++ if (!vq)
++ return -EINVAL;
++
++ q_data = &ctx->queue[V4L2_TYPE_IS_OUTPUT(f->type) ? 0 : 1];
++
++ /* ...processing is locked? tbd */
++ f->fmt.pix = q_data->fmt;
++
++ return 0;
++}
++
++/* ...test particular format; operation is not locked */
++static int imr_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
++{
++ struct imr_ctx *ctx = fh_to_ctx(priv);
++ struct vb2_queue *vq;
++
++ /* ...make sure we have a queue of particular type */
++ vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
++ if (!vq)
++ return -EINVAL;
++
++ /* ...test if format is supported (adjust as appropriate) */
++ return (__imr_try_fmt(ctx, f) >= 0 ? 0 : -EINVAL);
++}
++
++/* ...apply queue format; operation is locked ? */
++static int imr_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
++{
++ struct imr_ctx *ctx = fh_to_ctx(priv);
++ struct vb2_queue *vq;
++ struct imr_q_data *q_data;
++ int i;
++
++ vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
++ if (!vq)
++ return -EINVAL;
++
++ /* ...check if queue is busy */
++ if (vb2_is_busy(vq))
++ return -EBUSY;
++
++ /* ...test if format is supported (adjust as appropriate) */
++ i = __imr_try_fmt(ctx, f);
++ if (i < 0)
++ return -EINVAL;
++
++ /* ...format is supported; save current format in a queue-specific data */
++ q_data = &ctx->queue[V4L2_TYPE_IS_OUTPUT(f->type) ? 0 : 1];
++
++ /* ...processing is locked? tbd */
++ q_data->fmt = f->fmt.pix;
++ q_data->flags = imr_lx4_formats[i].flags;
++
++ /* ...set default crop factors */
++ if (V4L2_TYPE_IS_OUTPUT(f->type) == 0) {
++ ctx->crop[0] = 0;
++ ctx->crop[1] = f->fmt.pix.width - 1;
++ ctx->crop[2] = 0;
++ ctx->crop[3] = f->fmt.pix.height - 1;
++ }
++
++ return 0;
++}
++
++static int imr_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *reqbufs)
++{
++ struct imr_ctx *ctx = fh_to_ctx(priv);
++
++ return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs);
++}
++
++static int imr_querybuf(struct file *file, void *priv, struct v4l2_buffer *buf)
++{
++ struct imr_ctx *ctx = fh_to_ctx(priv);
++
++ return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf);
++}
++
++static int imr_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
++{
++ struct imr_ctx *ctx = fh_to_ctx(priv);
++
++ /* ...operation is protected with a queue lock */
++ WARN_ON(!mutex_is_locked(&ctx->imr->mutex));
++
++ /* ...verify the configuration is complete */
++ if (!V4L2_TYPE_IS_OUTPUT(buf->type) && !ctx->cfg) {
++ v4l2_err(&ctx->imr->v4l2_dev, "stream configuration is not complete\n");
++ return -EINVAL;
++ }
++
++ return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
++}
++
++static int imr_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
++{
++ struct imr_ctx *ctx = fh_to_ctx(priv);
++
++ return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
++}
++
++static int imr_expbuf(struct file *file, void *priv, struct v4l2_exportbuffer *eb)
++{
++ struct imr_ctx *ctx = fh_to_ctx(priv);
++
++ return v4l2_m2m_expbuf(file, ctx->m2m_ctx, eb);
++}
++
++static int imr_streamon(struct file *file, void *priv, enum v4l2_buf_type type)
++{
++ struct imr_ctx *ctx = fh_to_ctx(priv);
++
++ /* ...context is prepared for a streaming */
++ return v4l2_m2m_streamon(file, ctx->m2m_ctx, type);
++}
++
++static int imr_streamoff(struct file *file, void *priv, enum v4l2_buf_type type)
++{
++ struct imr_ctx *ctx = fh_to_ctx(priv);
++
++ return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type);
++}
++
++static int imr_g_crop(struct file *file, void *priv, struct v4l2_crop *cr)
++{
++ struct imr_ctx *ctx = fh_to_ctx(priv);
++
++ /* ...subpixel resolution of output buffer is not counted here */
++ cr->c.left = ctx->crop[0];
++ cr->c.top = ctx->crop[2];
++ cr->c.width = ctx->crop[1] - ctx->crop[0];
++ cr->c.height = ctx->crop[3] - ctx->crop[2];
++
++ return 0;
++}
++
++static int imr_s_crop(struct file *file, void *priv, const struct v4l2_crop *cr)
++{
++ struct imr_ctx *ctx = fh_to_ctx(priv);
++ int x0 = cr->c.left;
++ int y0 = cr->c.top;
++ int x1 = x0 + cr->c.width;
++ int y1 = y0 + cr->c.height;
++
++ if (x0 < 0 || x1 >= 2048 || y0 < 0 || y1 >= 2048) {
++ v4l2_err(&ctx->imr->v4l2_dev, "invalid cropping: %d/%d/%d/%d\n", x0, x1, y0, y1);
++ return -EINVAL;
++ }
++
++ /* ...subpixel resolution of output buffer is not counted here */
++ ctx->crop[0] = x0;
++ ctx->crop[1] = x1;
++ ctx->crop[2] = y0;
++ ctx->crop[3] = y1;
++
++ return 0;
++}
++
++/* ...customized I/O control processing */
++static long imr_default(struct file *file, void *fh, bool valid_prio, unsigned int cmd, void *arg)
++{
++ struct imr_ctx *ctx = fh_to_ctx(fh);
++
++ switch (cmd) {
++ case VIDIOC_IMR_MESH:
++ /* ...set mesh data */
++ return imr_ioctl_map(ctx, (struct imr_map_desc *)arg);
++
++ default:
++ return -ENOIOCTLCMD;
++ }
++}
++
++static const struct v4l2_ioctl_ops imr_ioctl_ops = {
++ .vidioc_querycap = imr_querycap,
++
++ .vidioc_enum_fmt_vid_cap = imr_enum_fmt,
++ .vidioc_enum_fmt_vid_out = imr_enum_fmt,
++ .vidioc_g_fmt_vid_cap = imr_g_fmt,
++ .vidioc_g_fmt_vid_out = imr_g_fmt,
++ .vidioc_try_fmt_vid_cap = imr_try_fmt,
++ .vidioc_try_fmt_vid_out = imr_try_fmt,
++ .vidioc_s_fmt_vid_cap = imr_s_fmt,
++ .vidioc_s_fmt_vid_out = imr_s_fmt,
++
++ .vidioc_reqbufs = imr_reqbufs,
++ .vidioc_querybuf = imr_querybuf,
++ .vidioc_qbuf = imr_qbuf,
++ .vidioc_dqbuf = imr_dqbuf,
++ .vidioc_expbuf = imr_expbuf,
++ .vidioc_streamon = imr_streamon,
++ .vidioc_streamoff = imr_streamoff,
++
++ .vidioc_g_crop = imr_g_crop,
++ .vidioc_s_crop = imr_s_crop,
++
++ .vidioc_default = imr_default,
++};
++
++/*******************************************************************************
++ * Generic device file operations
++ ******************************************************************************/
++
++static int imr_open(struct file *file)
++{
++ struct imr_device *imr = video_drvdata(file);
++ struct video_device *vfd = video_devdata(file);
++ struct imr_ctx *ctx;
++ int ret;
++
++ /* ...allocate processing context associated with given instance */
++ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
++ if (!ctx)
++ return -ENOMEM;
++
++ /* ...initialize per-file-handle structure */
++ v4l2_fh_init(&ctx->fh, vfd);
++ //ctx->fh.ctrl_handler = &ctx->ctrl_handler;
++ file->private_data = &ctx->fh;
++ v4l2_fh_add(&ctx->fh);
++
++ /* ...set default source / destination formats - need that? */
++ ctx->imr = imr;
++ ctx->queue[0].fmt.pixelformat = 0;
++ ctx->queue[1].fmt.pixelformat = 0;
++
++ /* ...set default cropping parameters */
++ ctx->crop[1] = ctx->crop[3] = 0x3FF;
++
++ /* ...initialize M2M processing context */
++ ctx->m2m_ctx = v4l2_m2m_ctx_init(imr->m2m_dev, ctx, imr_queue_init);
++ if (IS_ERR(ctx->m2m_ctx)) {
++ ret = PTR_ERR(ctx->m2m_ctx);
++ goto v4l_prepare_rollback;
++ }
++
++#if 0
++ /* ...initialize controls and stuff */
++ ret = imr_controls_create(ctx);
++ if (ret < 0)
++ goto v4l_prepare_rollback;
++#endif
++
++ /* ...lock access to global device data */
++ if (mutex_lock_interruptible(&imr->mutex)) {
++ ret = -ERESTARTSYS;
++ goto v4l_prepare_rollback;
++ }
++
++ /* ...bring-up device as needed */
++ if (imr->refcount == 0) {
++ ret = clk_prepare_enable(imr->clock);
++ if (ret < 0)
++ goto device_prepare_rollback;
++ }
++
++ imr->refcount++;
++
++ mutex_unlock(&imr->mutex);
++
++ v4l2_dbg(1, debug, &imr->v4l2_dev, "IMR device opened (refcount=%u)\n", imr->refcount);
++
++ return 0;
++
++device_prepare_rollback:
++ /* ...unlock global device data */
++ mutex_unlock(&imr->mutex);
++
++v4l_prepare_rollback:
++ /* ...destroy context */
++ v4l2_fh_del(&ctx->fh);
++ v4l2_fh_exit(&ctx->fh);
++ kfree(ctx);
++
++ return ret;
++}
++
++static int imr_release(struct file *file)
++{
++ struct imr_device *imr = video_drvdata(file);
++ struct imr_ctx *ctx = fh_to_ctx(file->private_data);
++
++ /* ...I don't need to get a device-scope lock here really - tbd */
++ mutex_lock(&imr->mutex);
++
++ /* ...destroy M2M device processing context */
++ v4l2_m2m_ctx_release(ctx->m2m_ctx);
++ //v4l2_ctrl_handler_free(&ctx->ctrl_handler);
++ v4l2_fh_del(&ctx->fh);
++ v4l2_fh_exit(&ctx->fh);
++
++ /* ...drop active configuration as needed */
++ imr_cfg_unref(ctx, ctx->cfg);
++
++ /* ...make sure there are no more active configs */
++ WARN_ON(ctx->cfg_num);
++
++ /* ...destroy context data */
++ kfree(ctx);
++
++ /* ...disable hardware operation */
++ if (--imr->refcount == 0)
++ clk_disable_unprepare(imr->clock);
++
++ mutex_unlock(&imr->mutex);
++
++ v4l2_dbg(1, debug, &imr->v4l2_dev, "closed device instance\n");
++
++ return 0;
++}
++
++static unsigned int imr_poll(struct file *file, struct poll_table_struct *wait)
++{
++ struct imr_device *imr = video_drvdata(file);
++ struct imr_ctx *ctx = fh_to_ctx(file->private_data);
++ unsigned int res;
++
++ if (mutex_lock_interruptible(&imr->mutex))
++ return -ERESTARTSYS;
++
++ res = v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
++ mutex_unlock(&imr->mutex);
++
++ return res;
++}
++
++static int imr_mmap(struct file *file, struct vm_area_struct *vma)
++{
++ struct imr_device *imr = video_drvdata(file);
++ struct imr_ctx *ctx = fh_to_ctx(file->private_data);
++ int ret;
++
++ /* ...should we protect all M2M operations with mutex? - tbd */
++ if (mutex_lock_interruptible(&imr->mutex))
++ return -ERESTARTSYS;
++
++ ret = v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
++
++ mutex_unlock(&imr->mutex);
++
++ return ret;
++}
++
++static const struct v4l2_file_operations imr_fops = {
++ .owner = THIS_MODULE,
++ .open = imr_open,
++ .release = imr_release,
++ .poll = imr_poll,
++ .mmap = imr_mmap,
++ .unlocked_ioctl = video_ioctl2,
++};
++
++/*******************************************************************************
++ * M2M device interface
++ ******************************************************************************/
++
++#if 0
++/* ...job cleanup function */
++static void imr_cleanup(struct imr_ctx *ctx)
++{
++ struct imr_device *imr = ctx->imr;
++ struct vb2_v4l2_buffer *src_buf, *dst_buf;
++ unsigned long flags;
++
++ /* ...interlock buffer handling with interrupt */
++ spin_lock_irqsave(&imr->lock, flags);
++
++ while ((src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx)) != NULL)
++ v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR);
++
++ while ((dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx)) != NULL)
++ v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR);
++
++ /* ...release lock before we mark current job as finished */
++ spin_unlock_irqrestore(&imr->lock, flags);
++}
++#endif
++
++/* ...job execution function */
++static void imr_device_run(void *priv)
++{
++ struct imr_ctx *ctx = priv;
++ struct imr_device *imr = ctx->imr;
++ struct imr_cfg *cfg;
++ struct vb2_buffer *src_buf, *dst_buf;
++ u32 src_addr, dst_addr;
++ unsigned long flags;
++
++ v4l2_dbg(3, debug, &imr->v4l2_dev, "run next job...\n");
++
++ /* ...protect access to internal device state */
++ spin_lock_irqsave(&imr->lock, flags);
++
++ /* ...retrieve input/output buffers */
++ src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
++ dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
++
++ /* ...take configuration pointer associated with input buffer */
++ cfg = to_imr_buffer(to_vb2_v4l2_buffer(src_buf))->cfg;
++
++ /* ...cancel software reset state as needed */
++ iowrite32(0, imr->mmio + IMR_CR);
++
++ /* ...set cropping data with respect to destination sub-pixel mode */
++ iowrite32(ctx->crop[0] << cfg->dst_subpixel, imr->mmio + IMR_XMINR);
++ iowrite32(ctx->crop[1] << cfg->dst_subpixel, imr->mmio + IMR_XMAXR);
++ iowrite32(ctx->crop[2] << cfg->dst_subpixel, imr->mmio + IMR_YMINR);
++ iowrite32(ctx->crop[3] << cfg->dst_subpixel, imr->mmio + IMR_YMAXR);
++
++ /* ...adjust source/destination parameters of the program (interleaved / semiplanar) */
++ *cfg->src_pa_ptr[0] = src_addr = (u32)vb2_dma_contig_plane_dma_addr(src_buf, 0);
++ *cfg->dst_pa_ptr[0] = dst_addr = (u32)vb2_dma_contig_plane_dma_addr(dst_buf, 0);
++
++ /* ...adjust source/destination parameters of the UV-plane as needed */
++ if (cfg->src_pa_ptr[1] && cfg->dst_pa_ptr[1]) {
++ *cfg->src_pa_ptr[1] = src_addr + ctx->queue[0].fmt.width * ctx->queue[0].fmt.height;
++ *cfg->dst_pa_ptr[1] = dst_addr + ctx->queue[1].fmt.width * ctx->queue[1].fmt.height;
++ }
++
++ v4l2_dbg(3, debug, &imr->v4l2_dev, "process buffer-pair 0x%08x:0x%08x\n",
++ *cfg->src_pa_ptr[0], *cfg->dst_pa_ptr[0]);
++
++ /* ...force clearing of status register bits */
++ iowrite32(0x7, imr->mmio + IMR_SRCR);
++
++ /* ...unmask/enable interrupts */
++ iowrite32(ioread32(imr->mmio + IMR_ICR) | (IMR_ICR_TRAEN | IMR_ICR_IEREN | IMR_ICR_INTEN), imr->mmio + IMR_ICR);
++ iowrite32(ioread32(imr->mmio + IMR_IMR) & ~(IMR_ICR_TRAEN | IMR_ICR_IEREN | IMR_ICR_INTEN), imr->mmio + IMR_IMR);
++
++ /* ...set display list address */
++ iowrite32(cfg->dl_dma_addr + cfg->dl_start_offset, imr->mmio + IMR_DLSAR);
++
++ /* ...explicitly flush any pending write operations (don't need that, I guess) */
++ wmb();
++
++ /* ...start rendering operation */
++ iowrite32(IMR_CR_RS, imr->mmio + IMR_CR);
++
++ /* ...timestamp input buffer */
++ src_buf->timestamp = ktime_get_ns();
++
++ /* ...unlock device access */
++ spin_unlock_irqrestore(&imr->lock, flags);
++
++ v4l2_dbg(1, debug, &imr->v4l2_dev, "rendering started: status=%X, DLSAR=0x%08X, DLPR=0x%08X\n", ioread32(imr->mmio + IMR_SR), ioread32(imr->mmio + IMR_DLSAR), ioread32(imr->mmio + IMR_DLSR));
++}
++
++/* ...check whether a job is ready for execution */
++static int imr_job_ready(void *priv)
++{
++ /* ...no specific requirements on the job readiness */
++ return 1;
++}
++
++/* ...abort currently processed job */
++static void imr_job_abort(void *priv)
++{
++ struct imr_ctx *ctx = priv;
++ struct imr_device *imr = ctx->imr;
++ unsigned long flags;
++
++ /* ...protect access to internal device state */
++ spin_lock_irqsave(&imr->lock, flags);
++
++ /* ...make sure current job is still current (may get finished by interrupt already) */
++ if (v4l2_m2m_get_curr_priv(imr->m2m_dev) == ctx) {
++ v4l2_dbg(1, debug, &imr->v4l2_dev, "abort job: status=%X, DLSAR=0x%08X, DLPR=0x%08X\n",
++ ioread32(imr->mmio + IMR_SR), ioread32(imr->mmio + IMR_DLSAR), ioread32(imr->mmio + IMR_DLSR));
++
++ /* ...force device reset to stop processing of the buffers */
++ //iowrite32(IMR_CR_SWRST, imr->mmio + IMR_CR);
++
++ /* ...resetting the module while operation is active may lead to hw-stall */
++ spin_unlock_irqrestore(&imr->lock, flags);
++
++ /* ...finish current job as interrupt will probably not occur */
++ //v4l2_m2m_job_finish(imr->m2m_dev, ctx->m2m_ctx);
++ } else {
++ spin_unlock_irqrestore(&imr->lock, flags);
++ v4l2_dbg(1, debug, &imr->v4l2_dev, "job has completed already\n");
++ }
++}
++
++/* ...M2M interface definition */
++static struct v4l2_m2m_ops imr_m2m_ops = {
++ .device_run = imr_device_run,
++ .job_ready = imr_job_ready,
++ .job_abort = imr_job_abort,
++};
++
++/*******************************************************************************
++ * Interrupt handling
++ ******************************************************************************/
++
++static irqreturn_t imr_irq_handler(int irq, void *data)
++{
++ struct imr_device *imr = data;
++ struct imr_ctx *ctx;
++ struct vb2_v4l2_buffer *src_buf, *dst_buf;
++ u32 status;
++ irqreturn_t ret = IRQ_NONE;
++
++ /* ...check and ack interrupt status */
++ status = ioread32(imr->mmio + IMR_SR);
++ iowrite32(status, imr->mmio + IMR_SRCR);
++ if (!(status & (IMR_SR_INT | IMR_SR_IER | IMR_SR_TRA))) {
++ v4l2_err(&imr->v4l2_dev, "spurious interrupt: %x\n", status);
++ return ret;
++ }
++
++ /* ...protect access to current context */
++ spin_lock(&imr->lock);
++
++ /* ...get current job context (may have been cancelled already) */
++ ctx = v4l2_m2m_get_curr_priv(imr->m2m_dev);
++ if (!ctx) {
++ v4l2_dbg(3, debug, &imr->v4l2_dev, "no active job\n");
++ goto handled;
++ }
++
++ /* ...remove buffers (may have been removed already?) */
++ src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
++ dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
++ if (!src_buf || !dst_buf) {
++ v4l2_dbg(3, debug, &imr->v4l2_dev, "no buffers associated with current context\n");
++ goto handled;
++ }
++
++ /* ...check for a TRAP interrupt indicating completion of current DL */
++ if (status & IMR_SR_TRA) {
++ /* ...operation completed normally; timestamp output buffer */
++ dst_buf->vb2_buf.timestamp = ktime_get_ns();
++ if (src_buf->flags & V4L2_BUF_FLAG_TIMECODE)
++ dst_buf->timecode = src_buf->timecode;
++ dst_buf->flags = src_buf->flags & (V4L2_BUF_FLAG_TIMECODE | V4L2_BUF_FLAG_KEYFRAME |
++ V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_BFRAME | V4L2_BUF_FLAG_TSTAMP_SRC_MASK);
++ dst_buf->sequence = src_buf->sequence = ctx->sequence++;
++ v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
++ v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE);
++
++ v4l2_dbg(3, debug, &imr->v4l2_dev, "buffers <0x%08x,0x%08x> done\n",
++ (u32)vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0),
++ (u32)vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0));
++ } else {
++ /* ...operation completed in error; no way to understand what exactly went wrong */
++ v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR);
++ v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR);
++
++ v4l2_dbg(3, debug, &imr->v4l2_dev, "buffers <0x%08x,0x%08x> done in error\n",
++ (u32)vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0),
++ (u32)vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0));
++ }
++
++ spin_unlock(&imr->lock);
++
++ /* ...finish current job (and start any pending) */
++ v4l2_m2m_job_finish(imr->m2m_dev, ctx->m2m_ctx);
++
++ return IRQ_HANDLED;
++
++handled:
++ /* ...again, what exactly is to be protected? */
++ spin_unlock(&imr->lock);
++
++ return IRQ_HANDLED;
++}
++
++/*******************************************************************************
++ * Device probing / removal interface
++ ******************************************************************************/
++
++static int imr_probe(struct platform_device *pdev)
++{
++ struct imr_device *imr;
++ struct resource *res;
++ int ret;
++
++ imr = devm_kzalloc(&pdev->dev, sizeof(*imr), GFP_KERNEL);
++ if (!imr)
++ return -ENOMEM;
++
++ mutex_init(&imr->mutex);
++ spin_lock_init(&imr->lock);
++ imr->dev = &pdev->dev;
++
++ /* ...memory-mapped registers */
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!res) {
++ dev_err(&pdev->dev, "cannot get memory region\n");
++ return -EINVAL;
++ }
++
++ imr->mmio = devm_ioremap_resource(&pdev->dev, res);
++ if (IS_ERR(imr->mmio))
++ return PTR_ERR(imr->mmio);
++
++ /* ...interrupt service routine registration */
++ imr->irq = ret = platform_get_irq(pdev, 0);
++ if (ret < 0) {
++ dev_err(&pdev->dev, "cannot find IRQ\n");
++ return ret;
++ }
++
++ ret = devm_request_irq(&pdev->dev, imr->irq, imr_irq_handler, 0, dev_name(&pdev->dev), imr);
++ if (ret) {
++ dev_err(&pdev->dev, "cannot claim IRQ %d\n", imr->irq);
++ return ret;
++ }
++
++ imr->clock = devm_clk_get(&pdev->dev, NULL);
++ if (IS_ERR(imr->clock)) {
++ dev_err(&pdev->dev, "cannot get clock\n");
++ return PTR_ERR(imr->clock);
++ }
++
++ /* ...create v4l2 device */
++ ret = v4l2_device_register(&pdev->dev, &imr->v4l2_dev);
++ if (ret) {
++ dev_err(&pdev->dev, "Failed to register v4l2 device\n");
++ return ret;
++ }
++
++ /* ...create mem2mem device handle */
++ imr->m2m_dev = v4l2_m2m_init(&imr_m2m_ops);
++ if (IS_ERR(imr->m2m_dev)) {
++ v4l2_err(&imr->v4l2_dev, "Failed to init mem2mem device\n");
++ ret = PTR_ERR(imr->m2m_dev);
++ goto device_register_rollback;
++ }
++
++ strlcpy(imr->video_dev.name, dev_name(&pdev->dev), sizeof(imr->video_dev.name));
++ imr->video_dev.fops = &imr_fops;
++ imr->video_dev.ioctl_ops = &imr_ioctl_ops;
++ imr->video_dev.minor = -1;
++ imr->video_dev.release = video_device_release_empty;
++ imr->video_dev.lock = &imr->mutex;
++ imr->video_dev.v4l2_dev = &imr->v4l2_dev;
++ imr->video_dev.vfl_dir = VFL_DIR_M2M;
++
++ ret = video_register_device(&imr->video_dev, VFL_TYPE_GRABBER, -1);
++ if (ret) {
++ v4l2_err(&imr->v4l2_dev, "Failed to register video device\n");
++ goto m2m_init_rollback;
++ }
++
++ video_set_drvdata(&imr->video_dev, imr);
++ platform_set_drvdata(pdev, imr);
++ //pm_runtime_enable(&pdev->dev);
++
++ v4l2_info(&imr->v4l2_dev, "IMR device (pdev: %d) registered as /dev/video%d\n", pdev->id, imr->video_dev.num);
++
++ return 0;
++
++m2m_init_rollback:
++ v4l2_m2m_release(imr->m2m_dev);
++
++device_register_rollback:
++ v4l2_device_unregister(&imr->v4l2_dev);
++
++ return ret;
++}
++
++static int imr_remove(struct platform_device *pdev)
++{
++ struct imr_device *imr = platform_get_drvdata(pdev);
++
++ //pm_runtime_disable(imr->v4l2_dev.dev);
++ video_unregister_device(&imr->video_dev);
++ v4l2_m2m_release(imr->m2m_dev);
++ v4l2_device_unregister(&imr->v4l2_dev);
++
++ return 0;
++}
++
++/*******************************************************************************
++ * Power management
++ ******************************************************************************/
++
++#ifdef CONFIG_PM_SLEEP
++
++/* ...device suspend hook; clock control only - tbd */
++static int imr_pm_suspend(struct device *dev)
++{
++ struct imr_device *imr = dev_get_drvdata(dev);
++
++ WARN_ON(mutex_is_locked(&imr->mutex));
++
++ if (imr->refcount == 0)
++ return 0;
++
++ clk_disable_unprepare(imr->clock);
++
++ return 0;
++}
++
++/* ...device resume hook; clock control only */
++static int imr_pm_resume(struct device *dev)
++{
++ struct imr_device *imr = dev_get_drvdata(dev);
++
++ WARN_ON(mutex_is_locked(&imr->mutex));
++
++ if (imr->refcount == 0)
++ return 0;
++
++ clk_prepare_enable(imr->clock);
++
++ return 0;
++}
++
++#endif /* CONFIG_PM_SLEEP */
++
++/* ...power management callbacks */
++static const struct dev_pm_ops imr_pm_ops = {
++ SET_SYSTEM_SLEEP_PM_OPS(imr_pm_suspend, imr_pm_resume)
++};
++
++/* ...device table */
++static const struct of_device_id imr_of_match[] = {
++ { .compatible = "renesas,imr-lx4" },
++ { },
++};
++
++/* ...platform driver interface */
++static struct platform_driver imr_platform_driver = {
++ .probe = imr_probe,
++ .remove = imr_remove,
++ .driver = {
++ .owner = THIS_MODULE,
++ .name = "imr",
++ .pm = &imr_pm_ops,
++ .of_match_table = imr_of_match,
++ },
++};
++
++module_platform_driver(imr_platform_driver);
++
++MODULE_ALIAS("imr");
++MODULE_AUTHOR("Cogent Embedded Inc. <sources@cogentembedded.com>");
++MODULE_DESCRIPTION("Renesas IMR-LX4 Driver");
++MODULE_LICENSE("GPL");
+diff --git a/include/uapi/linux/rcar-imr.h b/include/uapi/linux/rcar-imr.h
+new file mode 100644
+index 0000000..d02082f
+--- /dev/null
++++ b/include/uapi/linux/rcar-imr.h
+@@ -0,0 +1,98 @@
++/*
++ * imr.h -- R-Car IMR-LX4 Driver UAPI
++ *
++ * Copyright (C) 2016 Cogent Embedded, Inc. <source@cogentembedded.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ */
++
++#ifndef RCAR_IMR_USER_H
++#define RCAR_IMR_USER_H
++
++#include <linux/videodev2.h>
++
++/*******************************************************************************
++ * Mapping specification descriptor
++ ******************************************************************************/
++
++struct imr_map_desc {
++ /* ...mapping types */
++ u32 type;
++
++ /* ...total size of the mesh structure */
++ u32 size;
++
++ /* ...map-specific user-pointer */
++ void *data;
++
++} __attribute__((packed));
++
++/* ...regular mesh specification */
++#define IMR_MAP_MESH (1 << 0)
++
++/* ...auto-generated source coordinates */
++#define IMR_MAP_AUTODG (1 << 1)
++
++/* ...auto-generated destination coordinates */
++#define IMR_MAP_AUTOSG (1 << 2)
++
++/* ...luminance correction flag */
++#define IMR_MAP_LUCE (1 << 3)
++
++/* ...chromacity correction flag */
++#define IMR_MAP_CLCE (1 << 4)
++
++/* ...vertex clockwise-mode order */
++#define IMR_MAP_TCM (1 << 5)
++
++/* ...source coordinate decimal point position bit index */
++#define __IMR_MAP_UVDPOR_SHIFT 8
++#define __IMR_MAP_UVDPOR(v) (((v) >> __IMR_MAP_UVDPOR_SHIFT) & 0x7)
++#define IMR_MAP_UVDPOR(n) ((n & 0x7) << __IMR_MAP_UVDPOR_SHIFT)
++
++/* ...destination coordinate sub-pixel mode */
++#define IMR_MAP_DDP (1 << 11)
++
++/* ...luminance correction offset decimal point position */
++#define __IMR_MAP_YLDPO_SHIFT 12
++#define __IMR_MAP_YLDPO(v) (((v) >> __IMR_MAP_YLDPO_SHIFT) & 0x7)
++#define IMR_MAP_YLDPO(n) ((n & 0x7) << __IMR_MAP_YLDPO_SHIFT)
++
++/* ...chromacity (U) correction offset decimal point position */
++#define __IMR_MAP_UBDPO_SHIFT 15
++#define __IMR_MAP_UBDPO(v) (((v) >> __IMR_MAP_UBDPO_SHIFT) & 0x7)
++#define IMR_MAP_UBDPO(n) ((n & 0x7) << __IMR_MAP_UBDPO_SHIFT)
++
++/* ...chromacity (V) correction offset decimal point position */
++#define __IMR_MAP_VRDPO_SHIFT 18
++#define __IMR_MAP_VRDPO(v) (((v) >> __IMR_MAP_VRDPO_SHIFT) & 0x7)
++#define IMR_MAP_VRDPO(n) ((n & 0x7) << __IMR_MAP_VRDPO_SHIFT)
++
++/* ...regular mesh specification */
++struct imr_mesh {
++ /* ...rectangular mesh size */
++ u16 rows, columns;
++
++ /* ...mesh parameters */
++ u16 x0, y0, dx, dy;
++
++} __attribute__((packed));
++
++/* ...VBO descriptor */
++struct imr_vbo {
++ /* ...number of triangles */
++ u16 num;
++
++} __attribute__((packed));
++
++
++/*******************************************************************************
++ * Private IOCTL codes
++ ******************************************************************************/
++
++#define VIDIOC_IMR_MESH _IOW('V', BASE_VIDIOC_PRIVATE + 0, struct imr_map_desc)
++
++#endif /* RCAR_IMR_USER_H */
+--
+1.9.1
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0014-lib-swiotlb-reduce-verbosity.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0014-lib-swiotlb-reduce-verbosity.patch
new file mode 100644
index 0000000..6cb5f65
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0014-lib-swiotlb-reduce-verbosity.patch
@@ -0,0 +1,40 @@
+From f52105d57c1ec04f8dac9b403232d8b1965a02ca Mon Sep 17 00:00:00 2001
+From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+Date: Thu, 26 Jan 2017 16:37:50 +0300
+Subject: [PATCH] lib: swiotlb: reduce verbosity
+
+Signed-off-by: Nikita Yushchenko <nikita.yoush@cogentembedded.com>
+Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+---
+ lib/swiotlb.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/lib/swiotlb.c b/lib/swiotlb.c
+index 771234d..b395abc 100644
+--- a/lib/swiotlb.c
++++ b/lib/swiotlb.c
+@@ -513,8 +513,10 @@ phys_addr_t swiotlb_tbl_map_single(struct device *hwdev,
+
+ not_found:
+ spin_unlock_irqrestore(&io_tlb_lock, flags);
++#if 0
+ if (printk_ratelimit())
+ dev_warn(hwdev, "swiotlb buffer is full (sz: %zd bytes)\n", size);
++#endif
+ return SWIOTLB_MAP_ERROR;
+ found:
+ spin_unlock_irqrestore(&io_tlb_lock, flags);
+@@ -714,8 +714,10 @@ swiotlb_full(struct device *dev, size_t size, enum dma_data_direction dir,
+ * When the mapping is small enough return a static buffer to limit
+ * the damage, or panic when the transfer is too big.
+ */
++#if 0
+ dev_err_ratelimited(dev, "DMA: Out of SW-IOMMU space for %zu bytes\n",
+ size);
++#endif
+
+ if (size <= io_tlb_overflow || !do_panic)
+ return;
+--
+1.9.1
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0015-gpio-max732x-fix-gpio-set.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0015-gpio-max732x-fix-gpio-set.patch
new file mode 100644
index 0000000..0195a11
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0015-gpio-max732x-fix-gpio-set.patch
@@ -0,0 +1,29 @@
+From 75b9bdbafde96b6af222f96e47d7a4a260ed32df Mon Sep 17 00:00:00 2001
+From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+Date: Tue, 11 Apr 2017 20:12:56 +0300
+Subject: [PATCH] gpio: max732x: fix gpio set
+
+gpio set value/direction must 0 or 1, but
+gpiolib sets it to random nonzero values
+
+Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+---
+ drivers/gpio/gpio-max732x.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpio/gpio-max732x.c b/drivers/gpio/gpio-max732x.c
+index a9aaf9d..b6fc8c5 100644
+--- a/drivers/gpio/gpio-max732x.c
++++ b/drivers/gpio/gpio-max732x.c
+@@ -237,7 +237,7 @@ static void max732x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
+ unsigned base = off & ~0x7;
+ uint8_t mask = 1u << (off & 0x7);
+
+- max732x_gpio_set_mask(gc, base, mask, val << (off & 0x7));
++ max732x_gpio_set_mask(gc, base, mask, (!!val) << (off & 0x7));
+ }
+
+ static void max732x_gpio_set_multiple(struct gpio_chip *gc,
+--
+1.9.1
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0016-gpio-gpiolib-suppress-gpiod-warning.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0016-gpio-gpiolib-suppress-gpiod-warning.patch
new file mode 100644
index 0000000..9a6ae18
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0016-gpio-gpiolib-suppress-gpiod-warning.patch
@@ -0,0 +1,29 @@
+From d5f7b238ab2b458876a50521f9c92487f4ba3226 Mon Sep 17 00:00:00 2001
+From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+Date: Thu, 13 Apr 2017 12:18:18 +0300
+Subject: [PATCH] gpio: gpiolib: suppress gpiod warning
+
+Suppress warning about use gpiod instead gpio deprecated callbacks
+
+Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+---
+ drivers/gpio/gpiolib.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
+index d407f904..06201ff 100644
+--- a/drivers/gpio/gpiolib.c
++++ b/drivers/gpio/gpiolib.c
+@@ -1945,7 +1945,9 @@ void gpiod_set_raw_value(struct gpio_desc *desc, int value)
+ {
+ VALIDATE_DESC_VOID(desc);
+ /* Should be using gpiod_set_value_cansleep() */
++#if 0
+ WARN_ON(desc->gdev->chip->can_sleep);
++#endif
+ _gpiod_set_raw_value(desc, value);
+ }
+ EXPORT_SYMBOL_GPL(gpiod_set_raw_value);
+--
+1.9.1
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0017-media-soc_camera-add-legacy-VIN-CSI2.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0017-media-soc_camera-add-legacy-VIN-CSI2.patch
new file mode 100644
index 0000000..9a349a0
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0017-media-soc_camera-add-legacy-VIN-CSI2.patch
@@ -0,0 +1,5055 @@
+From fd6f489456137d148132010c9da3251ba80f7948 Mon Sep 17 00:00:00 2001
+From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+Date: Sun, 14 May 2017 13:43:24 +0300
+Subject: [PATCH] media: soc_camera: add legacy VIN/CSI2
+
+Add legacy/old R-CAR VIN/CSI2 drivers
+
+Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+---
+ arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi | 348 ---
+ arch/arm64/boot/dts/renesas/r8a7795.dtsi | 271 ---
+ arch/arm64/boot/dts/renesas/r8a7796.dtsi | 258 ---
+ drivers/media/platform/soc_camera/Kconfig | 26 +
+ drivers/media/platform/soc_camera/Makefile | 2 +
+ drivers/media/platform/soc_camera/rcar_csi2.c | 708 ++++++
+ drivers/media/platform/soc_camera/rcar_vin.c | 3071 +++++++++++++++++++++++++
+ include/media/rcar_csi2.h | 66 +
+ 8 files changed, 3873 insertions(+), 877 deletions(-)
+ create mode 100644 drivers/media/platform/soc_camera/rcar_csi2.c
+ create mode 100644 drivers/media/platform/soc_camera/rcar_vin.c
+ create mode 100644 include/media/rcar_csi2.h
+
+diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi b/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi
+index 2bf5911..09e1284 100644
+--- a/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi
++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi
+@@ -1927,31 +1927,6 @@
+ clocks = <&cpg CPG_MOD 811>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ status = "disabled";
+-
+- ports {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- port@1 {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- reg = <1>;
+-
+- vin0csi20: endpoint@0 {
+- reg = <0>;
+- remote-endpoint= <&csi20vin0>;
+- };
+- vin0csi21: endpoint@1 {
+- reg = <1>;
+- remote-endpoint= <&csi21vin0>;
+- };
+- vin0csi40: endpoint@2 {
+- reg = <2>;
+- remote-endpoint= <&csi40vin0>;
+- };
+- };
+- };
+ };
+
+ vin1: video@e6ef1000 {
+@@ -1961,31 +1936,6 @@
+ clocks = <&cpg CPG_MOD 810>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ status = "disabled";
+-
+- ports {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- port@1 {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- reg = <1>;
+-
+- vin1csi20: endpoint@0 {
+- reg = <0>;
+- remote-endpoint= <&csi20vin1>;
+- };
+- vin1csi21: endpoint@1 {
+- reg = <1>;
+- remote-endpoint= <&csi21vin1>;
+- };
+- vin1csi40: endpoint@2 {
+- reg = <2>;
+- remote-endpoint= <&csi40vin1>;
+- };
+- };
+- };
+ };
+
+ vin2: video@e6ef2000 {
+@@ -1995,31 +1945,6 @@
+ clocks = <&cpg CPG_MOD 809>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ status = "disabled";
+-
+- ports {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- port@1 {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- reg = <1>;
+-
+- vin2csi20: endpoint@0 {
+- reg = <0>;
+- remote-endpoint= <&csi20vin2>;
+- };
+- vin2csi21: endpoint@1 {
+- reg = <1>;
+- remote-endpoint= <&csi21vin2>;
+- };
+- vin2csi40: endpoint@2 {
+- reg = <2>;
+- remote-endpoint= <&csi40vin2>;
+- };
+- };
+- };
+ };
+
+ vin3: video@e6ef3000 {
+@@ -2029,31 +1954,6 @@
+ clocks = <&cpg CPG_MOD 808>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ status = "disabled";
+-
+- ports {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- port@1 {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- reg = <1>;
+-
+- vin3csi20: endpoint@0 {
+- reg = <0>;
+- remote-endpoint= <&csi20vin3>;
+- };
+- vin3csi21: endpoint@1 {
+- reg = <1>;
+- remote-endpoint= <&csi21vin3>;
+- };
+- vin3csi40: endpoint@2 {
+- reg = <2>;
+- remote-endpoint= <&csi40vin3>;
+- };
+- };
+- };
+ };
+
+ vin4: video@e6ef4000 {
+@@ -2063,31 +1963,6 @@
+ clocks = <&cpg CPG_MOD 807>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ status = "disabled";
+-
+- ports {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- port@1 {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- reg = <1>;
+-
+- vin4csi20: endpoint@0 {
+- reg = <0>;
+- remote-endpoint= <&csi20vin4>;
+- };
+- vin4csi21: endpoint@1 {
+- reg = <1>;
+- remote-endpoint= <&csi21vin4>;
+- };
+- vin4csi41: endpoint@3 {
+- reg = <3>;
+- remote-endpoint= <&csi41vin4>;
+- };
+- };
+- };
+ };
+
+ vin5: video@e6ef5000 {
+@@ -2097,31 +1972,6 @@
+ clocks = <&cpg CPG_MOD 806>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ status = "disabled";
+-
+- ports {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- port@1 {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- reg = <1>;
+-
+- vin5csi20: endpoint@0 {
+- reg = <0>;
+- remote-endpoint= <&csi20vin5>;
+- };
+- vin5csi21: endpoint@1 {
+- reg = <1>;
+- remote-endpoint= <&csi21vin5>;
+- };
+- vin5csi41: endpoint@3 {
+- reg = <3>;
+- remote-endpoint= <&csi41vin5>;
+- };
+- };
+- };
+ };
+
+ vin6: video@e6ef6000 {
+@@ -2131,31 +1981,6 @@
+ clocks = <&cpg CPG_MOD 805>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ status = "disabled";
+-
+- ports {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- port@1 {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- reg = <1>;
+-
+- vin6csi20: endpoint@0 {
+- reg = <0>;
+- remote-endpoint= <&csi20vin6>;
+- };
+- vin6csi21: endpoint@1 {
+- reg = <1>;
+- remote-endpoint= <&csi21vin6>;
+- };
+- vin6csi41: endpoint@3 {
+- reg = <3>;
+- remote-endpoint= <&csi41vin6>;
+- };
+- };
+- };
+ };
+
+ vin7: video@e6ef7000 {
+@@ -2165,31 +1990,6 @@
+ clocks = <&cpg CPG_MOD 804>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ status = "disabled";
+-
+- ports {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- port@1 {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- reg = <1>;
+-
+- vin7csi20: endpoint@0 {
+- reg = <0>;
+- remote-endpoint= <&csi20vin7>;
+- };
+- vin7csi21: endpoint@1 {
+- reg = <1>;
+- remote-endpoint= <&csi21vin7>;
+- };
+- vin7csi41: endpoint@3 {
+- reg = <3>;
+- remote-endpoint= <&csi41vin7>;
+- };
+- };
+- };
+ };
+
+ csi2_20: csi2@fea80000 {
+@@ -2199,51 +1999,6 @@
+ clocks = <&cpg CPG_MOD 714>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ status = "disabled";
+-
+- ports {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- port@1 {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- reg = <1>;
+-
+- csi20vin0: endpoint@0 {
+- reg = <0>;
+- remote-endpoint = <&vin0csi20>;
+- };
+- csi20vin1: endpoint@1 {
+- reg = <1>;
+- remote-endpoint = <&vin1csi20>;
+- };
+- csi20vin2: endpoint@2 {
+- reg = <2>;
+- remote-endpoint = <&vin2csi20>;
+- };
+- csi20vin3: endpoint@3 {
+- reg = <3>;
+- remote-endpoint = <&vin3csi20>;
+- };
+- csi20vin4: endpoint@4 {
+- reg = <4>;
+- remote-endpoint = <&vin4csi20>;
+- };
+- csi20vin5: endpoint@5 {
+- reg = <5>;
+- remote-endpoint = <&vin5csi20>;
+- };
+- csi20vin6: endpoint@6 {
+- reg = <6>;
+- remote-endpoint = <&vin6csi20>;
+- };
+- csi20vin7: endpoint@7 {
+- reg = <7>;
+- remote-endpoint = <&vin7csi20>;
+- };
+- };
+- };
+ };
+
+ csi2_21: csi2@fea90000 {
+@@ -2253,51 +2008,6 @@
+ clocks = <&cpg CPG_MOD 713>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ status = "disabled";
+-
+- ports {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- port@1 {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- reg = <1>;
+-
+- csi21vin0: endpoint@0 {
+- reg = <0>;
+- remote-endpoint = <&vin0csi21>;
+- };
+- csi21vin1: endpoint@1 {
+- reg = <1>;
+- remote-endpoint = <&vin1csi21>;
+- };
+- csi21vin2: endpoint@2 {
+- reg = <2>;
+- remote-endpoint = <&vin2csi21>;
+- };
+- csi21vin3: endpoint@3 {
+- reg = <3>;
+- remote-endpoint = <&vin3csi21>;
+- };
+- csi21vin4: endpoint@4 {
+- reg = <4>;
+- remote-endpoint = <&vin4csi21>;
+- };
+- csi21vin5: endpoint@5 {
+- reg = <5>;
+- remote-endpoint = <&vin5csi21>;
+- };
+- csi21vin6: endpoint@6 {
+- reg = <6>;
+- remote-endpoint = <&vin6csi21>;
+- };
+- csi21vin7: endpoint@7 {
+- reg = <7>;
+- remote-endpoint = <&vin7csi21>;
+- };
+- };
+- };
+ };
+
+ csi2_40: csi2@feaa0000 {
+@@ -2307,35 +2017,6 @@
+ clocks = <&cpg CPG_MOD 716>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ status = "disabled";
+-
+- ports {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- port@1 {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- reg = <1>;
+-
+- csi40vin0: endpoint@0 {
+- reg = <0>;
+- remote-endpoint = <&vin0csi40>;
+- };
+- csi40vin1: endpoint@1 {
+- reg = <1>;
+- remote-endpoint = <&vin1csi40>;
+- };
+- csi40vin2: endpoint@2 {
+- reg = <2>;
+- remote-endpoint = <&vin2csi40>;
+- };
+- csi40vin3: endpoint@3 {
+- reg = <3>;
+- remote-endpoint = <&vin3csi40>;
+- };
+- };
+- };
+ };
+
+ csi2_41: csi2@feab0000 {
+@@ -2345,35 +2026,6 @@
+ clocks = <&cpg CPG_MOD 715>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ status = "disabled";
+-
+- ports {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- port@1 {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- reg = <1>;
+-
+- csi41vin4: endpoint@4 {
+- reg = <4>;
+- remote-endpoint = <&vin4csi41>;
+- };
+- csi41vin5: endpoint@5 {
+- reg = <5>;
+- remote-endpoint = <&vin5csi41>;
+- };
+- csi41vin6: endpoint@6 {
+- reg = <6>;
+- remote-endpoint = <&vin6csi41>;
+- };
+- csi41vin7: endpoint@7 {
+- reg = <7>;
+- remote-endpoint = <&vin7csi41>;
+- };
+- };
+- };
+ };
+
+ sata: sata@ee300000 {
+diff --git a/arch/arm64/boot/dts/renesas/r8a7795.dtsi b/arch/arm64/boot/dts/renesas/r8a7795.dtsi
+index 94262a1..82ebfd4 100644
+--- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi
++++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi
+@@ -1902,27 +1902,6 @@
+ clocks = <&cpg CPG_MOD 811>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ status = "disabled";
+-
+- ports {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- port@1 {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- reg = <1>;
+-
+- vin0csi20: endpoint@0 {
+- reg = <0>;
+- remote-endpoint= <&csi20vin0>;
+- };
+- vin0csi40: endpoint@2 {
+- reg = <2>;
+- remote-endpoint= <&csi40vin0>;
+- };
+- };
+- };
+ };
+
+ vin1: video@e6ef1000 {
+@@ -1932,27 +1911,6 @@
+ clocks = <&cpg CPG_MOD 810>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ status = "disabled";
+-
+- ports {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- port@1 {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- reg = <1>;
+-
+- vin1csi20: endpoint@0 {
+- reg = <0>;
+- remote-endpoint= <&csi20vin1>;
+- };
+- vin1csi40: endpoint@2 {
+- reg = <2>;
+- remote-endpoint= <&csi40vin1>;
+- };
+- };
+- };
+ };
+
+ vin2: video@e6ef2000 {
+@@ -1962,27 +1920,6 @@
+ clocks = <&cpg CPG_MOD 809>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ status = "disabled";
+-
+- ports {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- port@1 {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- reg = <1>;
+-
+- vin2csi20: endpoint@0 {
+- reg = <0>;
+- remote-endpoint= <&csi20vin2>;
+- };
+- vin2csi40: endpoint@2 {
+- reg = <2>;
+- remote-endpoint= <&csi40vin2>;
+- };
+- };
+- };
+ };
+
+ vin3: video@e6ef3000 {
+@@ -1992,27 +1929,6 @@
+ clocks = <&cpg CPG_MOD 808>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ status = "disabled";
+-
+- ports {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- port@1 {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- reg = <1>;
+-
+- vin3csi20: endpoint@0 {
+- reg = <0>;
+- remote-endpoint= <&csi20vin3>;
+- };
+- vin3csi40: endpoint@2 {
+- reg = <2>;
+- remote-endpoint= <&csi40vin3>;
+- };
+- };
+- };
+ };
+
+ vin4: video@e6ef4000 {
+@@ -2022,27 +1938,6 @@
+ clocks = <&cpg CPG_MOD 807>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ status = "disabled";
+-
+- ports {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- port@1 {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- reg = <1>;
+-
+- vin4csi20: endpoint@0 {
+- reg = <0>;
+- remote-endpoint= <&csi20vin4>;
+- };
+- vin4csi41: endpoint@3 {
+- reg = <3>;
+- remote-endpoint= <&csi41vin4>;
+- };
+- };
+- };
+ };
+
+ vin5: video@e6ef5000 {
+@@ -2052,27 +1947,6 @@
+ clocks = <&cpg CPG_MOD 806>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ status = "disabled";
+-
+- ports {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- port@1 {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- reg = <1>;
+-
+- vin5csi20: endpoint@0 {
+- reg = <0>;
+- remote-endpoint= <&csi20vin5>;
+- };
+- vin5csi41: endpoint@3 {
+- reg = <3>;
+- remote-endpoint= <&csi41vin5>;
+- };
+- };
+- };
+ };
+
+ vin6: video@e6ef6000 {
+@@ -2082,27 +1956,6 @@
+ clocks = <&cpg CPG_MOD 805>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ status = "disabled";
+-
+- ports {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- port@1 {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- reg = <1>;
+-
+- vin6csi20: endpoint@0 {
+- reg = <0>;
+- remote-endpoint= <&csi20vin6>;
+- };
+- vin6csi41: endpoint@3 {
+- reg = <3>;
+- remote-endpoint= <&csi41vin6>;
+- };
+- };
+- };
+ };
+
+ vin7: video@e6ef7000 {
+@@ -2112,27 +1965,6 @@
+ clocks = <&cpg CPG_MOD 804>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ status = "disabled";
+-
+- ports {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- port@1 {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- reg = <1>;
+-
+- vin7csi20: endpoint@0 {
+- reg = <0>;
+- remote-endpoint= <&csi20vin7>;
+- };
+- vin7csi41: endpoint@3 {
+- reg = <3>;
+- remote-endpoint= <&csi41vin7>;
+- };
+- };
+- };
+ };
+
+ csi2_20: csi2@fea80000 {
+@@ -2142,51 +1974,6 @@
+ clocks = <&cpg CPG_MOD 714>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ status = "disabled";
+-
+- ports {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- port@1 {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- reg = <1>;
+-
+- csi20vin0: endpoint@0 {
+- reg = <0>;
+- remote-endpoint = <&vin0csi20>;
+- };
+- csi20vin1: endpoint@1 {
+- reg = <1>;
+- remote-endpoint = <&vin1csi20>;
+- };
+- csi20vin2: endpoint@2 {
+- reg = <2>;
+- remote-endpoint = <&vin2csi20>;
+- };
+- csi20vin3: endpoint@3 {
+- reg = <3>;
+- remote-endpoint = <&vin3csi20>;
+- };
+- csi20vin4: endpoint@4 {
+- reg = <4>;
+- remote-endpoint = <&vin4csi20>;
+- };
+- csi20vin5: endpoint@5 {
+- reg = <5>;
+- remote-endpoint = <&vin5csi20>;
+- };
+- csi20vin6: endpoint@6 {
+- reg = <6>;
+- remote-endpoint = <&vin6csi20>;
+- };
+- csi20vin7: endpoint@7 {
+- reg = <7>;
+- remote-endpoint = <&vin7csi20>;
+- };
+- };
+- };
+ };
+
+ csi2_40: csi2@feaa0000 {
+@@ -2196,35 +1983,6 @@
+ clocks = <&cpg CPG_MOD 716>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ status = "disabled";
+-
+- ports {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- port@1 {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- reg = <1>;
+-
+- csi40vin0: endpoint@0 {
+- reg = <0>;
+- remote-endpoint = <&vin0csi40>;
+- };
+- csi40vin1: endpoint@1 {
+- reg = <1>;
+- remote-endpoint = <&vin1csi40>;
+- };
+- csi40vin2: endpoint@2 {
+- reg = <2>;
+- remote-endpoint = <&vin2csi40>;
+- };
+- csi40vin3: endpoint@3 {
+- reg = <3>;
+- remote-endpoint = <&vin3csi40>;
+- };
+- };
+- };
+ };
+
+ csi2_41: csi2@feab0000 {
+@@ -2234,35 +1992,6 @@
+ clocks = <&cpg CPG_MOD 715>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ status = "disabled";
+-
+- ports {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- port@1 {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- reg = <1>;
+-
+- csi41vin4: endpoint@4 {
+- reg = <4>;
+- remote-endpoint = <&vin4csi41>;
+- };
+- csi41vin5: endpoint@5 {
+- reg = <5>;
+- remote-endpoint = <&vin5csi41>;
+- };
+- csi41vin6: endpoint@6 {
+- reg = <6>;
+- remote-endpoint = <&vin6csi41>;
+- };
+- csi41vin7: endpoint@7 {
+- reg = <7>;
+- remote-endpoint = <&vin7csi41>;
+- };
+- };
+- };
+ };
+
+ sata: sata@ee300000 {
+diff --git a/arch/arm64/boot/dts/renesas/r8a7796.dtsi b/arch/arm64/boot/dts/renesas/r8a7796.dtsi
+index afdd69d..e653814 100644
+--- a/arch/arm64/boot/dts/renesas/r8a7796.dtsi
++++ b/arch/arm64/boot/dts/renesas/r8a7796.dtsi
+@@ -1592,27 +1592,6 @@
+ clocks = <&cpg CPG_MOD 811>;
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ status = "disabled";
+-
+- ports {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- port@1 {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- reg = <1>;
+-
+- vin0csi20: endpoint@0 {
+- reg = <0>;
+- remote-endpoint= <&csi20vin0>;
+- };
+- vin0csi40: endpoint@2 {
+- reg = <2>;
+- remote-endpoint= <&csi40vin0>;
+- };
+- };
+- };
+ };
+
+ vin1: video@e6ef1000 {
+@@ -1622,27 +1601,6 @@
+ clocks = <&cpg CPG_MOD 810>;
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ status = "disabled";
+-
+- ports {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- port@1 {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- reg = <1>;
+-
+- vin1csi20: endpoint@0 {
+- reg = <0>;
+- remote-endpoint= <&csi20vin1>;
+- };
+- vin1csi40: endpoint@2 {
+- reg = <2>;
+- remote-endpoint= <&csi40vin1>;
+- };
+- };
+- };
+ };
+
+ vin2: video@e6ef2000 {
+@@ -1652,27 +1610,6 @@
+ clocks = <&cpg CPG_MOD 809>;
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ status = "disabled";
+-
+- ports {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- port@1 {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- reg = <1>;
+-
+- vin2csi20: endpoint@0 {
+- reg = <0>;
+- remote-endpoint= <&csi20vin2>;
+- };
+- vin2csi40: endpoint@2 {
+- reg = <2>;
+- remote-endpoint= <&csi40vin2>;
+- };
+- };
+- };
+ };
+
+ vin3: video@e6ef3000 {
+@@ -1682,27 +1619,6 @@
+ clocks = <&cpg CPG_MOD 808>;
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ status = "disabled";
+-
+- ports {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- port@1 {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- reg = <1>;
+-
+- vin3csi20: endpoint@0 {
+- reg = <0>;
+- remote-endpoint= <&csi20vin3>;
+- };
+- vin3csi40: endpoint@2 {
+- reg = <2>;
+- remote-endpoint= <&csi40vin3>;
+- };
+- };
+- };
+ };
+
+ vin4: video@e6ef4000 {
+@@ -1712,27 +1628,6 @@
+ clocks = <&cpg CPG_MOD 807>;
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ status = "disabled";
+-
+- ports {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- port@1 {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- reg = <1>;
+-
+- vin4csi20: endpoint@0 {
+- reg = <0>;
+- remote-endpoint= <&csi20vin4>;
+- };
+- vin4csi40: endpoint@2 {
+- reg = <2>;
+- remote-endpoint= <&csi40vin4>;
+- };
+- };
+- };
+ };
+
+ vin5: video@e6ef5000 {
+@@ -1742,27 +1637,6 @@
+ clocks = <&cpg CPG_MOD 806>;
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ status = "disabled";
+-
+- ports {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- port@1 {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- reg = <1>;
+-
+- vin5csi20: endpoint@0 {
+- reg = <0>;
+- remote-endpoint= <&csi20vin5>;
+- };
+- vin5csi40: endpoint@2 {
+- reg = <2>;
+- remote-endpoint= <&csi40vin5>;
+- };
+- };
+- };
+ };
+
+ vin6: video@e6ef6000 {
+@@ -1772,27 +1646,6 @@
+ clocks = <&cpg CPG_MOD 805>;
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ status = "disabled";
+-
+- ports {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- port@1 {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- reg = <1>;
+-
+- vin6csi20: endpoint@0 {
+- reg = <0>;
+- remote-endpoint= <&csi20vin6>;
+- };
+- vin6csi40: endpoint@2 {
+- reg = <2>;
+- remote-endpoint= <&csi40vin6>;
+- };
+- };
+- };
+ };
+
+ vin7: video@e6ef7000 {
+@@ -1802,27 +1655,6 @@
+ clocks = <&cpg CPG_MOD 804>;
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ status = "disabled";
+-
+- ports {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- port@1 {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- reg = <1>;
+-
+- vin7csi20: endpoint@0 {
+- reg = <0>;
+- remote-endpoint= <&csi20vin7>;
+- };
+- vin7csi40: endpoint@2 {
+- reg = <2>;
+- remote-endpoint= <&csi40vin7>;
+- };
+- };
+- };
+ };
+
+ csi2_20: csi2@fea80000 {
+@@ -1832,51 +1664,6 @@
+ clocks = <&cpg CPG_MOD 714>;
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ status = "disabled";
+-
+- ports {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- port@1 {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- reg = <1>;
+-
+- csi20vin0: endpoint@0 {
+- reg = <0>;
+- remote-endpoint = <&vin0csi20>;
+- };
+- csi20vin1: endpoint@1 {
+- reg = <1>;
+- remote-endpoint = <&vin1csi20>;
+- };
+- csi20vin2: endpoint@2 {
+- reg = <2>;
+- remote-endpoint = <&vin2csi20>;
+- };
+- csi20vin3: endpoint@3 {
+- reg = <3>;
+- remote-endpoint = <&vin3csi20>;
+- };
+- csi20vin4: endpoint@4 {
+- reg = <4>;
+- remote-endpoint = <&vin4csi20>;
+- };
+- csi20vin5: endpoint@5 {
+- reg = <5>;
+- remote-endpoint = <&vin5csi20>;
+- };
+- csi20vin6: endpoint@6 {
+- reg = <6>;
+- remote-endpoint = <&vin6csi20>;
+- };
+- csi20vin7: endpoint@7 {
+- reg = <7>;
+- remote-endpoint = <&vin7csi20>;
+- };
+- };
+- };
+ };
+
+ csi2_40: csi2@feaa0000 {
+@@ -1886,51 +1673,6 @@
+ clocks = <&cpg CPG_MOD 716>;
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ status = "disabled";
+-
+- ports {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- port@1 {
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- reg = <1>;
+-
+- csi40vin0: endpoint@0 {
+- reg = <0>;
+- remote-endpoint = <&vin0csi40>;
+- };
+- csi40vin1: endpoint@1 {
+- reg = <1>;
+- remote-endpoint = <&vin1csi40>;
+- };
+- csi40vin2: endpoint@2 {
+- reg = <2>;
+- remote-endpoint = <&vin2csi40>;
+- };
+- csi40vin3: endpoint@3 {
+- reg = <3>;
+- remote-endpoint = <&vin3csi40>;
+- };
+- csi40vin4: endpoint@4 {
+- reg = <4>;
+- remote-endpoint = <&vin4csi40>;
+- };
+- csi40vin5: endpoint@5 {
+- reg = <5>;
+- remote-endpoint = <&vin5csi40>;
+- };
+- csi40vin6: endpoint@6 {
+- reg = <6>;
+- remote-endpoint = <&vin6csi40>;
+- };
+- csi40vin7: endpoint@7 {
+- reg = <7>;
+- remote-endpoint = <&vin7csi40>;
+- };
+- };
+- };
+ };
+
+ vcplf: vcp4@fe910000 {
+diff --git a/drivers/media/platform/soc_camera/Kconfig b/drivers/media/platform/soc_camera/Kconfig
+index 86d7478..17178ad 100644
+--- a/drivers/media/platform/soc_camera/Kconfig
++++ b/drivers/media/platform/soc_camera/Kconfig
+@@ -17,6 +17,32 @@ config SOC_CAMERA_PLATFORM
+ help
+ This is a generic SoC camera platform driver, useful for testing
+
++config VIDEO_RCAR_VIN_LEGACY
++ tristate "R-Car Video Input (VIN) support"
++ depends on VIDEO_DEV && SOC_CAMERA
++ depends on ARCH_RENESAS || COMPILE_TEST
++ depends on HAS_DMA
++ select VIDEOBUF2_DMA_CONTIG
++ select SOC_CAMERA_SCALE_CROP
++ ---help---
++ This is a v4l2 driver for the R-Car VIN Interface
++
++config VIDEO_RCAR_VIN_LEGACY_DEBUG
++ bool "Renesas VIN overflow debug messages"
++ depends on VIDEO_RCAR_VIN_LEGACY
++ ---help---
++ Enable debug overflow messages on R-Car Video
++ Input driver.
++ If you set to enable, When an overflow occurred,
++ a debug overflow message is output.
++
++config VIDEO_RCAR_CSI2_LEGACY
++ tristate "R-Car MIPI CSI-2 Interface driver"
++ depends on VIDEO_DEV && SOC_CAMERA && HAVE_CLK
++ depends on ARCH_R8A7795 || ARCH_R8A7796 || COMPILE_TEST
++ ---help---
++ This is a v4l2 driver for the R-Car CSI-2 Interface
++
+ config VIDEO_SH_MOBILE_CEU
+ tristate "SuperH Mobile CEU Interface driver"
+ depends on VIDEO_DEV && SOC_CAMERA && HAS_DMA && HAVE_CLK
+diff --git a/drivers/media/platform/soc_camera/Makefile b/drivers/media/platform/soc_camera/Makefile
+index 7633a0f..8c7ede6 100644
+--- a/drivers/media/platform/soc_camera/Makefile
++++ b/drivers/media/platform/soc_camera/Makefile
+@@ -8,3 +8,5 @@ obj-$(CONFIG_SOC_CAMERA_PLATFORM) += soc_camera_platform.o
+ # soc-camera host drivers have to be linked after camera drivers
+ obj-$(CONFIG_VIDEO_ATMEL_ISI) += atmel-isi.o
+ obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o
++obj-$(CONFIG_VIDEO_RCAR_CSI2_LEGACY) += rcar_csi2.o
++obj-$(CONFIG_VIDEO_RCAR_VIN_LEGACY) += rcar_vin.o
+diff --git a/drivers/media/platform/soc_camera/rcar_csi2.c b/drivers/media/platform/soc_camera/rcar_csi2.c
+new file mode 100644
+index 0000000..05f623468
+--- /dev/null
++++ b/drivers/media/platform/soc_camera/rcar_csi2.c
+@@ -0,0 +1,708 @@
++/*
++ * drivers/media/platform/soc_camera/rcar_csi2.c
++ * This file is the driver for the R-Car MIPI CSI-2 unit.
++ *
++ * Copyright (C) 2015-2016 Renesas Electronics Corporation
++ *
++ * This file is based on the drivers/media/platform/soc_camera/sh_mobile_csi2.c
++ *
++ * Driver for the SH-Mobile MIPI CSI-2 unit
++ *
++ * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++#include <linux/err.h>
++#include <linux/i2c.h>
++#include <linux/io.h>
++#include <linux/platform_device.h>
++#include <linux/pm_runtime.h>
++#include <linux/slab.h>
++#include <linux/videodev2.h>
++#include <linux/module.h>
++
++#include <media/rcar_csi2.h>
++#include <media/soc_camera.h>
++#include <media/v4l2-common.h>
++#include <media/v4l2-dev.h>
++#include <media/v4l2-device.h>
++#include <media/v4l2-mediabus.h>
++#include <media/v4l2-subdev.h>
++
++#include <media/v4l2-of.h>
++
++#define DRV_NAME "rcar_csi2"
++#define CONNECT_SLAVE_NAME "adv7482"
++#define VC_MAX_CHANNEL 4
++
++#define RCAR_CSI2_TREF 0x00
++#define RCAR_CSI2_SRST 0x04
++#define RCAR_CSI2_PHYCNT 0x08
++#define RCAR_CSI2_CHKSUM 0x0C
++#define RCAR_CSI2_VCDT 0x10
++
++#define RCAR_CSI2_VCDT2 0x14 /* Channel Data Type Select */
++#define RCAR_CSI2_FRDT 0x18 /* Frame Data Type Select */
++#define RCAR_CSI2_FLD 0x1C /* Field Detection Control */
++#define RCAR_CSI2_ASTBY 0x20 /* Automatic standby control */
++#define RCAR_CSI2_LNGDT0 0x28
++#define RCAR_CSI2_LNGDT1 0x2C
++#define RCAR_CSI2_INTEN 0x30
++#define RCAR_CSI2_INTCLOSE 0x34
++#define RCAR_CSI2_INTSTATE 0x38
++#define RCAR_CSI2_INTERRSTATE 0x3C
++
++#define RCAR_CSI2_SHPDAT 0x40
++#define RCAR_CSI2_SHPCNT 0x44
++
++#define RCAR_CSI2_LINKCNT 0x48
++#define RCAR_CSI2_LSWAP 0x4C
++#define RCAR_CSI2_PHTC 0x58
++#define RCAR_CSI2_PHYPLL 0x68
++
++#define RCAR_CSI2_PHEERM 0x74
++#define RCAR_CSI2_PHCLM 0x78
++#define RCAR_CSI2_PHDLM 0x7C
++
++#define RCAR_CSI2_PHYCNT_SHUTDOWNZ (1 << 17)
++#define RCAR_CSI2_PHYCNT_RSTZ (1 << 16)
++#define RCAR_CSI2_PHYCNT_ENABLECLK (1 << 4)
++#define RCAR_CSI2_PHYCNT_ENABLE_3 (1 << 3)
++#define RCAR_CSI2_PHYCNT_ENABLE_2 (1 << 2)
++#define RCAR_CSI2_PHYCNT_ENABLE_1 (1 << 1)
++#define RCAR_CSI2_PHYCNT_ENABLE_0 (1 << 0)
++
++#define RCAR_CSI2_VCDT_VCDTN_EN (1 << 15)
++#define RCAR_CSI2_VCDT_SEL_VCN (1 << 8)
++#define RCAR_CSI2_VCDT_SEL_DTN_ON (1 << 6)
++#define RCAR_CSI2_VCDT_SEL_DTN (1 << 0)
++
++#define RCAR_CSI2_LINKCNT_MONITOR_EN (1 << 31)
++#define RCAR_CSI2_LINKCNT_REG_MONI_PACT_EN (1 << 25)
++
++#define RCAR_CSI2_LSWAP_L3SEL_PLANE0 (0 << 6)
++#define RCAR_CSI2_LSWAP_L3SEL_PLANE1 (1 << 6)
++#define RCAR_CSI2_LSWAP_L3SEL_PLANE2 (2 << 6)
++#define RCAR_CSI2_LSWAP_L3SEL_PLANE3 (3 << 6)
++
++#define RCAR_CSI2_LSWAP_L2SEL_PLANE0 (0 << 4)
++#define RCAR_CSI2_LSWAP_L2SEL_PLANE1 (1 << 4)
++#define RCAR_CSI2_LSWAP_L2SEL_PLANE2 (2 << 4)
++#define RCAR_CSI2_LSWAP_L2SEL_PLANE3 (3 << 4)
++
++#define RCAR_CSI2_LSWAP_L1SEL_PLANE0 (0 << 2)
++#define RCAR_CSI2_LSWAP_L1SEL_PLANE1 (1 << 2)
++#define RCAR_CSI2_LSWAP_L1SEL_PLANE2 (2 << 2)
++#define RCAR_CSI2_LSWAP_L1SEL_PLANE3 (3 << 2)
++
++#define RCAR_CSI2_LSWAP_L0SEL_PLANE0 (0 << 0)
++#define RCAR_CSI2_LSWAP_L0SEL_PLANE1 (1 << 0)
++#define RCAR_CSI2_LSWAP_L0SEL_PLANE2 (2 << 0)
++#define RCAR_CSI2_LSWAP_L0SEL_PLANE3 (3 << 0)
++
++#define RCAR_CSI2_PHTC_TESTCLR (1 << 0)
++
++/* interrupt status registers */
++#define RCAR_CSI2_INTSTATE_EBD_CH1 (1 << 29)
++#define RCAR_CSI2_INTSTATE_LESS_THAN_WC (1 << 28)
++#define RCAR_CSI2_INTSTATE_AFIFO_OF (1 << 27)
++#define RCAR_CSI2_INTSTATE_VD4_START (1 << 26)
++#define RCAR_CSI2_INTSTATE_VD4_END (1 << 25)
++#define RCAR_CSI2_INTSTATE_VD3_START (1 << 24)
++#define RCAR_CSI2_INTSTATE_VD3_END (1 << 23)
++#define RCAR_CSI2_INTSTATE_VD2_START (1 << 22)
++#define RCAR_CSI2_INTSTATE_VD2_END (1 << 21)
++#define RCAR_CSI2_INTSTATE_VD1_START (1 << 20)
++#define RCAR_CSI2_INTSTATE_VD1_END (1 << 19)
++#define RCAR_CSI2_INTSTATE_SHP (1 << 18)
++#define RCAR_CSI2_INTSTATE_FSFE (1 << 17)
++#define RCAR_CSI2_INTSTATE_LNP (1 << 16)
++#define RCAR_CSI2_INTSTATE_CRC_ERR (1 << 15)
++#define RCAR_CSI2_INTSTATE_HD_WC_ZERO (1 << 14)
++#define RCAR_CSI2_INTSTATE_FRM_SEQ_ERR1 (1 << 13)
++#define RCAR_CSI2_INTSTATE_FRM_SEQ_ERR2 (1 << 12)
++#define RCAR_CSI2_INTSTATE_ECC_ERR (1 << 11)
++#define RCAR_CSI2_INTSTATE_ECC_CRCT_ERR (1 << 10)
++#define RCAR_CSI2_INTSTATE_LPDT_START (1 << 9)
++#define RCAR_CSI2_INTSTATE_LPDT_END (1 << 8)
++#define RCAR_CSI2_INTSTATE_ULPS_START (1 << 7)
++#define RCAR_CSI2_INTSTATE_ULPS_END (1 << 6)
++#define RCAR_CSI2_INTSTATE_RESERVED (1 << 5)
++#define RCAR_CSI2_INTSTATE_ERRSOTHS (1 << 4)
++#define RCAR_CSI2_INTSTATE_ERRSOTSYNCCHS (1 << 3)
++#define RCAR_CSI2_INTSTATE_ERRESC (1 << 2)
++#define RCAR_CSI2_INTSTATE_ERRSYNCESC (1 << 1)
++#define RCAR_CSI2_INTSTATE_ERRCONTROL (1 << 0)
++
++/* monitoring registers of interrupt error status */
++#define RCAR_CSI2_INTSTATE_ECC_ERR (1 << 11)
++#define RCAR_CSI2_INTSTATE_ECC_CRCT_ERR (1 << 10)
++#define RCAR_CSI2_INTSTATE_LPDT_START (1 << 9)
++#define RCAR_CSI2_INTSTATE_LPDT_END (1 << 8)
++#define RCAR_CSI2_INTSTATE_ULPS_START (1 << 7)
++#define RCAR_CSI2_INTSTATE_ULPS_END (1 << 6)
++#define RCAR_CSI2_INTSTATE_RESERVED (1 << 5)
++#define RCAR_CSI2_INTSTATE_ERRSOTHS (1 << 4)
++#define RCAR_CSI2_INTSTATE_ERRSOTSYNCCHS (1 << 3)
++#define RCAR_CSI2_INTSTATE_ERRESC (1 << 2)
++#define RCAR_CSI2_INTSTATE_ERRSYNCESC (1 << 1)
++#define RCAR_CSI2_INTSTATE_ERRCONTROL (1 << 0)
++
++enum chip_id {
++ RCAR_GEN3,
++ RCAR_GEN2,
++};
++
++enum decoder_input_interface {
++ DECODER_INPUT_INTERFACE_RGB888,
++ DECODER_INPUT_INTERFACE_YCBCR422,
++ DECODER_INPUT_INTERFACE_NONE,
++};
++
++/**
++ * struct rcar_csi2_link_config - Describes rcar_csi2 hardware configuration
++ * @input_colorspace: The input colorspace (RGB, YUV444, YUV422)
++ */
++struct rcar_csi2_link_config {
++ enum decoder_input_interface input_interface;
++ unsigned char lanes;
++ unsigned long vcdt;
++ unsigned long vcdt2;
++};
++
++#define INIT_RCAR_CSI2_LINK_CONFIG(m) \
++{ \
++ m.input_interface = DECODER_INPUT_INTERFACE_NONE; \
++ m.lanes = 0; \
++}
++
++struct rcar_csi_irq_counter_log {
++ unsigned long crc_err;
++};
++
++struct rcar_csi2 {
++ struct v4l2_subdev subdev;
++ struct v4l2_mbus_framefmt *mf;
++ unsigned int irq;
++ unsigned long mipi_flags;
++ void __iomem *base;
++ struct platform_device *pdev;
++ struct rcar_csi2_client_config *client;
++ unsigned long vcdt;
++ unsigned long vcdt2;
++
++ unsigned int field;
++ unsigned int code;
++ unsigned int lanes;
++ spinlock_t lock;
++};
++
++#define RCAR_CSI_80MBPS 0
++#define RCAR_CSI_90MBPS 1
++#define RCAR_CSI_100MBPS 2
++#define RCAR_CSI_110MBPS 3
++#define RCAR_CSI_120MBPS 4
++#define RCAR_CSI_130MBPS 5
++#define RCAR_CSI_140MBPS 6
++#define RCAR_CSI_150MBPS 7
++#define RCAR_CSI_160MBPS 8
++#define RCAR_CSI_170MBPS 9
++#define RCAR_CSI_180MBPS 10
++#define RCAR_CSI_190MBPS 11
++#define RCAR_CSI_205MBPS 12
++#define RCAR_CSI_220MBPS 13
++#define RCAR_CSI_235MBPS 14
++#define RCAR_CSI_250MBPS 15
++#define RCAR_CSI_275MBPS 16
++#define RCAR_CSI_300MBPS 17
++#define RCAR_CSI_325MBPS 18
++#define RCAR_CSI_350MBPS 19
++#define RCAR_CSI_400MBPS 20
++#define RCAR_CSI_450MBPS 21
++#define RCAR_CSI_500MBPS 22
++#define RCAR_CSI_550MBPS 23
++#define RCAR_CSI_600MBPS 24
++#define RCAR_CSI_650MBPS 25
++#define RCAR_CSI_700MBPS 26
++#define RCAR_CSI_750MBPS 27
++#define RCAR_CSI_800MBPS 28
++#define RCAR_CSI_850MBPS 29
++#define RCAR_CSI_900MBPS 30
++#define RCAR_CSI_950MBPS 31
++#define RCAR_CSI_1000MBPS 32
++#define RCAR_CSI_1050MBPS 33
++#define RCAR_CSI_1100MBPS 34
++#define RCAR_CSI_1150MBPS 35
++#define RCAR_CSI_1200MBPS 36
++#define RCAR_CSI_1250MBPS 37
++#define RCAR_CSI_1300MBPS 38
++#define RCAR_CSI_1350MBPS 39
++#define RCAR_CSI_1400MBPS 40
++#define RCAR_CSI_1450MBPS 41
++#define RCAR_CSI_1500MBPS 42
++
++static int rcar_csi2_set_phy_freq(struct rcar_csi2 *priv)
++{
++ const uint32_t const hs_freq_range[43] = {
++ 0x00, 0x10, 0x20, 0x30, 0x01, /* 0-4 */
++ 0x11, 0x21, 0x31, 0x02, 0x12, /* 5-9 */
++ 0x22, 0x32, 0x03, 0x13, 0x23, /* 10-14 */
++ 0x33, 0x04, 0x14, 0x05, 0x15, /* 15-19 */
++ 0x25, 0x06, 0x16, 0x07, 0x17, /* 20-24 */
++ 0x08, 0x18, 0x09, 0x19, 0x29, /* 25-29 */
++ 0x39, 0x0A, 0x1A, 0x2A, 0x3A, /* 30-34 */
++ 0x0B, 0x1B, 0x2B, 0x3B, 0x0C, /* 35-39 */
++ 0x1C, 0x2C, 0x3C /* 40-42 */
++ };
++ uint32_t bps_per_lane = RCAR_CSI_190MBPS;
++
++ dev_dbg(&priv->pdev->dev, "Input size (%dx%d%c)\n",
++ priv->mf->width, priv->mf->height,
++ (priv->mf->field == V4L2_FIELD_NONE) ? 'p' : 'i');
++
++ switch (priv->lanes) {
++ case 1:
++ bps_per_lane = RCAR_CSI_400MBPS;
++ break;
++ case 4:
++ if (priv->mf->field == V4L2_FIELD_NONE) {
++ if ((priv->mf->width == 1920) &&
++ (priv->mf->height == 1080))
++ bps_per_lane = RCAR_CSI_900MBPS;
++ else if ((priv->mf->width == 1280) &&
++ (priv->mf->height == 720))
++ bps_per_lane = RCAR_CSI_450MBPS;
++ else if ((priv->mf->width == 720) &&
++ (priv->mf->height == 480))
++ bps_per_lane = RCAR_CSI_190MBPS;
++ else if ((priv->mf->width == 720) &&
++ (priv->mf->height == 576))
++ bps_per_lane = RCAR_CSI_190MBPS;
++ else if ((priv->mf->width == 640) &&
++ (priv->mf->height == 480))
++ bps_per_lane = RCAR_CSI_100MBPS;
++ else
++ goto error;
++ } else {
++ if ((priv->mf->width == 1920) &&
++ (priv->mf->height == 1080))
++ bps_per_lane = RCAR_CSI_450MBPS;
++ else
++ goto error;
++ }
++ break;
++ default:
++ dev_err(&priv->pdev->dev, "ERROR: lanes is invalid (%d)\n",
++ priv->lanes);
++ return -EINVAL;
++ }
++
++ dev_dbg(&priv->pdev->dev, "bps_per_lane (%d)\n", bps_per_lane);
++
++ iowrite32((hs_freq_range[bps_per_lane] << 16),
++ priv->base + RCAR_CSI2_PHYPLL);
++ return 0;
++
++error:
++ dev_err(&priv->pdev->dev, "Not support resolution (%dx%d%c)\n",
++ priv->mf->width, priv->mf->height,
++ (priv->mf->field == V4L2_FIELD_NONE) ? 'p' : 'i');
++ return -EINVAL;
++}
++
++static irqreturn_t rcar_csi2_irq(int irq, void *data)
++{
++ struct rcar_csi2 *priv = data;
++ u32 int_status;
++ unsigned int handled = 0;
++
++ spin_lock(&priv->lock);
++
++ int_status = ioread32(priv->base + RCAR_CSI2_INTSTATE);
++ if (!int_status)
++ goto done;
++
++ /* ack interrupts */
++ iowrite32(int_status, priv->base + RCAR_CSI2_INTSTATE);
++ handled = 1;
++
++done:
++ spin_unlock(&priv->lock);
++
++ return IRQ_RETVAL(handled);
++
++}
++
++static void rcar_csi2_hwdeinit(struct rcar_csi2 *priv)
++{
++ iowrite32(0, priv->base + RCAR_CSI2_PHYCNT);
++
++ /* reset CSI2 hardware */
++ iowrite32(0x00000001, priv->base + RCAR_CSI2_SRST);
++ udelay(5);
++ iowrite32(0x00000000, priv->base + RCAR_CSI2_SRST);
++}
++
++static int rcar_csi2_hwinit(struct rcar_csi2 *priv)
++{
++ int ret;
++ __u32 tmp = 0x10; /* Enable MIPI CSI clock lane */
++
++ /* Reflect registers immediately */
++ iowrite32(0x00000001, priv->base + RCAR_CSI2_TREF);
++ /* reset CSI2 hardware */
++ iowrite32(0x00000001, priv->base + RCAR_CSI2_SRST);
++ udelay(5);
++ iowrite32(0x00000000, priv->base + RCAR_CSI2_SRST);
++
++ iowrite32(0x00000000, priv->base + RCAR_CSI2_PHTC);
++
++ /* setting HS reception frequency */
++ {
++ switch (priv->lanes) {
++ case 1:
++ /* First field number setting */
++ iowrite32(0x0001000f, priv->base + RCAR_CSI2_FLD);
++ tmp |= 0x1;
++ break;
++ case 4:
++ /* First field number setting */
++ iowrite32(0x0002000f, priv->base + RCAR_CSI2_FLD);
++ tmp |= 0xF;
++ break;
++ default:
++ dev_err(&priv->pdev->dev,
++ "ERROR: lanes is invalid (%d)\n",
++ priv->lanes);
++ return -EINVAL;
++ }
++
++ /* set PHY frequency */
++ ret = rcar_csi2_set_phy_freq(priv);
++ if (ret < 0)
++ return ret;
++
++ /* Enable lanes */
++ iowrite32(tmp, priv->base + RCAR_CSI2_PHYCNT);
++
++ iowrite32(tmp | RCAR_CSI2_PHYCNT_SHUTDOWNZ,
++ priv->base + RCAR_CSI2_PHYCNT);
++ iowrite32(tmp | (RCAR_CSI2_PHYCNT_SHUTDOWNZ |
++ RCAR_CSI2_PHYCNT_RSTZ),
++ priv->base + RCAR_CSI2_PHYCNT);
++ }
++
++ iowrite32(0x00000003, priv->base + RCAR_CSI2_CHKSUM);
++ iowrite32(priv->vcdt, priv->base + RCAR_CSI2_VCDT);
++ iowrite32(priv->vcdt2, priv->base + RCAR_CSI2_VCDT2);
++ iowrite32(0x00010000, priv->base + RCAR_CSI2_FRDT);
++ udelay(10);
++ iowrite32(0x83000000, priv->base + RCAR_CSI2_LINKCNT);
++ iowrite32(0x000000e4, priv->base + RCAR_CSI2_LSWAP);
++
++ dev_dbg(&priv->pdev->dev, "CSI2 VCDT: 0x%x\n",
++ ioread32(priv->base + RCAR_CSI2_VCDT));
++ dev_dbg(&priv->pdev->dev, "CSI2 VCDT2: 0x%x\n",
++ ioread32(priv->base + RCAR_CSI2_VCDT2));
++
++ /* wait until video decoder power off */
++ msleep(10);
++ {
++ int timeout = 100;
++
++ /* Read the PHY clock lane monitor register (PHCLM). */
++ while (!(ioread32(priv->base + RCAR_CSI2_PHCLM) & 0x01)
++ && timeout) {
++ timeout--;
++ }
++ if (timeout == 0)
++ dev_err(&priv->pdev->dev,
++ "Timeout of reading the PHY clock lane\n");
++ else
++ dev_dbg(&priv->pdev->dev,
++ "Detected the PHY clock lane\n");
++
++ timeout = 100;
++
++ /* Read the PHY data lane monitor register (PHDLM). */
++ while (!(ioread32(priv->base + RCAR_CSI2_PHDLM) & 0x01)
++ && timeout) {
++ timeout--;
++ }
++ if (timeout == 0)
++ dev_err(&priv->pdev->dev,
++ "Timeout of reading the PHY data lane\n");
++ else
++ dev_dbg(&priv->pdev->dev,
++ "Detected the PHY data lane\n");
++ }
++
++ return 0;
++}
++
++static int rcar_csi2_s_power(struct v4l2_subdev *sd, int on)
++{
++ struct rcar_csi2 *priv = container_of(sd, struct rcar_csi2, subdev);
++ struct v4l2_subdev *tmp_sd;
++ struct v4l2_subdev_format fmt = {
++ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
++ };
++ struct v4l2_mbus_framefmt *mf = &fmt.format;
++ int ret = 0;
++
++ if (on) {
++ v4l2_device_for_each_subdev(tmp_sd, sd->v4l2_dev) {
++ if (strncmp(tmp_sd->name, CONNECT_SLAVE_NAME,
++ sizeof(CONNECT_SLAVE_NAME) - 1) == 0) {
++ v4l2_subdev_call(tmp_sd, pad, get_fmt,
++ NULL, &fmt);
++ if (ret < 0)
++ return ret;
++ }
++ }
++ priv->mf = mf;
++ pm_runtime_get_sync(&priv->pdev->dev);
++ ret = rcar_csi2_hwinit(priv);
++ if (ret < 0)
++ return ret;
++ } else {
++ rcar_csi2_hwdeinit(priv);
++ pm_runtime_put_sync(&priv->pdev->dev);
++ }
++
++ return ret;
++}
++
++static struct v4l2_subdev_core_ops rcar_csi2_subdev_core_ops = {
++ .s_power = rcar_csi2_s_power,
++};
++
++static struct v4l2_subdev_ops rcar_csi2_subdev_ops = {
++ .core = &rcar_csi2_subdev_core_ops,
++};
++
++#ifdef CONFIG_OF
++static const struct of_device_id rcar_csi2_of_table[] = {
++ { .compatible = "renesas,r8a7796-csi2", .data = (void *)RCAR_GEN3 },
++ { .compatible = "renesas,r8a7795-csi2", .data = (void *)RCAR_GEN3 },
++ { },
++};
++MODULE_DEVICE_TABLE(of, rcar_csi2_of_table);
++#endif
++
++static struct platform_device_id rcar_csi2_id_table[] = {
++ { "r8a7796-csi2", RCAR_GEN3 },
++ { "r8a7795-csi2", RCAR_GEN3 },
++ {},
++};
++MODULE_DEVICE_TABLE(platform, rcar_csi2_id_table);
++
++static int rcar_csi2_parse_dt(struct device_node *np,
++ struct rcar_csi2_link_config *config)
++{
++ struct v4l2_of_endpoint bus_cfg;
++ struct device_node *endpoint;
++ struct device_node *vc_np, *vc_ch;
++ const char *str;
++ char csi_name[9];
++ int ret;
++ int i, ch;
++
++ /* Parse the endpoint. */
++ endpoint = of_graph_get_next_endpoint(np, NULL);
++ if (!endpoint)
++ return -EINVAL;
++
++ v4l2_of_parse_endpoint(endpoint, &bus_cfg);
++ of_node_put(endpoint);
++
++ config->lanes = bus_cfg.bus.mipi_csi2.num_data_lanes;
++
++ ret = of_property_read_string(np, "adi,input-interface", &str);
++ if (ret < 0)
++ return ret;
++
++ vc_np = of_get_child_by_name(np, "virtual,channel");
++
++ config->vcdt = 0;
++ config->vcdt2 = 0;
++ for (i = 0; i < VC_MAX_CHANNEL; i++) {
++ sprintf(csi_name, "csi2_vc%d", i);
++
++ vc_ch = of_get_child_by_name(vc_np, csi_name);
++ if (!vc_ch)
++ continue;
++ ret = of_property_read_string(vc_ch, "data,type", &str);
++ if (ret < 0)
++ return ret;
++ ret = of_property_read_u32(vc_ch, "receive,vc", &ch);
++ if (ret < 0)
++ return ret;
++
++ if (i < 2) {
++ if (!strcmp(str, "rgb888"))
++ config->vcdt |= (0x24 << (i * 16));
++ else if (!strcmp(str, "ycbcr422"))
++ config->vcdt |= (0x1e << (i * 16));
++ else
++ config->vcdt |= 0;
++
++ config->vcdt |= (ch << (8 + (i * 16)));
++ config->vcdt |= (RCAR_CSI2_VCDT_VCDTN_EN << (i * 16)) |
++ (RCAR_CSI2_VCDT_SEL_DTN_ON << (i * 16));
++ }
++ if (i >= 2) {
++ int j = (i - 2);
++
++ if (!strcmp(str, "rgb888"))
++ config->vcdt2 |= (0x24 << (j * 16));
++ else if (!strcmp(str, "ycbcr422"))
++ config->vcdt2 |= (0x1e << (j * 16));
++ else
++ config->vcdt2 |= 0;
++
++ config->vcdt2 |= (ch << (8 + (j * 16)));
++ config->vcdt2 |= (RCAR_CSI2_VCDT_VCDTN_EN << (j * 16)) |
++ (RCAR_CSI2_VCDT_SEL_DTN_ON << (j * 16));
++ }
++ }
++
++ return 0;
++}
++
++static int rcar_csi2_probe(struct platform_device *pdev)
++{
++ struct resource *res;
++ unsigned int irq;
++ int ret;
++ struct rcar_csi2 *priv;
++ /* Platform data specify the PHY, lanes, ECC, CRC */
++ struct rcar_csi2_pdata *pdata;
++ struct rcar_csi2_link_config link_config;
++
++ dev_dbg(&pdev->dev, "CSI2 probed.\n");
++
++ INIT_RCAR_CSI2_LINK_CONFIG(link_config);
++
++ if (pdev->dev.of_node) {
++ ret = rcar_csi2_parse_dt(pdev->dev.of_node, &link_config);
++ if (ret)
++ return ret;
++
++ if (link_config.lanes == 4)
++ dev_info(&pdev->dev,
++ "Detected rgb888 in rcar_csi2_parse_dt\n");
++ else
++ dev_info(&pdev->dev,
++ "Detected YCbCr422 in rcar_csi2_parse_dt\n");
++ } else {
++ pdata = pdev->dev.platform_data;
++ if (!pdata)
++ return -EINVAL;
++ }
++
++ priv = devm_kzalloc(&pdev->dev, sizeof(struct rcar_csi2), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ /* Interrupt unused so far */
++ irq = platform_get_irq(pdev, 0);
++
++ if (!res || (int)irq <= 0) {
++ dev_err(&pdev->dev, "Not enough CSI2 platform resources.\n");
++ return -ENODEV;
++ }
++
++ priv->irq = irq;
++
++ priv->base = devm_ioremap_resource(&pdev->dev, res);
++ if (IS_ERR(priv->base))
++ return PTR_ERR(priv->base);
++
++ ret = devm_request_irq(&pdev->dev, irq, rcar_csi2_irq, IRQF_SHARED,
++ dev_name(&pdev->dev), priv);
++ if (ret)
++ return ret;
++
++ priv->pdev = pdev;
++ priv->subdev.owner = THIS_MODULE;
++ priv->subdev.dev = &pdev->dev;
++ priv->lanes = link_config.lanes;
++ priv->vcdt = link_config.vcdt;
++ priv->vcdt2 = link_config.vcdt2;
++
++ platform_set_drvdata(pdev, &priv->subdev);
++
++ v4l2_subdev_init(&priv->subdev, &rcar_csi2_subdev_ops);
++ v4l2_set_subdevdata(&priv->subdev, &pdev->dev);
++
++ snprintf(priv->subdev.name, V4L2_SUBDEV_NAME_SIZE, "rcar_csi2.%s",
++ dev_name(&pdev->dev));
++
++ ret = v4l2_async_register_subdev(&priv->subdev);
++ if (ret < 0)
++ return ret;
++
++ spin_lock_init(&priv->lock);
++
++ pm_runtime_enable(&pdev->dev);
++
++ dev_dbg(&pdev->dev, "CSI2 probed.\n");
++
++ return 0;
++}
++
++static int rcar_csi2_remove(struct platform_device *pdev)
++{
++ struct v4l2_subdev *subdev = platform_get_drvdata(pdev);
++ struct rcar_csi2 *priv = container_of(subdev, struct rcar_csi2, subdev);
++
++ v4l2_async_unregister_subdev(&priv->subdev);
++ pm_runtime_disable(&pdev->dev);
++
++ return 0;
++}
++
++#ifdef CONFIG_PM_SLEEP
++static int rcar_csi2_suspend(struct device *dev)
++{
++ /* Empty function for now */
++ return 0;
++}
++
++static int rcar_csi2_resume(struct device *dev)
++{
++ /* Empty function for now */
++ return 0;
++}
++
++static SIMPLE_DEV_PM_OPS(rcar_csi2_pm_ops,
++ rcar_csi2_suspend, rcar_csi2_resume);
++#define DEV_PM_OPS (&rcar_csi2_pm_ops)
++#else
++#define DEV_PM_OPS NULL
++#endif /* CONFIG_PM_SLEEP */
++
++static struct platform_driver __refdata rcar_csi2_pdrv = {
++ .remove = rcar_csi2_remove,
++ .probe = rcar_csi2_probe,
++ .driver = {
++ .name = DRV_NAME,
++ .pm = DEV_PM_OPS,
++ .of_match_table = of_match_ptr(rcar_csi2_of_table),
++ },
++ .id_table = rcar_csi2_id_table,
++};
++
++module_platform_driver(rcar_csi2_pdrv);
++
++MODULE_DESCRIPTION("Renesas R-Car MIPI CSI-2 driver");
++MODULE_AUTHOR("Koji Matsuoka <koji.matsuoka.xm@renesas.com>");
++MODULE_LICENSE("GPL v2");
++MODULE_ALIAS("platform:rcar-csi2");
+diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c
+new file mode 100644
+index 0000000..400958b
+--- /dev/null
++++ b/drivers/media/platform/soc_camera/rcar_vin.c
+@@ -0,0 +1,3071 @@
++/*
++ * SoC-camera host driver for Renesas R-Car VIN unit
++ *
++ * Copyright (C) 2015-2016 Renesas Electronics Corporation
++ * Copyright (C) 2011-2013 Renesas Solutions Corp.
++ * Copyright (C) 2013 Cogent Embedded, Inc., <source@cogentembedded.com>
++ *
++ * Based on V4L2 Driver for SuperH Mobile CEU interface "sh_mobile_ceu_camera.c"
++ *
++ * Copyright (C) 2008 Magnus Damm
++ *
++ * 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.
++ */
++
++#ifdef CONFIG_VIDEO_RCAR_VIN_LEGACY_DEBUG
++#define DEBUG
++#endif
++
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++#include <linux/io.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/platform_device.h>
++#include <linux/pm_runtime.h>
++#include <linux/slab.h>
++#include <linux/videodev2.h>
++#include <linux/list.h>
++
++#include <media/soc_camera.h>
++#include <media/drv-intf/soc_mediabus.h>
++#include <media/v4l2-common.h>
++#include <media/v4l2-dev.h>
++#include <media/v4l2-device.h>
++#include <media/v4l2-mediabus.h>
++#include <media/v4l2-of.h>
++#include <media/v4l2-subdev.h>
++#include <media/videobuf2-dma-contig.h>
++
++#include <media/rcar_csi2.h>
++
++#include "soc_scale_crop.h"
++
++#define DRV_NAME "rcar_vin"
++
++/* Register offsets for R-Car VIN */
++#define VNMC_REG 0x00 /* Video n Main Control Register */
++#define VNMS_REG 0x04 /* Video n Module Status Register */
++#define VNFC_REG 0x08 /* Video n Frame Capture Register */
++#define VNSLPRC_REG 0x0C /* Video n Start Line Pre-Clip Register */
++#define VNELPRC_REG 0x10 /* Video n End Line Pre-Clip Register */
++#define VNSPPRC_REG 0x14 /* Video n Start Pixel Pre-Clip Register */
++#define VNEPPRC_REG 0x18 /* Video n End Pixel Pre-Clip Register */
++#define VNSLPOC_REG 0x1C /* Video n Start Line Post-Clip Register */
++#define VNELPOC_REG 0x20 /* Video n End Line Post-Clip Register */
++#define VNSPPOC_REG 0x24 /* Video n Start Pixel Post-Clip Register */
++#define VNEPPOC_REG 0x28 /* Video n End Pixel Post-Clip Register */
++#define VNIS_REG 0x2C /* Video n Image Stride Register */
++#define VNMB_REG(m) (0x30 + ((m) << 2)) /* Video n Memory Base m Register */
++#define VNIE_REG 0x40 /* Video n Interrupt Enable Register */
++#define VNINTS_REG 0x44 /* Video n Interrupt Status Register */
++#define VNSI_REG 0x48 /* Video n Scanline Interrupt Register */
++#define VNMTC_REG 0x4C /* Video n Memory Transfer Control Register */
++#define VNYS_REG 0x50 /* Video n Y Scale Register */
++#define VNXS_REG 0x54 /* Video n X Scale Register */
++#define VNDMR_REG 0x58 /* Video n Data Mode Register */
++#define VNDMR2_REG 0x5C /* Video n Data Mode Register 2 */
++#define VNUVAOF_REG 0x60 /* Video n UV Address Offset Register */
++#define VNC1A_REG 0x80 /* Video n Coefficient Set C1A Register */
++#define VNC1B_REG 0x84 /* Video n Coefficient Set C1B Register */
++#define VNC1C_REG 0x88 /* Video n Coefficient Set C1C Register */
++#define VNC2A_REG 0x90 /* Video n Coefficient Set C2A Register */
++#define VNC2B_REG 0x94 /* Video n Coefficient Set C2B Register */
++#define VNC2C_REG 0x98 /* Video n Coefficient Set C2C Register */
++#define VNC3A_REG 0xA0 /* Video n Coefficient Set C3A Register */
++#define VNC3B_REG 0xA4 /* Video n Coefficient Set C3B Register */
++#define VNC3C_REG 0xA8 /* Video n Coefficient Set C3C Register */
++#define VNC4A_REG 0xB0 /* Video n Coefficient Set C4A Register */
++#define VNC4B_REG 0xB4 /* Video n Coefficient Set C4B Register */
++#define VNC4C_REG 0xB8 /* Video n Coefficient Set C4C Register */
++#define VNC5A_REG 0xC0 /* Video n Coefficient Set C5A Register */
++#define VNC5B_REG 0xC4 /* Video n Coefficient Set C5B Register */
++#define VNC5C_REG 0xC8 /* Video n Coefficient Set C5C Register */
++#define VNC6A_REG 0xD0 /* Video n Coefficient Set C6A Register */
++#define VNC6B_REG 0xD4 /* Video n Coefficient Set C6B Register */
++#define VNC6C_REG 0xD8 /* Video n Coefficient Set C6C Register */
++#define VNC7A_REG 0xE0 /* Video n Coefficient Set C7A Register */
++#define VNC7B_REG 0xE4 /* Video n Coefficient Set C7B Register */
++#define VNC7C_REG 0xE8 /* Video n Coefficient Set C7C Register */
++#define VNC8A_REG 0xF0 /* Video n Coefficient Set C8A Register */
++#define VNC8B_REG 0xF4 /* Video n Coefficient Set C8B Register */
++#define VNC8C_REG 0xF8 /* Video n Coefficient Set C8C Register */
++
++/* Register bit fields for R-Car VIN */
++/* Video n Main Control Register bits */
++#define VNMC_DPINE (1 << 27)
++#define VNMC_SCLE (1 << 26)
++#define VNMC_FOC (1 << 21)
++#define VNMC_YCAL (1 << 19)
++#define VNMC_INF_YUV8_BT656 (0 << 16)
++#define VNMC_INF_YUV8_BT601 (1 << 16)
++#define VNMC_INF_YUV10_BT656 (2 << 16)
++#define VNMC_INF_YUV10_BT601 (3 << 16)
++#define VNMC_INF_YUV16 (5 << 16)
++#define VNMC_INF_RGB888 (6 << 16)
++#define VNMC_INF_MASK (7 << 16)
++#define VNMC_VUP (1 << 10)
++#define VNMC_IM_ODD (0 << 3)
++#define VNMC_IM_ODD_EVEN (1 << 3)
++#define VNMC_IM_EVEN (2 << 3)
++#define VNMC_IM_FULL (3 << 3)
++#define VNMC_BPS (1 << 1)
++#define VNMC_ME (1 << 0)
++
++/* Video n Module Status Register bits */
++#define VNMS_FBS_MASK (3 << 3)
++#define VNMS_FBS_SHIFT 3
++#define VNMS_AV (1 << 1)
++#define VNMS_CA (1 << 0)
++
++/* Video n Frame Capture Register bits */
++#define VNFC_C_FRAME (1 << 1)
++#define VNFC_S_FRAME (1 << 0)
++
++/* Video n Interrupt Enable Register bits */
++#define VNIE_FIE (1 << 4)
++#define VNIE_EFE (1 << 1)
++#define VNIE_FOE (1 << 0)
++
++/* Video n Interrupt Status Register bits */
++#define VNINTS_FIS (1 << 4)
++#define VNINTS_EFS (1 << 1)
++#define VNINTS_FOS (1 << 0)
++
++/* Video n Data Mode Register bits */
++#define VNDMR_EXRGB (1 << 8)
++#define VNDMR_BPSM (1 << 4)
++#define VNDMR_DTMD_YCSEP (1 << 1)
++#define VNDMR_DTMD_ARGB (1 << 0)
++#define VNDMR_DTMD_YCSEP_YCBCR420 (3 << 0)
++
++/* Video n Data Mode Register 2 bits */
++#define VNDMR2_VPS (1 << 30)
++#define VNDMR2_HPS (1 << 29)
++#define VNDMR2_FTEV (1 << 17)
++#define VNDMR2_VLV(n) ((n & 0xf) << 12)
++
++/* setting CSI2 on R-Car Gen3*/
++#define VNCSI_IFMD_REG 0x20 /* Video n CSI2 Interface Mode Register */
++
++#define VNCSI_IFMD_DES1 (1 << 26) /* CSI20 */
++#define VNCSI_IFMD_DES0 (1 << 25) /* H3:CSI40/41, M3:CSI40 */
++
++#define VNCSI_IFMD_CSI_CHSEL(n) (n << 0)
++#define VNCSI_IFMD_SEL_NUMBER 5
++
++/* UDS */
++#define VNUDS_CTRL_REG 0x80 /* Scaling Control Registers */
++#define VNUDS_CTRL_AMD (1 << 30)
++#define VNUDS_CTRL_BC (1 << 20)
++#define VNUDS_CTRL_TDIPC (1 << 1)
++
++#define VNUDS_SCALE_REG 0x84 /* Scaling Factor Register */
++#define VNUDS_PASS_BWIDTH_REG 0x90 /* Passband Registers */
++#define VNUDS_IPC_REG 0x98 /* 2D IPC Setting Register */
++#define VNUDS_CLIP_SIZE_REG 0xA4 /* UDS Output Size Clipping Register */
++
++#define TIMEOUT_MS 100
++
++#define RCAR_VIN_HSYNC_ACTIVE_LOW (1 << 0)
++#define RCAR_VIN_VSYNC_ACTIVE_LOW (1 << 1)
++#define RCAR_VIN_BT601 (1 << 2)
++#define RCAR_VIN_BT656 (1 << 3)
++#define RCAR_VIN_CSI2 (1 << 4)
++
++static int ifmd0_reg_match[VNCSI_IFMD_SEL_NUMBER];
++static int ifmd4_reg_match[VNCSI_IFMD_SEL_NUMBER];
++static int ifmd0_init = true;
++static int ifmd4_init = true;
++
++enum chip_id {
++ RCAR_GEN3,
++ RCAR_M3,
++ RCAR_H3,
++ RCAR_GEN2,
++ RCAR_H1,
++ RCAR_M1,
++ RCAR_E1,
++};
++
++enum csi2_ch {
++ RCAR_CSI_CH_NONE = -1,
++ RCAR_CSI40,
++ RCAR_CSI20,
++ RCAR_CSI41,
++ RCAR_CSI21,
++ RCAR_CSI_MAX,
++};
++
++enum gen3_vin_ch {
++ RCAR_VIN_CH_NONE = -1,
++ RCAR_VIDEO_0,
++ RCAR_VIDEO_1,
++ RCAR_VIDEO_2,
++ RCAR_VIDEO_3,
++ RCAR_VIDEO_4,
++ RCAR_VIDEO_5,
++ RCAR_VIDEO_6,
++ RCAR_VIDEO_7,
++ RCAR_VIDEO_MAX,
++};
++
++enum virtual_ch {
++ RCAR_VIRTUAL_NONE = -1,
++ RCAR_VIRTUAL_CH0,
++ RCAR_VIRTUAL_CH1,
++ RCAR_VIRTUAL_CH2,
++ RCAR_VIRTUAL_CH3,
++ RCAR_VIRTUAL_MAX,
++};
++
++struct vin_gen3_virtual_sel {
++ enum csi2_ch csi2_ch;
++ enum virtual_ch vc;
++};
++
++struct vin_gen3_ifmd {
++ unsigned int set_reg;
++ struct vin_gen3_virtual_sel v_sel[8];
++};
++
++static const struct vin_gen3_ifmd vin_h3_vc_ifmd[] = {
++ { 0x0000,
++ {
++ {RCAR_CSI40, RCAR_VIRTUAL_CH0},
++ {RCAR_CSI20, RCAR_VIRTUAL_CH0},
++ {RCAR_CSI20, RCAR_VIRTUAL_CH1},
++ {RCAR_CSI40, RCAR_VIRTUAL_CH1},
++ {RCAR_CSI41, RCAR_VIRTUAL_CH0},
++ {RCAR_CSI20, RCAR_VIRTUAL_CH0},
++ {RCAR_CSI20, RCAR_VIRTUAL_CH1},
++ {RCAR_CSI41, RCAR_VIRTUAL_CH1},
++ }
++ },
++ { 0x0001,
++ {
++ {RCAR_CSI20, RCAR_VIRTUAL_CH0},
++ {RCAR_CSI40, RCAR_VIRTUAL_CH1},
++ {RCAR_CSI40, RCAR_VIRTUAL_CH0},
++ {RCAR_CSI20, RCAR_VIRTUAL_CH1},
++ {RCAR_CSI20, RCAR_VIRTUAL_CH0},
++ {RCAR_CSI41, RCAR_VIRTUAL_CH1},
++ {RCAR_CSI41, RCAR_VIRTUAL_CH0},
++ {RCAR_CSI20, RCAR_VIRTUAL_CH1},
++ }
++ },
++ { 0x0002,
++ {
++ {RCAR_CSI40, RCAR_VIRTUAL_CH1},
++ {RCAR_CSI40, RCAR_VIRTUAL_CH0},
++ {RCAR_CSI20, RCAR_VIRTUAL_CH0},
++ {RCAR_CSI20, RCAR_VIRTUAL_CH1},
++ {RCAR_CSI41, RCAR_VIRTUAL_CH1},
++ {RCAR_CSI41, RCAR_VIRTUAL_CH0},
++ {RCAR_CSI20, RCAR_VIRTUAL_CH0},
++ {RCAR_CSI20, RCAR_VIRTUAL_CH1},
++ }
++ },
++ { 0x0003,
++ {
++ {RCAR_CSI40, RCAR_VIRTUAL_CH0},
++ {RCAR_CSI40, RCAR_VIRTUAL_CH1},
++ {RCAR_CSI40, RCAR_VIRTUAL_CH2},
++ {RCAR_CSI40, RCAR_VIRTUAL_CH3},
++ {RCAR_CSI41, RCAR_VIRTUAL_CH0},
++ {RCAR_CSI41, RCAR_VIRTUAL_CH1},
++ {RCAR_CSI41, RCAR_VIRTUAL_CH2},
++ {RCAR_CSI41, RCAR_VIRTUAL_CH3},
++ }
++ },
++ { 0x0004,
++ {
++ {RCAR_CSI20, RCAR_VIRTUAL_CH0},
++ {RCAR_CSI20, RCAR_VIRTUAL_CH1},
++ {RCAR_CSI20, RCAR_VIRTUAL_CH2},
++ {RCAR_CSI20, RCAR_VIRTUAL_CH3},
++ {RCAR_CSI20, RCAR_VIRTUAL_CH0},
++ {RCAR_CSI20, RCAR_VIRTUAL_CH1},
++ {RCAR_CSI20, RCAR_VIRTUAL_CH2},
++ {RCAR_CSI20, RCAR_VIRTUAL_CH3},
++ }
++ },
++};
++
++static const struct vin_gen3_ifmd vin_m3_vc_ifmd[] = {
++ { 0x0000,
++ {
++ {RCAR_CSI40, RCAR_VIRTUAL_CH0},
++ {RCAR_CSI20, RCAR_VIRTUAL_CH0},
++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE},
++ {RCAR_CSI40, RCAR_VIRTUAL_CH1},
++ {RCAR_CSI40, RCAR_VIRTUAL_CH0},
++ {RCAR_CSI20, RCAR_VIRTUAL_CH0},
++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE},
++ {RCAR_CSI40, RCAR_VIRTUAL_CH1},
++ }
++ },
++ { 0x0001,
++ {
++ {RCAR_CSI20, RCAR_VIRTUAL_CH0},
++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE},
++ {RCAR_CSI40, RCAR_VIRTUAL_CH0},
++ {RCAR_CSI20, RCAR_VIRTUAL_CH1},
++ {RCAR_CSI20, RCAR_VIRTUAL_CH0},
++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE},
++ {RCAR_CSI40, RCAR_VIRTUAL_CH0},
++ {RCAR_CSI20, RCAR_VIRTUAL_CH1},
++ }
++ },
++ { 0x0002,
++ {
++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE},
++ {RCAR_CSI40, RCAR_VIRTUAL_CH0},
++ {RCAR_CSI20, RCAR_VIRTUAL_CH0},
++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE},
++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE},
++ {RCAR_CSI40, RCAR_VIRTUAL_CH0},
++ {RCAR_CSI20, RCAR_VIRTUAL_CH0},
++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE},
++ }
++ },
++ { 0x0003,
++ {
++ {RCAR_CSI40, RCAR_VIRTUAL_CH0},
++ {RCAR_CSI40, RCAR_VIRTUAL_CH1},
++ {RCAR_CSI40, RCAR_VIRTUAL_CH2},
++ {RCAR_CSI40, RCAR_VIRTUAL_CH3},
++ {RCAR_CSI40, RCAR_VIRTUAL_CH0},
++ {RCAR_CSI40, RCAR_VIRTUAL_CH1},
++ {RCAR_CSI40, RCAR_VIRTUAL_CH2},
++ {RCAR_CSI40, RCAR_VIRTUAL_CH3},
++ }
++ },
++ { 0x0004,
++ {
++ {RCAR_CSI20, RCAR_VIRTUAL_CH0},
++ {RCAR_CSI20, RCAR_VIRTUAL_CH1},
++ {RCAR_CSI20, RCAR_VIRTUAL_CH2},
++ {RCAR_CSI20, RCAR_VIRTUAL_CH3},
++ {RCAR_CSI20, RCAR_VIRTUAL_CH0},
++ {RCAR_CSI20, RCAR_VIRTUAL_CH1},
++ {RCAR_CSI20, RCAR_VIRTUAL_CH2},
++ {RCAR_CSI20, RCAR_VIRTUAL_CH3},
++ }
++ },
++};
++
++enum csi2_fmt {
++ RCAR_CSI_FMT_NONE = -1,
++ RCAR_CSI_RGB888,
++ RCAR_CSI_YCBCR422,
++};
++
++struct vin_coeff {
++ unsigned short xs_value;
++ u32 coeff_set[24];
++};
++
++static const struct vin_coeff vin_coeff_set[] = {
++ { 0x0000, {
++ 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000,
++ 0x00000000, 0x00000000, 0x00000000 },
++ },
++ { 0x1000, {
++ 0x000fa400, 0x000fa400, 0x09625902,
++ 0x000003f8, 0x00000403, 0x3de0d9f0,
++ 0x001fffed, 0x00000804, 0x3cc1f9c3,
++ 0x001003de, 0x00000c01, 0x3cb34d7f,
++ 0x002003d2, 0x00000c00, 0x3d24a92d,
++ 0x00200bca, 0x00000bff, 0x3df600d2,
++ 0x002013cc, 0x000007ff, 0x3ed70c7e,
++ 0x00100fde, 0x00000000, 0x3f87c036 },
++ },
++ { 0x1200, {
++ 0x002ffff1, 0x002ffff1, 0x02a0a9c8,
++ 0x002003e7, 0x001ffffa, 0x000185bc,
++ 0x002007dc, 0x000003ff, 0x3e52859c,
++ 0x00200bd4, 0x00000002, 0x3d53996b,
++ 0x00100fd0, 0x00000403, 0x3d04ad2d,
++ 0x00000bd5, 0x00000403, 0x3d35ace7,
++ 0x3ff003e4, 0x00000801, 0x3dc674a1,
++ 0x3fffe800, 0x00000800, 0x3e76f461 },
++ },
++ { 0x1400, {
++ 0x00100be3, 0x00100be3, 0x04d1359a,
++ 0x00000fdb, 0x002003ed, 0x0211fd93,
++ 0x00000fd6, 0x002003f4, 0x0002d97b,
++ 0x000007d6, 0x002ffffb, 0x3e93b956,
++ 0x3ff003da, 0x001003ff, 0x3db49926,
++ 0x3fffefe9, 0x00100001, 0x3d655cee,
++ 0x3fffd400, 0x00000003, 0x3d65f4b6,
++ 0x000fb421, 0x00000402, 0x3dc6547e },
++ },
++ { 0x1600, {
++ 0x00000bdd, 0x00000bdd, 0x06519578,
++ 0x3ff007da, 0x00000be3, 0x03c24973,
++ 0x3ff003d9, 0x00000be9, 0x01b30d5f,
++ 0x3ffff7df, 0x001003f1, 0x0003c542,
++ 0x000fdfec, 0x001003f7, 0x3ec4711d,
++ 0x000fc400, 0x002ffffd, 0x3df504f1,
++ 0x001fa81a, 0x002ffc00, 0x3d957cc2,
++ 0x002f8c3c, 0x00100000, 0x3db5c891 },
++ },
++ { 0x1800, {
++ 0x3ff003dc, 0x3ff003dc, 0x0791e558,
++ 0x000ff7dd, 0x3ff007de, 0x05328554,
++ 0x000fe7e3, 0x3ff00be2, 0x03232546,
++ 0x000fd7ee, 0x000007e9, 0x0143bd30,
++ 0x001fb800, 0x000007ee, 0x00044511,
++ 0x002fa015, 0x000007f4, 0x3ef4bcee,
++ 0x002f8832, 0x001003f9, 0x3e4514c7,
++ 0x001f7853, 0x001003fd, 0x3de54c9f },
++ },
++ { 0x1a00, {
++ 0x000fefe0, 0x000fefe0, 0x08721d3c,
++ 0x001fdbe7, 0x000ffbde, 0x0652a139,
++ 0x001fcbf0, 0x000003df, 0x0463292e,
++ 0x002fb3ff, 0x3ff007e3, 0x0293a91d,
++ 0x002f9c12, 0x3ff00be7, 0x01241905,
++ 0x001f8c29, 0x000007ed, 0x3fe470eb,
++ 0x000f7c46, 0x000007f2, 0x3f04b8ca,
++ 0x3fef7865, 0x000007f6, 0x3e74e4a8 },
++ },
++ { 0x1c00, {
++ 0x001fd3e9, 0x001fd3e9, 0x08f23d26,
++ 0x002fbff3, 0x001fe3e4, 0x0712ad23,
++ 0x002fa800, 0x000ff3e0, 0x05631d1b,
++ 0x001f9810, 0x000ffbe1, 0x03b3890d,
++ 0x000f8c23, 0x000003e3, 0x0233e8fa,
++ 0x3fef843b, 0x000003e7, 0x00f430e4,
++ 0x3fbf8456, 0x3ff00bea, 0x00046cc8,
++ 0x3f8f8c72, 0x3ff00bef, 0x3f3490ac },
++ },
++ { 0x1e00, {
++ 0x001fbbf4, 0x001fbbf4, 0x09425112,
++ 0x001fa800, 0x002fc7ed, 0x0792b110,
++ 0x000f980e, 0x001fdbe6, 0x0613110a,
++ 0x3fff8c20, 0x001fe7e3, 0x04a368fd,
++ 0x3fcf8c33, 0x000ff7e2, 0x0343b8ed,
++ 0x3f9f8c4a, 0x000fffe3, 0x0203f8da,
++ 0x3f5f9c61, 0x000003e6, 0x00e428c5,
++ 0x3f1fb07b, 0x000003eb, 0x3fe440af },
++ },
++ { 0x2000, {
++ 0x000fa400, 0x000fa400, 0x09625902,
++ 0x3fff980c, 0x001fb7f5, 0x0812b0ff,
++ 0x3fdf901c, 0x001fc7ed, 0x06b2fcfa,
++ 0x3faf902d, 0x001fd3e8, 0x055348f1,
++ 0x3f7f983f, 0x001fe3e5, 0x04038ce3,
++ 0x3f3fa454, 0x001fefe3, 0x02e3c8d1,
++ 0x3f0fb86a, 0x001ff7e4, 0x01c3e8c0,
++ 0x3ecfd880, 0x000fffe6, 0x00c404ac },
++ },
++ { 0x2200, {
++ 0x3fdf9c0b, 0x3fdf9c0b, 0x09725cf4,
++ 0x3fbf9818, 0x3fffa400, 0x0842a8f1,
++ 0x3f8f9827, 0x000fb3f7, 0x0702f0ec,
++ 0x3f5fa037, 0x000fc3ef, 0x05d330e4,
++ 0x3f2fac49, 0x001fcfea, 0x04a364d9,
++ 0x3effc05c, 0x001fdbe7, 0x038394ca,
++ 0x3ecfdc6f, 0x001fe7e6, 0x0273b0bb,
++ 0x3ea00083, 0x001fefe6, 0x0183c0a9 },
++ },
++ { 0x2400, {
++ 0x3f9fa014, 0x3f9fa014, 0x098260e6,
++ 0x3f7f9c23, 0x3fcf9c0a, 0x08629ce5,
++ 0x3f4fa431, 0x3fefa400, 0x0742d8e1,
++ 0x3f1fb440, 0x3fffb3f8, 0x062310d9,
++ 0x3eefc850, 0x000fbbf2, 0x050340d0,
++ 0x3ecfe062, 0x000fcbec, 0x041364c2,
++ 0x3ea00073, 0x001fd3ea, 0x03037cb5,
++ 0x3e902086, 0x001fdfe8, 0x022388a5 },
++ },
++ { 0x2600, {
++ 0x3f5fa81e, 0x3f5fa81e, 0x096258da,
++ 0x3f3fac2b, 0x3f8fa412, 0x088290d8,
++ 0x3f0fbc38, 0x3fafa408, 0x0772c8d5,
++ 0x3eefcc47, 0x3fcfa800, 0x0672f4ce,
++ 0x3ecfe456, 0x3fefaffa, 0x05531cc6,
++ 0x3eb00066, 0x3fffbbf3, 0x047334bb,
++ 0x3ea01c77, 0x000fc7ee, 0x039348ae,
++ 0x3ea04486, 0x000fd3eb, 0x02b350a1 },
++ },
++ { 0x2800, {
++ 0x3f2fb426, 0x3f2fb426, 0x094250ce,
++ 0x3f0fc032, 0x3f4fac1b, 0x086284cd,
++ 0x3eefd040, 0x3f7fa811, 0x0782acc9,
++ 0x3ecfe84c, 0x3f9fa807, 0x06a2d8c4,
++ 0x3eb0005b, 0x3fbfac00, 0x05b2f4bc,
++ 0x3eb0186a, 0x3fdfb3fa, 0x04c308b4,
++ 0x3eb04077, 0x3fefbbf4, 0x03f31ca8,
++ 0x3ec06884, 0x000fbff2, 0x03031c9e },
++ },
++ { 0x2a00, {
++ 0x3f0fc42d, 0x3f0fc42d, 0x090240c4,
++ 0x3eefd439, 0x3f2fb822, 0x08526cc2,
++ 0x3edfe845, 0x3f4fb018, 0x078294bf,
++ 0x3ec00051, 0x3f6fac0f, 0x06b2b4bb,
++ 0x3ec0185f, 0x3f8fac07, 0x05e2ccb4,
++ 0x3ec0386b, 0x3fafac00, 0x0502e8ac,
++ 0x3ed05c77, 0x3fcfb3fb, 0x0432f0a3,
++ 0x3ef08482, 0x3fdfbbf6, 0x0372f898 },
++ },
++ { 0x2c00, {
++ 0x3eefdc31, 0x3eefdc31, 0x08e238b8,
++ 0x3edfec3d, 0x3f0fc828, 0x082258b9,
++ 0x3ed00049, 0x3f1fc01e, 0x077278b6,
++ 0x3ed01455, 0x3f3fb815, 0x06c294b2,
++ 0x3ed03460, 0x3f5fb40d, 0x0602acac,
++ 0x3ef0506c, 0x3f7fb006, 0x0542c0a4,
++ 0x3f107476, 0x3f9fb400, 0x0472c89d,
++ 0x3f309c80, 0x3fbfb7fc, 0x03b2cc94 },
++ },
++ { 0x2e00, {
++ 0x3eefec37, 0x3eefec37, 0x088220b0,
++ 0x3ee00041, 0x3effdc2d, 0x07f244ae,
++ 0x3ee0144c, 0x3f0fd023, 0x07625cad,
++ 0x3ef02c57, 0x3f1fc81a, 0x06c274a9,
++ 0x3f004861, 0x3f3fbc13, 0x060288a6,
++ 0x3f20686b, 0x3f5fb80c, 0x05529c9e,
++ 0x3f408c74, 0x3f6fb805, 0x04b2ac96,
++ 0x3f80ac7e, 0x3f8fb800, 0x0402ac8e },
++ },
++ { 0x3000, {
++ 0x3ef0003a, 0x3ef0003a, 0x084210a6,
++ 0x3ef01045, 0x3effec32, 0x07b228a7,
++ 0x3f00284e, 0x3f0fdc29, 0x073244a4,
++ 0x3f104058, 0x3f0fd420, 0x06a258a2,
++ 0x3f305c62, 0x3f2fc818, 0x0612689d,
++ 0x3f508069, 0x3f3fc011, 0x05728496,
++ 0x3f80a072, 0x3f4fc00a, 0x04d28c90,
++ 0x3fc0c07b, 0x3f6fbc04, 0x04429088 },
++ },
++ { 0x3200, {
++ 0x3f00103e, 0x3f00103e, 0x07f1fc9e,
++ 0x3f102447, 0x3f000035, 0x0782149d,
++ 0x3f203c4f, 0x3f0ff02c, 0x07122c9c,
++ 0x3f405458, 0x3f0fe424, 0x06924099,
++ 0x3f607061, 0x3f1fd41d, 0x06024c97,
++ 0x3f909068, 0x3f2fcc16, 0x05726490,
++ 0x3fc0b070, 0x3f3fc80f, 0x04f26c8a,
++ 0x0000d077, 0x3f4fc409, 0x04627484 },
++ },
++ { 0x3400, {
++ 0x3f202040, 0x3f202040, 0x07a1e898,
++ 0x3f303449, 0x3f100c38, 0x0741fc98,
++ 0x3f504c50, 0x3f10002f, 0x06e21495,
++ 0x3f706459, 0x3f1ff028, 0x06722492,
++ 0x3fa08060, 0x3f1fe421, 0x05f2348f,
++ 0x3fd09c67, 0x3f1fdc19, 0x05824c89,
++ 0x0000bc6e, 0x3f2fd014, 0x04f25086,
++ 0x0040dc74, 0x3f3fcc0d, 0x04825c7f },
++ },
++ { 0x3600, {
++ 0x3f403042, 0x3f403042, 0x0761d890,
++ 0x3f504848, 0x3f301c3b, 0x0701f090,
++ 0x3f805c50, 0x3f200c33, 0x06a2008f,
++ 0x3fa07458, 0x3f10002b, 0x06520c8d,
++ 0x3fd0905e, 0x3f1ff424, 0x05e22089,
++ 0x0000ac65, 0x3f1fe81d, 0x05823483,
++ 0x0030cc6a, 0x3f2fdc18, 0x04f23c81,
++ 0x0080e871, 0x3f2fd412, 0x0482407c },
++ },
++ { 0x3800, {
++ 0x3f604043, 0x3f604043, 0x0721c88a,
++ 0x3f80544a, 0x3f502c3c, 0x06d1d88a,
++ 0x3fb06851, 0x3f301c35, 0x0681e889,
++ 0x3fd08456, 0x3f30082f, 0x0611fc88,
++ 0x00009c5d, 0x3f200027, 0x05d20884,
++ 0x0030b863, 0x3f2ff421, 0x05621880,
++ 0x0070d468, 0x3f2fe81b, 0x0502247c,
++ 0x00c0ec6f, 0x3f2fe015, 0x04a22877 },
++ },
++ { 0x3a00, {
++ 0x3f904c44, 0x3f904c44, 0x06e1b884,
++ 0x3fb0604a, 0x3f70383e, 0x0691c885,
++ 0x3fe07451, 0x3f502c36, 0x0661d483,
++ 0x00009055, 0x3f401831, 0x0601ec81,
++ 0x0030a85b, 0x3f300c2a, 0x05b1f480,
++ 0x0070c061, 0x3f300024, 0x0562047a,
++ 0x00b0d867, 0x3f3ff41e, 0x05020c77,
++ 0x00f0f46b, 0x3f2fec19, 0x04a21474 },
++ },
++ { 0x3c00, {
++ 0x3fb05c43, 0x3fb05c43, 0x06c1b07e,
++ 0x3fe06c4b, 0x3f902c3f, 0x0681c081,
++ 0x0000844f, 0x3f703838, 0x0631cc7d,
++ 0x00309855, 0x3f602433, 0x05d1d47e,
++ 0x0060b459, 0x3f50142e, 0x0581e47b,
++ 0x00a0c85f, 0x3f400828, 0x0531f078,
++ 0x00e0e064, 0x3f300021, 0x0501fc73,
++ 0x00b0fc6a, 0x3f3ff41d, 0x04a20873 },
++ },
++ { 0x3e00, {
++ 0x3fe06444, 0x3fe06444, 0x0681a07a,
++ 0x00007849, 0x3fc0503f, 0x0641b07a,
++ 0x0020904d, 0x3fa0403a, 0x05f1c07a,
++ 0x0060a453, 0x3f803034, 0x05c1c878,
++ 0x0090b858, 0x3f70202f, 0x0571d477,
++ 0x00d0d05d, 0x3f501829, 0x0531e073,
++ 0x0110e462, 0x3f500825, 0x04e1e471,
++ 0x01510065, 0x3f40001f, 0x04a1f06d },
++ },
++ { 0x4000, {
++ 0x00007044, 0x00007044, 0x06519476,
++ 0x00208448, 0x3fe05c3f, 0x0621a476,
++ 0x0050984d, 0x3fc04c3a, 0x05e1b075,
++ 0x0080ac52, 0x3fa03c35, 0x05a1b875,
++ 0x00c0c056, 0x3f803030, 0x0561c473,
++ 0x0100d45b, 0x3f70202b, 0x0521d46f,
++ 0x0140e860, 0x3f601427, 0x04d1d46e,
++ 0x01810064, 0x3f500822, 0x0491dc6b },
++ },
++ { 0x5000, {
++ 0x0110a442, 0x0110a442, 0x0551545e,
++ 0x0140b045, 0x00e0983f, 0x0531585f,
++ 0x0160c047, 0x00c08c3c, 0x0511645e,
++ 0x0190cc4a, 0x00908039, 0x04f1685f,
++ 0x01c0dc4c, 0x00707436, 0x04d1705e,
++ 0x0200e850, 0x00506833, 0x04b1785b,
++ 0x0230f453, 0x00305c30, 0x0491805a,
++ 0x02710056, 0x0010542d, 0x04718059 },
++ },
++ { 0x6000, {
++ 0x01c0bc40, 0x01c0bc40, 0x04c13052,
++ 0x01e0c841, 0x01a0b43d, 0x04c13851,
++ 0x0210cc44, 0x0180a83c, 0x04a13453,
++ 0x0230d845, 0x0160a03a, 0x04913c52,
++ 0x0260e047, 0x01409838, 0x04714052,
++ 0x0280ec49, 0x01208c37, 0x04514c50,
++ 0x02b0f44b, 0x01008435, 0x04414c50,
++ 0x02d1004c, 0x00e07c33, 0x0431544f },
++ },
++ { 0x7000, {
++ 0x0230c83e, 0x0230c83e, 0x04711c4c,
++ 0x0250d03f, 0x0210c43c, 0x0471204b,
++ 0x0270d840, 0x0200b83c, 0x0451244b,
++ 0x0290dc42, 0x01e0b43a, 0x0441244c,
++ 0x02b0e443, 0x01c0b038, 0x0441284b,
++ 0x02d0ec44, 0x01b0a438, 0x0421304a,
++ 0x02f0f445, 0x0190a036, 0x04213449,
++ 0x0310f847, 0x01709c34, 0x04213848 },
++ },
++ { 0x8000, {
++ 0x0280d03d, 0x0280d03d, 0x04310c48,
++ 0x02a0d43e, 0x0270c83c, 0x04311047,
++ 0x02b0dc3e, 0x0250c83a, 0x04311447,
++ 0x02d0e040, 0x0240c03a, 0x04211446,
++ 0x02e0e840, 0x0220bc39, 0x04111847,
++ 0x0300e842, 0x0210b438, 0x04012445,
++ 0x0310f043, 0x0200b037, 0x04012045,
++ 0x0330f444, 0x01e0ac36, 0x03f12445 },
++ },
++ { 0xefff, {
++ 0x0340dc3a, 0x0340dc3a, 0x03b0ec40,
++ 0x0340e03a, 0x0330e039, 0x03c0f03e,
++ 0x0350e03b, 0x0330dc39, 0x03c0ec3e,
++ 0x0350e43a, 0x0320dc38, 0x03c0f43e,
++ 0x0360e43b, 0x0320d839, 0x03b0f03e,
++ 0x0360e83b, 0x0310d838, 0x03c0fc3b,
++ 0x0370e83b, 0x0310d439, 0x03a0f83d,
++ 0x0370e83c, 0x0300d438, 0x03b0fc3c },
++ }
++};
++
++enum rcar_vin_state {
++ STOPPED = 0,
++ RUNNING,
++ STOPPING,
++};
++
++struct rcar_vin_async_client {
++ struct v4l2_async_subdev *sensor;
++ struct v4l2_async_notifier notifier;
++ struct platform_device *pdev;
++ struct list_head list; /* needed for clean up */
++};
++
++struct soc_of_info {
++ struct soc_camera_async_subdev sasd;
++ struct rcar_vin_async_client sasc;
++ struct v4l2_async_subdev *subdev;
++};
++
++struct rcar_vin_priv {
++ void __iomem *base;
++ spinlock_t lock;
++ int sequence;
++ /* State of the VIN module in capturing mode */
++ enum rcar_vin_state state;
++ struct soc_camera_host ici;
++ struct list_head capture;
++#define MAX_BUFFER_NUM 3
++ struct vb2_v4l2_buffer *queue_buf[MAX_BUFFER_NUM];
++ enum v4l2_field field;
++ unsigned int pdata_flags;
++ unsigned int vb_count;
++ unsigned int nr_hw_slots;
++ bool request_to_stop;
++ struct completion capture_stop;
++ enum chip_id chip;
++ unsigned int max_width;
++ unsigned int max_height;
++ unsigned int ratio_h;
++ unsigned int ratio_v;
++ bool error_flag;
++ enum csi2_ch csi_ch;
++ enum csi2_fmt csi_fmt;
++ enum virtual_ch vc;
++ bool csi_sync;
++
++ struct rcar_vin_async_client *async_client;
++ /* Asynchronous CSI2 linking */
++ struct v4l2_subdev *csi2_sd;
++ /* Synchronous probing compatibility */
++ struct platform_device *csi2_pdev;
++
++ unsigned int index;
++};
++
++#define is_continuous_transfer(priv) (priv->vb_count > MAX_BUFFER_NUM)
++
++struct rcar_vin_buffer {
++ struct vb2_v4l2_buffer vb;
++ struct list_head list;
++};
++
++#define to_buf_list(vb2_buffer) (&container_of(vb2_buffer, \
++ struct rcar_vin_buffer, \
++ vb)->list)
++
++struct rcar_vin_cam {
++ /* VIN offsets within the camera output, before the VIN scaler */
++ unsigned int vin_left;
++ unsigned int vin_top;
++ /* Client output, as seen by the VIN */
++ unsigned int width;
++ unsigned int height;
++ /* User window from S_FMT */
++ unsigned int out_width;
++ unsigned int out_height;
++ /*
++ * User window from S_SELECTION / G_SELECTION, produced by client cropping and
++ * scaling, VIN scaling and VIN cropping, mapped back onto the client
++ * input window
++ */
++ struct v4l2_rect subrect;
++ /* Camera cropping rectangle */
++ struct v4l2_rect rect;
++ const struct soc_mbus_pixelfmt *extra_fmt;
++};
++
++#define VIN_UT_IRQ 0x01
++
++static unsigned int vin_debug;
++module_param_named(debug, vin_debug, int, 0600);
++static int overflow_video[RCAR_VIDEO_MAX];
++module_param_array(overflow_video, int, NULL, 0600);
++
++#ifdef CONFIG_VIDEO_RCAR_VIN_LEGACY_DEBUG
++#define VIN_IRQ_DEBUG(fmt, args...) \
++ do { \
++ if (unlikely(vin_debug & VIN_UT_IRQ)) \
++ vin_ut_debug_printk(__func__, fmt, ##args); \
++ } while (0)
++#else
++#define VIN_IRQ_DEBUG(fmt, args...)
++#endif
++
++void vin_ut_debug_printk(const char *function_name, const char *format, ...)
++{
++ struct va_format vaf;
++ va_list args;
++
++ va_start(args, format);
++ vaf.fmt = format;
++ vaf.va = &args;
++
++ pr_debug("[" DRV_NAME ":%s] %pV", function_name, &vaf);
++
++ va_end(args);
++}
++
++static void rcar_vin_cpg_enable_for_ifmd(unsigned int ch, bool enable)
++{
++ void __iomem *smstpcr8;
++
++ smstpcr8 = ioremap(0xE6150990, 0x04);
++
++ if (enable) {
++ if (ch < RCAR_VIDEO_4)
++ iowrite32((ioread32(smstpcr8) & 0xFFFFF7FF), smstpcr8);
++ else
++ iowrite32((ioread32(smstpcr8) & 0xFFFFFF7F), smstpcr8);
++ } else {
++ if (ch < RCAR_VIDEO_4)
++ iowrite32((ioread32(smstpcr8) | 0x00000800), smstpcr8);
++ else
++ iowrite32((ioread32(smstpcr8) | 0x00000080), smstpcr8);
++ }
++
++ iounmap(smstpcr8);
++}
++
++static inline int is_scaling(struct rcar_vin_cam *cam)
++{
++ struct v4l2_rect *cam_subrect = &cam->subrect;
++
++ if ((cam_subrect->width != cam->out_width) ||
++ (cam_subrect->height != cam->out_height))
++ return 1;
++
++ return 0;
++}
++
++/*
++ * .queue_setup() is called to check whether the driver can accept the requested
++ * number of buffers and to fill in plane sizes for the current frame format if
++ * required
++ */
++static int rcar_vin_videobuf_setup(struct vb2_queue *vq,
++ unsigned int *count,
++ unsigned int *num_planes,
++ unsigned int sizes[], struct device *alloc_devs[])
++{
++ struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
++ struct rcar_vin_priv *priv = ici->priv;
++ struct rcar_vin_cam *cam = icd->host_priv;
++
++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) {
++ if ((priv->ratio_h > 0x10000) || (priv->ratio_v > 0x10000)) {
++ dev_err(icd->parent, "Scaling rate parameter error\n");
++ return -EINVAL;
++ }
++ if (is_scaling(cam) && (cam->out_width % 32)) {
++ dev_err(icd->parent, "Scaling parameter error\n");
++ return -EINVAL;
++ }
++ if (!is_scaling(cam) && (cam->out_width % 16)) {
++ dev_err(icd->parent, "Image stride parameter error\n");
++ return -EINVAL;
++ }
++ }
++
++ if (!vq->num_buffers)
++ priv->sequence = 0;
++
++ if (!*count)
++ *count = 2;
++ priv->vb_count = *count;
++
++ /* Number of hardware slots */
++ if (is_continuous_transfer(priv))
++ priv->nr_hw_slots = MAX_BUFFER_NUM;
++ else
++ priv->nr_hw_slots = 1;
++
++ if (*num_planes)
++ return sizes[0] < icd->sizeimage ? -EINVAL : 0;
++
++ sizes[0] = icd->sizeimage;
++ *num_planes = 1;
++
++ dev_dbg(icd->parent, "count=%d, size=%u\n", *count, sizes[0]);
++
++ return 0;
++}
++
++static int rcar_vin_setup(struct rcar_vin_priv *priv)
++{
++ struct soc_camera_device *icd = priv->ici.icd;
++ struct rcar_vin_cam *cam = icd->host_priv;
++ u32 vnmc, dmr, interrupts;
++ bool progressive = false, output_is_yuv = false, input_is_yuv = false;
++
++ switch (priv->field) {
++ case V4L2_FIELD_TOP:
++ vnmc = VNMC_IM_ODD;
++ break;
++ case V4L2_FIELD_BOTTOM:
++ vnmc = VNMC_IM_EVEN;
++ break;
++ case V4L2_FIELD_INTERLACED:
++ case V4L2_FIELD_INTERLACED_TB:
++ vnmc = VNMC_IM_FULL;
++ break;
++ case V4L2_FIELD_INTERLACED_BT:
++ vnmc = VNMC_IM_FULL | VNMC_FOC;
++ break;
++ case V4L2_FIELD_NONE:
++ if (is_continuous_transfer(priv)) {
++ vnmc = VNMC_IM_ODD_EVEN;
++ progressive = true;
++ } else {
++ vnmc = VNMC_IM_ODD;
++ }
++ break;
++ default:
++ vnmc = VNMC_IM_ODD;
++ break;
++ }
++
++ /* input interface */
++ switch (icd->current_fmt->code) {
++ case MEDIA_BUS_FMT_YUYV8_1X16:
++ /* BT.601/BT.1358 16bit YCbCr422 */
++ vnmc |= VNMC_INF_YUV16;
++ input_is_yuv = true;
++ break;
++ case MEDIA_BUS_FMT_YUYV8_2X8:
++ /* BT.656 8bit YCbCr422 or BT.601 8bit YCbCr422 */
++ vnmc |= priv->pdata_flags & RCAR_VIN_BT656 ?
++ VNMC_INF_YUV8_BT656 : VNMC_INF_YUV8_BT601;
++ input_is_yuv = true;
++ break;
++ case MEDIA_BUS_FMT_RGB888_1X24:
++ vnmc |= VNMC_INF_RGB888;
++ break;
++ case MEDIA_BUS_FMT_YUYV10_2X10:
++ /* BT.656 10bit YCbCr422 or BT.601 10bit YCbCr422 */
++ vnmc |= priv->pdata_flags & RCAR_VIN_BT656 ?
++ VNMC_INF_YUV10_BT656 : VNMC_INF_YUV10_BT601;
++ input_is_yuv = true;
++ break;
++ default:
++ break;
++ }
++
++ /* output format */
++ switch (icd->current_fmt->host_fmt->fourcc) {
++ case V4L2_PIX_FMT_NV12:
++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) {
++ iowrite32(ALIGN((cam->out_width * cam->out_height),
++ 0x80), priv->base + VNUVAOF_REG);
++ dmr = VNDMR_DTMD_YCSEP_YCBCR420;
++ output_is_yuv = true;
++ } else {
++ dev_warn(icd->parent, "Not support format\n");
++ return -EINVAL;
++ }
++ break;
++ case V4L2_PIX_FMT_NV16:
++ iowrite32(ALIGN((cam->out_width * cam->out_height), 0x80),
++ priv->base + VNUVAOF_REG);
++ dmr = VNDMR_DTMD_YCSEP;
++ output_is_yuv = true;
++ break;
++ case V4L2_PIX_FMT_YUYV:
++ dmr = VNDMR_BPSM;
++ output_is_yuv = true;
++ break;
++ case V4L2_PIX_FMT_UYVY:
++ dmr = 0;
++ output_is_yuv = true;
++ break;
++ case V4L2_PIX_FMT_ARGB555:
++ dmr = VNDMR_DTMD_ARGB;
++ break;
++ case V4L2_PIX_FMT_RGB565:
++ dmr = 0;
++ break;
++ case V4L2_PIX_FMT_XBGR32:
++ if (priv->chip != RCAR_H3 && priv->chip != RCAR_M3 &&
++ priv->chip != RCAR_GEN2 && priv->chip != RCAR_H1 &&
++ priv->chip != RCAR_E1)
++ goto e_format;
++
++ dmr = VNDMR_EXRGB;
++ break;
++ case V4L2_PIX_FMT_ABGR32:
++ if (priv->chip != RCAR_H3 && priv->chip != RCAR_M3)
++ goto e_format;
++
++ dmr = VNDMR_EXRGB | VNDMR_DTMD_ARGB;
++ break;
++ default:
++ goto e_format;
++ }
++
++ /* Always update on field change */
++ vnmc |= VNMC_VUP;
++
++ /* If input and output use the same colorspace, use bypass mode */
++ if (input_is_yuv == output_is_yuv)
++ vnmc |= VNMC_BPS;
++
++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) {
++ if (priv->pdata_flags & RCAR_VIN_CSI2)
++ vnmc &= ~VNMC_DPINE;
++ else
++ vnmc |= VNMC_DPINE;
++
++ if ((icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_NV12)
++ && is_scaling(cam))
++ vnmc |= VNMC_SCLE;
++ }
++
++ /* progressive or interlaced mode */
++ interrupts = progressive ? VNIE_FIE : VNIE_EFE;
++
++ /* Enable Overflow */
++ if (vin_debug)
++ interrupts |= VNIE_FOE;
++
++ /* ack interrupts */
++ iowrite32(interrupts, priv->base + VNINTS_REG);
++ /* enable interrupts */
++ iowrite32(interrupts, priv->base + VNIE_REG);
++ /* start capturing */
++ iowrite32(dmr, priv->base + VNDMR_REG);
++ iowrite32(vnmc | VNMC_ME, priv->base + VNMC_REG);
++
++ return 0;
++
++e_format:
++ dev_warn(icd->parent, "Invalid fourcc format (0x%x)\n",
++ icd->current_fmt->host_fmt->fourcc);
++ return -EINVAL;
++}
++
++static void rcar_vin_capture(struct rcar_vin_priv *priv)
++{
++ if (is_continuous_transfer(priv))
++ /* Continuous Frame Capture Mode */
++ iowrite32(VNFC_C_FRAME, priv->base + VNFC_REG);
++ else
++ /* Single Frame Capture Mode */
++ iowrite32(VNFC_S_FRAME, priv->base + VNFC_REG);
++}
++
++static void rcar_vin_request_capture_stop(struct rcar_vin_priv *priv)
++{
++ priv->state = STOPPING;
++
++ /* set continuous & single transfer off */
++ iowrite32(0, priv->base + VNFC_REG);
++ /* disable capture (release DMA buffer), reset */
++ iowrite32(ioread32(priv->base + VNMC_REG) & ~VNMC_ME,
++ priv->base + VNMC_REG);
++
++ /* update the status if stopped already */
++ if (!(ioread32(priv->base + VNMS_REG) & VNMS_CA))
++ priv->state = STOPPED;
++}
++
++static int rcar_vin_get_free_hw_slot(struct rcar_vin_priv *priv)
++{
++ int slot;
++
++ for (slot = 0; slot < priv->nr_hw_slots; slot++)
++ if (priv->queue_buf[slot] == NULL)
++ return slot;
++
++ return -1;
++}
++
++static int rcar_vin_hw_ready(struct rcar_vin_priv *priv)
++{
++ /* Ensure all HW slots are filled */
++ return rcar_vin_get_free_hw_slot(priv) < 0 ? 1 : 0;
++}
++
++/* Moves a buffer from the queue to the HW slots */
++static int rcar_vin_fill_hw_slot(struct rcar_vin_priv *priv)
++{
++ struct vb2_v4l2_buffer *vbuf;
++ dma_addr_t phys_addr_top;
++ int slot;
++
++ if (list_empty(&priv->capture))
++ return 0;
++
++ /* Find a free HW slot */
++ slot = rcar_vin_get_free_hw_slot(priv);
++ if (slot < 0)
++ return 0;
++
++ vbuf = &list_entry(priv->capture.next,
++ struct rcar_vin_buffer, list)->vb;
++ list_del_init(to_buf_list(vbuf));
++ priv->queue_buf[slot] = vbuf;
++ phys_addr_top = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 0);
++ iowrite32(phys_addr_top, priv->base + VNMB_REG(slot));
++
++ return 1;
++}
++
++static void rcar_vin_videobuf_queue(struct vb2_buffer *vb)
++{
++ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
++ struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
++ struct rcar_vin_priv *priv = ici->priv;
++ unsigned long size;
++
++ size = icd->sizeimage;
++
++ if (vb2_plane_size(vb, 0) < size) {
++ dev_err(icd->parent, "Buffer #%d too small (%lu < %lu)\n",
++ vb->index, vb2_plane_size(vb, 0), size);
++ goto error;
++ }
++
++ vb2_set_plane_payload(vb, 0, size);
++
++ dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__,
++ vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));
++
++ spin_lock_irq(&priv->lock);
++
++ list_add_tail(to_buf_list(vbuf), &priv->capture);
++ rcar_vin_fill_hw_slot(priv);
++
++ /* If we weren't running, and have enough buffers, start capturing! */
++ if (priv->state != RUNNING && rcar_vin_hw_ready(priv)) {
++ if (rcar_vin_setup(priv)) {
++ /* Submit error */
++ list_del_init(to_buf_list(vbuf));
++ spin_unlock_irq(&priv->lock);
++ goto error;
++ }
++ priv->request_to_stop = false;
++ init_completion(&priv->capture_stop);
++ priv->state = RUNNING;
++ rcar_vin_capture(priv);
++ }
++
++ spin_unlock_irq(&priv->lock);
++
++ return;
++
++error:
++ vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
++}
++
++/*
++ * Wait for capture to stop and all in-flight buffers to be finished with by
++ * the video hardware. This must be called under &priv->lock
++ *
++ */
++static void rcar_vin_wait_stop_streaming(struct rcar_vin_priv *priv)
++{
++ while (priv->state != STOPPED) {
++ /* issue stop if running */
++ if (priv->state == RUNNING)
++ rcar_vin_request_capture_stop(priv);
++
++ /* wait until capturing has been stopped */
++ if (priv->state == STOPPING) {
++ priv->request_to_stop = true;
++ spin_unlock_irq(&priv->lock);
++ if (!wait_for_completion_timeout(
++ &priv->capture_stop,
++ msecs_to_jiffies(TIMEOUT_MS)))
++ priv->state = STOPPED;
++ spin_lock_irq(&priv->lock);
++ }
++ }
++}
++
++static void rcar_vin_stop_streaming(struct vb2_queue *vq)
++{
++ struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
++ struct rcar_vin_priv *priv = ici->priv;
++ struct list_head *buf_head, *tmp;
++ int i;
++
++ spin_lock_irq(&priv->lock);
++ rcar_vin_wait_stop_streaming(priv);
++
++ for (i = 0; i < MAX_BUFFER_NUM; i++) {
++ if (priv->queue_buf[i]) {
++ vb2_buffer_done(&priv->queue_buf[i]->vb2_buf,
++ VB2_BUF_STATE_ERROR);
++ priv->queue_buf[i] = NULL;
++ }
++ }
++
++ list_for_each_safe(buf_head, tmp, &priv->capture) {
++ vb2_buffer_done(&list_entry(buf_head,
++ struct rcar_vin_buffer, list)->vb.vb2_buf,
++ VB2_BUF_STATE_ERROR);
++ list_del_init(buf_head);
++ }
++ spin_unlock_irq(&priv->lock);
++}
++
++static const struct vb2_ops rcar_vin_vb2_ops = {
++ .queue_setup = rcar_vin_videobuf_setup,
++ .buf_queue = rcar_vin_videobuf_queue,
++ .stop_streaming = rcar_vin_stop_streaming,
++ .wait_prepare = vb2_ops_wait_prepare,
++ .wait_finish = vb2_ops_wait_finish,
++};
++
++static irqreturn_t rcar_vin_irq(int irq, void *data)
++{
++ struct rcar_vin_priv *priv = data;
++ u32 int_status;
++ bool can_run = false, hw_stopped;
++ int slot;
++ unsigned int handled = 0;
++ int vin_ovr_cnt = 0;
++
++ spin_lock(&priv->lock);
++
++ int_status = ioread32(priv->base + VNINTS_REG);
++ if (!int_status)
++ goto done;
++
++ /* ack interrupts */
++ iowrite32(int_status, priv->base + VNINTS_REG);
++ handled = 1;
++
++ /* overflow occurs */
++ if (vin_debug && (int_status & VNINTS_FOS)) {
++ vin_ovr_cnt = ++overflow_video[priv->index];
++ VIN_IRQ_DEBUG("overflow occurrs num[%d] at VIN (%s)\n",
++ vin_ovr_cnt, dev_name(priv->ici.v4l2_dev.dev));
++ }
++
++ /* nothing to do if capture status is 'STOPPED' */
++ if (priv->state == STOPPED)
++ goto done;
++
++ hw_stopped = !(ioread32(priv->base + VNMS_REG) & VNMS_CA);
++
++ if (!priv->request_to_stop) {
++ if (is_continuous_transfer(priv))
++ slot = (ioread32(priv->base + VNMS_REG) &
++ VNMS_FBS_MASK) >> VNMS_FBS_SHIFT;
++ else
++ slot = 0;
++
++ if (!is_continuous_transfer(priv) || ((priv->state == RUNNING)
++ && !list_empty(&priv->capture))) {
++ priv->queue_buf[slot]->field = priv->field;
++ priv->queue_buf[slot]->sequence = priv->sequence++;
++ priv->queue_buf[slot]->vb2_buf.timestamp =
++ ktime_get_ns();
++ vb2_buffer_done(&priv->queue_buf[slot]->vb2_buf,
++ VB2_BUF_STATE_DONE);
++ priv->queue_buf[slot] = NULL;
++
++ can_run = rcar_vin_fill_hw_slot(priv);
++ }
++
++ if (is_continuous_transfer(priv)) {
++ if (hw_stopped)
++ priv->state = STOPPED;
++ else if (list_empty(&priv->capture) &&
++ priv->state == RUNNING)
++ /*
++ * The continuous capturing requires an
++ * explicit stop operation when there is no
++ * buffer to be set into the VnMBm registers.
++ */
++ rcar_vin_request_capture_stop(priv);
++ } else {
++ if (can_run)
++ rcar_vin_capture(priv);
++ else
++ priv->state = STOPPED;
++ }
++ } else if (hw_stopped) {
++ priv->state = STOPPED;
++ priv->request_to_stop = false;
++ complete(&priv->capture_stop);
++ }
++
++done:
++ spin_unlock(&priv->lock);
++
++ return IRQ_RETVAL(handled);
++}
++
++static struct v4l2_subdev *find_csi2(struct rcar_vin_priv *pcdev)
++{
++ struct v4l2_subdev *sd;
++ char name[] = "rcar_csi2";
++
++ v4l2_device_for_each_subdev(sd, &pcdev->ici.v4l2_dev) {
++ if (!strncmp(name, sd->name, sizeof(name) - 1)) {
++ pcdev->csi2_sd = sd;
++ return sd;
++ }
++ }
++
++ return NULL;
++}
++
++static int rcar_vin_add_device(struct soc_camera_device *icd)
++{
++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
++ struct rcar_vin_priv *priv = ici->priv;
++ int i;
++
++ for (i = 0; i < MAX_BUFFER_NUM; i++)
++ priv->queue_buf[i] = NULL;
++
++ pm_runtime_get_sync(ici->v4l2_dev.dev);
++
++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) {
++ struct v4l2_subdev *csi2_sd = find_csi2(priv);
++ int ret;
++
++ if (csi2_sd) {
++ csi2_sd->grp_id = soc_camera_grp_id(icd);
++ v4l2_set_subdev_hostdata(csi2_sd, icd);
++
++ ret = v4l2_subdev_call(csi2_sd, core, s_power, 1);
++ priv->csi_sync = true;
++
++ if (ret < 0 && ret != -EINVAL)
++ priv->csi_sync = false;
++
++ if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
++ return ret;
++ }
++ /*
++ * -ENODEV is special:
++ * either csi2_sd == NULL or the CSI-2 driver
++ * has not found this soc-camera device among its clients
++ */
++ if (csi2_sd && ret == -ENODEV)
++ csi2_sd->grp_id = 0;
++
++ dev_dbg(icd->parent,
++ "R-Car VIN/CSI-2 driver attached to camera %d\n",
++ icd->devnum);
++
++ } else
++ dev_dbg(icd->parent, "R-Car VIN driver attached to camera %d\n",
++ icd->devnum);
++
++ priv->error_flag = false;
++
++ return 0;
++}
++
++static void rcar_vin_remove_device(struct soc_camera_device *icd)
++{
++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
++ struct rcar_vin_priv *priv = ici->priv;
++ struct vb2_v4l2_buffer *vbuf;
++ struct v4l2_subdev *csi2_sd = find_csi2(priv);
++ int i;
++
++ /* disable capture, disable interrupts */
++ iowrite32(ioread32(priv->base + VNMC_REG) & ~VNMC_ME,
++ priv->base + VNMC_REG);
++ iowrite32(0, priv->base + VNIE_REG);
++
++ priv->state = STOPPED;
++ priv->request_to_stop = false;
++ priv->error_flag = false;
++
++ /* make sure active buffer is cancelled */
++ spin_lock_irq(&priv->lock);
++ for (i = 0; i < MAX_BUFFER_NUM; i++) {
++ vbuf = priv->queue_buf[i];
++ if (vbuf) {
++ list_del_init(to_buf_list(vbuf));
++ vb2_buffer_done(&vbuf->vb2_buf, VB2_BUF_STATE_ERROR);
++ }
++ }
++ spin_unlock_irq(&priv->lock);
++
++ pm_runtime_put(ici->v4l2_dev.dev);
++
++ if ((csi2_sd) && (priv->csi_sync))
++ v4l2_subdev_call(csi2_sd, core, s_power, 0);
++
++ dev_dbg(icd->parent, "R-Car VIN driver detached from camera %d\n",
++ icd->devnum);
++}
++
++struct rcar_vin_uds_regs {
++ unsigned long ctrl;
++ unsigned long scale;
++ unsigned long pass_bwidth;
++ unsigned long clip_size;
++};
++
++static unsigned long rcar_vin_get_bwidth(unsigned long ratio)
++{
++ unsigned long bwidth;
++ unsigned long mant, frac;
++
++ mant = (ratio & 0xF000) >> 12;
++ frac = ratio & 0x0FFF;
++ if (mant)
++ bwidth = 64 * 4096 * mant / (4096 * mant + frac);
++ else
++ bwidth = 64;
++
++ return bwidth;
++}
++
++static unsigned long rcar_vin_compute_ratio(unsigned int input,
++ unsigned int output)
++{
++ return ((input * 4096 / output) == 0x10000) ?
++ 0xFFFF : (input * 4096 / output);
++}
++
++int rcar_vin_uds_set(struct rcar_vin_priv *priv, struct rcar_vin_cam *cam)
++{
++ struct rcar_vin_uds_regs regs;
++ unsigned long ratio_h, ratio_v;
++ unsigned long bwidth_h, bwidth_v;
++ unsigned long ctrl;
++ unsigned long clip_size;
++ struct v4l2_rect *cam_subrect = &cam->subrect;
++ u32 vnmc;
++
++ ratio_h = rcar_vin_compute_ratio(cam_subrect->width, cam->out_width);
++ ratio_v = rcar_vin_compute_ratio(cam_subrect->height, cam->out_height);
++
++ priv->ratio_h = ratio_h;
++ priv->ratio_v = ratio_v;
++
++ bwidth_h = rcar_vin_get_bwidth(ratio_h);
++ bwidth_v = rcar_vin_get_bwidth(ratio_v);
++
++ ctrl = VNUDS_CTRL_AMD;
++
++ if (priv->field == V4L2_FIELD_NONE)
++ clip_size = (cam->out_width << 16) | (cam->out_height);
++ else
++ clip_size = (cam->out_width << 16) | (cam->out_height / 2);
++
++ regs.ctrl = ctrl;
++ regs.scale = (ratio_h << 16) | ratio_v;
++ regs.pass_bwidth = (bwidth_h << 16) | bwidth_v;
++ regs.clip_size = clip_size;
++
++ vnmc = ioread32(priv->base + VNMC_REG);
++ iowrite32(vnmc | VNMC_SCLE, priv->base + VNMC_REG);
++ iowrite32(regs.ctrl, priv->base + VNUDS_CTRL_REG);
++ iowrite32(regs.scale, priv->base + VNUDS_SCALE_REG);
++ iowrite32(regs.pass_bwidth, priv->base + VNUDS_PASS_BWIDTH_REG);
++ iowrite32(regs.clip_size, priv->base + VNUDS_CLIP_SIZE_REG);
++
++ return 0;
++}
++
++static void set_coeff(struct rcar_vin_priv *priv, unsigned short xs)
++{
++ int i;
++ const struct vin_coeff *p_prev_set = NULL;
++ const struct vin_coeff *p_set = NULL;
++
++ /* Look for suitable coefficient values */
++ for (i = 0; i < ARRAY_SIZE(vin_coeff_set); i++) {
++ p_prev_set = p_set;
++ p_set = &vin_coeff_set[i];
++
++ if (xs < p_set->xs_value)
++ break;
++ }
++
++ /* Use previous value if its XS value is closer */
++ if (p_prev_set && p_set &&
++ xs - p_prev_set->xs_value < p_set->xs_value - xs)
++ p_set = p_prev_set;
++
++ /* Set coefficient registers */
++ iowrite32(p_set->coeff_set[0], priv->base + VNC1A_REG);
++ iowrite32(p_set->coeff_set[1], priv->base + VNC1B_REG);
++ iowrite32(p_set->coeff_set[2], priv->base + VNC1C_REG);
++
++ iowrite32(p_set->coeff_set[3], priv->base + VNC2A_REG);
++ iowrite32(p_set->coeff_set[4], priv->base + VNC2B_REG);
++ iowrite32(p_set->coeff_set[5], priv->base + VNC2C_REG);
++
++ iowrite32(p_set->coeff_set[6], priv->base + VNC3A_REG);
++ iowrite32(p_set->coeff_set[7], priv->base + VNC3B_REG);
++ iowrite32(p_set->coeff_set[8], priv->base + VNC3C_REG);
++
++ iowrite32(p_set->coeff_set[9], priv->base + VNC4A_REG);
++ iowrite32(p_set->coeff_set[10], priv->base + VNC4B_REG);
++ iowrite32(p_set->coeff_set[11], priv->base + VNC4C_REG);
++
++ iowrite32(p_set->coeff_set[12], priv->base + VNC5A_REG);
++ iowrite32(p_set->coeff_set[13], priv->base + VNC5B_REG);
++ iowrite32(p_set->coeff_set[14], priv->base + VNC5C_REG);
++
++ iowrite32(p_set->coeff_set[15], priv->base + VNC6A_REG);
++ iowrite32(p_set->coeff_set[16], priv->base + VNC6B_REG);
++ iowrite32(p_set->coeff_set[17], priv->base + VNC6C_REG);
++
++ iowrite32(p_set->coeff_set[18], priv->base + VNC7A_REG);
++ iowrite32(p_set->coeff_set[19], priv->base + VNC7B_REG);
++ iowrite32(p_set->coeff_set[20], priv->base + VNC7C_REG);
++
++ iowrite32(p_set->coeff_set[21], priv->base + VNC8A_REG);
++ iowrite32(p_set->coeff_set[22], priv->base + VNC8B_REG);
++ iowrite32(p_set->coeff_set[23], priv->base + VNC8C_REG);
++}
++
++/* rect is guaranteed to not exceed the scaled camera rectangle */
++static int rcar_vin_set_rect(struct soc_camera_device *icd)
++{
++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
++ struct rcar_vin_cam *cam = icd->host_priv;
++ struct rcar_vin_priv *priv = ici->priv;
++ unsigned int left_offset, top_offset;
++ unsigned char dsize = 0;
++ struct v4l2_rect *cam_subrect = &cam->subrect;
++ u32 value;
++ int ret = 0;
++
++ dev_dbg(icd->parent, "Crop %ux%u@%u:%u\n",
++ icd->user_width, icd->user_height, cam->vin_left, cam->vin_top);
++
++ left_offset = cam->vin_left;
++ top_offset = cam->vin_top;
++
++ if (icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_XBGR32 &&
++ priv->chip == RCAR_E1)
++ dsize = 1;
++
++ dev_dbg(icd->parent, "Cam %ux%u@%u:%u\n",
++ cam->width, cam->height, cam->vin_left, cam->vin_top);
++ dev_dbg(icd->parent, "Cam subrect %ux%u@%u:%u\n",
++ cam_subrect->width, cam_subrect->height,
++ cam_subrect->left, cam_subrect->top);
++
++ /* Set Start/End Pixel/Line Pre-Clip */
++ iowrite32(left_offset << dsize, priv->base + VNSPPRC_REG);
++ iowrite32((left_offset + cam_subrect->width - 1) << dsize,
++ priv->base + VNEPPRC_REG);
++ switch (priv->field) {
++ case V4L2_FIELD_INTERLACED:
++ case V4L2_FIELD_INTERLACED_TB:
++ case V4L2_FIELD_INTERLACED_BT:
++ iowrite32(top_offset / 2, priv->base + VNSLPRC_REG);
++ iowrite32((top_offset + cam_subrect->height) / 2 - 1,
++ priv->base + VNELPRC_REG);
++ break;
++ default:
++ iowrite32(top_offset, priv->base + VNSLPRC_REG);
++ iowrite32(top_offset + cam_subrect->height - 1,
++ priv->base + VNELPRC_REG);
++ break;
++ }
++
++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) {
++ if ((icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_NV12)
++ && is_scaling(cam)) {
++ ret = rcar_vin_uds_set(priv, cam);
++ if (ret < 0)
++ return ret;
++ }
++ if (is_scaling(cam) ||
++ (icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_NV16) ||
++ (icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_NV12))
++ iowrite32(ALIGN(cam->out_width, 0x20),
++ priv->base + VNIS_REG);
++ else
++ iowrite32(ALIGN(cam->out_width, 0x10),
++ priv->base + VNIS_REG);
++ } else {
++ /* Set scaling coefficient */
++ value = 0;
++ if (cam_subrect->height != cam->out_height)
++ value = (4096 * cam_subrect->height) / cam->out_height;
++ dev_dbg(icd->parent, "YS Value: %x\n", value);
++ iowrite32(value, priv->base + VNYS_REG);
++
++ value = 0;
++ if (cam_subrect->width != cam->out_width)
++ value = (4096 * cam_subrect->width) / cam->out_width;
++
++ /* Horizontal upscaling is up to double size */
++ if (value < 2048)
++ value = 2048;
++
++ dev_dbg(icd->parent, "XS Value: %x\n", value);
++ iowrite32(value, priv->base + VNXS_REG);
++
++ /* Horizontal upscaling is carried out */
++ /* by scaling down from double size */
++ if (value < 4096)
++ value *= 2;
++
++ set_coeff(priv, value);
++
++ /* Set Start/End Pixel/Line Post-Clip */
++ iowrite32(0, priv->base + VNSPPOC_REG);
++ iowrite32(0, priv->base + VNSLPOC_REG);
++ iowrite32((cam->out_width - 1) << dsize,
++ priv->base + VNEPPOC_REG);
++ switch (priv->field) {
++ case V4L2_FIELD_INTERLACED:
++ case V4L2_FIELD_INTERLACED_TB:
++ case V4L2_FIELD_INTERLACED_BT:
++ iowrite32(cam->out_height / 2 - 1,
++ priv->base + VNELPOC_REG);
++ break;
++ default:
++ iowrite32(cam->out_height - 1,
++ priv->base + VNELPOC_REG);
++ break;
++ }
++
++ iowrite32(ALIGN(cam->out_width, 0x10), priv->base + VNIS_REG);
++ }
++
++ return ret;
++}
++
++static void capture_stop_preserve(struct rcar_vin_priv *priv, u32 *vnmc)
++{
++ *vnmc = ioread32(priv->base + VNMC_REG);
++ /* module disable */
++ iowrite32(*vnmc & ~VNMC_ME, priv->base + VNMC_REG);
++}
++
++static void capture_restore(struct rcar_vin_priv *priv, u32 vnmc)
++{
++ unsigned long timeout = jiffies + 10 * HZ;
++
++ /*
++ * Wait until the end of the current frame. It can take a long time,
++ * but if it has been aborted by a MRST1 reset, it should exit sooner.
++ */
++ while ((ioread32(priv->base + VNMS_REG) & VNMS_AV) &&
++ time_before(jiffies, timeout))
++ msleep(1);
++
++ if (time_after(jiffies, timeout)) {
++ dev_err(priv->ici.v4l2_dev.dev,
++ "Timeout waiting for frame end! Interface problem?\n");
++ return;
++ }
++
++ iowrite32(vnmc, priv->base + VNMC_REG);
++}
++
++#define VIN_MBUS_FLAGS (V4L2_MBUS_MASTER | \
++ V4L2_MBUS_PCLK_SAMPLE_RISING | \
++ V4L2_MBUS_HSYNC_ACTIVE_HIGH | \
++ V4L2_MBUS_HSYNC_ACTIVE_LOW | \
++ V4L2_MBUS_VSYNC_ACTIVE_HIGH | \
++ V4L2_MBUS_VSYNC_ACTIVE_LOW | \
++ V4L2_MBUS_DATA_ACTIVE_HIGH)
++
++static int rcar_vin_set_bus_param(struct soc_camera_device *icd)
++{
++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
++ struct rcar_vin_priv *priv = ici->priv;
++ struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
++ struct v4l2_mbus_config cfg;
++ unsigned long common_flags;
++ u32 vnmc;
++ u32 val;
++ int ret;
++
++ capture_stop_preserve(priv, &vnmc);
++
++ ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
++ if (!ret) {
++ common_flags = soc_mbus_config_compatible(&cfg, VIN_MBUS_FLAGS);
++ if (!common_flags) {
++ dev_warn(icd->parent,
++ "MBUS flags incompatible: camera 0x%x, host 0x%x\n",
++ cfg.flags, VIN_MBUS_FLAGS);
++ return -EINVAL;
++ }
++ } else if (ret != -ENOIOCTLCMD) {
++ return ret;
++ } else {
++ common_flags = VIN_MBUS_FLAGS;
++ }
++
++ /* Make choises, based on platform preferences */
++ if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) &&
++ (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) {
++ if (priv->pdata_flags & RCAR_VIN_HSYNC_ACTIVE_LOW)
++ common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH;
++ else
++ common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW;
++ }
++
++ if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) &&
++ (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) {
++ if (priv->pdata_flags & RCAR_VIN_VSYNC_ACTIVE_LOW)
++ common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH;
++ else
++ common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW;
++ }
++
++ cfg.flags = common_flags;
++ ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg);
++ if (ret < 0 && ret != -ENOIOCTLCMD)
++ return ret;
++
++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) {
++ if (cfg.type == V4L2_MBUS_CSI2)
++ vnmc &= ~VNMC_DPINE;
++ else
++ vnmc |= VNMC_DPINE;
++ }
++
++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3)
++ val = VNDMR2_FTEV;
++ else
++ val = VNDMR2_FTEV | VNDMR2_VLV(1);
++ if (!(common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW))
++ val |= VNDMR2_VPS;
++ if (!(common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW))
++ val |= VNDMR2_HPS;
++ iowrite32(val, priv->base + VNDMR2_REG);
++
++ ret = rcar_vin_set_rect(icd);
++ if (ret < 0)
++ return ret;
++
++ capture_restore(priv, vnmc);
++
++ return 0;
++}
++
++static int rcar_vin_try_bus_param(struct soc_camera_device *icd,
++ unsigned char buswidth)
++{
++ struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
++ struct v4l2_mbus_config cfg;
++ int ret;
++
++ ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
++ if (ret == -ENOIOCTLCMD)
++ return 0;
++ else if (ret)
++ return ret;
++
++ if (buswidth > 24)
++ return -EINVAL;
++
++ /* check is there common mbus flags */
++ ret = soc_mbus_config_compatible(&cfg, VIN_MBUS_FLAGS);
++ if (ret)
++ return 0;
++
++ dev_warn(icd->parent,
++ "MBUS flags incompatible: camera 0x%x, host 0x%x\n",
++ cfg.flags, VIN_MBUS_FLAGS);
++
++ return -EINVAL;
++}
++
++static bool rcar_vin_packing_supported(const struct soc_mbus_pixelfmt *fmt)
++{
++ return fmt->packing == SOC_MBUS_PACKING_NONE ||
++ (fmt->bits_per_sample > 8 &&
++ fmt->packing == SOC_MBUS_PACKING_EXTEND16);
++}
++
++static const struct soc_mbus_pixelfmt rcar_vin_formats[] = {
++ {
++ .fourcc = V4L2_PIX_FMT_NV12,
++ .name = "NV12",
++ .bits_per_sample = 8,
++ .packing = SOC_MBUS_PACKING_1_5X8,
++ .order = SOC_MBUS_ORDER_LE,
++ .layout = SOC_MBUS_LAYOUT_PLANAR_2Y_C,
++ },
++ {
++ .fourcc = V4L2_PIX_FMT_NV16,
++ .name = "NV16",
++ .bits_per_sample = 8,
++ .packing = SOC_MBUS_PACKING_2X8_PADHI,
++ .order = SOC_MBUS_ORDER_LE,
++ .layout = SOC_MBUS_LAYOUT_PLANAR_Y_C,
++ },
++ {
++ .fourcc = V4L2_PIX_FMT_YUYV,
++ .name = "YUYV",
++ .bits_per_sample = 16,
++ .packing = SOC_MBUS_PACKING_NONE,
++ .order = SOC_MBUS_ORDER_LE,
++ .layout = SOC_MBUS_LAYOUT_PACKED,
++ },
++ {
++ .fourcc = V4L2_PIX_FMT_UYVY,
++ .name = "UYVY",
++ .bits_per_sample = 16,
++ .packing = SOC_MBUS_PACKING_NONE,
++ .order = SOC_MBUS_ORDER_LE,
++ .layout = SOC_MBUS_LAYOUT_PACKED,
++ },
++ {
++ .fourcc = V4L2_PIX_FMT_RGB565,
++ .name = "RGB565",
++ .bits_per_sample = 16,
++ .packing = SOC_MBUS_PACKING_NONE,
++ .order = SOC_MBUS_ORDER_LE,
++ .layout = SOC_MBUS_LAYOUT_PACKED,
++ },
++ {
++ .fourcc = V4L2_PIX_FMT_ARGB555,
++ .name = "ARGB1555",
++ .bits_per_sample = 16,
++ .packing = SOC_MBUS_PACKING_NONE,
++ .order = SOC_MBUS_ORDER_LE,
++ .layout = SOC_MBUS_LAYOUT_PACKED,
++ },
++ {
++ .fourcc = V4L2_PIX_FMT_XBGR32,
++ .name = "RGB888",
++ .bits_per_sample = 32,
++ .packing = SOC_MBUS_PACKING_NONE,
++ .order = SOC_MBUS_ORDER_LE,
++ .layout = SOC_MBUS_LAYOUT_PACKED,
++ },
++ {
++ .fourcc = V4L2_PIX_FMT_ABGR32,
++ .name = "ARGB8888",
++ .bits_per_sample = 32,
++ .packing = SOC_MBUS_PACKING_NONE,
++ .order = SOC_MBUS_ORDER_LE,
++ .layout = SOC_MBUS_LAYOUT_PACKED,
++ },
++};
++
++static int rcar_vin_get_formats(struct soc_camera_device *icd, unsigned int idx,
++ struct soc_camera_format_xlate *xlate)
++{
++ struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
++ struct device *dev = icd->parent;
++ int ret, k, n;
++ int formats = 0;
++ struct rcar_vin_cam *cam;
++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
++ struct rcar_vin_priv *priv = ici->priv;
++ struct v4l2_subdev_mbus_code_enum code = {
++ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
++ .index = idx,
++ };
++ const struct soc_mbus_pixelfmt *fmt;
++
++ ret = v4l2_subdev_call(sd, pad, enum_mbus_code, NULL, &code);
++ if (ret < 0)
++ return 0;
++
++ fmt = soc_mbus_get_fmtdesc(code.code);
++ if (!fmt) {
++ dev_warn(dev, "unsupported format code #%u: %d\n", idx, code.code);
++ return 0;
++ }
++
++ ret = rcar_vin_try_bus_param(icd, fmt->bits_per_sample);
++ if (ret < 0)
++ return 0;
++
++ if (!icd->host_priv) {
++ struct v4l2_subdev_format fmt = {
++ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
++ };
++ struct v4l2_mbus_framefmt *mf = &fmt.format;
++ struct v4l2_rect rect;
++ struct device *dev = icd->parent;
++ int shift;
++
++ ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt);
++ if (ret < 0)
++ return ret;
++
++ /* Cache current client geometry */
++ ret = soc_camera_client_g_rect(sd, &rect);
++ if (ret == -ENOIOCTLCMD) {
++ /* Sensor driver doesn't support cropping */
++ rect.left = 0;
++ rect.top = 0;
++ rect.width = mf->width;
++ rect.height = mf->height;
++ } else if (ret < 0) {
++ return ret;
++ }
++
++ /*
++ * If sensor proposes too large format then try smaller ones:
++ * 1280x960, 640x480, 320x240
++ */
++ for (shift = 0; shift < 3; shift++) {
++ if (mf->width <= priv->max_width &&
++ mf->height <= priv->max_height)
++ break;
++
++ mf->width = 1280 >> shift;
++ mf->height = 960 >> shift;
++ ret = v4l2_device_call_until_err(sd->v4l2_dev,
++ soc_camera_grp_id(icd),
++ pad, set_fmt, NULL,
++ &fmt);
++ if (ret < 0)
++ return ret;
++ }
++
++ if (shift == 3) {
++ dev_err(dev,
++ "Failed to configure the client below %ux%u\n",
++ mf->width, mf->height);
++ return -EIO;
++ }
++
++ dev_dbg(dev, "camera fmt %ux%u\n", mf->width, mf->height);
++
++ cam = kzalloc(sizeof(*cam), GFP_KERNEL);
++ if (!cam)
++ return -ENOMEM;
++ /*
++ * We are called with current camera crop,
++ * initialise subrect with it
++ */
++ cam->rect = rect;
++ cam->subrect = rect;
++ cam->width = mf->width;
++ cam->height = mf->height;
++ cam->out_width = mf->width;
++ cam->out_height = mf->height;
++
++ icd->host_priv = cam;
++ } else {
++ cam = icd->host_priv;
++ }
++
++ /* Beginning of a pass */
++ if (!idx)
++ cam->extra_fmt = NULL;
++
++ switch (code.code) {
++ case MEDIA_BUS_FMT_YUYV8_1X16:
++ case MEDIA_BUS_FMT_YUYV8_2X8:
++ case MEDIA_BUS_FMT_YUYV10_2X10:
++ case MEDIA_BUS_FMT_RGB888_1X24:
++ if (cam->extra_fmt)
++ break;
++
++ /* Add all our formats that can be generated by VIN */
++ cam->extra_fmt = rcar_vin_formats;
++
++ n = ARRAY_SIZE(rcar_vin_formats);
++ formats += n;
++ for (k = 0; xlate && k < n; k++, xlate++) {
++ xlate->host_fmt = &rcar_vin_formats[k];
++ xlate->code = code.code;
++ dev_dbg(dev, "Providing format %s using code %d\n",
++ rcar_vin_formats[k].name, code.code);
++ }
++ break;
++ default:
++ if (!rcar_vin_packing_supported(fmt))
++ return 0;
++
++ dev_dbg(dev, "Providing format %s in pass-through mode\n",
++ fmt->name);
++ break;
++ }
++
++ /* Generic pass-through */
++ formats++;
++ if (xlate) {
++ xlate->host_fmt = fmt;
++ xlate->code = code.code;
++ xlate++;
++ }
++
++ return formats;
++}
++
++static void rcar_vin_put_formats(struct soc_camera_device *icd)
++{
++ kfree(icd->host_priv);
++ icd->host_priv = NULL;
++}
++
++static int rcar_vin_set_selection(struct soc_camera_device *icd,
++ struct v4l2_selection *sel)
++{
++ const struct v4l2_rect *rect = &sel->r;
++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
++ struct rcar_vin_priv *priv = ici->priv;
++ struct v4l2_selection cam_sel;
++ struct rcar_vin_cam *cam = icd->host_priv;
++ struct v4l2_rect *cam_rect = &cam_sel.r;
++ struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
++ struct device *dev = icd->parent;
++ struct v4l2_subdev_format fmt = {
++ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
++ };
++ struct v4l2_mbus_framefmt *mf = &fmt.format;
++ u32 vnmc;
++ int ret, i;
++
++ dev_dbg(dev, "S_SELECTION(%ux%u@%u:%u)\n", rect->width, rect->height,
++ rect->left, rect->top);
++
++ /* During camera cropping its output window can change too, stop VIN */
++ capture_stop_preserve(priv, &vnmc);
++ dev_dbg(dev, "VNMC_REG 0x%x\n", vnmc);
++
++ /* Apply iterative camera S_SELECTION for new input window. */
++ ret = soc_camera_client_s_selection(sd, sel, &cam_sel,
++ &cam->rect, &cam->subrect);
++ if (ret < 0)
++ return ret;
++
++ dev_dbg(dev, "camera cropped to %ux%u@%u:%u\n",
++ cam_rect->width, cam_rect->height,
++ cam_rect->left, cam_rect->top);
++
++ /* On success cam_crop contains current camera crop */
++
++ /* Retrieve camera output window */
++ ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt);
++ if (ret < 0)
++ return ret;
++
++ if (mf->width > priv->max_width || mf->height > priv->max_height)
++ return -EINVAL;
++
++ /* Cache camera output window */
++ cam->width = mf->width;
++ cam->height = mf->height;
++
++ cam->vin_left = rect->left;
++ cam->vin_top = rect->top;
++
++ /* Use VIN cropping to crop to the new window. */
++ ret = rcar_vin_set_rect(icd);
++ if (ret < 0)
++ return ret;
++
++ dev_dbg(dev, "VIN cropped to %ux%u@%u:%u\n",
++ icd->user_width, icd->user_height,
++ cam->vin_left, cam->vin_top);
++
++ /* Restore capture */
++ for (i = 0; i < MAX_BUFFER_NUM; i++) {
++ if (priv->queue_buf[i] && priv->state == STOPPED) {
++ vnmc |= VNMC_ME;
++ break;
++ }
++ }
++ capture_restore(priv, vnmc);
++
++ /* Even if only camera cropping succeeded */
++ return ret;
++}
++
++static int rcar_vin_get_selection(struct soc_camera_device *icd,
++ struct v4l2_selection *sel)
++{
++ struct rcar_vin_cam *cam = icd->host_priv;
++
++ sel->r = cam->subrect;
++
++ return 0;
++}
++
++/* Similar to set_crop multistage iterative algorithm */
++static int rcar_vin_set_fmt(struct soc_camera_device *icd,
++ struct v4l2_format *f)
++{
++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
++ struct rcar_vin_priv *priv = ici->priv;
++ struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
++ struct rcar_vin_cam *cam = icd->host_priv;
++ struct v4l2_pix_format *pix = &f->fmt.pix;
++ struct v4l2_mbus_framefmt mf;
++ struct device *dev = icd->parent;
++ __u32 pixfmt = pix->pixelformat;
++ const struct soc_camera_format_xlate *xlate;
++ unsigned int vin_sub_width = 0, vin_sub_height = 0;
++ int ret;
++ bool can_scale;
++ enum v4l2_field field;
++ v4l2_std_id std;
++
++ dev_dbg(dev, "S_FMT(pix=0x%x, %ux%u)\n",
++ pixfmt, pix->width, pix->height);
++
++ /* At the time of NV16 capture format, the user has to specify */
++ /* the width of the multiple of 32 for H/W specification. */
++ if (priv->error_flag == false)
++ priv->error_flag = true;
++ else {
++ if (((pixfmt == V4L2_PIX_FMT_NV16) ||
++ (pixfmt == V4L2_PIX_FMT_NV12)) &&
++ (pix->width & 0x1F)) {
++ dev_dbg(icd->parent,
++ "specify width of 32 multiple in separate format.\n");
++ return -EINVAL;
++ }
++ }
++
++ switch (pix->field) {
++ default:
++ pix->field = V4L2_FIELD_NONE;
++ /* fall-through */
++ case V4L2_FIELD_NONE:
++ case V4L2_FIELD_TOP:
++ case V4L2_FIELD_BOTTOM:
++ case V4L2_FIELD_INTERLACED_TB:
++ case V4L2_FIELD_INTERLACED_BT:
++ field = pix->field;
++ break;
++ case V4L2_FIELD_INTERLACED:
++ /* Query for standard if not explicitly mentioned _TB/_BT */
++ ret = v4l2_subdev_call(sd, video, querystd, &std);
++ if (ret == -ENOIOCTLCMD) {
++ field = V4L2_FIELD_NONE;
++ } else if (ret < 0) {
++ return ret;
++ } else {
++ field = std & V4L2_STD_625_50 ?
++ V4L2_FIELD_INTERLACED_TB :
++ V4L2_FIELD_INTERLACED_BT;
++ }
++ break;
++ }
++
++ xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
++ if (!xlate) {
++ dev_warn(dev, "Format %x not found\n", pixfmt);
++ return -EINVAL;
++ }
++ /* Calculate client output geometry */
++ soc_camera_calc_client_output(icd, &cam->rect, &cam->subrect, pix, &mf,
++ 12);
++ mf.field = pix->field;
++ mf.colorspace = pix->colorspace;
++ mf.code = xlate->code;
++
++ switch (pixfmt) {
++ case V4L2_PIX_FMT_XBGR32:
++ can_scale = priv->chip != RCAR_E1;
++ break;
++ case V4L2_PIX_FMT_ABGR32:
++ case V4L2_PIX_FMT_UYVY:
++ case V4L2_PIX_FMT_YUYV:
++ case V4L2_PIX_FMT_RGB565:
++ case V4L2_PIX_FMT_ARGB555:
++ case V4L2_PIX_FMT_NV16:
++ can_scale = true;
++ break;
++ case V4L2_PIX_FMT_NV12:
++ default:
++ can_scale = false;
++ break;
++ }
++
++ dev_dbg(dev, "request camera output %ux%u\n", mf.width, mf.height);
++
++ ret = soc_camera_client_scale(icd, &cam->rect, &cam->subrect,
++ &mf, &vin_sub_width, &vin_sub_height,
++ can_scale, 12);
++
++ /* Done with the camera. Now see if we can improve the result */
++ dev_dbg(dev, "Camera %d fmt %ux%u, requested %ux%u\n",
++ ret, mf.width, mf.height, pix->width, pix->height);
++
++ if (ret == -ENOIOCTLCMD)
++ dev_dbg(dev, "Sensor doesn't support scaling\n");
++ else if (ret < 0)
++ return ret;
++
++ if (mf.code != xlate->code)
++ return -EINVAL;
++
++ /* Prepare VIN crop */
++ cam->width = mf.width;
++ cam->height = mf.height;
++
++ /* Use VIN scaling to scale to the requested user window. */
++
++ /* We cannot scale up */
++ if (pix->width > vin_sub_width)
++ vin_sub_width = pix->width;
++
++ if (pix->height > vin_sub_height)
++ vin_sub_height = pix->height;
++
++ pix->colorspace = mf.colorspace;
++
++ if (!can_scale) {
++ pix->width = vin_sub_width;
++ pix->height = vin_sub_height;
++ }
++
++ /*
++ * We have calculated CFLCR, the actual configuration will be performed
++ * in rcar_vin_set_bus_param()
++ */
++
++ dev_dbg(dev, "W: %u : %u, H: %u : %u\n",
++ vin_sub_width, pix->width, vin_sub_height, pix->height);
++
++ cam->out_width = pix->width;
++ cam->out_height = pix->height;
++
++ icd->current_fmt = xlate;
++
++ priv->field = field;
++
++ return 0;
++}
++
++static int rcar_vin_try_fmt(struct soc_camera_device *icd,
++ struct v4l2_format *f)
++{
++ const struct soc_camera_format_xlate *xlate;
++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
++ struct rcar_vin_priv *priv = ici->priv;
++ struct v4l2_pix_format *pix = &f->fmt.pix;
++ struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
++ struct v4l2_subdev_pad_config pad_cfg;
++ struct v4l2_subdev_format format = {
++ .which = V4L2_SUBDEV_FORMAT_TRY,
++ };
++ struct v4l2_mbus_framefmt *mf = &format.format;
++ __u32 pixfmt = pix->pixelformat;
++ int width, height;
++ int ret;
++
++ xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
++ if (!xlate) {
++ xlate = icd->current_fmt;
++ dev_dbg(icd->parent, "Format %x not found, keeping %x\n",
++ pixfmt, xlate->host_fmt->fourcc);
++ pixfmt = xlate->host_fmt->fourcc;
++ pix->pixelformat = pixfmt;
++ pix->colorspace = icd->colorspace;
++ }
++
++ /* When performing a YCbCr-422 format output, even if it performs */
++ /* odd number clipping by pixel post clip processing, */
++ /* it is outputted to a memory per even pixels. */
++ if ((pixfmt == V4L2_PIX_FMT_NV16) || (pixfmt == V4L2_PIX_FMT_NV12) ||
++ (pixfmt == V4L2_PIX_FMT_YUYV) || (pixfmt == V4L2_PIX_FMT_UYVY))
++ v4l_bound_align_image(&pix->width, 5, priv->max_width, 1,
++ &pix->height, 2, priv->max_height, 0, 0);
++ else
++ v4l_bound_align_image(&pix->width, 5, priv->max_width, 0,
++ &pix->height, 2, priv->max_height, 0, 0);
++
++ width = pix->width;
++ height = pix->height;
++
++ /* let soc-camera calculate these values */
++ pix->bytesperline = 0;
++ pix->sizeimage = 0;
++
++ /* limit to sensor capabilities */
++ mf->width = pix->width;
++ mf->height = pix->height;
++ mf->field = pix->field;
++ mf->code = xlate->code;
++ mf->colorspace = pix->colorspace;
++
++ ret = v4l2_device_call_until_err(sd->v4l2_dev, soc_camera_grp_id(icd),
++ pad, set_fmt, &pad_cfg, &format);
++ if (ret < 0)
++ return ret;
++
++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) {
++ /* Adjust max scaling size for Gen3 */
++ if (pix->width > 4096)
++ pix->width = priv->max_width;
++ if (pix->height > 4096)
++ pix->height = priv->max_height;
++ } else {
++ /* Adjust only if VIN cannot scale */
++ if (pix->width > mf->width * 2)
++ pix->width = mf->width * 2;
++ if (pix->height > mf->height * 3)
++ pix->height = mf->height * 3;
++ }
++
++ pix->field = mf->field;
++ pix->colorspace = mf->colorspace;
++
++ if (pixfmt == V4L2_PIX_FMT_NV16) {
++ /* FIXME: check against rect_max after converting soc-camera */
++ /* We can scale precisely, need a bigger image from camera */
++ if (pix->width < width || pix->height < height) {
++ /*
++ * We presume, the sensor behaves sanely, i.e. if
++ * requested a bigger rectangle, it will not return a
++ * smaller one.
++ */
++ mf->width = priv->max_width;
++ mf->height = priv->max_height;
++ ret = v4l2_device_call_until_err(sd->v4l2_dev,
++ soc_camera_grp_id(icd),
++ pad, set_fmt, &pad_cfg,
++ &format);
++ if (ret < 0) {
++ dev_err(icd->parent,
++ "client try_fmt() = %d\n", ret);
++ return ret;
++ }
++ }
++ /* We will scale exactly */
++ if (mf->width > width)
++ pix->width = width;
++ if (mf->height > height)
++ pix->height = height;
++ }
++
++ return ret;
++}
++
++static unsigned int rcar_vin_poll(struct file *file, poll_table *pt)
++{
++ struct soc_camera_device *icd = file->private_data;
++
++ return vb2_poll(&icd->vb2_vidq, file, pt);
++}
++
++static int rcar_vin_querycap(struct soc_camera_host *ici,
++ struct v4l2_capability *cap)
++{
++ strlcpy(cap->card, "R_Car_VIN", sizeof(cap->card));
++ cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
++ cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
++ snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s%d", DRV_NAME, ici->nr);
++
++ return 0;
++}
++
++static int rcar_vin_init_videobuf2(struct vb2_queue *vq,
++ struct soc_camera_device *icd)
++{
++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
++
++ vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++ vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
++ vq->drv_priv = icd;
++ vq->ops = &rcar_vin_vb2_ops;
++ vq->mem_ops = &vb2_dma_contig_memops;
++ vq->buf_struct_size = sizeof(struct rcar_vin_buffer);
++ vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
++ vq->lock = &ici->host_lock;
++ vq->dev = ici->v4l2_dev.dev;
++
++ return vb2_queue_init(vq);
++}
++
++#if 0
++static int rcar_vin_get_selection(struct soc_camera_device *icd,
++ struct v4l2_selection *sel)
++{
++ struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
++ struct v4l2_subdev_format fmt = {
++ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
++ };
++ struct v4l2_mbus_framefmt *mf = &fmt.format;
++ int ret;
++
++ ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt);
++ if (ret < 0)
++ return ret;
++
++ if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
++ return -EINVAL;
++
++ switch (sel->target) {
++ case V4L2_SEL_TGT_CROP_BOUNDS:
++ case V4L2_SEL_TGT_CROP_DEFAULT:
++ sel->r.left = sel->r.top = 0;
++ sel->r.width = mf->width;
++ sel->r.height = mf->height;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++static int rcar_vin_cropcap(struct soc_camera_device *icd,
++ struct v4l2_cropcap *crop)
++{
++ struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
++ struct v4l2_subdev_format fmt = {
++ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
++ };
++ struct v4l2_mbus_framefmt *mf = &fmt.format;
++ int ret;
++
++ ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt);
++ if (ret < 0)
++ return ret;
++
++ crop->bounds.left = 0;
++ crop->bounds.top = 0;
++ crop->bounds.width = mf->width;
++ crop->bounds.height = mf->height;
++
++ /* default cropping rectangle */
++ crop->defrect = crop->bounds;
++ crop->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++
++ return 0;
++}
++#endif
++
++static struct soc_camera_host_ops rcar_vin_host_ops = {
++ .owner = THIS_MODULE,
++ .add = rcar_vin_add_device,
++ .remove = rcar_vin_remove_device,
++ .get_formats = rcar_vin_get_formats,
++ .put_formats = rcar_vin_put_formats,
++ .get_selection = rcar_vin_get_selection,
++ .set_selection = rcar_vin_set_selection,
++ .try_fmt = rcar_vin_try_fmt,
++ .set_fmt = rcar_vin_set_fmt,
++ .poll = rcar_vin_poll,
++ .querycap = rcar_vin_querycap,
++ .set_bus_param = rcar_vin_set_bus_param,
++ .init_videobuf2 = rcar_vin_init_videobuf2,
++#if 0
++ .get_selection = rcar_vin_get_selection,
++ .cropcap = rcar_vin_cropcap,
++#endif
++};
++
++#ifdef CONFIG_OF
++static const struct of_device_id rcar_vin_of_table[] = {
++ { .compatible = "renesas,vin-r8a7796", .data = (void *)RCAR_M3 },
++ { .compatible = "renesas,vin-r8a7795", .data = (void *)RCAR_H3 },
++ { .compatible = "renesas,vin-r8a7794", .data = (void *)RCAR_GEN2 },
++ { .compatible = "renesas,vin-r8a7793", .data = (void *)RCAR_GEN2 },
++ { .compatible = "renesas,vin-r8a7791", .data = (void *)RCAR_GEN2 },
++ { .compatible = "renesas,vin-r8a7790", .data = (void *)RCAR_GEN2 },
++ { .compatible = "renesas,vin-r8a7779", .data = (void *)RCAR_H1 },
++ { .compatible = "renesas,vin-r8a7778", .data = (void *)RCAR_M1 },
++ { .compatible = "renesas,rcar-gen3-vin", .data = (void *)RCAR_GEN3 },
++ { .compatible = "renesas,rcar-gen2-vin", .data = (void *)RCAR_GEN2 },
++ { },
++};
++MODULE_DEVICE_TABLE(of, rcar_vin_of_table);
++#endif
++
++#define MAP_MAX_NUM 32
++static DECLARE_BITMAP(device_map, MAP_MAX_NUM);
++static DEFINE_MUTEX(list_lock);
++
++static int rcar_vin_dyn_pdev(struct soc_camera_desc *sdesc,
++ struct rcar_vin_async_client *sasc)
++{
++ struct platform_device *pdev;
++ int ret, i;
++
++ mutex_lock(&list_lock);
++ i = find_first_zero_bit(device_map, MAP_MAX_NUM);
++ if (i < MAP_MAX_NUM)
++ set_bit(i, device_map);
++ mutex_unlock(&list_lock);
++ if (i >= MAP_MAX_NUM)
++ return -ENOMEM;
++
++ pdev = platform_device_alloc("soc-camera-pdrv", ((2 * i) + 1));
++ if (!pdev)
++ return -ENOMEM;
++
++ ret = platform_device_add_data(pdev, sdesc, sizeof(*sdesc));
++ if (ret < 0) {
++ platform_device_put(pdev);
++ return ret;
++ }
++
++ sasc->pdev = pdev;
++
++ return 0;
++}
++
++static int rcar_vin_async_bound(struct v4l2_async_notifier *notifier,
++ struct v4l2_subdev *sd,
++ struct v4l2_async_subdev *asd)
++{
++ /* None. */
++ return 0;
++}
++
++static void rcar_vin_async_unbind(struct v4l2_async_notifier *notifier,
++ struct v4l2_subdev *sd,
++ struct v4l2_async_subdev *asd)
++{
++ /* None. */
++}
++
++static int rcar_vin_async_probe(struct soc_camera_host *ici,
++ struct soc_camera_device *icd)
++{
++ struct soc_camera_desc *sdesc = to_soc_camera_desc(icd);
++ struct soc_camera_host_desc *shd = &sdesc->host_desc;
++ struct device *control = NULL;
++ int ret;
++
++ ret = v4l2_ctrl_handler_init(&icd->ctrl_handler, 16);
++ if (ret < 0)
++ return ret;
++
++ if (shd->module_name)
++ ret = request_module(shd->module_name);
++
++ ret = shd->add_device(icd);
++
++ control = to_soc_camera_control(icd);
++ if (!control || !control->driver || !dev_get_drvdata(control) ||
++ !try_module_get(control->driver->owner)) {
++ shd->del_device(icd);
++ ret = -ENODEV;
++ }
++
++ return ret;
++}
++
++static int rcar_vin_async_complete(struct v4l2_async_notifier *notifier)
++{
++ struct rcar_vin_async_client *sasc = container_of(notifier,
++ struct rcar_vin_async_client, notifier);
++ struct soc_camera_device *icd = platform_get_drvdata(sasc->pdev);
++
++ if (to_soc_camera_control(icd)) {
++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
++ int ret;
++
++ mutex_lock(&list_lock);
++ ret = rcar_vin_async_probe(ici, icd);
++ mutex_unlock(&list_lock);
++ if (ret < 0)
++ return ret;
++ }
++
++ return 0;
++}
++
++static struct soc_camera_device *rcar_vin_add_pdev(
++ struct rcar_vin_async_client *sasc)
++{
++ struct platform_device *pdev = sasc->pdev;
++ int ret;
++
++ ret = platform_device_add(pdev);
++
++ if (ret < 0 || !pdev->dev.driver)
++ return NULL;
++
++ return platform_get_drvdata(pdev);
++}
++
++static int rcar_vin_soc_of_bind(struct rcar_vin_priv *priv,
++ struct soc_camera_host *ici,
++ struct device_node *ep,
++ struct device_node *remote)
++{
++ struct soc_camera_device *icd;
++ struct soc_camera_desc sdesc = {.host_desc.bus_id = ici->nr,};
++ struct rcar_vin_async_client *sasc;
++ struct soc_of_info *info;
++ struct i2c_client *client;
++ char clk_name[V4L2_SUBDEV_NAME_SIZE];
++ int ret;
++
++ /* allocate a new subdev and add match info to it */
++ info = devm_kzalloc(ici->v4l2_dev.dev, sizeof(struct soc_of_info),
++ GFP_KERNEL);
++ if (!info)
++ return -ENOMEM;
++
++ info->sasd.asd.match.of.node = remote;
++ info->sasd.asd.match_type = V4L2_ASYNC_MATCH_OF;
++ info->subdev = &info->sasd.asd;
++
++ /* Or shall this be managed by the soc-camera device? */
++ sasc = &info->sasc;
++
++ ret = rcar_vin_dyn_pdev(&sdesc, sasc);
++ if (ret < 0)
++ goto eallocpdev;
++
++ sasc->sensor = &info->sasd.asd;
++
++ icd = rcar_vin_add_pdev(sasc);
++ if (!icd) {
++ ret = -ENOMEM;
++ goto eaddpdev;
++ }
++
++ sasc->notifier.subdevs = &info->subdev;
++ sasc->notifier.num_subdevs = 1;
++ sasc->notifier.bound = rcar_vin_async_bound;
++ sasc->notifier.unbind = rcar_vin_async_unbind;
++ sasc->notifier.complete = rcar_vin_async_complete;
++
++ priv->async_client = sasc;
++
++ client = of_find_i2c_device_by_node(remote);
++
++ if (client)
++ snprintf(clk_name, sizeof(clk_name), "%d-%04x",
++ client->adapter->nr, client->addr);
++ else
++ snprintf(clk_name, sizeof(clk_name), "of-%s",
++ of_node_full_name(remote));
++
++ ret = v4l2_async_notifier_register(&ici->v4l2_dev, &sasc->notifier);
++ if (!ret)
++ return 0;
++
++ platform_device_del(sasc->pdev);
++eaddpdev:
++ platform_device_put(sasc->pdev);
++eallocpdev:
++ devm_kfree(ici->v4l2_dev.dev, info);
++ dev_err(ici->v4l2_dev.dev, "group probe failed: %d\n", ret);
++
++ return ret;
++}
++
++static int rcar_vin_probe(struct platform_device *pdev)
++{
++ const struct of_device_id *match = NULL;
++ struct rcar_vin_priv *priv;
++ struct v4l2_of_endpoint ep;
++ struct device_node *np;
++ struct resource *mem;
++ unsigned int pdata_flags;
++ int irq, ret;
++ const char *str;
++ unsigned int i;
++ struct device_node *epn = NULL, *ren = NULL;
++ bool csi_use = false;
++
++ match = of_match_device(of_match_ptr(rcar_vin_of_table), &pdev->dev);
++
++ np = of_graph_get_next_endpoint(pdev->dev.of_node, NULL);
++ if (!np) {
++ dev_err(&pdev->dev, "could not find endpoint\n");
++ return -EINVAL;
++ }
++
++ for (i = 0; ; i++) {
++ epn = of_graph_get_next_endpoint(pdev->dev.of_node,
++ epn);
++ if (!epn)
++ break;
++
++ ren = of_graph_get_remote_port(epn);
++ if (!ren) {
++ dev_notice(&pdev->dev, "no remote for %s\n",
++ of_node_full_name(epn));
++ continue;
++ }
++
++ /* so we now have a remote node to connect */
++ dev_dbg(&pdev->dev, "node name:%s\n",
++ of_node_full_name(ren->parent));
++
++ if (strcmp(ren->parent->name, "csi2") == 0)
++ csi_use = true;
++
++ of_node_put(ren);
++
++ if (i)
++ break;
++ }
++
++ ret = v4l2_of_parse_endpoint(np, &ep);
++ if (ret) {
++ dev_err(&pdev->dev, "could not parse endpoint\n");
++ return ret;
++ }
++
++ if (ep.bus_type == V4L2_MBUS_BT656)
++ pdata_flags = RCAR_VIN_BT656;
++ else if (ep.bus_type == V4L2_MBUS_CSI2)
++ pdata_flags = RCAR_VIN_BT656 | RCAR_VIN_CSI2;
++ else {
++ pdata_flags = 0;
++ if (ep.bus.parallel.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
++ pdata_flags |= RCAR_VIN_HSYNC_ACTIVE_LOW;
++ if (ep.bus.parallel.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
++ pdata_flags |= RCAR_VIN_VSYNC_ACTIVE_LOW;
++ }
++
++ of_node_put(np);
++
++ dev_dbg(&pdev->dev, "pdata_flags = %08x\n", pdata_flags);
++
++ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (mem == NULL)
++ return -EINVAL;
++
++ irq = platform_get_irq(pdev, 0);
++ if (irq <= 0)
++ return -EINVAL;
++
++ priv = devm_kzalloc(&pdev->dev, sizeof(struct rcar_vin_priv),
++ GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ priv->base = devm_ioremap_resource(&pdev->dev, mem);
++ if (IS_ERR(priv->base))
++ return PTR_ERR(priv->base);
++
++ ret = devm_request_irq(&pdev->dev, irq, rcar_vin_irq, IRQF_SHARED,
++ dev_name(&pdev->dev), priv);
++ if (ret)
++ return ret;
++
++ priv->ici.priv = priv;
++ priv->ici.v4l2_dev.dev = &pdev->dev;
++ priv->ici.drv_name = dev_name(&pdev->dev);
++ priv->ici.ops = &rcar_vin_host_ops;
++ priv->csi_sync = false;
++
++ priv->pdata_flags = pdata_flags;
++ if (!match) {
++ priv->ici.nr = pdev->id;
++ priv->chip = pdev->id_entry->driver_data;
++ } else {
++ priv->ici.nr = of_alias_get_id(pdev->dev.of_node, "vin");
++ priv->chip = (enum chip_id)match->data;
++ }
++
++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) {
++ priv->max_width = 4096;
++ priv->max_height = 4096;
++ } else {
++ priv->max_width = 2048;
++ priv->max_height = 2048;
++ }
++
++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) {
++ u32 ifmd = 0;
++ bool match_flag = false;
++ const struct vin_gen3_ifmd *gen3_ifmd_table = NULL;
++ int vc, num;
++
++ num = VNCSI_IFMD_SEL_NUMBER;
++
++ if (strcmp(dev_name(priv->ici.v4l2_dev.dev),
++ "e6ef0000.video") == 0)
++ priv->index = RCAR_VIDEO_0;
++ else if (strcmp(dev_name(priv->ici.v4l2_dev.dev),
++ "e6ef1000.video") == 0)
++ priv->index = RCAR_VIDEO_1;
++ else if (strcmp(dev_name(priv->ici.v4l2_dev.dev),
++ "e6ef2000.video") == 0)
++ priv->index = RCAR_VIDEO_2;
++ else if (strcmp(dev_name(priv->ici.v4l2_dev.dev),
++ "e6ef3000.video") == 0)
++ priv->index = RCAR_VIDEO_3;
++ else if (strcmp(dev_name(priv->ici.v4l2_dev.dev),
++ "e6ef4000.video") == 0)
++ priv->index = RCAR_VIDEO_4;
++ else if (strcmp(dev_name(priv->ici.v4l2_dev.dev),
++ "e6ef5000.video") == 0)
++ priv->index = RCAR_VIDEO_5;
++ else if (strcmp(dev_name(priv->ici.v4l2_dev.dev),
++ "e6ef6000.video") == 0)
++ priv->index = RCAR_VIDEO_6;
++ else if (strcmp(dev_name(priv->ici.v4l2_dev.dev),
++ "e6ef7000.video") == 0)
++ priv->index = RCAR_VIDEO_7;
++ else
++ priv->index = RCAR_VIN_CH_NONE;
++
++ ret = of_property_read_string(np, "csi,select", &str);
++ if (ret) {
++ dev_err(&pdev->dev, "could not parse csi,select\n");
++ return ret;
++ }
++
++ if (strcmp(str, "csi40") == 0)
++ priv->csi_ch = RCAR_CSI40;
++ else if (strcmp(str, "csi20") == 0)
++ priv->csi_ch = RCAR_CSI20;
++ else if (strcmp(str, "csi41") == 0)
++ priv->csi_ch = RCAR_CSI41;
++ else if (strcmp(str, "csi21") == 0)
++ priv->csi_ch = RCAR_CSI21;
++ else
++ priv->csi_ch = RCAR_CSI_CH_NONE;
++
++ ret = of_property_read_u32(np, "virtual,channel", &vc);
++ if (ret) {
++ dev_err(&pdev->dev,
++ "could not parse virtual,channel\n");
++ return ret;
++ }
++
++ if (vc == 0)
++ priv->vc = RCAR_VIRTUAL_CH0;
++ else if (vc == 1)
++ priv->vc = RCAR_VIRTUAL_CH1;
++ else if (vc == 2)
++ priv->vc = RCAR_VIRTUAL_CH2;
++ else if (vc == 3)
++ priv->vc = RCAR_VIRTUAL_CH3;
++ else
++ priv->vc = RCAR_VIRTUAL_NONE;
++
++ dev_dbg(&pdev->dev, "csi_ch:%d, vc:%d\n",
++ priv->csi_ch, priv->vc);
++
++ ifmd = VNCSI_IFMD_DES1 | VNCSI_IFMD_DES0;
++
++ if (priv->chip == RCAR_H3)
++ gen3_ifmd_table = vin_h3_vc_ifmd;
++ else if (priv->chip == RCAR_M3)
++ gen3_ifmd_table = vin_m3_vc_ifmd;
++
++ for (i = 0; i < num; i++) {
++ if ((gen3_ifmd_table[i].v_sel[priv->index].csi2_ch
++ == priv->csi_ch) &&
++ (gen3_ifmd_table[i].v_sel[priv->index].vc
++ == priv->vc)) {
++ if (priv->index < RCAR_VIDEO_4) {
++ if (ifmd0_init) {
++ ifmd0_reg_match[i] = true;
++ match_flag = true;
++ } else if (ifmd0_reg_match[i])
++ match_flag = true;
++ } else {
++ if (ifmd4_init) {
++ ifmd4_reg_match[i] = true;
++ match_flag = true;
++ } else if (ifmd4_reg_match[i])
++ match_flag = true;
++ }
++ } else {
++ if (priv->index < RCAR_VIDEO_4)
++ ifmd0_reg_match[i] = false;
++ else
++ ifmd4_reg_match[i] = false;
++ }
++ }
++ if (priv->index < RCAR_VIDEO_4)
++ ifmd0_init = false;
++ else
++ ifmd4_init = false;
++
++ if (!match_flag) {
++ dev_err(&pdev->dev,
++ "Not match, virtual channel pattern error.\n");
++ return -EINVAL;
++ }
++
++ rcar_vin_cpg_enable_for_ifmd(priv->index, true);
++
++ if (priv->index < RCAR_VIDEO_4) {
++ void __iomem *ifmd0_mem;
++
++ for (i = 0; i < num; i++) {
++ if (ifmd0_reg_match[i]) {
++ ifmd |= gen3_ifmd_table[i].set_reg;
++ break;
++ }
++ }
++
++ ifmd0_mem = ioremap(0xe6ef0000 + VNCSI_IFMD_REG, 0x04);
++ iowrite32(ifmd, ifmd0_mem);
++ iounmap(ifmd0_mem);
++ } else {
++ void __iomem *ifmd4_mem;
++
++ for (i = 0; i < num; i++) {
++ if (ifmd4_reg_match[i]) {
++ ifmd |= gen3_ifmd_table[i].set_reg;
++ break;
++ }
++ }
++
++ ifmd4_mem = ioremap(0xe6ef4000 + VNCSI_IFMD_REG, 0x04);
++ iowrite32(ifmd, ifmd4_mem);
++ iounmap(ifmd4_mem);
++ }
++
++ rcar_vin_cpg_enable_for_ifmd(priv->index, false);
++ }
++
++ spin_lock_init(&priv->lock);
++ INIT_LIST_HEAD(&priv->capture);
++
++ priv->state = STOPPED;
++
++ pm_suspend_ignore_children(&pdev->dev, true);
++ pm_runtime_enable(&pdev->dev);
++
++ ret = soc_camera_host_register(&priv->ici);
++ if (ret)
++ goto cleanup;
++
++ if (csi_use) {
++ ret = rcar_vin_soc_of_bind(priv, &priv->ici, epn, ren->parent);
++ if (ret)
++ goto cleanup;
++ }
++
++ vin_debug = 0;
++
++ return 0;
++
++cleanup:
++ pm_runtime_disable(&pdev->dev);
++
++ return ret;
++}
++
++static int rcar_vin_remove(struct platform_device *pdev)
++{
++ struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
++ struct rcar_vin_priv *priv = container_of(soc_host,
++ struct rcar_vin_priv, ici);
++
++ platform_device_del(priv->async_client->pdev);
++ platform_device_put(priv->async_client->pdev);
++
++ v4l2_async_notifier_unregister(&priv->async_client->notifier);
++
++ soc_camera_host_unregister(soc_host);
++ pm_runtime_disable(&pdev->dev);
++
++ return 0;
++}
++
++#ifdef CONFIG_PM_SLEEP
++static int rcar_vin_suspend(struct device *dev)
++{
++ /* Empty function for now */
++ return 0;
++}
++
++static int rcar_vin_resume(struct device *dev)
++{
++ u32 ifmd = 0;
++ bool match_flag = false;
++ const struct vin_gen3_ifmd *gen3_ifmd_table = NULL;
++ int num;
++ unsigned int i;
++ struct soc_camera_host *soc_host = to_soc_camera_host(dev);
++ struct rcar_vin_priv *priv = container_of(soc_host,
++ struct rcar_vin_priv, ici);
++ num = VNCSI_IFMD_SEL_NUMBER;
++ ifmd0_init = true;
++ ifmd4_init = true;
++
++ if (priv->chip == RCAR_H3) {
++ ifmd = VNCSI_IFMD_DES1 | VNCSI_IFMD_DES0;
++ gen3_ifmd_table = vin_h3_vc_ifmd;
++ } else if (priv->chip == RCAR_M3) {
++ ifmd = VNCSI_IFMD_DES1;
++ gen3_ifmd_table = vin_m3_vc_ifmd;
++ }
++
++ for (i = 0; i < num; i++) {
++ if ((gen3_ifmd_table[i].v_sel[priv->index].csi2_ch
++ == priv->csi_ch) &&
++ (gen3_ifmd_table[i].v_sel[priv->index].vc
++ == priv->vc)) {
++ if (priv->index < RCAR_VIDEO_4) {
++ if (ifmd0_init) {
++ ifmd0_reg_match[i] = true;
++ match_flag = true;
++ } else if (ifmd0_reg_match[i])
++ match_flag = true;
++ } else {
++ if (ifmd4_init) {
++ ifmd4_reg_match[i] = true;
++ match_flag = true;
++ } else if (ifmd4_reg_match[i])
++ match_flag = true;
++ }
++ } else {
++ if (priv->index < RCAR_VIDEO_4)
++ ifmd0_reg_match[i] = false;
++ else
++ ifmd4_reg_match[i] = false;
++ }
++ }
++ if (priv->index < RCAR_VIDEO_4)
++ ifmd0_init = false;
++ else
++ ifmd4_init = false;
++
++ if (priv->index < RCAR_VIDEO_4) {
++ void __iomem *ifmd0_mem;
++
++ for (i = 0; i < num; i++) {
++ if (ifmd0_reg_match[i]) {
++ ifmd |= gen3_ifmd_table[i].set_reg;
++ break;
++ }
++ }
++
++ ifmd0_mem = ioremap(0xe6ef0000 + VNCSI_IFMD_REG, 0x04);
++ iowrite32(ifmd, ifmd0_mem);
++ iounmap(ifmd0_mem);
++ } else {
++ void __iomem *ifmd4_mem;
++
++ for (i = 0; i < num; i++) {
++ if (ifmd4_reg_match[i]) {
++ ifmd |= gen3_ifmd_table[i].set_reg;
++ break;
++ }
++ }
++
++ ifmd4_mem = ioremap(0xe6ef4000 + VNCSI_IFMD_REG, 0x04);
++ iowrite32(ifmd, ifmd4_mem);
++ iounmap(ifmd4_mem);
++ }
++
++ return 0;
++}
++
++static SIMPLE_DEV_PM_OPS(rcar_vin_pm_ops,
++ rcar_vin_suspend, rcar_vin_resume);
++#define DEV_PM_OPS (&rcar_vin_pm_ops)
++#else
++#define DEV_PM_OPS NULL
++#endif /* CONFIG_PM_SLEEP */
++
++static struct platform_driver rcar_vin_driver = {
++ .probe = rcar_vin_probe,
++ .remove = rcar_vin_remove,
++ .driver = {
++ .name = DRV_NAME,
++ .pm = DEV_PM_OPS,
++ .of_match_table = of_match_ptr(rcar_vin_of_table),
++ },
++};
++
++module_platform_driver(rcar_vin_driver);
++
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:rcar_vin");
++MODULE_DESCRIPTION("Renesas R-Car VIN camera host driver");
++MODULE_AUTHOR("Koji Matsuoka <koji.matsuoka.xm@renesas.com>");
+diff --git a/include/media/rcar_csi2.h b/include/media/rcar_csi2.h
+new file mode 100644
+index 0000000..1a040fa
+--- /dev/null
++++ b/include/media/rcar_csi2.h
+@@ -0,0 +1,66 @@
++/*
++ * include/media/rcar_csi2.h
++ * This file is the driver header
++ * for the Renesas R-Car MIPI CSI-2 unit.
++ *
++ * Copyright (C) 2015 Renesas Electronics Corporation
++ *
++ * This file is based on the include/media/sh_mobile_csi2.h
++ *
++ * Driver header for the SH-Mobile MIPI CSI-2 unit
++ *
++ * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef RCAR_MIPI_CSI
++#define RCAR_MIPI_CSI
++
++#include <linux/list.h>
++
++enum rcar_csi2_phy {
++ RCAR_CSI2_PHY_CSI40, /* CSI0 */
++ RCAR_CSI2_PHY_CSI20, /* CSI1 */
++ RCAR_CSI2_PHY_CSI41, /* CSI2 */
++ RCAR_CSI2_PHY_CSI21, /* CSI3 */
++};
++
++enum rcar_csi2_link {
++ RCAR_CSI2_LINK_CSI40,
++ RCAR_CSI2_LINK_CSI20,
++ RCAR_CSI2_LINK_CSI41,
++ RCAR_CSI2_LINK_CSI21,
++};
++
++enum rcar_csi2_type {
++ RCAR_CSI2_CSI4X,
++ RCAR_CSI2_CSI2X,
++};
++
++#define RCAR_CSI2_CRC (1 << 0)
++#define RCAR_CSI2_ECC (1 << 1)
++
++struct platform_device;
++
++struct rcar_csi2_client_config {
++ enum rcar_csi2_phy phy;
++ enum rcar_csi2_link link;
++ unsigned char lanes; /* bitmask[3:0] */
++ unsigned char channel; /* 0..3 */
++ struct platform_device *pdev; /* client platform device */
++ const char *name; /* async matching: client name */
++};
++
++struct v4l2_device;
++
++struct rcar_csi2_pdata {
++ enum rcar_csi2_type type;
++ unsigned int flags;
++ struct rcar_csi2_client_config *clients;
++ int num_clients;
++};
++
++#endif
+--
+1.9.1
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0018-arm64-renesas-r8a7797-Add-Renesas-R8A7797-SoC-suppor.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0018-arm64-renesas-r8a7797-Add-Renesas-R8A7797-SoC-suppor.patch
new file mode 100644
index 0000000..02e4e4d
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0018-arm64-renesas-r8a7797-Add-Renesas-R8A7797-SoC-suppor.patch
@@ -0,0 +1,5014 @@
+From e8fd03e53c50c67a2aebf19f39a9f14b583f0e2d Mon Sep 17 00:00:00 2001
+From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+Date: Sun, 14 May 2017 14:48:08 +0300
+Subject: [PATCH] arm64: renesas: r8a7797: Add Renesas R8A7797 SoC support
+
+This adds Renesas R8A7797 SoC support
+
+Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+---
+ arch/arm64/Kconfig.platforms | 6 +
+ arch/arm64/boot/dts/renesas/r8a7797.dtsi | 986 ++++++++++
+ drivers/clk/renesas/Kconfig | 1 +
+ drivers/clk/renesas/Makefile | 1 +
+ drivers/clk/renesas/r8a7797-cpg-mssr.c | 217 ++
+ drivers/clk/renesas/renesas-cpg-mssr.c | 6 +
+ drivers/clk/renesas/renesas-cpg-mssr.h | 1 +
+ drivers/gpio/gpio-rcar.c | 6 +-
+ drivers/gpu/drm/rcar-du/rcar_du_drv.c | 25 +
+ drivers/gpu/drm/rcar-du/rcar_du_group.c | 12 +-
+ drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c | 38 +-
+ drivers/hwspinlock/rcar_hwspinlock.c | 8 +-
+ drivers/i2c/busses/i2c-rcar.c | 1 +
+ drivers/iommu/ipmmu-vmsa.c | 7 +-
+ drivers/media/platform/soc_camera/Kconfig | 2 +-
+ drivers/media/platform/soc_camera/rcar_csi2.c | 25 +-
+ drivers/media/platform/soc_camera/rcar_vin.c | 86 +-
+ drivers/media/platform/vsp1/vsp1_drv.c | 8 +
+ drivers/media/platform/vsp1/vsp1_lif.c | 13 +
+ drivers/media/platform/vsp1/vsp1_regs.h | 7 +
+ drivers/mmc/host/sh_mobile_sdhi.c | 1 +
+ drivers/net/ethernet/renesas/ravb_main.c | 1 +
+ drivers/pinctrl/sh-pfc/Kconfig | 5 +
+ drivers/pinctrl/sh-pfc/Makefile | 1 +
+ drivers/pinctrl/sh-pfc/core.c | 7 +
+ drivers/pinctrl/sh-pfc/pfc-r8a7797.c | 2615 +++++++++++++++++++++++++
+ drivers/pinctrl/sh-pfc/sh_pfc.h | 12 +
+ drivers/soc/renesas/Makefile | 3 +
+ drivers/soc/renesas/r8a7797-sysc.c | 39 +
+ drivers/soc/renesas/rcar-sysc.c | 3 +
+ drivers/soc/renesas/rcar-sysc.h | 1 +
+ drivers/soc/renesas/rcar_ems_ctrl.c | 10 +
+ drivers/soc/renesas/renesas-soc.c | 8 +
+ drivers/spi/spi-sh-msiof.c | 4 +-
+ drivers/thermal/rcar_gen3_thermal.c | 29 +
+ include/dt-bindings/clock/r8a7797-cpg-mssr.h | 48 +
+ include/dt-bindings/power/r8a7797-sysc.h | 32 +
+ 37 files changed, 4247 insertions(+), 28 deletions(-)
+ create mode 100644 arch/arm64/boot/dts/renesas/r8a7797.dtsi
+ create mode 100644 drivers/clk/renesas/r8a7797-cpg-mssr.c
+ create mode 100644 drivers/pinctrl/sh-pfc/pfc-r8a7797.c
+ create mode 100644 drivers/soc/renesas/r8a7797-sysc.c
+ create mode 100644 include/dt-bindings/clock/r8a7797-cpg-mssr.h
+ create mode 100644 include/dt-bindings/power/r8a7797-sysc.h
+
+diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
+index 7c104ca..9380fc6 100644
+--- a/arch/arm64/Kconfig.platforms
++++ b/arch/arm64/Kconfig.platforms
+@@ -160,6 +160,12 @@ config ARCH_R8A7796
+ help
+ This enables support for the Renesas R-Car M3-W SoC.
+
++config ARCH_R8A7797
++ bool "Renesas R-Car V3M SoC Platform"
++ depends on ARCH_RENESAS
++ help
++ This enables support for the Renesas R-Car V3M SoC.
++
+ config ARCH_STRATIX10
+ bool "Altera's Stratix 10 SoCFPGA Family"
+ help
+diff --git a/arch/arm64/boot/dts/renesas/r8a7797.dtsi b/arch/arm64/boot/dts/renesas/r8a7797.dtsi
+new file mode 100644
+index 0000000..c09df87
+--- /dev/null
++++ b/arch/arm64/boot/dts/renesas/r8a7797.dtsi
+@@ -0,0 +1,986 @@
++/*
++ * Device Tree Source for the r8a7797 SoC
++ *
++ * Copyright (C) 2016 - 2017 Renesas Electronics Corp.
++ *
++ * This file is licensed under the terms of the GNU General Public License
++ * version 2. This program is licensed "as is" without any warranty of any
++ * kind, whether express or implied.
++ */
++
++#include <dt-bindings/clock/r8a7797-cpg-mssr.h>
++#include <dt-bindings/interrupt-controller/arm-gic.h>
++#include <dt-bindings/power/r8a7797-sysc.h>
++
++/ {
++ compatible = "renesas,r8a7797";
++ #address-cells = <2>;
++ #size-cells = <2>;
++
++ aliases {
++ csi2_40 = &csi2_40;
++ i2c0 = &i2c0;
++ i2c1 = &i2c1;
++ i2c2 = &i2c2;
++ i2c3 = &i2c3;
++ i2c4 = &i2c4;
++ spi1 = &msiof0;
++ spi2 = &msiof1;
++ spi3 = &msiof2;
++ spi4 = &msiof3;
++ vin0 = &vin0;
++ vin1 = &vin1;
++ vin2 = &vin2;
++ vin3 = &vin3;
++ tsc0 = &tsc1;
++ };
++
++ psci {
++ compatible = "arm,psci-1.0";
++ method = "smc";
++ };
++
++ cpus {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ a53_0: cpu@0 {
++ compatible = "arm,cortex-a53", "arm,armv8";
++ reg = <0x0>;
++ device_type = "cpu";
++ power-domains = <&sysc R8A7797_PD_CA53_CPU0>;
++ next-level-cache = <&L2_CA53>;
++ enable-method = "psci";
++ cpu-idle-states = <&CPU_SLEEP_0>;
++ #cooling-cells = <2>;
++ dynamic-power-coefficient = <277>;
++ cooling-min-level = <0>;
++ cooling-max-level = <2>;
++ clocks =<&cpg CPG_CORE R8A7797_CLK_Z2>;
++ operating-points-v2 = <&cluster0_opp_tb0>;
++ /*cpu-supply = <&vdd_dvfs>;*/
++ };
++
++ a53_1: cpu@1 {
++ compatible = "arm,cortex-a53","arm,armv8";
++ reg = <0x1>;
++ device_type = "cpu";
++ power-domains = <&sysc R8A7797_PD_CA53_CPU1>;
++ next-level-cache = <&L2_CA53>;
++ enable-method = "psci";
++ cpu-idle-states = <&CPU_SLEEP_0>;
++ operating-points-v2 = <&cluster0_opp_tb0>;
++ };
++
++ idle-states {
++ entry-method = "psci";
++
++ CPU_SLEEP_0: cpu-sleep-0 {
++ compatible = "arm,idle-state";
++ arm,psci-suspend-param = <0x0010000>;
++ local-timer-stop;
++ entry-latency-us = <639>;
++ exit-latency-us = <680>;
++ min-residency-us = <1088>;
++ status = "disabled";
++ };
++ };
++ };
++
++ L2_CA53: cache-controller@1 {
++ compatible = "cache";
++ power-domains = <&sysc R8A7797_PD_CA53_SCU>;
++ cache-unified;
++ cache-level = <2>;
++ };
++
++ cluster0_opp_tb0: opp_table0 {
++ compatible = "operating-points-v2";
++ opp-shared;
++
++ opp@800000000 {
++ opp-hz = /bits/ 64 <800000000>;
++ opp-microvolt = <850000>;
++ clock-latency-ns = <300000>;
++ };
++ };
++
++ extal_clk: extal {
++ compatible = "fixed-clock";
++ #clock-cells = <0>;
++ /* This value must be overridden by the board */
++ clock-frequency = <0>;
++ };
++
++ extalr_clk: extalr {
++ compatible = "fixed-clock";
++ #clock-cells = <0>;
++ /* This value must be overridden by the board */
++ clock-frequency = <0>;
++ };
++
++ /* External CAN clock - to be overridden by boards that provide it */
++ can_clk: can {
++ compatible = "fixed-clock";
++ #clock-cells = <0>;
++ clock-frequency = <0>;
++ };
++
++ /* External SCIF clock - to be overridden by boards that provide it */
++ scif_clk: scif {
++ compatible = "fixed-clock";
++ #clock-cells = <0>;
++ clock-frequency = <0>;
++ };
++
++ /* DU input dot clock - tob be overriden by boards that probide it */
++ du_dotclkin0: dclkin-0 {
++ compatible = "fixed-clock";
++ #clock-cells = <0>;
++ clock-frequency = <148500000>;
++ };
++
++ soc {
++ compatible = "simple-bus";
++ interrupt-parent = <&gic>;
++
++ #address-cells = <2>;
++ #size-cells = <2>;
++ ranges;
++
++ gic: interrupt-controller@0xf1010000 {
++ compatible = "arm,gic-400";
++ #interrupt-cells = <3>;
++ #address-cells = <0>;
++ interrupt-controller;
++ reg = <0x0 0xf1010000 0 0x1000>,
++ <0x0 0xf1020000 0 0x20000>,
++ <0x0 0xf1040000 0 0x20000>,
++ <0x0 0xf1060000 0 0x20000>;
++ interrupts = <GIC_PPI 9
++ (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>; /* PPI9:Virtual maintenance interrupt */
++/* clocks = <&cpg CPG_MOD 408>;
++ clock-names = "clk";
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; */
++ };
++
++ gpio0: gpio@e6050000 {
++ compatible = "renesas,gpio-r8a7797",
++ "renesas,gpio-rcar";
++ reg = <0 0xe6050000 0 0x50>;
++ interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>; /* SPI4:GPIO.ch0 */
++ #gpio-cells = <2>;
++ gpio-controller;
++ gpio-ranges = <&pfc 0 0 22>;
++ #interrupt-cells = <2>;
++ interrupt-controller;
++ clocks = <&cpg CPG_MOD 912>; /* RMSTPCR9/bit12:GPIO0 */
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ };
++
++ gpio1: gpio@e6051000 {
++ compatible = "renesas,gpio-r8a7797",
++ "renesas,gpio-rcar";
++ reg = <0 0xe6051000 0 0x50>;
++ interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>; /* SPI5:GPIO.ch1 */
++ #gpio-cells = <2>;
++ gpio-controller;
++ gpio-ranges = <&pfc 0 32 27>;
++ #interrupt-cells = <2>;
++ interrupt-controller;
++ clocks = <&cpg CPG_MOD 911>; /* RMSTPCR9/bit11:GPIO1 */
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ };
++
++ gpio2: gpio@e6052000 {
++ compatible = "renesas,gpio-r8a7797",
++ "renesas,gpio-rcar";
++ reg = <0 0xe6052000 0 0x50>;
++ interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>; /* SPI6:GPIO.ch2 */
++ #gpio-cells = <2>;
++ gpio-controller;
++ gpio-ranges = <&pfc 0 64 17>;
++ #interrupt-cells = <2>;
++ interrupt-controller;
++ clocks = <&cpg CPG_MOD 910>; /* RMSTPCR9/bit10:GPIO2 */
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ };
++
++ gpio3: gpio@e6053000 {
++ compatible = "renesas,gpio-r8a7797",
++ "renesas,gpio-rcar";
++ reg = <0 0xe6053000 0 0x50>;
++ interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; /* SPI7:GPIO.ch3 */
++ #gpio-cells = <2>;
++ gpio-controller;
++ gpio-ranges = <&pfc 0 96 17>;
++ #interrupt-cells = <2>;
++ interrupt-controller;
++ clocks = <&cpg CPG_MOD 909>; /* RMSTPCR9/bit9:GPIO3 */
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ };
++
++ gpio4: gpio@e6054000 {
++ compatible = "renesas,gpio-r8a7797",
++ "renesas,gpio-rcar";
++ reg = <0 0xe6054000 0 0x50>;
++ interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>; /* SPI8:GPIO.ch4 */
++ #gpio-cells = <2>;
++ gpio-controller;
++ gpio-ranges = <&pfc 0 128 6>;
++ #interrupt-cells = <2>;
++ interrupt-controller;
++ clocks = <&cpg CPG_MOD 908>; /* RMSTPCR9/bit8:GPIO4 */
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ };
++
++ gpio5: gpio@e6055000 {
++ compatible = "renesas,gpio-r8a7797",
++ "renesas,gpio-rcar";
++ reg = <0 0xe6055000 0 0x50>;
++ interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>; /* SPI9:GPIO.ch5 */
++ #gpio-cells = <2>;
++ gpio-controller;
++ gpio-ranges = <&pfc 0 160 15>;
++ #interrupt-cells = <2>;
++ interrupt-controller;
++ clocks = <&cpg CPG_MOD 907>; /* RMSTPCR9/bit7:GPIO5 */
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ };
++
++ pmu_a53 {
++ compatible = "arm,cortex-a53-pmu";
++ interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>; /* SPI84:AP-System Core.CA53core0 pmu, SPI85:AP-System Core.CA53core1 pmu */
++ interrupt-affinity = <&a53_0>,
++ <&a53_1>;
++ };
++
++ timer {
++ compatible = "arm,armv8-timer";
++ interrupts = <GIC_PPI 13
++ (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
++ <GIC_PPI 14
++ (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
++ <GIC_PPI 11
++ (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
++ <GIC_PPI 10
++ (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>; /* PPI13:Secure physical timer, PPI14:Non-secure physical timer,
++ PPI11:Virtual timer, PPI10:Hypervisor timer */
++ };
++
++ wdt0: wdt@e6020000 {
++ compatible = "renesas,r8a7797-wdt", "renesas,rcar-gen3-wdt";
++ reg = <0 0xe6020000 0 0x0c>;
++ clocks = <&cpg CPG_MOD 402>; /* RMSTPCR4/bit2:RWDT */
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ status = "disabled";
++ };
++
++ cpg: clock-controller@e6150000 {
++ compatible = "renesas,r8a7797-cpg-mssr";
++ reg = <0 0xe6150000 0 0x1000>;
++ clocks = <&extal_clk>, <&extalr_clk>;
++ clock-names = "extal", "extalr";
++ #clock-cells = <2>;
++ #power-domain-cells = <0>;
++ };
++
++ csi2_40: csi2@feaa0000 {
++ compatible = "renesas,csi2-r8a7797";
++ reg = <0 0xfeaa0000 0 0x10000>;
++ interrupts = <GIC_SPI 246 IRQ_TYPE_LEVEL_HIGH>; /* SPI246:CSI2.ch2 */
++ clocks = <&cpg CPG_MOD 716>; /* RMSTPCR7/bit16:CSI40 */
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ status = "disabled";
++ };
++
++ sysc: system-controller@e6180000 {
++ compatible = "renesas,r8a7797-sysc";
++ reg = <0 0xe6180000 0 0x0440>;
++ #power-domain-cells = <1>;
++ };
++
++ pfc: pfc@e6060000 {
++ compatible = "renesas,pfc-r8a7797";
++ reg = <0 0xe6060000 0 0x50c>;
++ };
++
++ intc_ex: interrupt-controller@e61c0000 {
++ compatible = "renesas,intc-ex-r8a7797", "renesas,irqc";
++ #interrupt-cells = <2>;
++ interrupt-controller;
++ reg = <0 0xe61c0000 0 0x200>;
++ interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH
++ GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH
++ GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH
++ GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH
++ GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH
++ GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>; /* SPI1:IRQ1, SPI2:IRQ2, SPI3:IRQ3, SPI18:IRQ4, SPI161:IRQ5 */
++ clocks = <&cpg CPG_MOD 407>; /* RMSTPCR4/bit7:INTC-EX */
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ };
++
++ ipmmu_vi: mmu@febd0000 {
++ compatible = "renesas,ipmmu-r8a7797";
++ reg = <0 0xfebd0000 0 0x1000>; /* IPMMU-VI */
++ renesas,ipmmu-main = <&ipmmu_mm 11>;
++ #iommu-cells = <1>;
++ status = "disabled";
++ };
++
++ ipmmu_ir: mmu@ff8b0000 {
++ compatible = "renesas,ipmmu-r8a7797";
++ reg = <0 0xff8b0000 0 0x1000>; /* IPMMU-IR */
++ renesas,ipmmu-main = <&ipmmu_mm 3>;
++ #iommu-cells = <1>;
++ status = "disabled";
++ };
++
++ ipmmu_rt: mmu@ffc80000 {
++ compatible = "renesas,ipmmu-r8a7797";
++ reg = <0 0xffc80000 0 0x1000>; /* IPMMU-RT */
++ renesas,ipmmu-main = <&ipmmu_mm 7>;
++ #iommu-cells = <1>;
++ status = "disabled";
++ };
++
++ ipmmu_ds0: mmu@e6740000 {
++ compatible = "renesas,ipmmu-r8a7797";
++ reg = <0 0xe6740000 0 0x1000>; /* IPMMU-DS0 */
++ renesas,ipmmu-main = <&ipmmu_mm 0>;
++ #iommu-cells = <1>;
++ status = "disabled";
++ };
++
++ ipmmu_mm: mmu@e67b0000 {
++ compatible = "renesas,ipmmu-r8a7797";
++ reg = <0 0xe67b0000 0 0x1000>; /* IPMMU-MM */
++ interrupts = <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>; /* SPI196:IPMMU, SPI197:IPMMU sec */
++ #iommu-cells = <1>;
++ status = "disabled";
++ };
++
++ dmac1: dma-controller@e7300000 {
++ compatible = "renesas,dmac-r8a7797",
++ "renesas,rcar-dmac";
++ reg = <0 0xe7300000 0 0x10000>;
++ interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH
++ GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH
++ GIC_SPI 217 IRQ_TYPE_LEVEL_HIGH
++ GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH
++ GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH
++ GIC_SPI 308 IRQ_TYPE_LEVEL_HIGH
++ GIC_SPI 309 IRQ_TYPE_LEVEL_HIGH
++ GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH
++ GIC_SPI 311 IRQ_TYPE_LEVEL_HIGH>; /* SPI220::SYS-DMAC1 err,
++ SPI216~219:SYS-DMAC1.ch0~SYS-DMAC1.ch3,
++ SPI308~311:SYS-DMAC1.ch4~SYS-DMAC1.ch7 */
++ interrupt-names = "error",
++ "ch0", "ch1", "ch2", "ch3",
++ "ch4", "ch5", "ch6", "ch7";
++ clocks = <&cpg CPG_MOD 218>; /* RMSTPCR2/bit18:SYS-DMAC1 */
++ clock-names = "fck";
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ #dma-cells = <1>;
++ dma-channels = <8>;
++ iommus = <&ipmmu_ds0 0>, <&ipmmu_ds0 1>,
++ <&ipmmu_ds0 2>, <&ipmmu_ds0 3>,
++ <&ipmmu_ds0 4>, <&ipmmu_ds0 5>,
++ <&ipmmu_ds0 6>, <&ipmmu_ds0 7>; /* @@ */
++ };
++
++ dmac2: dma-controller@e7310000 {
++ compatible = "renesas,dmac-r8a7797",
++ "renesas,rcar-dmac";
++ reg = <0 0xe7310000 0 0x10000>;
++ interrupts = <GIC_SPI 307 IRQ_TYPE_LEVEL_HIGH
++ GIC_SPI 312 IRQ_TYPE_LEVEL_HIGH
++ GIC_SPI 313 IRQ_TYPE_LEVEL_HIGH
++ GIC_SPI 314 IRQ_TYPE_LEVEL_HIGH
++ GIC_SPI 315 IRQ_TYPE_LEVEL_HIGH
++ GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH
++ GIC_SPI 317 IRQ_TYPE_LEVEL_HIGH
++ GIC_SPI 318 IRQ_TYPE_LEVEL_HIGH
++ GIC_SPI 319 IRQ_TYPE_LEVEL_HIGH>; /* SPI307::SYS-DMAC2 err,
++ SPI312~319:SYS-DMAC2.ch0~SYS-DMAC1.ch7 */
++ interrupt-names = "error",
++ "ch0", "ch1", "ch2", "ch3",
++ "ch4", "ch5", "ch6", "ch7";
++ clocks = <&cpg CPG_MOD 217>; /* RMSTPCR2/bit17:SYS-DMAC2 */
++ clock-names = "fck";
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ #dma-cells = <1>;
++ dma-channels = <8>;
++ iommus = <&ipmmu_ds0 16>, <&ipmmu_ds0 17>,
++ <&ipmmu_ds0 18>, <&ipmmu_ds0 19>,
++ <&ipmmu_ds0 20>, <&ipmmu_ds0 21>,
++ <&ipmmu_ds0 22>, <&ipmmu_ds0 23>; /* @@ */
++ };
++
++ avb: ethernet@e6800000 {
++ compatible = "renesas,etheravb-r8a7797",
++ "renesas,etheravb-rcar-gen3";
++ reg = <0 0xe6800000 0 0x800>, <0 0xe6a00000 0 0x10000>;
++ interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>; /* SPI39~63:Ethernet AVB.ch0~24 */
++ /* @@ errreq_avb_p[0]~[3] add (T.B.D) */
++ interrupt-names = "ch0", "ch1", "ch2", "ch3",
++ "ch4", "ch5", "ch6", "ch7",
++ "ch8", "ch9", "ch10", "ch11",
++ "ch12", "ch13", "ch14", "ch15",
++ "ch16", "ch17", "ch18", "ch19",
++ "ch20", "ch21", "ch22", "ch23",
++ "ch24";
++ clocks = <&cpg CPG_MOD 812>; /* RMSTPCR8/bit12:EAVB-IF */
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ phy-mode = "rgmii-id";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ };
++
++ /* Future
++ canfd: canfd@e66c0000 {
++ compatible = "renesas,r8a7797-canfd",
++ "renesas,rcar-gen3-canfd";
++ reg = <0 0xe66c0000 0 0x8000>;
++ interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>; ** SPI29:CAN-FD channel, SPI30:CAN-FD global **
++ clocks = <&cpg CPG_MOD 914>,
++ <&cpg CPG_CORE R8A7797_CLK_CANFD>,
++ <&can_clk>; ** RMSTPCR9/bit14:CAN-FD **
++ clock-names = "fck", "canfd", "can_clk";
++ assigned-clocks = <&cpg CPG_CORE R8A7797_CLK_CANFD>;
++ assigned-clock-rates = <40000000>;
++ power-domains = <&cpg>;
++ status = "disabled";
++
++ channel0 {
++ status = "disabled";
++ };
++
++ channel1 {
++ status = "disabled";
++ };
++ }; */
++
++ pwm0: pwm@e6e30000 {
++ compatible = "renesas,pwm-r8a7797", "renesas,pwm-rcar";
++ reg = <0 0xe6e30000 0 0x10>;
++ #pwm-cells = <2>;
++ clocks = <&cpg CPG_MOD 523>; /* RMSTPCR5/bit23:PWM */
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ status = "disabled";
++ };
++
++ pwm1: pwm@e6e31000 {
++ compatible = "renesas,pwm-r8a7797", "renesas,pwm-rcar";
++ reg = <0 0xe6e31000 0 0x10>;
++ #pwm-cells = <2>;
++ clocks = <&cpg CPG_MOD 523>; /* RMSTPCR5/bit23:PWM */
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ status = "disabled";
++ };
++
++ pwm2: pwm@e6e32000 {
++ compatible = "renesas,pwm-r8a7797", "renesas,pwm-rcar";
++ reg = <0 0xe6e32000 0 0x10>;
++ #pwm-cells = <2>;
++ clocks = <&cpg CPG_MOD 523>; /* RMSTPCR5/bit23:PWM */
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ status = "disabled";
++ };
++
++ pwm3: pwm@e6e33000 {
++ compatible = "renesas,pwm-r8a7797", "renesas,pwm-rcar";
++ reg = <0 0xe6e33000 0 0x10>;
++ #pwm-cells = <2>;
++ clocks = <&cpg CPG_MOD 523>; /* RMSTPCR5/bit23:PWM */
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ status = "disabled";
++ };
++
++ pwm4: pwm@e6e34000 {
++ compatible = "renesas,pwm-r8a7797", "renesas,pwm-rcar";
++ reg = <0 0xe6e34000 0 0x10>;
++ #pwm-cells = <2>;
++ clocks = <&cpg CPG_MOD 523>; /* RMSTPCR5/bit23:PWM */
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ status = "disabled";
++ };
++
++ hscif0: serial@e6540000 {
++ compatible = "renesas,hscif-r8a7797",
++ "renesas,rcar-gen3-hscif",
++ "renesas,hscif";
++ reg = <0 0xe6540000 0 96>;
++ interrupts = <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>; /* SPI154:HSCIF.ch0 */
++ clocks = <&cpg CPG_MOD 520>,
++ <&cpg CPG_CORE R8A7797_CLK_S2D1>,
++ <&scif_clk>; /* RMSTPCR5/bit20:HSCIF0 */
++ clock-names = "fck", "brg_int", "scif_clk";
++ dmas = <&dmac1 0x31>, <&dmac1 0x30>;
++ dma-names = "tx", "rx";
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ status = "disabled";
++ };
++
++ hscif1: serial@e6550000 {
++ compatible = "renesas,hscif-r8a7797",
++ "renesas,rcar-gen3-hscif",
++ "renesas,hscif";
++ reg = <0 0xe6550000 0 96>;
++ interrupts = <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>; /* SPI155:HSCIF.ch1 */
++ clocks = <&cpg CPG_MOD 519>,
++ <&cpg CPG_CORE R8A7797_CLK_S2D1>,
++ <&scif_clk>; /* RMSTPCR5/bit19:HSCIF1 */
++ clock-names = "fck", "brg_int", "scif_clk";
++ dmas = <&dmac1 0x33>, <&dmac1 0x32>;
++ dma-names = "tx", "rx";
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ status = "disabled";
++ };
++
++ hscif2: serial@e6560000 {
++ compatible = "renesas,hscif-r8a7797",
++ "renesas,rcar-gen3-hscif",
++ "renesas,hscif";
++ reg = <0 0xe6560000 0 96>;
++ interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>; /* SPI144:HSCIF.ch2 */
++ clocks = <&cpg CPG_MOD 518>,
++ <&cpg CPG_CORE R8A7797_CLK_S2D1>,
++ <&scif_clk>; /* RMSTPCR5/bit18:HSCIF2 */
++ clock-names = "fck", "brg_int", "scif_clk";
++ dmas = <&dmac1 0x35>, <&dmac1 0x34>;
++ dma-names = "tx", "rx";
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ status = "disabled";
++ };
++
++ hscif3: serial@e66a0000 {
++ compatible = "renesas,hscif-r8a7797",
++ "renesas,rcar-gen3-hscif",
++ "renesas,hscif";
++ reg = <0 0xe66a0000 0 96>;
++ interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>; /* SPI145:HSCIF.ch3 */
++ clocks = <&cpg CPG_MOD 517>,
++ <&cpg CPG_CORE R8A7797_CLK_S2D1>,
++ <&scif_clk>; /* RMSTPCR5/bit17:HSCIF3 */
++ clock-names = "fck", "brg_int", "scif_clk";
++ dmas = <&dmac1 0x37>, <&dmac1 0x36>;
++ dma-names = "tx", "rx";
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ status = "disabled";
++ };
++
++ scif0: serial@e6e60000 {
++ compatible = "renesas,scif-r8a7797",
++ "renesas,rcar-gen3-scif", "renesas,scif";
++ reg = <0 0xe6e60000 0 64>;
++ interrupts = <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>; /* SPI152:SCIF.ch0 */
++ clocks = <&cpg CPG_MOD 207>,
++ <&cpg CPG_CORE R8A7797_CLK_S2D1>,
++ <&scif_clk>; /* RMSTPCR2/bit7:SCIF0 */
++ /*clock-names = "fck", "sck", "brg_int", "scif_clk"; */
++ clock-names = "fck";
++ dmas = <&dmac1 0x51>, <&dmac1 0x50>;
++ dma-names = "tx", "rx";
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ status = "disabled";
++ };
++
++ scif1: serial@e6e68000 {
++ compatible = "renesas,scif-r8a7797",
++ "renesas,rcar-gen3-scif", "renesas,scif";
++ reg = <0 0xe6e68000 0 64>;
++ interrupts = <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>; /* SPI153:SCIF.ch1 */
++ clocks = <&cpg CPG_MOD 206>,
++ <&cpg CPG_CORE R8A7797_CLK_S2D1>,
++ <&scif_clk>; /* RMSTPCR2/bit6:SCIF1 */
++ clock-names = "fck", "brg_int", "scif_clk";
++ dmas = <&dmac1 0x53>, <&dmac1 0x52>;
++ dma-names = "tx", "rx";
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ status = "disabled";
++ };
++
++ scif3: serial@e6c50000 {
++ compatible = "renesas,scif-r8a7797",
++ "renesas,rcar-gen3-scif", "renesas,scif";
++ reg = <0 0xe6c50000 0 64>;
++ interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>; /* SPI23:SCIF.ch3 */
++ clocks = <&cpg CPG_MOD 204>,
++ <&cpg CPG_CORE R8A7797_CLK_S2D1>,
++ <&scif_clk>; /* RMSTPCR2/bit4:SCIF3 */
++ clock-names = "fck", "brg_int", "scif_clk";
++ dmas = <&dmac1 0x57>, <&dmac1 0x56>;
++ dma-names = "tx", "rx";
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ status = "disabled";
++ };
++
++ scif4: serial@e6c40000 {
++ compatible = "renesas,scif-r8a7797",
++ "renesas,rcar-gen3-scif", "renesas,scif";
++ reg = <0 0xe6c40000 0 64>;
++ interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>; /* SPI16:SCIF.ch4 */
++ clocks = <&cpg CPG_MOD 203>,
++ <&cpg CPG_CORE R8A7797_CLK_S2D1>,
++ <&scif_clk>; /* RMSTPCR2/bit3:SCIF4 */
++ clock-names = "fck", "brg_int", "scif_clk";
++ dmas = <&dmac1 0x59>, <&dmac1 0x58>;
++ dma-names = "tx", "rx";
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ status = "disabled";
++ };
++
++ i2c0: i2c@e6500000 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ compatible = "renesas,i2c-r8a7797";
++ reg = <0 0xe6500000 0 0x40>;
++ interrupts = <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>; /* SPI287:I2C.ch0 */
++ clocks = <&cpg CPG_MOD 931>; /* RMSTPCR9/bit31:I2C-IF0 */
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ dmas = <&dmac1 0x91>, <&dmac1 0x90>;
++ dma-names = "tx", "rx";
++ i2c-scl-internal-delay-ns = <6>;
++ status = "disabled";
++ };
++
++ i2c1: i2c@e6508000 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ compatible = "renesas,i2c-r8a7797";
++ reg = <0 0xe6508000 0 0x40>;
++ interrupts = <GIC_SPI 288 IRQ_TYPE_LEVEL_HIGH>; /* SPI288:I2C.ch1 */
++ clocks = <&cpg CPG_MOD 930>; /* RMSTPCR9/bit30:I2C-IF1 */
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ dmas = <&dmac1 0x93>, <&dmac1 0x92>;
++ dma-names = "tx", "rx";
++ i2c-scl-internal-delay-ns = <6>;
++ status = "disabled";
++ };
++
++ i2c2: i2c@e6510000 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ compatible = "renesas,i2c-r8a7797";
++ reg = <0 0xe6510000 0 0x40>;
++ interrupts = <GIC_SPI 286 IRQ_TYPE_LEVEL_HIGH>; /* SPI286:I2C.ch2 */
++ clocks = <&cpg CPG_MOD 929>; /* RMSTPCR9/bit29:I2C-IF2 */
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ dmas = <&dmac1 0x95>, <&dmac1 0x94>;
++ dma-names = "tx", "rx";
++ i2c-scl-internal-delay-ns = <6>;
++ status = "disabled";
++ };
++
++ i2c3: i2c@e66d0000 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ compatible = "renesas,i2c-r8a7797";
++ reg = <0 0xe66d0000 0 0x40>;
++ interrupts = <GIC_SPI 290 IRQ_TYPE_LEVEL_HIGH>; /* SPI290:I2C.ch3 */
++ clocks = <&cpg CPG_MOD 928>; /* RMSTPCR9/bit28:I2C-IF3 */
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ dmas = <&dmac1 0x97>, <&dmac1 0x96>;
++ dma-names = "tx", "rx";
++ i2c-scl-internal-delay-ns = <6>;
++ status = "disabled";
++ };
++
++ i2c4: i2c@e66d8000 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ compatible = "renesas,i2c-r8a7797";
++ reg = <0 0xe66d8000 0 0x40>;
++ interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>; /* SPI19:I2C.ch4 */
++ clocks = <&cpg CPG_MOD 927>; /* RMSTPCR9/bit27:I2C-IF4 */
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ dmas = <&dmac1 0x99>, <&dmac1 0x98>;
++ dma-names = "tx", "rx";
++ i2c-scl-internal-delay-ns = <6>;
++ status = "disabled";
++ };
++
++ msiof0: spi@e6e90000 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ compatible = "renesas,msiof-r8a7797";
++ reg = <0 0xe6e90000 0 0x64>;
++ interrupts = <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>; /* SPI156:MSIOF.ch0 */
++ clocks = <&cpg CPG_MOD 211>, <&msiof_ref_clk>; /* RMSTPCR2/bit11:MSIOF0, @@ msiof_ref_clk->Eagle.dts */
++ clock-names = "msiof_clk", "msiof_ref_clk";
++ dmas = <&dmac1 0x41>, <&dmac1 0x40>;
++ dma-names = "tx", "rx";
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ status = "disabled";
++ };
++
++ msiof1: spi@e6ea0000 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ compatible = "renesas,msiof-r8a7797";
++ reg = <0 0xe6ea0000 0 0x0064>;
++ interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>; /* SPI157:MSIOF.ch1 */
++ clocks = <&cpg CPG_MOD 210>, <&msiof_ref_clk>; /* RMSTPCR2/bit10:MSIOF1, @@ msiof_ref_clk->Eagle.dts */
++ clock-names = "msiof_clk", "msiof_ref_clk";
++ dmas = <&dmac1 0x43>, <&dmac1 0x42>;
++ dma-names = "tx", "rx";
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ status = "disabled";
++ };
++
++ msiof2: spi@e6c00000 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ compatible = "renesas,msiof-r8a7797";
++ reg = <0 0xe6c00000 0 0x0064>;
++ interrupts = <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>; /* SPI158:MSIOF.ch2 */
++ clocks = <&cpg CPG_MOD 209>, <&msiof_ref_clk>; /* RMSTPCR2/bit9:MSIOF2, @@ msiof_ref_clk->Eagle.dts */
++ clock-names = "msiof_clk", "msiof_ref_clk";
++ dmas = <&dmac1 0x45>, <&dmac1 0x44>;
++ dma-names = "tx", "rx";
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ status = "disabled";
++ };
++
++ msiof3: spi@e6c10000 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ compatible = "renesas,msiof-r8a7797";
++ reg = <0 0xe6c10000 0 0x0064>;
++ interrupts = <GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>; /* SPI159:MSIOF.ch3 */
++ clocks = <&cpg CPG_MOD 208>, <&msiof_ref_clk>; /* RMSTPCR2/bit8:MSIOF3, @@ msiof_ref_clk->Eagle.dts */
++ clock-names = "msiof_clk", "msiof_ref_clk";
++ dmas = <&dmac1 0x47>, <&dmac1 0x46>;
++ dma-names = "tx", "rx";
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ status = "disabled";
++ };
++
++ vin0: video@e6ef0000 {
++ compatible = "renesas,vin-r8a7797";
++ reg = <0 0xe6ef0000 0 0x1000>;
++ interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>; /* SPI188:VIN.ch0 */
++ clocks = <&cpg CPG_MOD 811>; /* RMSTPCR8/bit11:VIN0 */
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ status = "disabled";
++ };
++
++ vin1: video@e6ef1000 {
++ compatible = "renesas,vin-r8a7797";
++ reg = <0 0xe6ef1000 0 0x1000>;
++ interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>; /* SPI189:VIN.ch1 */
++ clocks = <&cpg CPG_MOD 810>; /* RMSTPCR8/bit10:VIN1 */
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ status = "disabled";
++ };
++
++ vin2: video@e6ef2000 {
++ compatible = "renesas,vin-r8a7797";
++ reg = <0 0xe6ef2000 0 0x1000>;
++ interrupts = <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>; /* SPI190:VIN.ch2 */
++ clocks = <&cpg CPG_MOD 809>; /* RMSTPCR8/bit9:VIN2 */
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ status = "disabled";
++ };
++
++ vin3: video@e6ef3000 {
++ compatible = "renesas,vin-r8a7797";
++ reg = <0 0xe6ef3000 0 0x1000>;
++ interrupts = <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>; /* SPI191:VIN.ch3 */
++ clocks = <&cpg CPG_MOD 808>; /* RMSTPCR8/bit8:VIN3 */
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ status = "disabled";
++ };
++
++/*
++ sdhi2: sd@ee140000 {
++ compatible = "renesas,sdhi-r8a7797";
++ reg = <0 0xee140000 0 0x2000>;
++ interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>; ** SPI165:SDHI.ch0 **
++ clocks = <&cpg CPG_MOD 314>; ** RMSTPCR3/bit14:SDIF **
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ renesas,clk-rate = <200000000>;
++ cap-sd-highspeed;
++ sd-uhs-sdr50;
++ sd-uhs-sdr104;
++ renesas,mmc-scc-tapnum = <8>;
++ status = "disabled";
++ };
++*/
++ mmc0: mmc@ee140000 {
++ compatible = "renesas,mmc-r8a7797";
++ reg = <0 0xee140000 0 0x2000>;
++ interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>; /* SPI165:SDHI.ch0 */
++ clocks = <&cpg CPG_MOD 314>; /* RMSTPCR3/bit14:SDIF */
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ renesas,clk-rate = <200000000>;
++/* cap-sd-highspeed;
++ sd-uhs-sdr104;
++ sd-uhs-sdr50;
++ cap-mmc-highspeed;
++*/
++ mmc-hs200-1_8v;
++ renesas,mmc-scc-tapnum = <8>;
++ status = "disabled";
++ };
++
++ qos@e67e0000 {
++ compatible = "renesas,qos";
++ };
++
++ vspd0: vsp@fea20000 {
++ compatible = "renesas,vsp2";
++ reg = <0 0xfea20000 0 0x4000>;
++
++ interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&cpg CPG_MOD 623>; /* RMSTPCR6/bit23:VSP(VSPD0) */
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++
++ renesas,fcp = <&fcpvd0>;
++ };
++
++ fcpvd0: fcp@fea27000 {
++ compatible = "renesas,r8a7797-fcpv", "renesas,fcpv";
++ reg = <0 0xfea27000 0 0x200>;
++ clocks = <&cpg CPG_MOD 603>; /* RMSTPCR6/bit3:FCPVD0 */
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ };
++
++ du: display@feb00000 {
++ compatible = "renesas,du-r8a7797";
++ reg = <0 0xfeb00000 0 0x80000>,
++ <0 0xfeb90000 0 0x14>; /* LDVS */
++ reg-names = "du", "lvds.0";
++ interrupts = <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>; /* SPI256:DU.ch0 */
++ clocks = <&cpg CPG_MOD 724>,
++ <&cpg CPG_MOD 727>,
++ <&dclkin_p0>;
++ clock-names = "du.0", "lvds.0", "dclkin.0";
++ status = "disabled";
++
++ vsps = <&vspd0>;
++
++ interlaced = <1>;
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ reg = <0>;
++ du_out_lvds0: endpoint {
++ };
++ };
++ };
++ };
++
++ tsc1: thermal@0xe6190000 {
++ compatible = "renesas,thermal-r8a7797";
++ reg = <0 0xe6190000 0 0x5c>;
++ interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>; /* SPI67~69:Thermal Sensor.ch0~2 */
++ clocks = <&cpg CPG_MOD 522>; /* RMSTPCR5/bit22:THS/TSC */
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ #thermal-sensor-cells = <0>;
++ status = "okay";
++ };
++
++ thermal-zones {
++ emergency {
++ polling-delay = <1000>;
++ on-temperature = <110000>;
++ off-temperature = <95000>;
++ target_cpus = <&a53_1>;
++ status = "disabled";
++ };
++
++ sensor_thermal1: sensor-thermal1 {
++ polling-delay-passive = <250>;
++ polling-delay = <0>;
++ sustainable-power = <6313>;
++
++ /* sensor ID */
++ thermal-sensors = <&tsc1>;
++
++ trips {
++ threshold: trip-point@0 {
++ /* miliCelsius */
++ temperature = <90000>;
++ hysteresis = <2000>;
++ type = "passive";
++ };
++
++ target: trip-point@1 {
++ /* miliCelsius */
++ temperature = <100000>;
++ hysteresis = <2000>;
++ type = "passive";
++ };
++
++ sensor1_crit: sensor1-crit {
++ temperature = <120000>;
++ hysteresis = <2000>;
++ type = "critical";
++ };
++ };
++
++ cooling-maps {
++ map0 {
++ trip = <&target>;
++ cooling-device = <&a53_0 0 2>;
++ contribution = <1024>;
++ };
++ };
++ };
++ };
++
++ mfis: mfis@e6260000 {
++ compatible = "renesas,mfis-r8a7797", "renesas,mfis";
++ reg = <0 0xe6260000 0 0x0200>;
++ interrupts = <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>; /* SPI180:MFIS eicr0 */
++ interrupt-names = "eicr0";
++ clocks = <&cpg CPG_MOD 213>; /* RMSTPCR2/bit13:MFIS */
++ clock-names = "mfis";
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ status = "okay";
++ };
++
++ mfis_lock: mfis-lock {
++ compatible = "renesas,mfis-lock-r8a7797",
++ "renesas,mfis-lock";
++ reg = <0 0xe62600c0 0 0x0750>; /* @@ transitional 0x20->0x750 */
++ clocks = <&cpg CPG_MOD 213>; /* RMSTPCR2/bit13:MFIS */
++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>;
++ status = "okay";
++ };
++ };
++};
+diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig
+index 2586dfa..f86f2bf 100644
+--- a/drivers/clk/renesas/Kconfig
++++ b/drivers/clk/renesas/Kconfig
+@@ -4,6 +4,7 @@ config CLK_RENESAS_CPG_MSSR
+ default y if ARCH_R8A7745
+ default y if ARCH_R8A7795
+ default y if ARCH_R8A7796
++ default y if ARCH_R8A7797
+
+ config CLK_RENESAS_CPG_MSTP
+ bool
+diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile
+index 1072f76..c6f0abb 100644
+--- a/drivers/clk/renesas/Makefile
++++ b/drivers/clk/renesas/Makefile
+@@ -13,6 +13,7 @@ obj-$(CONFIG_ARCH_R8A7793) += clk-rcar-gen2.o clk-div6.o
+ obj-$(CONFIG_ARCH_R8A7794) += clk-rcar-gen2.o clk-div6.o
+ obj-$(CONFIG_ARCH_R8A7795) += r8a7795-cpg-mssr.o rcar-gen3-cpg.o
+ obj-$(CONFIG_ARCH_R8A7796) += r8a7796-cpg-mssr.o rcar-gen3-cpg.o
++obj-$(CONFIG_ARCH_R8A7797) += r8a7797-cpg-mssr.o rcar-gen3-cpg.o
+ obj-$(CONFIG_ARCH_SH73A0) += clk-sh73a0.o clk-div6.o
+
+ obj-$(CONFIG_CLK_RENESAS_CPG_MSSR) += renesas-cpg-mssr.o clk-div6.o
+diff --git a/drivers/clk/renesas/r8a7797-cpg-mssr.c b/drivers/clk/renesas/r8a7797-cpg-mssr.c
+new file mode 100644
+index 0000000..e758685
+--- /dev/null
++++ b/drivers/clk/renesas/r8a7797-cpg-mssr.c
+@@ -0,0 +1,217 @@
++/*
++ * r8a7797 Clock Pulse Generator / Module Standby and Software Reset
++ *
++ * Copyright (C) 2016 Glider bvba
++ *
++ * Based on r8a7795-cpg-mssr.c
++ *
++ * Copyright (C) 2016 Renesas Electronics Corp.
++ *
++ * 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; version 2 of the License.
++ */
++
++#include <linux/device.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/soc/renesas/rcar-rst.h>
++#include <linux/sys_soc.h>
++
++#include <dt-bindings/clock/r8a7797-cpg-mssr.h>
++
++#include "renesas-cpg-mssr.h"
++#include "rcar-gen3-cpg.h"
++
++enum clk_ids {
++ /* Core Clock Outputs exported to DT */
++ LAST_DT_CORE_CLK = R8A7797_CLK_OSC,
++
++ /* External Input Clocks */
++ CLK_EXTAL,
++ CLK_EXTALR,
++
++ /* Internal Core Clocks */
++ CLK_MAIN,
++ CLK_PLL0,
++ CLK_PLL1,
++ CLK_PLL3,
++ CLK_PLL1_DIV2,
++ CLK_PLL1_DIV4,
++ CLK_S1,
++ CLK_S2,
++ CLK_RINT,
++
++ /* Module Clocks */
++ MOD_CLK_BASE
++};
++
++static const struct cpg_core_clk r8a7797_core_clks[] __initconst = {
++ /* External Clock Inputs */
++ DEF_INPUT("extal", CLK_EXTAL),
++ DEF_INPUT("extalr", CLK_EXTALR),
++
++ /* Internal Core Clocks */
++ DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL),
++ DEF_BASE(".pll0", CLK_PLL0, CLK_TYPE_GEN3_PLL0, CLK_MAIN),
++ DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN3_PLL1, CLK_MAIN),
++ DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN3_PLL3, CLK_MAIN),
++
++ DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
++ DEF_FIXED(".pll1_div4", CLK_PLL1_DIV4, CLK_PLL1_DIV2, 2, 1),
++ DEF_FIXED(".s1", CLK_S1, CLK_PLL1_DIV2, 4, 1),
++ DEF_FIXED(".s2", CLK_S2, CLK_PLL1_DIV2, 6, 1),
++
++ /* Core Clock Outputs */
++ DEF_BASE("z2", R8A7797_CLK_Z2, CLK_TYPE_GEN3_Z2, CLK_PLL0),
++ DEF_FIXED("ztr", R8A7797_CLK_ZTR, CLK_PLL1_DIV2, 6, 1),
++ DEF_FIXED("ztrd2", R8A7797_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1),
++ DEF_FIXED("zt", R8A7797_CLK_ZT, CLK_PLL1_DIV2, 4, 1),
++ DEF_FIXED("zx", R8A7797_CLK_ZX, CLK_PLL1_DIV2, 3, 1),
++ DEF_FIXED("s1d1", R8A7797_CLK_S1D1, CLK_S1, 1, 1),
++ DEF_FIXED("s1d2", R8A7797_CLK_S1D2, CLK_S1, 2, 1),
++ DEF_FIXED("s1d4", R8A7797_CLK_S1D4, CLK_S1, 4, 1),
++ DEF_FIXED("s2d1", R8A7797_CLK_S2D1, CLK_S2, 1, 1),
++ DEF_FIXED("s2d2", R8A7797_CLK_S2D2, CLK_S2, 2, 1),
++ DEF_FIXED("s2d4", R8A7797_CLK_S2D4, CLK_S2, 4, 1),
++
++ DEF_GEN3_SD("sd0", R8A7797_CLK_SD0, CLK_PLL1_DIV4, 0x0074), /* FIXME */
++
++ DEF_FIXED("cl", R8A7797_CLK_CL, CLK_PLL1_DIV2, 48, 1),
++ DEF_FIXED("cp", R8A7797_CLK_CP, CLK_EXTAL, 2, 1),
++
++ DEF_FIXED("mso", R8A7797_CLK_MSO, CLK_PLL1_DIV4, 6, 1),
++ DEF_FIXED("canfd", R8A7797_CLK_CANFD, CLK_PLL1_DIV4, 20, 1),
++ DEF_DIV6P1("csi0", R8A7797_CLK_CSI0, CLK_PLL1_DIV4, 0x00c),
++
++ DEF_FIXED("osc", R8A7797_CLK_OSC, CLK_PLL1_DIV2, (12*1024), 1),
++ DEF_DIV6_RO("r_int", CLK_RINT, CLK_EXTAL, CPG_RCKCR, 32),
++
++ DEF_BASE("r", R8A7797_CLK_R, CLK_TYPE_GEN3_R, CLK_RINT),
++};
++
++static const struct mssr_mod_clk r8a7797_mod_clks[] __initconst = {
++ DEF_MOD("ivcp1e", 127, R8A7797_CLK_S2D1),
++ DEF_MOD("scif4", 203, R8A7797_CLK_S2D4), /* @@ H3=S3D4 */
++ DEF_MOD("scif3", 204, R8A7797_CLK_S2D4), /* @@ H3=S3D4 */
++ DEF_MOD("scif1", 206, R8A7797_CLK_S2D4), /* @@ H3=S3D4 */
++ DEF_MOD("scif0", 207, R8A7797_CLK_S2D4), /* @@ H3=S3D4 */
++ DEF_MOD("msiof3", 208, R8A7797_CLK_MSO),
++ DEF_MOD("msiof2", 209, R8A7797_CLK_MSO),
++ DEF_MOD("msiof1", 210, R8A7797_CLK_MSO),
++ DEF_MOD("msiof0", 211, R8A7797_CLK_MSO),
++ DEF_MOD("mfis", 213, R8A7797_CLK_S2D2), /* @@ H3=S3D2 */
++ DEF_MOD("sys-dmac2", 217, R8A7797_CLK_S2D1), /* @@ H3=S3D1 */
++ DEF_MOD("sys-dmac1", 218, R8A7797_CLK_S2D1), /* @@ H3=S3D1 */
++ DEF_MOD("sdif", 314, R8A7797_CLK_SD0),
++ DEF_MOD("rwdt0", 402, R8A7797_CLK_R),
++ DEF_MOD("intc-ex", 407, R8A7797_CLK_CP),
++ DEF_MOD("intc-ap", 408, R8A7797_CLK_S2D1), /* @@ H3=S3D1 */
++ DEF_MOD("hscif3", 517, R8A7797_CLK_S2D1), /* @@ H3=S3D1 */
++ DEF_MOD("hscif2", 518, R8A7797_CLK_S2D1), /* @@ H3=S3D1 */
++ DEF_MOD("hscif1", 519, R8A7797_CLK_S2D1), /* @@ H3=S3D1 */
++ DEF_MOD("hscif0", 520, R8A7797_CLK_S2D1), /* @@ H3=S3D1 */
++ DEF_MOD("thermal", 522, R8A7797_CLK_CP),
++ DEF_MOD("pwm", 523, R8A7797_CLK_S2D4),
++ DEF_MOD("fcpvd0", 603, R8A7797_CLK_S2D1),
++ DEF_MOD("vspd0", 623, R8A7797_CLK_S2D1),
++ DEF_MOD("csi40", 716, R8A7797_CLK_CSI0),
++ DEF_MOD("du0", 724, R8A7797_CLK_S2D1),
++ DEF_MOD("lvds", 727, R8A7797_CLK_S2D1),
++ DEF_MOD("vin3", 808, R8A7797_CLK_S2D1),
++ DEF_MOD("vin2", 809, R8A7797_CLK_S2D1),
++ DEF_MOD("vin1", 810, R8A7797_CLK_S2D1),
++ DEF_MOD("vin0", 811, R8A7797_CLK_S2D1),
++ DEF_MOD("etheravb", 812, R8A7797_CLK_S2D2),
++ DEF_MOD("isp", 817, R8A7797_CLK_S2D1), /* @@ Unknown Module Clock */
++ DEF_MOD("gpio5", 907, R8A7797_CLK_CP),
++ DEF_MOD("gpio4", 908, R8A7797_CLK_CP),
++ DEF_MOD("gpio3", 909, R8A7797_CLK_CP),
++ DEF_MOD("gpio2", 910, R8A7797_CLK_CP),
++ DEF_MOD("gpio1", 911, R8A7797_CLK_CP),
++ DEF_MOD("gpio0", 912, R8A7797_CLK_CP),
++ DEF_MOD("can-fd", 914, R8A7797_CLK_S2D2), /* @@ H3=S3D2 */
++ DEF_MOD("i2c4", 927, R8A7797_CLK_S2D2),
++ DEF_MOD("i2c3", 928, R8A7797_CLK_S2D2),
++ DEF_MOD("i2c2", 929, R8A7797_CLK_S2D2),
++ DEF_MOD("i2c1", 930, R8A7797_CLK_S2D2),
++ DEF_MOD("i2c0", 931, R8A7797_CLK_S2D2),
++};
++
++static const unsigned int r8a7797_crit_mod_clks[] __initconst = {
++ MOD_CLK_ID(408), /* INTC-AP (GIC) */
++};
++
++
++/*
++ * CPG Clock Data
++ */
++
++/*
++ * MD EXTAL PLL0 PLL1 PLL3
++ * 14 13 19 (MHz)
++ *-------------------------------------------------
++ * 0 0 0 16.66 x 1 x192 x192 x96
++ * 0 0 1 16.66 x 1 x192 x192 x80
++ * 0 1 0 20 x 1 x160 x160 x80
++ * 0 1 1 20 x 1 x160 x160 x66
++ * 1 0 0 27 / 2 x236 x236 x118
++ * 1 0 1 27 / 2 x236 x236 x98
++ * 1 1 0 33.33 / 2 x192 x192 x96
++ * 1 1 1 33.33 / 2 x192 x192 x80
++ */
++#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 12) | \
++ (((md) & BIT(13)) >> 12) | \
++ (((md) & BIT(19)) >> 19))
++
++static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[8] __initconst = {
++ /* EXTAL div PLL1 mult PLL3 mult */
++ { 1, 192, 96, },
++ { 1, 192, 80, },
++ { 1, 160, 80, },
++ { 1, 160, 66, },
++ { 2, 236, 118, },
++ { 2, 236, 98, },
++ { 2, 192, 96, },
++ { 2, 192, 80, },
++};
++
++static int __init r8a7797_cpg_mssr_init(struct device *dev)
++{
++ const struct rcar_gen3_cpg_pll_config *cpg_pll_config;
++ u32 cpg_mode;
++ int error;
++
++ error = rcar_rst_read_mode_pins(&cpg_mode);
++ if (error)
++ return error;
++
++ cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
++ if (!cpg_pll_config->extal_div) {
++ dev_err(dev, "Prohibited setting (cpg_mode=0x%x)\n", cpg_mode);
++ return -EINVAL;
++ }
++
++ return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode);
++}
++
++const struct cpg_mssr_info r8a7797_cpg_mssr_info __initconst = {
++ /* Core Clocks */
++ .core_clks = r8a7797_core_clks,
++ .num_core_clks = ARRAY_SIZE(r8a7797_core_clks),
++ .last_dt_core_clk = LAST_DT_CORE_CLK,
++ .num_total_core_clks = MOD_CLK_BASE,
++
++ /* Module Clocks */
++ .mod_clks = r8a7797_mod_clks,
++ .num_mod_clks = ARRAY_SIZE(r8a7797_mod_clks),
++ .num_hw_mod_clks = 12 * 32,
++
++ /* Critical Module Clocks */
++ .crit_mod_clks = r8a7797_crit_mod_clks,
++ .num_crit_mod_clks = ARRAY_SIZE(r8a7797_crit_mod_clks),
++
++ /* Callbacks */
++ .init = r8a7797_cpg_mssr_init,
++ .cpg_clk_register = rcar_gen3_cpg_clk_register,
++};
+diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c
+index 494e4e8..e523ab7 100644
+--- a/drivers/clk/renesas/renesas-cpg-mssr.c
++++ b/drivers/clk/renesas/renesas-cpg-mssr.c
+@@ -588,6 +588,12 @@ static int __init cpg_mssr_add_clk_domain(struct device *dev,
+ .data = &r8a7796_cpg_mssr_info,
+ },
+ #endif
++#ifdef CONFIG_ARCH_R8A7797
++ {
++ .compatible = "renesas,r8a7797-cpg-mssr",
++ .data = &r8a7797_cpg_mssr_info,
++ },
++#endif
+ { /* sentinel */ }
+ };
+
+diff --git a/drivers/clk/renesas/renesas-cpg-mssr.h b/drivers/clk/renesas/renesas-cpg-mssr.h
+index 148f4f0a..77c27d8 100644
+--- a/drivers/clk/renesas/renesas-cpg-mssr.h
++++ b/drivers/clk/renesas/renesas-cpg-mssr.h
+@@ -134,6 +134,7 @@ struct cpg_mssr_info {
+ extern const struct cpg_mssr_info r8a7745_cpg_mssr_info;
+ extern const struct cpg_mssr_info r8a7795_cpg_mssr_info;
+ extern const struct cpg_mssr_info r8a7796_cpg_mssr_info;
++extern const struct cpg_mssr_info r8a7797_cpg_mssr_info;
+
+
+ /*
+diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c
+index f721a89..118e579 100644
+--- a/drivers/gpio/gpio-rcar.c
++++ b/drivers/gpio/gpio-rcar.c
+@@ -1,7 +1,7 @@
+ /*
+ * Renesas R-Car GPIO Support
+ *
+- * Copyright (C) 2014 Renesas Electronics Corporation
++ * Copyright (C) 2014-2016 Renesas Electronics Corporation
+ * Copyright (C) 2013 Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+@@ -579,6 +579,10 @@ struct gpio_rcar_info {
+ /* Gen3 GPIO is identical to Gen2. */
+ .data = &gpio_rcar_info_gen2,
+ }, {
++ .compatible = "renesas,gpio-r8a7797",
++ /* Gen3 GPIO is identical to Gen2. */
++ .data = &gpio_rcar_info_gen2,
++ }, {
+ .compatible = "renesas,gpio-rcar",
+ .data = &gpio_rcar_info_gen1,
+ }, {
+diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+index 6295c73..0f9fe44 100644
+--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
++++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+@@ -289,6 +289,30 @@
+ {/*sentinel*/}
+ };
+
++static const struct rcar_du_device_info rcar_du_r8a7797_info = {
++ .gen = 3,
++ .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
++ | RCAR_DU_FEATURE_EXT_CTRL_REGS
++ | RCAR_DU_FEATURE_VSP1_SOURCE
++ | RCAR_DU_FEATURE_GEN3_REGS,
++ .num_crtcs = 1,
++ .routes = {
++ /* R8A7797 has one RGB output, one LVDS output. */
++ [RCAR_DU_OUTPUT_DPAD0] = {
++ .possible_crtcs = BIT(0),
++ .encoder_type = DRM_MODE_ENCODER_NONE,
++ .port = 1,
++ },
++ [RCAR_DU_OUTPUT_LVDS0] = {
++ .possible_crtcs = BIT(0),
++ .encoder_type = DRM_MODE_ENCODER_LVDS,
++ .port = 0,
++ },
++ },
++ .num_lvds = 1,
++ .dpll_ch = 0,
++};
++
+ static const struct of_device_id rcar_du_of_table[] = {
+ { .compatible = "renesas,du-r8a7779", .data = &rcar_du_r8a7779_info },
+ { .compatible = "renesas,du-r8a7790", .data = &rcar_du_r8a7790_info },
+@@ -298,6 +322,7 @@
+ { .compatible = "renesas,du-r8a7794", .data = &rcar_du_r8a7794_info },
+ { .compatible = "renesas,du-r8a7795", .data = &rcar_du_r8a7795_info },
+ { .compatible = "renesas,du-r8a7796", .data = &rcar_du_r8a7796_info },
++ { .compatible = "renesas,du-r8a7797", .data = &rcar_du_r8a7797_info },
+ { }
+ };
+
+diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
+index c15611c..95023bd 100644
+--- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
++++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
+@@ -29,11 +29,17 @@
+
+ #include <linux/clk.h>
+ #include <linux/io.h>
++#include <linux/sys_soc.h>
+
+ #include "rcar_du_drv.h"
+ #include "rcar_du_group.h"
+ #include "rcar_du_regs.h"
+
++static const struct soc_device_attribute r8a7797[] = {
++ { .soc_id = "r8a7797" },
++ { }
++};
++
+ u32 rcar_du_group_read(struct rcar_du_group *rgrp, u32 reg)
+ {
+ return rcar_du_read(rgrp->dev, rgrp->mmio_offset + reg);
+@@ -147,8 +153,10 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp)
+
+ /* Apply planes to CRTCs association. */
+ mutex_lock(&rgrp->lock);
+- rcar_du_group_write(rgrp, DPTSR, (rgrp->dptsr_planes << 16) |
+- rgrp->dptsr_planes);
++ if (!soc_device_match(r8a7797))
++ rcar_du_group_write(rgrp, DPTSR, (rgrp->dptsr_planes << 16) |
++ rgrp->dptsr_planes);
++
+ mutex_unlock(&rgrp->lock);
+ }
+
+diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
+index ecae864..42eb45c 100644
+--- a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
++++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
+@@ -17,12 +17,18 @@
+ #include <linux/of_gpio.h>
+ #include <linux/platform_device.h>
+ #include <linux/slab.h>
++#include <linux/sys_soc.h>
+
+ #include "rcar_du_drv.h"
+ #include "rcar_du_encoder.h"
+ #include "rcar_du_lvdsenc.h"
+ #include "rcar_lvds_regs.h"
+
++static const struct soc_device_attribute r8a7797[] = {
++ { .soc_id = "r8a7797" },
++ { }
++};
++
+ struct rcar_du_lvdsenc {
+ struct rcar_du_device *dev;
+
+@@ -96,14 +102,25 @@ static void rcar_du_lvdsenc_start_gen3(struct rcar_du_lvdsenc *lvds,
+ u32 pllcr;
+
+ /* PLL clock configuration */
+- if (freq < 42000)
+- pllcr = LVDPLLCR_PLLDIVCNT_42M;
+- else if (freq < 85000)
+- pllcr = LVDPLLCR_PLLDIVCNT_85M;
+- else if (freq < 128000)
+- pllcr = LVDPLLCR_PLLDIVCNT_128M;
+- else
+- pllcr = LVDPLLCR_PLLDIVCNT_148M;
++ if (soc_device_match(r8a7797)) {
++ if (freq < 39000)
++ pllcr = LVDPLLCR_PLLDLYCNT_38M;
++ else if (freq < 61000)
++ pllcr = LVDPLLCR_PLLDLYCNT_60M;
++ else if (freq < 121000)
++ pllcr = LVDPLLCR_PLLDLYCNT_121M;
++ else
++ pllcr = LVDPLLCR_PLLDLYCNT_150M;
++ } else {
++ if (freq < 42000)
++ pllcr = LVDPLLCR_PLLDIVCNT_42M;
++ else if (freq < 85000)
++ pllcr = LVDPLLCR_PLLDIVCNT_85M;
++ else if (freq < 128000)
++ pllcr = LVDPLLCR_PLLDIVCNT_128M;
++ else
++ pllcr = LVDPLLCR_PLLDIVCNT_148M;
++ }
+
+ rcar_lvds_write(lvds, LVDPLLCR, pllcr);
+
+@@ -123,6 +140,11 @@ static void rcar_du_lvdsenc_start_gen3(struct rcar_du_lvdsenc *lvds,
+ lvdcr0 |= LVDCR0_PWD;
+ rcar_lvds_write(lvds, LVDCR0, lvdcr0);
+
++ if (soc_device_match(r8a7797)) {
++ lvdcr0 |= LVDCR0_LVEN;
++ rcar_lvds_write(lvds, LVDCR0, lvdcr0);
++ }
++
+ usleep_range(100, 150);
+
+ lvdcr0 |= LVDCR0_LVRES;
+diff --git a/drivers/hwspinlock/rcar_hwspinlock.c b/drivers/hwspinlock/rcar_hwspinlock.c
+index b92db1b..a656c0a 100644
+--- a/drivers/hwspinlock/rcar_hwspinlock.c
++++ b/drivers/hwspinlock/rcar_hwspinlock.c
+@@ -21,10 +21,16 @@
+ #include <linux/of_address.h>
+ #include <linux/platform_device.h>
+ #include <linux/io.h>
++#include <linux/sys_soc.h>
+
+ #include "hwspinlock_internal.h"
+
+-#define RCAR_HWSPINLOCK_NUM (8)
++static const struct soc_device_attribute r8a7797[] = {
++ { .soc_id = "r8a7797" },
++ { }
++};
++
++#define RCAR_HWSPINLOCK_NUM (soc_device_match(r8a7797) ? 64 : 8)
+
+ static int rcar_hwspinlock_trylock(struct hwspinlock *lock)
+ {
+diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c
+index 73ff520..306ba97 100644
+--- a/drivers/i2c/busses/i2c-rcar.c
++++ b/drivers/i2c/busses/i2c-rcar.c
+@@ -807,6 +807,7 @@ static u32 rcar_i2c_func(struct i2c_adapter *adap)
+ { .compatible = "renesas,i2c-r8a7794", .data = (void *)I2C_RCAR_GEN2 },
+ { .compatible = "renesas,i2c-r8a7795", .data = (void *)I2C_RCAR_GEN3 },
+ { .compatible = "renesas,i2c-r8a7796", .data = (void *)I2C_RCAR_GEN3 },
++ { .compatible = "renesas,i2c-r8a7797", .data = (void *)I2C_RCAR_GEN3 },
+ {},
+ };
+ MODULE_DEVICE_TABLE(of, rcar_i2c_dt_ids);
+diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c
+index 2b380ff..b9ef21a 100644
+--- a/drivers/iommu/ipmmu-vmsa.c
++++ b/drivers/iommu/ipmmu-vmsa.c
+@@ -1,7 +1,7 @@
+ /*
+ * IPMMU VMSA
+ *
+- * Copyright (C) 2014 Renesas Electronics Corporation
++ * Copyright (C) 2014-2016 Renesas Electronics Corporation
+ *
+ * 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
+@@ -1274,6 +1274,9 @@ static void ipmmu_device_reset(struct ipmmu_vmsa_device *mmu)
+ .compatible = "renesas,ipmmu-r8a7796",
+ .data = &ipmmu_features_rcar_gen3,
+ }, {
++ .compatible = "renesas,ipmmu-r8a7797",
++ .data = &ipmmu_features_rcar_gen3,
++ }, {
+ /* Terminator */
+ },
+ };
+@@ -1640,6 +1643,8 @@ static int __init ipmmu_vmsa_iommu_of_setup(struct device_node *np)
+ ipmmu_vmsa_iommu_of_setup);
+ IOMMU_OF_DECLARE(ipmmu_r8a7796_iommu_of, "renesas,ipmmu-r8a7796",
+ ipmmu_vmsa_iommu_of_setup);
++IOMMU_OF_DECLARE(ipmmu_r8a7797_iommu_of, "renesas,ipmmu-r8a7797",
++ ipmmu_vmsa_iommu_of_setup);
+ #endif
+
+ MODULE_DESCRIPTION("IOMMU API for Renesas VMSA-compatible IPMMU");
+diff --git a/drivers/media/platform/soc_camera/Kconfig b/drivers/media/platform/soc_camera/Kconfig
+index 17178ad..5539c5d 100644
+--- a/drivers/media/platform/soc_camera/Kconfig
++++ b/drivers/media/platform/soc_camera/Kconfig
+@@ -39,7 +39,7 @@ config VIDEO_RCAR_VIN_LEGACY_DEBUG
+ config VIDEO_RCAR_CSI2_LEGACY
+ tristate "R-Car MIPI CSI-2 Interface driver"
+ depends on VIDEO_DEV && SOC_CAMERA && HAVE_CLK
+- depends on ARCH_R8A7795 || ARCH_R8A7796 || COMPILE_TEST
++ depends on ARCH_R8A7795 || ARCH_R8A7796 || ARCH_R8A7797 || COMPILE_TEST
+ ---help---
+ This is a v4l2 driver for the R-Car CSI-2 Interface
+
+diff --git a/drivers/media/platform/soc_camera/rcar_csi2.c b/drivers/media/platform/soc_camera/rcar_csi2.c
+index 851a4ca..1b8a6c6 100644
+--- a/drivers/media/platform/soc_camera/rcar_csi2.c
++++ b/drivers/media/platform/soc_camera/rcar_csi2.c
+@@ -25,6 +25,7 @@
+ #include <linux/slab.h>
+ #include <linux/videodev2.h>
+ #include <linux/module.h>
++#include <linux/sys_soc.h>
+
+ #include <media/rcar_csi2.h>
+ #include <media/soc_camera.h>
+@@ -153,6 +154,11 @@
+ #define RCAR_CSI2_INTSTATE_ERRSYNCESC (1 << 1)
+ #define RCAR_CSI2_INTSTATE_ERRCONTROL (1 << 0)
+
++static const struct soc_device_attribute r8a7797[] = {
++ { .soc_id = "r8a7797" },
++ { }
++};
++
+ enum chip_id {
+ RCAR_GEN3,
+ RCAR_GEN2,
+@@ -248,6 +254,17 @@ struct rcar_csi2 {
+
+ static int rcar_csi2_set_phy_freq(struct rcar_csi2 *priv)
+ {
++ const uint32_t const hs_freq_range_v3m[43] = {
++ 0x00, 0x00, 0x20, 0x40, 0x02, /* 80M, 90M, 100M, 110M, 120M */
++ 0x02, 0x22, 0x42, 0x04, 0x04, /* 130M, 140M, 150M, 160M, 170M */
++ 0x24, 0x44, 0x44, 0x06, 0x26, /* 180M, 190M, 205M, 220M, 235M */
++ 0x46, 0x08, 0x28, 0x0a, 0x2a, /* 250M, 270M, 300M, 325M, 350M */
++ 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, /* 400M, 450M, 500M, 550M, 600M */
++ 0x10, 0x30, 0x12, 0x32, 0x52, /* 650M, 700M, 750M, 800M, 950M */
++ 0x72, 0x14, 0x34, 0x52, 0x74, /* 900M, 950M, 1000M, 1050M, 1100M */
++ 0x16, 0x36, 0x56, 0x76, 0x18, /* 1150M, 1200M, 1250M, 1300M, 1350M */
++ 0x38, 0x58, 0x38 /* 1400M, 1450M, 1500M */
++ };
+ const uint32_t const hs_freq_range[43] = {
+ 0x00, 0x10, 0x20, 0x30, 0x01, /* 0-4 */
+ 0x11, 0x21, 0x31, 0x02, 0x12, /* 5-9 */
+@@ -304,7 +321,12 @@ static int rcar_csi2_set_phy_freq(struct rcar_csi2 *priv)
+
+ dev_dbg(&priv->pdev->dev, "bps_per_lane (%d)\n", bps_per_lane);
+
+- iowrite32((hs_freq_range[bps_per_lane] << 16),
++ if (soc_device_match(r8a7797))
++ iowrite32((hs_freq_range_v3m[bps_per_lane] << 16) |
++ RCAR_CSI2_PHTW_DWEN | RCAR_CSI2_PHTW_CWEN | 0x44,
++ priv->base + RCAR_CSI2_PHTW);
++ else
++ iowrite32(hs_freq_range[bps_per_lane] << 16,
+ priv->base + RCAR_CSI2_PHYPLL);
+ return 0;
+
+@@ -488,6 +509,7 @@ static int rcar_csi2_s_power(struct v4l2_subdev *sd, int on)
+
+ #ifdef CONFIG_OF
+ static const struct of_device_id rcar_csi2_of_table[] = {
++ { .compatible = "renesas,r8a7797-csi2", .data = (void *)RCAR_GEN3 },
+ { .compatible = "renesas,r8a7796-csi2", .data = (void *)RCAR_GEN3 },
+ { .compatible = "renesas,r8a7795-csi2", .data = (void *)RCAR_GEN3 },
+ { },
+@@ -496,6 +518,7 @@ static int rcar_csi2_s_power(struct v4l2_subdev *sd, int on)
+ #endif
+
+ static struct platform_device_id rcar_csi2_id_table[] = {
++ { "r8a7797-csi2", RCAR_GEN3 },
+ { "r8a7796-csi2", RCAR_GEN3 },
+ { "r8a7795-csi2", RCAR_GEN3 },
+ {},
+diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c
+index 400958b..74fb005 100644
+--- a/drivers/media/platform/soc_camera/rcar_vin.c
++++ b/drivers/media/platform/soc_camera/rcar_vin.c
+@@ -154,7 +154,7 @@
+ #define VNCSI_IFMD_REG 0x20 /* Video n CSI2 Interface Mode Register */
+
+ #define VNCSI_IFMD_DES1 (1 << 26) /* CSI20 */
+-#define VNCSI_IFMD_DES0 (1 << 25) /* H3:CSI40/41, M3:CSI40 */
++#define VNCSI_IFMD_DES0 (1 << 25) /* H3:CSI40/41, M3:CSI40, V3M:CSI40 */
+
+ #define VNCSI_IFMD_CSI_CHSEL(n) (n << 0)
+ #define VNCSI_IFMD_SEL_NUMBER 5
+@@ -185,6 +185,7 @@
+
+ enum chip_id {
+ RCAR_GEN3,
++ RCAR_V3M,
+ RCAR_M3,
+ RCAR_H3,
+ RCAR_GEN2,
+@@ -360,6 +361,49 @@ struct vin_gen3_ifmd {
+ },
+ };
+
++static const struct vin_gen3_ifmd vin_v3_vc_ifmd[] = {
++ { 0x0000,
++ {
++ {RCAR_CSI40, RCAR_VIRTUAL_CH0},
++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE},
++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE},
++ {RCAR_CSI40, RCAR_VIRTUAL_CH1},
++ }
++ },
++ { 0x0001,
++ {
++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE},
++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE},
++ {RCAR_CSI40, RCAR_VIRTUAL_CH0},
++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE},
++ }
++ },
++ { 0x0002,
++ {
++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE},
++ {RCAR_CSI40, RCAR_VIRTUAL_CH0},
++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE},
++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE},
++ }
++ },
++ { 0x0003,
++ {
++ {RCAR_CSI40, RCAR_VIRTUAL_CH0},
++ {RCAR_CSI40, RCAR_VIRTUAL_CH1},
++ {RCAR_CSI40, RCAR_VIRTUAL_CH2},
++ {RCAR_CSI40, RCAR_VIRTUAL_CH3},
++ }
++ },
++ { 0x0004,
++ {
++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE},
++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE},
++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE},
++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE},
++ }
++ },
++};
++
+ enum csi2_fmt {
+ RCAR_CSI_FMT_NONE = -1,
+ RCAR_CSI_RGB888,
+@@ -849,7 +893,8 @@ static int rcar_vin_videobuf_setup(struct vb2_queue *vq,
+ struct rcar_vin_priv *priv = ici->priv;
+ struct rcar_vin_cam *cam = icd->host_priv;
+
+- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) {
++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 ||
++ priv->chip == RCAR_V3M) {
+ if ((priv->ratio_h > 0x10000) || (priv->ratio_v > 0x10000)) {
+ dev_err(icd->parent, "Scaling rate parameter error\n");
+ return -EINVAL;
+@@ -951,7 +996,8 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv)
+ /* output format */
+ switch (icd->current_fmt->host_fmt->fourcc) {
+ case V4L2_PIX_FMT_NV12:
+- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) {
++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 ||
++ priv->chip == RCAR_V3M) {
+ iowrite32(ALIGN((cam->out_width * cam->out_height),
+ 0x80), priv->base + VNUVAOF_REG);
+ dmr = VNDMR_DTMD_YCSEP_YCBCR420;
+@@ -983,6 +1029,7 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv)
+ break;
+ case V4L2_PIX_FMT_XBGR32:
+ if (priv->chip != RCAR_H3 && priv->chip != RCAR_M3 &&
++ priv->chip != RCAR_V3M &&
+ priv->chip != RCAR_GEN2 && priv->chip != RCAR_H1 &&
+ priv->chip != RCAR_E1)
+ goto e_format;
+@@ -990,7 +1037,8 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv)
+ dmr = VNDMR_EXRGB;
+ break;
+ case V4L2_PIX_FMT_ABGR32:
+- if (priv->chip != RCAR_H3 && priv->chip != RCAR_M3)
++ if (priv->chip != RCAR_H3 && priv->chip != RCAR_M3 &&
++ priv->chip != RCAR_V3M)
+ goto e_format;
+
+ dmr = VNDMR_EXRGB | VNDMR_DTMD_ARGB;
+@@ -1006,7 +1054,8 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv)
+ if (input_is_yuv == output_is_yuv)
+ vnmc |= VNMC_BPS;
+
+- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) {
++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 ||
++ priv->chip == RCAR_V3M) {
+ if (priv->pdata_flags & RCAR_VIN_CSI2)
+ vnmc &= ~VNMC_DPINE;
+ else
+@@ -1323,7 +1372,8 @@ static int rcar_vin_add_device(struct soc_camera_device *icd)
+
+ pm_runtime_get_sync(ici->v4l2_dev.dev);
+
+- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) {
++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 ||
++ priv->chip == RCAR_V3M) {
+ struct v4l2_subdev *csi2_sd = find_csi2(priv);
+ int ret;
+
+@@ -1569,7 +1619,8 @@ static int rcar_vin_set_rect(struct soc_camera_device *icd)
+ break;
+ }
+
+- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) {
++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 ||
++ priv->chip == RCAR_V3M) {
+ if ((icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_NV12)
+ && is_scaling(cam)) {
+ ret = rcar_vin_uds_set(priv, cam);
+@@ -1720,14 +1771,16 @@ static int rcar_vin_set_bus_param(struct soc_camera_device *icd)
+ if (ret < 0 && ret != -ENOIOCTLCMD)
+ return ret;
+
+- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) {
++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 ||
++ priv->chip == RCAR_V3M) {
+ if (cfg.type == V4L2_MBUS_CSI2)
+ vnmc &= ~VNMC_DPINE;
+ else
+ vnmc |= VNMC_DPINE;
+ }
+
+- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3)
++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 ||
++ priv->chip == RCAR_V3M)
+ val = VNDMR2_FTEV;
+ else
+ val = VNDMR2_FTEV | VNDMR2_VLV(1);
+@@ -2289,7 +2342,8 @@ static int rcar_vin_try_fmt(struct soc_camera_device *icd,
+ if (ret < 0)
+ return ret;
+
+- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) {
++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 ||
++ priv->chip == RCAR_V3M) {
+ /* Adjust max scaling size for Gen3 */
+ if (pix->width > 4096)
+ pix->width = priv->max_width;
+@@ -2454,6 +2508,7 @@ static int rcar_vin_cropcap(struct soc_camera_device *icd,
+
+ #ifdef CONFIG_OF
+ static const struct of_device_id rcar_vin_of_table[] = {
++ { .compatible = "renesas,vin-r8a7797", .data = (void *)RCAR_V3M },
+ { .compatible = "renesas,vin-r8a7796", .data = (void *)RCAR_M3 },
+ { .compatible = "renesas,vin-r8a7795", .data = (void *)RCAR_H3 },
+ { .compatible = "renesas,vin-r8a7794", .data = (void *)RCAR_GEN2 },
+@@ -2754,7 +2809,8 @@ static int rcar_vin_probe(struct platform_device *pdev)
+ priv->chip = (enum chip_id)match->data;
+ }
+
+- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) {
++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 ||
++ priv->chip == RCAR_V3M) {
+ priv->max_width = 4096;
+ priv->max_height = 4096;
+ } else {
+@@ -2762,7 +2818,8 @@ static int rcar_vin_probe(struct platform_device *pdev)
+ priv->max_height = 2048;
+ }
+
+- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) {
++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 ||
++ priv->chip == RCAR_V3M) {
+ u32 ifmd = 0;
+ bool match_flag = false;
+ const struct vin_gen3_ifmd *gen3_ifmd_table = NULL;
+@@ -2841,6 +2898,8 @@ static int rcar_vin_probe(struct platform_device *pdev)
+ gen3_ifmd_table = vin_h3_vc_ifmd;
+ else if (priv->chip == RCAR_M3)
+ gen3_ifmd_table = vin_m3_vc_ifmd;
++ else if (priv->chip == RCAR_V3M)
++ gen3_ifmd_table = vin_v3_vc_ifmd;
+
+ for (i = 0; i < num; i++) {
+ if ((gen3_ifmd_table[i].v_sel[priv->index].csi2_ch
+@@ -2983,6 +3042,9 @@ static int rcar_vin_resume(struct device *dev)
+ } else if (priv->chip == RCAR_M3) {
+ ifmd = VNCSI_IFMD_DES1;
+ gen3_ifmd_table = vin_m3_vc_ifmd;
++ } else if (priv->chip == RCAR_V3M) {
++ ifmd = VNCSI_IFMD_DES1;
++ gen3_ifmd_table = vin_v3_vc_ifmd;
+ }
+
+ for (i = 0; i < num; i++) {
+diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
+index 45bd0f3..50eea8a 100644
+--- a/drivers/media/platform/vsp1/vsp1_drv.c
++++ b/drivers/media/platform/vsp1/vsp1_drv.c
+@@ -888,6 +888,14 @@ void vsp1_device_put(struct vsp1_device *vsp1)
+ .wpf_count = 2,
+ .num_bru_inputs = 5,
+ .header_mode = true,
++ }, {
++ .version = VI6_IP_VERSION_MODEL_VSPD_V3M,
++ .gen = 3,
++ .features = VSP1_HAS_BRU | VSP1_HAS_LIF,
++ .rpf_count = 5,
++ .wpf_count = 1,
++ .num_bru_inputs = 5,
++ .header_mode = true,
+ },
+ };
+
+diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c
+index b442d14..536ee4a 100644
+--- a/drivers/media/platform/vsp1/vsp1_lif.c
++++ b/drivers/media/platform/vsp1/vsp1_lif.c
+@@ -13,6 +13,7 @@
+
+ #include <linux/device.h>
+ #include <linux/gfp.h>
++#include <linux/sys_soc.h>
+
+ #include <media/v4l2-subdev.h>
+
+@@ -23,6 +24,11 @@
+ #define LIF_MIN_SIZE 2U
+ #define LIF_MAX_SIZE 8190U
+
++static const struct soc_device_attribute r8a7797[] = {
++ { .soc_id = "r8a7797" },
++ { }
++};
++
+ /* -----------------------------------------------------------------------------
+ * Device Access
+ */
+@@ -142,6 +148,9 @@ static void lif_configure(struct vsp1_entity *entity,
+ if (params != VSP1_ENTITY_PARAMS_INIT)
+ return;
+
++ if (soc_device_match(r8a7797))
++ obth = 1500;
++
+ format = vsp1_entity_get_pad_format(&lif->entity, lif->entity.config,
+ LIF_PAD_SOURCE);
+
+@@ -158,6 +167,10 @@ static void lif_configure(struct vsp1_entity *entity,
+ (obth << VI6_LIF_CTRL_OBTH_SHIFT) |
+ (format->code == 0 ? VI6_LIF_CTRL_CFMT : 0) |
+ VI6_LIF_CTRL_REQSEL | VI6_LIF_CTRL_LIF_EN);
++
++ if (soc_device_match(r8a7797))
++ vsp1_lif_write(lif, dl, VI6_LIF_LBA, VI6_LIF_LBA_LBA0 |
++ VI6_LIF_LBA_LBA1);
+ }
+
+ static const struct vsp1_entity_operations lif_entity_ops = {
+diff --git a/drivers/media/platform/vsp1/vsp1_regs.h b/drivers/media/platform/vsp1/vsp1_regs.h
+index 885f60b..2d863a7 100644
+--- a/drivers/media/platform/vsp1/vsp1_regs.h
++++ b/drivers/media/platform/vsp1/vsp1_regs.h
+@@ -788,6 +788,12 @@
+ #define VI6_LIF_CSBTH_LBTH_MASK (0x7ff << 0)
+ #define VI6_LIF_CSBTH_LBTH_SHIFT 0
+
++
++#define VI6_LIF_LBA 0x3b0c
++#define VI6_LIF_LBA_LBA0 (1 << 31)
++#define VI6_LIF_LBA_LBA1 (0x600 << 16)
++
++
+ /* -----------------------------------------------------------------------------
+ * Security Control Registers
+ */
+@@ -811,6 +817,7 @@
+ #define VI6_IP_VERSION_MODEL_VSPBD_GEN3 (0x15 << 8)
+ #define VI6_IP_VERSION_MODEL_VSPBC_GEN3 (0x16 << 8)
+ #define VI6_IP_VERSION_MODEL_VSPD_GEN3 (0x17 << 8)
++#define VI6_IP_VERSION_MODEL_VSPD_V3M (0x18 << 8)
+ #define VI6_IP_VERSION_MODEL_VSPDL_H3 (0x19 << 8)
+ #define VI6_IP_VERSION_SOC_MASK (0xff << 0)
+ #define VI6_IP_VERSION_SOC_H (0x01 << 0)
+diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
+index 98c4e11..ee7b188 100644
+--- a/drivers/mmc/host/sh_mobile_sdhi.c
++++ b/drivers/mmc/host/sh_mobile_sdhi.c
+@@ -137,6 +137,7 @@ struct sh_mobile_sdhi_of_data {
+ { .compatible = "renesas,sdhi-r8a7794", .data = &of_rcar_gen2_compatible, },
+ { .compatible = "renesas,sdhi-r8a7795", .data = &of_rcar_gen3_compatible, },
+ { .compatible = "renesas,sdhi-r8a7796", .data = &of_rcar_gen3_compatible, },
++ { .compatible = "renesas,sdhi-r8a7797", .data = &of_rcar_gen3_compatible, },
+ {},
+ };
+ MODULE_DEVICE_TABLE(of, sh_mobile_sdhi_of_match);
+diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
+index 6c65426..97c52dd 100644
+--- a/drivers/net/ethernet/renesas/ravb_main.c
++++ b/drivers/net/ethernet/renesas/ravb_main.c
+@@ -1922,6 +1922,7 @@ static int ravb_mdio_release(struct ravb_private *priv)
+ { .compatible = "renesas,etheravb-rcar-gen2", .data = (void *)RCAR_GEN2 },
+ { .compatible = "renesas,etheravb-r8a7795", .data = (void *)RCAR_GEN3 },
+ { .compatible = "renesas,etheravb-r8a7796", .data = (void *)RCAR_GEN3 },
++ { .compatible = "renesas,etheravb-r8a7797", .data = (void *)RCAR_GEN3 },
+ { .compatible = "renesas,etheravb-rcar-gen3", .data = (void *)RCAR_GEN3 },
+ { }
+ };
+diff --git a/drivers/pinctrl/sh-pfc/Kconfig b/drivers/pinctrl/sh-pfc/Kconfig
+index 07eca54..002541f 100644
+--- a/drivers/pinctrl/sh-pfc/Kconfig
++++ b/drivers/pinctrl/sh-pfc/Kconfig
+@@ -79,6 +79,11 @@ config PINCTRL_PFC_R8A7796
+ depends on ARCH_R8A7796
+ select PINCTRL_SH_PFC
+
++config PINCTRL_PFC_R8A7797
++ def_bool y
++ depends on ARCH_R8A7797
++ select PINCTRL_SH_PFC
++
+ config PINCTRL_PFC_SH7203
+ def_bool y
+ depends on CPU_SUBTYPE_SH7203
+diff --git a/drivers/pinctrl/sh-pfc/Makefile b/drivers/pinctrl/sh-pfc/Makefile
+index 8e08684..10adc18 100644
+--- a/drivers/pinctrl/sh-pfc/Makefile
++++ b/drivers/pinctrl/sh-pfc/Makefile
+@@ -13,6 +13,7 @@ obj-$(CONFIG_PINCTRL_PFC_R8A7794) += pfc-r8a7794.o
+ obj-$(CONFIG_PINCTRL_PFC_R8A7795) += pfc-r8a7795.o
+ obj-$(CONFIG_PINCTRL_PFC_R8A7795) += pfc-r8a7795-es1.o
+ obj-$(CONFIG_PINCTRL_PFC_R8A7796) += pfc-r8a7796.o
++obj-$(CONFIG_PINCTRL_PFC_R8A7797) += pfc-r8a7797.o
+ obj-$(CONFIG_PINCTRL_PFC_SH7203) += pfc-sh7203.o
+ obj-$(CONFIG_PINCTRL_PFC_SH7264) += pfc-sh7264.o
+ obj-$(CONFIG_PINCTRL_PFC_SH7269) += pfc-sh7269.o
+diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c
+index 6399eb1..9bb3665 100644
+--- a/drivers/pinctrl/sh-pfc/core.c
++++ b/drivers/pinctrl/sh-pfc/core.c
+@@ -5,6 +5,7 @@
+ *
+ * Copyright (C) 2008 Magnus Damm
+ * Copyright (C) 2009 - 2012 Paul Mundt
++ * Copyright (C) 2016 Renesas Electronics Corp.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+@@ -622,6 +623,12 @@ static int sh_pfc_init_ranges(struct sh_pfc *pfc)
+ .data = &r8a7796_pinmux_info,
+ },
+ #endif
++#ifdef CONFIG_PINCTRL_PFC_R8A7797
++ {
++ .compatible = "renesas,pfc-r8a7797",
++ .data = &r8a7797_pinmux_info,
++ },
++#endif
+ #ifdef CONFIG_PINCTRL_PFC_SH73A0
+ {
+ .compatible = "renesas,pfc-sh73a0",
+diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7797.c b/drivers/pinctrl/sh-pfc/pfc-r8a7797.c
+new file mode 100644
+index 0000000..a528b44
+--- /dev/null
++++ b/drivers/pinctrl/sh-pfc/pfc-r8a7797.c
+@@ -0,0 +1,2615 @@
++/*
++ * R8A7797 processor support - PFC hardware block.
++ *
++ * Copyright (C) 2016 Renesas Electronics Corp.
++ *
++ * This file is based on the drivers/pinctrl/sh-pfc/pfc-r8a7795.c
++ *
++ * R-Car Gen3 processor support - PFC hardware block.
++ *
++ * Copyright (C) 2015 Renesas Electronics Corporation
++ *
++ * 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; version 2 of the License.
++ */
++
++#include <linux/io.h>
++#include <linux/kernel.h>
++
++#include "core.h"
++#include "sh_pfc.h"
++
++#define CPU_ALL_PORT(fn, sfx) \
++ PORT_GP_CFG_22(0, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \
++ PORT_GP_CFG_28(1, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \
++ PORT_GP_CFG_17(2, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \
++ PORT_GP_CFG_17(3, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \
++ PORT_GP_CFG_6(4, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \
++ PORT_GP_CFG_15(5, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH)
++/*
++ * F_() : just information
++ * FM() : macro for FN_xxx / xxx_MARK
++ */
++
++/* GPSR0 */
++#define GPSR0_21 F_(DU_EXODDF_DU_ODDF_DISP_CDE, IP2_23_20)
++#define GPSR0_20 F_(DU_EXVSYNC_DU_VSYNC, IP2_19_16)
++#define GPSR0_19 F_(DU_EXHSYNC_DU_HSYNC, IP2_15_12)
++#define GPSR0_18 F_(DU_DOTCLKOUT, IP2_11_8)
++#define GPSR0_17 F_(DU_DB7, IP2_7_4)
++#define GPSR0_16 F_(DU_DB6, IP2_3_0)
++#define GPSR0_15 F_(DU_DB5, IP1_31_28)
++#define GPSR0_14 F_(DU_DB4, IP1_27_24)
++#define GPSR0_13 F_(DU_DB3, IP1_23_20)
++#define GPSR0_12 F_(DU_DB2, IP1_19_16)
++#define GPSR0_11 F_(DU_DG7, IP1_15_12)
++#define GPSR0_10 F_(DU_DG6, IP1_11_8)
++#define GPSR0_9 F_(DU_DG5, IP1_7_4)
++#define GPSR0_8 F_(DU_DG4, IP1_3_0)
++#define GPSR0_7 F_(DU_DG3, IP0_31_28)
++#define GPSR0_6 F_(DU_DG2, IP0_27_24)
++#define GPSR0_5 F_(DU_DR7, IP0_23_20)
++#define GPSR0_4 F_(DU_DR6, IP0_19_16)
++#define GPSR0_3 F_(DU_DR5, IP0_15_12)
++#define GPSR0_2 F_(DU_DR4, IP0_11_8)
++#define GPSR0_1 F_(DU_DR3, IP0_7_4)
++#define GPSR0_0 F_(DU_DR2, IP0_3_0)
++
++/* GPSR1 */
++#define GPSR1_27 F_(DIGRF_CLKOUT, IP8_27_24)
++#define GPSR1_26 F_(DIGRF_CLKIN, IP8_23_20)
++#define GPSR1_25 F_(CANFD_CLK_A, IP8_19_16)
++#define GPSR1_24 F_(CANFD1_RX, IP8_15_12)
++#define GPSR1_23 F_(CANFD1_TX, IP8_11_8)
++#define GPSR1_22 F_(CANFD0_RX_A, IP8_7_4)
++#define GPSR1_21 F_(CANFD0_TX_A, IP8_3_0)
++#define GPSR1_20 F_(AVB0_AVTP_CAPTURE, IP7_31_28)
++#define GPSR1_19 FM(AVB0_AVTP_MATCH)
++#define GPSR1_18 FM(AVB0_LINK)
++#define GPSR1_17 FM(AVB0_PHY_INT)
++#define GPSR1_16 FM(AVB0_MAGIC)
++#define GPSR1_15 FM(AVB0_MDC)
++#define GPSR1_14 FM(AVB0_MDIO)
++#define GPSR1_13 FM(AVB0_TXCREFCLK)
++#define GPSR1_12 FM(AVB0_TD3)
++#define GPSR1_11 FM(AVB0_TD2)
++#define GPSR1_10 FM(AVB0_TD1)
++#define GPSR1_9 FM(AVB0_TD0)
++#define GPSR1_8 FM(AVB0_TXC)
++#define GPSR1_7 FM(AVB0_TX_CTL)
++#define GPSR1_6 FM(AVB0_RD3)
++#define GPSR1_5 FM(AVB0_RD2)
++#define GPSR1_4 FM(AVB0_RD1)
++#define GPSR1_3 FM(AVB0_RD0)
++#define GPSR1_2 FM(AVB0_RXC)
++#define GPSR1_1 FM(AVB0_RX_CTL)
++#define GPSR1_0 F_(IRQ0, IP2_27_24)
++
++/* GPSR2 */
++#define GPSR2_16 F_(VI0_FIELD, IP4_31_28)
++#define GPSR2_15 F_(VI0_DATA11, IP4_27_24)
++#define GPSR2_14 F_(VI0_DATA10, IP4_23_20)
++#define GPSR2_13 F_(VI0_DATA9, IP4_19_16)
++#define GPSR2_12 F_(VI0_DATA8, IP4_15_12)
++#define GPSR2_11 F_(VI0_DATA7, IP4_11_8)
++#define GPSR2_10 F_(VI0_DATA6, IP4_7_4)
++#define GPSR2_9 F_(VI0_DATA5, IP4_3_0)
++#define GPSR2_8 F_(VI0_DATA4, IP3_31_28)
++#define GPSR2_7 F_(VI0_DATA3, IP3_27_24)
++#define GPSR2_6 F_(VI0_DATA2, IP3_23_20)
++#define GPSR2_5 F_(VI0_DATA1, IP3_19_16)
++#define GPSR2_4 F_(VI0_DATA0, IP3_15_12)
++#define GPSR2_3 F_(VI0_VSYNC_N, IP3_11_8)
++#define GPSR2_2 F_(VI0_HSYNC_N, IP3_7_4)
++#define GPSR2_1 F_(VI0_CLKENB, IP3_3_0)
++#define GPSR2_0 F_(VI0_CLK, IP2_31_28)
++
++/* GPSR3 */
++#define GPSR3_16 F_(VI1_FIELD, IP7_3_0)
++#define GPSR3_15 F_(VI1_DATA11, IP6_31_28)
++#define GPSR3_14 F_(VI1_DATA10, IP6_27_24)
++#define GPSR3_13 F_(VI1_DATA9, IP6_23_20)
++#define GPSR3_12 F_(VI1_DATA8, IP6_19_16)
++#define GPSR3_11 F_(VI1_DATA7, IP6_15_12)
++#define GPSR3_10 F_(VI1_DATA6, IP6_11_8)
++#define GPSR3_9 F_(VI1_DATA5, IP6_7_4)
++#define GPSR3_8 F_(VI1_DATA4, IP6_3_0)
++#define GPSR3_7 F_(VI1_DATA3, IP5_31_28)
++#define GPSR3_6 F_(VI1_DATA2, IP5_27_24)
++#define GPSR3_5 F_(VI1_DATA1, IP5_23_20)
++#define GPSR3_4 F_(VI1_DATA0, IP5_19_16)
++#define GPSR3_3 F_(VI1_VSYNC_N, IP5_15_12)
++#define GPSR3_2 F_(VI1_HSYNC_N, IP5_11_8)
++#define GPSR3_1 F_(VI1_CLKENB, IP5_7_4)
++#define GPSR3_0 F_(VI1_CLK, IP5_3_0)
++
++/* GPSR4 */
++#define GPSR4_5 F_(SDA2, IP7_27_24)
++#define GPSR4_4 F_(SCL2, IP7_23_20)
++#define GPSR4_3 F_(SDA1, IP7_19_16)
++#define GPSR4_2 F_(SCL1, IP7_15_12)
++#define GPSR4_1 F_(SDA0, IP7_11_8)
++#define GPSR4_0 F_(SCL0, IP7_7_4)
++
++/* GPSR5 */
++#define GPSR5_14 FM(RPC_INT_N)
++#define GPSR5_13 FM(RPC_WP_N)
++#define GPSR5_12 FM(RPC_RESET_N)
++#define GPSR5_11 FM(QSPI1_SSL)
++#define GPSR5_10 FM(QSPI1_IO3)
++#define GPSR5_9 FM(QSPI1_IO2)
++#define GPSR5_8 FM(QSPI1_MISO_IO1)
++#define GPSR5_7 FM(QSPI1_MOSI_IO0)
++#define GPSR5_6 FM(QSPI1_SPCLK)
++#define GPSR5_5 FM(QSPI0_SSL)
++#define GPSR5_4 FM(QSPI0_IO3)
++#define GPSR5_3 FM(QSPI0_IO2)
++#define GPSR5_2 FM(QSPI0_MISO_IO1)
++#define GPSR5_1 FM(QSPI0_MOSI_IO0)
++#define GPSR5_0 FM(QSPI0_SPCLK)
++
++
++/* IPSRx */ /* 0 */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 */ /* 7 */ /* 8 */ /* 9 */ /* A */ /* B */ /* C */ /* D */ /* E */ /* F */
++#define IP0_3_0 FM(DU_DR2) FM(HSCK0) F_(0, 0) FM(A0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP0_7_4 FM(DU_DR3) FM(HRTS0_N) F_(0, 0) FM(A1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP0_11_8 FM(DU_DR4) FM(HCTS0_N) F_(0, 0) FM(A2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP0_15_12 FM(DU_DR5) FM(HTX0) F_(0, 0) FM(A3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP0_19_16 FM(DU_DR6) FM(MSIOF3_RXD) F_(0, 0) FM(A4) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP0_23_20 FM(DU_DR7) FM(MSIOF3_TXD) F_(0, 0) FM(A5) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP0_27_24 FM(DU_DG2) FM(MSIOF3_SS1) F_(0, 0) FM(A6) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP0_31_28 FM(DU_DG3) FM(MSIOF3_SS2) F_(0, 0) FM(A7) FM(PWMFSW0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP1_3_0 FM(DU_DG4) F_(0, 0) F_(0, 0) FM(A8) FM(FSO_CFE_0_N_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP1_7_4 FM(DU_DG5) F_(0, 0) F_(0, 0) FM(A9) FM(FSO_CFE_1_N_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP1_11_8 FM(DU_DG6) F_(0, 0) F_(0, 0) FM(A10) FM(FSO_TOE_N_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP1_15_12 FM(DU_DG7) F_(0, 0) F_(0, 0) FM(A11) FM(IRQ1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP1_19_16 FM(DU_DB2) F_(0, 0) F_(0, 0) FM(A12) FM(IRQ2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP1_23_20 FM(DU_DB3) F_(0, 0) F_(0, 0) FM(A13) FM(FXR_CLKOUT1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP1_27_24 FM(DU_DB4) F_(0, 0) F_(0, 0) FM(A14) FM(FXR_CLKOUT2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP1_31_28 FM(DU_DB5) F_(0, 0) F_(0, 0) FM(A15) FM(FXR_TXENA_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP2_3_0 FM(DU_DB6) F_(0, 0) F_(0, 0) FM(A16) FM(FXR_TXENB_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP2_7_4 FM(DU_DB7) F_(0, 0) F_(0, 0) FM(A17) FM(STPWT_EXTFXR) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP2_11_8 FM(DU_DOTCLKOUT) FM(SCIF_CLK_A) F_(0, 0) FM(A18) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP2_15_12 FM(DU_EXHSYNC_DU_HSYNC) FM(HRX0) F_(0, 0) FM(A19) FM(IRQ3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP2_19_16 FM(DU_EXVSYNC_DU_VSYNC) FM(MSIOF3_SCK) F_(0, 0) FM(A20) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP2_23_20 FM(DU_EXODDF_DU_ODDF_DISP_CDE) FM(MSIOF3_SYNC) F_(0, 0) FM(A21) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP2_27_24 FM(IRQ0) FM(CC5_OSCOUT) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP2_31_28 FM(VI0_CLK) FM(MSIOF2_SCK) FM(SCK3) F_(0, 0) FM(HSCK3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP3_3_0 FM(VI0_CLKENB) FM(MSIOF2_RXD) FM(RX3) FM(RD_WR_N) FM(HCTS3_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP3_7_4 FM(VI0_HSYNC_N) FM(MSIOF2_TXD) FM(TX3) F_(0, 0) FM(HRTS3_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP3_11_8 FM(VI0_VSYNC_N) FM(MSIOF2_SYNC) FM(CTS3_N) F_(0, 0) FM(HTX3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP3_15_12 FM(VI0_DATA0) FM(MSIOF2_SS1) FM(RTS3_N_TANS) F_(0, 0) FM(HRX3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP3_19_16 FM(VI0_DATA1) FM(MSIOF2_SS2) FM(SCK1) F_(0, 0) FM(SPEEDIN_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP3_23_20 FM(VI0_DATA2) FM(AVB0_AVTP_PPS) FM(SDA3_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP3_27_24 FM(VI0_DATA3) FM(HSCK1) FM(SCL3_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP3_31_28 FM(VI0_DATA4) FM(HRTS1_N) FM(RX1_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP4_3_0 FM(VI0_DATA5) FM(HCTS1_N) FM(TX1_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP4_7_4 FM(VI0_DATA6) FM(HTX1) FM(CTS1_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP4_11_8 FM(VI0_DATA7) FM(HRX1) FM(RTS1_N_TANS) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP4_15_12 FM(VI0_DATA8) FM(HSCK2) FM(PWM0_A) FM(A22) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP4_19_16 FM(VI0_DATA9) FM(HCTS2_N) FM(PWM1_A) FM(A23) FM(FSO_CFE_0_N_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP4_23_20 FM(VI0_DATA10) FM(HRTS2_N) FM(PWM2_A) FM(A24) FM(FSO_CFE_1_N_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP4_27_24 FM(VI0_DATA11) FM(HTX2) FM(PWM3_A) FM(A25) FM(FSO_TOE_N_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP4_31_28 FM(VI0_FIELD) FM(HRX2) FM(PWM4_A) FM(CS1_N_A26) FM(FSCLKST2_N_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP5_3_0 FM(VI1_CLK) FM(MSIOF1_RXD) F_(0, 0) FM(CS0_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP5_7_4 FM(VI1_CLKENB) FM(MSIOF1_TXD) F_(0, 0) FM(D0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP5_11_8 FM(VI1_HSYNC_N) FM(MSIOF1_SCK) F_(0, 0) FM(D1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP5_15_12 FM(VI1_VSYNC_N) FM(MSIOF1_SYNC) F_(0, 0) FM(D2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP5_19_16 FM(VI1_DATA0) FM(MSIOF1_SS1) F_(0, 0) FM(D3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP5_23_20 FM(VI1_DATA1) FM(MSIOF1_SS2) F_(0, 0) FM(D4) FM(MMC_CMD) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP5_27_24 FM(VI1_DATA2) FM(CANFD0_TX_B) F_(0, 0) FM(D5) FM(MMC_D0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP5_31_28 FM(VI1_DATA3) FM(CANFD0_RX_B) F_(0, 0) FM(D6) FM(MMC_D1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP6_3_0 FM(VI1_DATA4) FM(CANFD_CLK_B) F_(0, 0) FM(D7) FM(MMC_D2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP6_7_4 FM(VI1_DATA5) F_(0,0) FM(SCK4) FM(D8) FM(MMC_D3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP6_11_8 FM(VI1_DATA6) F_(0,0) FM(RX4) FM(D9) FM(MMC_CLK) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP6_15_12 FM(VI1_DATA7) F_(0,0) FM(TX4) FM(D10) FM(MMC_D4) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP6_19_16 FM(VI1_DATA8) F_(0,0) FM(CTS4_N) FM(D11) FM(MMC_D5) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP6_23_20 FM(VI1_DATA9) F_(0,0) FM(RTS4_N_TANS) FM(D12) FM(MMC_D6) FM(SCL3_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP6_27_24 FM(VI1_DATA10) F_(0,0) F_(0, 0) FM(D13) FM(MMC_D7) FM(SDA3_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP6_31_28 FM(VI1_DATA11) FM(SCL4) FM(IRQ4) FM(D14) FM(MMC_WP) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP7_3_0 FM(VI1_FIELD) FM(SDA4) FM(IRQ5) FM(D15) FM(MMC_CD) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP7_7_4 FM(SCL0) FM(DU_DR0) FM(TPU0TO0) FM(CLKOUT) F_(0, 0) FM(MSIOF0_RXD) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP7_11_8 FM(SDA0) FM(DU_DR1) FM(TPU0TO1) FM(BS_N) FM(SCK0) FM(MSIOF0_TXD) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP7_15_12 FM(SCL1) FM(DU_DG0) FM(TPU0TO2) FM(RD_N) FM(CTS0_N) FM(MSIOF0_SCK) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP7_19_16 FM(SDA1) FM(DU_DG1) FM(TPU0TO3) FM(WE0_N) FM(RTS0_N_TANS) FM(MSIOF0_SYNC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP7_23_20 FM(SCL2) FM(DU_DB0) FM(TCLK1_A) FM(WE1_N) FM(RX0) FM(MSIOF0_SS1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP7_27_24 FM(SDA2) FM(DU_DB1) FM(TCLK2_A) FM(EX_WAIT0) FM(TX0) FM(MSIOF0_SS2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP7_31_28 FM(AVB0_AVTP_CAPTURE) F_(0, 0) F_(0, 0) F_(0, 0) FM(FSCLKST2_N_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP8_3_0 FM(CANFD0_TX_A) FM(FXR_TXDA) FM(PWM0_B) FM(DU_DISP) FM(FSCLKST2_N_C) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP8_7_4 FM(CANFD0_RX_A) FM(RXDA_EXTFXR) FM(PWM1_B) FM(DU_CDE) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP8_11_8 FM(CANFD1_TX) FM(FXR_TXDB) FM(PWM2_B) FM(TCLK1_B) FM(TX1_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP8_15_12 FM(CANFD1_RX) FM(RXDB_EXTFXR) FM(PWM3_B) FM(TCLK2_B) FM(RX1_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP8_19_16 FM(CANFD_CLK_A) FM(CLK_EXTFXR) FM(PWM4_B) FM(SPEEDIN_B) FM(SCIF_CLK_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP8_23_20 FM(DIGRF_CLKIN) FM(DIGRF_CLKEN_IN) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP8_27_24 FM(DIGRF_CLKOUT) FM(DIGRF_CLKEN_OUT) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++#define IP8_31_28 F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
++
++#define PINMUX_GPSR \
++\
++ GPSR1_27 \
++ GPSR1_26 \
++ GPSR1_25 \
++ GPSR1_24 \
++ GPSR1_23 \
++ GPSR1_22 \
++GPSR0_21 GPSR1_21 \
++GPSR0_20 GPSR1_20 \
++GPSR0_19 GPSR1_19 \
++GPSR0_18 GPSR1_18 \
++GPSR0_17 GPSR1_17 \
++GPSR0_16 GPSR1_16 GPSR2_16 GPSR3_16 \
++GPSR0_15 GPSR1_15 GPSR2_15 GPSR3_15 \
++GPSR0_14 GPSR1_14 GPSR2_14 GPSR3_14 GPSR5_14 \
++GPSR0_13 GPSR1_13 GPSR2_13 GPSR3_13 GPSR5_13 \
++GPSR0_12 GPSR1_12 GPSR2_12 GPSR3_12 GPSR5_12 \
++GPSR0_11 GPSR1_11 GPSR2_11 GPSR3_11 GPSR5_11 \
++GPSR0_10 GPSR1_10 GPSR2_10 GPSR3_10 GPSR5_10 \
++GPSR0_9 GPSR1_9 GPSR2_9 GPSR3_9 GPSR5_9 \
++GPSR0_8 GPSR1_8 GPSR2_8 GPSR3_8 GPSR5_8 \
++GPSR0_7 GPSR1_7 GPSR2_7 GPSR3_7 GPSR5_7 \
++GPSR0_6 GPSR1_6 GPSR2_6 GPSR3_6 GPSR5_6 \
++GPSR0_5 GPSR1_5 GPSR2_5 GPSR3_5 GPSR4_5 GPSR5_5 \
++GPSR0_4 GPSR1_4 GPSR2_4 GPSR3_4 GPSR4_4 GPSR5_4 \
++GPSR0_3 GPSR1_3 GPSR2_3 GPSR3_3 GPSR4_3 GPSR5_3 \
++GPSR0_2 GPSR1_2 GPSR2_2 GPSR3_2 GPSR4_2 GPSR5_2 \
++GPSR0_1 GPSR1_1 GPSR2_1 GPSR3_1 GPSR4_1 GPSR5_1 \
++GPSR0_0 GPSR1_0 GPSR2_0 GPSR3_0 GPSR4_0 GPSR5_0
++
++#define PINMUX_IPSR \
++\
++FM(IP0_3_0) IP0_3_0 FM(IP1_3_0) IP1_3_0 FM(IP2_3_0) IP2_3_0 FM(IP3_3_0) IP3_3_0 \
++FM(IP0_7_4) IP0_7_4 FM(IP1_7_4) IP1_7_4 FM(IP2_7_4) IP2_7_4 FM(IP3_7_4) IP3_7_4 \
++FM(IP0_11_8) IP0_11_8 FM(IP1_11_8) IP1_11_8 FM(IP2_11_8) IP2_11_8 FM(IP3_11_8) IP3_11_8 \
++FM(IP0_15_12) IP0_15_12 FM(IP1_15_12) IP1_15_12 FM(IP2_15_12) IP2_15_12 FM(IP3_15_12) IP3_15_12 \
++FM(IP0_19_16) IP0_19_16 FM(IP1_19_16) IP1_19_16 FM(IP2_19_16) IP2_19_16 FM(IP3_19_16) IP3_19_16 \
++FM(IP0_23_20) IP0_23_20 FM(IP1_23_20) IP1_23_20 FM(IP2_23_20) IP2_23_20 FM(IP3_23_20) IP3_23_20 \
++FM(IP0_27_24) IP0_27_24 FM(IP1_27_24) IP1_27_24 FM(IP2_27_24) IP2_27_24 FM(IP3_27_24) IP3_27_24 \
++FM(IP0_31_28) IP0_31_28 FM(IP1_31_28) IP1_31_28 FM(IP2_31_28) IP2_31_28 FM(IP3_31_28) IP3_31_28 \
++\
++FM(IP4_3_0) IP4_3_0 FM(IP5_3_0) IP5_3_0 FM(IP6_3_0) IP6_3_0 FM(IP7_3_0) IP7_3_0 \
++FM(IP4_7_4) IP4_7_4 FM(IP5_7_4) IP5_7_4 FM(IP6_7_4) IP6_7_4 FM(IP7_7_4) IP7_7_4 \
++FM(IP4_11_8) IP4_11_8 FM(IP5_11_8) IP5_11_8 FM(IP6_11_8) IP6_11_8 FM(IP7_11_8) IP7_11_8 \
++FM(IP4_15_12) IP4_15_12 FM(IP5_15_12) IP5_15_12 FM(IP6_15_12) IP6_15_12 FM(IP7_15_12) IP7_15_12 \
++FM(IP4_19_16) IP4_19_16 FM(IP5_19_16) IP5_19_16 FM(IP6_19_16) IP6_19_16 FM(IP7_19_16) IP7_19_16 \
++FM(IP4_23_20) IP4_23_20 FM(IP5_23_20) IP5_23_20 FM(IP6_23_20) IP6_23_20 FM(IP7_23_20) IP7_23_20 \
++FM(IP4_27_24) IP4_27_24 FM(IP5_27_24) IP5_27_24 FM(IP6_27_24) IP6_27_24 FM(IP7_27_24) IP7_27_24 \
++FM(IP4_31_28) IP4_31_28 FM(IP5_31_28) IP5_31_28 FM(IP6_31_28) IP6_31_28 FM(IP7_31_28) IP7_31_28 \
++\
++FM(IP8_3_0) IP8_3_0 \
++FM(IP8_7_4) IP8_7_4 \
++FM(IP8_11_8) IP8_11_8 \
++FM(IP8_15_12) IP8_15_12 \
++FM(IP8_19_16) IP8_19_16 \
++FM(IP8_23_20) IP8_23_20 \
++FM(IP8_27_24) IP8_27_24 \
++FM(IP8_31_28) IP8_31_28
++
++/*
++ Set Value = H'0 Set Value = H'1
++Register Function Pin Function Pin
++------------------------------------------------------------
++sel_hscif0 HSCIF0_A SCIF_CLK HSCIF0_B SCIF_CLK
++sel_scif1 SCIF1_A RX1 SCIF1_B TX1
++ SCIF1_A TX1 SCIF1_B RX1
++sel_canfd0 CANFD0_A CANFD0_TX CANFD0_B CANFD0_TX
++ CANFD0_A CANFD0_RX CANFD0_B CANFD0_RX
++ CANFD0_A CANFD_CLK CANFD0_B CANFD_CLK
++sel_pwm4 PWM4_A PWM4 PWM4_B PWM4
++sel_pwm3 PWM3_A PWM3 PWM3_B PWM3
++sel_pwm2 PWM2_A PWM2 PWM2_B PWM2
++sel_pwm1 PWM1_A PWM1 PWM1_B PWM1
++sel_pwm0 PWM0_A PWM0 PWM0_B PWM0
++sel_rfso RFSO_A FSO_CFE_0_N RFSO_B FSO_CFE_0_N
++ RFSO_A FSO_CFE_1_N RFSO_B FSO_CFE_1_N
++ RFSO_A FSO_TOE_N RFSO_B FSO_TOE_N
++sel_rsp RSP_A SPEEDIN RSP_B SPEEDIN
++sel_tmu TMU_A TCLK1 TMU_B TCLK1
++ TMU_A TCLK2 TMU_B TCLK2
++*/
++/* MOD_SEL0 */ /* 0 */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 */ /* 7 */
++#define MOD_SEL0_10 FM(SEL_HSCIF0_0) FM(SEL_HSCIF0_1)
++#define MOD_SEL0_9 FM(SEL_SCIF1_0) FM(SEL_SCIF1_1)
++#define MOD_SEL0_8 FM(SEL_CANFD0_0) FM(SEL_CANFD0_1)
++#define MOD_SEL0_7 FM(SEL_PWM4_0) FM(SEL_PWM4_1)
++#define MOD_SEL0_6 FM(SEL_PWM3_0) FM(SEL_PWM3_1)
++#define MOD_SEL0_5 FM(SEL_PWM2_0) FM(SEL_PWM2_1)
++#define MOD_SEL0_4 FM(SEL_PWM1_0) FM(SEL_PWM1_1)
++#define MOD_SEL0_3 FM(SEL_PWM0_0) FM(SEL_PWM0_1)
++#define MOD_SEL0_2 FM(SEL_RFSO_0) FM(SEL_RFSO_1)
++#define MOD_SEL0_1 FM(SEL_RSP_0) FM(SEL_RSP_1)
++#define MOD_SEL0_0 FM(SEL_TMU_0) FM(SEL_TMU_1)
++
++#define PINMUX_MOD_SELS \
++\
++MOD_SEL0_10 \
++MOD_SEL0_9 \
++MOD_SEL0_8 \
++MOD_SEL0_7 \
++MOD_SEL0_6 \
++MOD_SEL0_5 \
++MOD_SEL0_4 \
++MOD_SEL0_3 \
++MOD_SEL0_2 \
++MOD_SEL0_1 \
++MOD_SEL0_0
++
++enum {
++ PINMUX_RESERVED = 0,
++
++ PINMUX_DATA_BEGIN,
++ GP_ALL(DATA),
++ PINMUX_DATA_END,
++
++#define F_(x, y)
++#define FM(x) FN_##x,
++ PINMUX_FUNCTION_BEGIN,
++ GP_ALL(FN),
++ PINMUX_GPSR
++ PINMUX_IPSR
++ PINMUX_MOD_SELS
++ PINMUX_FUNCTION_END,
++#undef F_
++#undef FM
++
++#define F_(x, y)
++#define FM(x) x##_MARK,
++ PINMUX_MARK_BEGIN,
++ PINMUX_GPSR
++ PINMUX_IPSR
++ PINMUX_MOD_SELS
++ PINMUX_MARK_END,
++#undef F_
++#undef FM
++};
++
++static const u16 pinmux_data[] = {
++ PINMUX_DATA_GP_ALL(),
++
++ PINMUX_SINGLE(AVB0_RX_CTL),
++ PINMUX_SINGLE(AVB0_RXC),
++ PINMUX_SINGLE(AVB0_RD0),
++ PINMUX_SINGLE(AVB0_RD1),
++ PINMUX_SINGLE(AVB0_RD2),
++ PINMUX_SINGLE(AVB0_RD3),
++ PINMUX_SINGLE(AVB0_TX_CTL),
++ PINMUX_SINGLE(AVB0_TXC),
++ PINMUX_SINGLE(AVB0_TD0),
++ PINMUX_SINGLE(AVB0_TD1),
++ PINMUX_SINGLE(AVB0_TD2),
++ PINMUX_SINGLE(AVB0_TD3),
++ PINMUX_SINGLE(AVB0_TXCREFCLK),
++ PINMUX_SINGLE(AVB0_MDIO),
++ PINMUX_SINGLE(AVB0_MDC),
++ PINMUX_SINGLE(AVB0_MAGIC),
++ PINMUX_SINGLE(AVB0_PHY_INT),
++ PINMUX_SINGLE(AVB0_LINK),
++ PINMUX_SINGLE(AVB0_AVTP_MATCH),
++
++ PINMUX_SINGLE(QSPI0_SPCLK),
++ PINMUX_SINGLE(QSPI0_MOSI_IO0),
++ PINMUX_SINGLE(QSPI0_MISO_IO1),
++ PINMUX_SINGLE(QSPI0_IO2),
++ PINMUX_SINGLE(QSPI0_IO3),
++ PINMUX_SINGLE(QSPI0_SSL),
++ PINMUX_SINGLE(QSPI1_SPCLK),
++ PINMUX_SINGLE(QSPI1_MOSI_IO0),
++ PINMUX_SINGLE(QSPI1_MISO_IO1),
++ PINMUX_SINGLE(QSPI1_IO2),
++ PINMUX_SINGLE(QSPI1_IO3),
++ PINMUX_SINGLE(QSPI1_SSL),
++ PINMUX_SINGLE(RPC_RESET_N),
++ PINMUX_SINGLE(RPC_WP_N),
++ PINMUX_SINGLE(RPC_INT_N),
++
++ /* IPSR0 */
++ PINMUX_IPSR_GPSR(IP0_3_0, DU_DR2),
++ PINMUX_IPSR_GPSR(IP0_3_0, HSCK0),
++ PINMUX_IPSR_GPSR(IP0_3_0, A0),
++
++ PINMUX_IPSR_GPSR(IP0_7_4, DU_DR3),
++ PINMUX_IPSR_GPSR(IP0_7_4, HRTS0_N),
++ PINMUX_IPSR_GPSR(IP0_7_4, A1),
++
++ PINMUX_IPSR_GPSR(IP0_11_8, DU_DR4),
++ PINMUX_IPSR_GPSR(IP0_11_8, HCTS0_N),
++ PINMUX_IPSR_GPSR(IP0_11_8, A2),
++
++ PINMUX_IPSR_GPSR(IP0_15_12, DU_DR5),
++ PINMUX_IPSR_GPSR(IP0_15_12, HTX0),
++ PINMUX_IPSR_GPSR(IP0_15_12, A3),
++
++ PINMUX_IPSR_GPSR(IP0_19_16, DU_DR6),
++ PINMUX_IPSR_GPSR(IP0_19_16, MSIOF3_RXD),
++ PINMUX_IPSR_GPSR(IP0_19_16, A4),
++
++ PINMUX_IPSR_GPSR(IP0_23_20, DU_DR7),
++ PINMUX_IPSR_GPSR(IP0_23_20, MSIOF3_TXD),
++ PINMUX_IPSR_GPSR(IP0_23_20, A5),
++
++ PINMUX_IPSR_GPSR(IP0_27_24, DU_DG2),
++ PINMUX_IPSR_GPSR(IP0_27_24, MSIOF3_SS1),
++ PINMUX_IPSR_GPSR(IP0_27_24, A6),
++
++ PINMUX_IPSR_GPSR(IP0_31_28, DU_DG3),
++ PINMUX_IPSR_GPSR(IP0_31_28, MSIOF3_SS2),
++ PINMUX_IPSR_GPSR(IP0_31_28, A7),
++ PINMUX_IPSR_GPSR(IP0_31_28, PWMFSW0),
++
++ /* IPSR1 */
++ PINMUX_IPSR_GPSR(IP1_3_0, DU_DG4),
++ PINMUX_IPSR_GPSR(IP1_3_0, A8),
++ PINMUX_IPSR_MSEL(IP1_3_0, FSO_CFE_0_N_A, SEL_RFSO_0),
++
++ PINMUX_IPSR_GPSR(IP1_7_4, DU_DG5),
++ PINMUX_IPSR_GPSR(IP1_7_4, A9),
++ PINMUX_IPSR_MSEL(IP1_7_4, FSO_CFE_1_N_A, SEL_RFSO_0),
++
++ PINMUX_IPSR_GPSR(IP1_11_8, DU_DG6),
++ PINMUX_IPSR_GPSR(IP1_11_8, A10),
++ PINMUX_IPSR_MSEL(IP1_11_8, FSO_TOE_N_A, SEL_RFSO_0),
++
++ PINMUX_IPSR_GPSR(IP1_15_12, DU_DG7),
++ PINMUX_IPSR_GPSR(IP1_15_12, A11),
++ PINMUX_IPSR_GPSR(IP1_15_12, IRQ1),
++
++ PINMUX_IPSR_GPSR(IP1_19_16, DU_DB2),
++ PINMUX_IPSR_GPSR(IP1_19_16, A12),
++ PINMUX_IPSR_GPSR(IP1_19_16, IRQ2),
++
++ PINMUX_IPSR_GPSR(IP1_23_20, DU_DB3),
++ PINMUX_IPSR_GPSR(IP1_23_20, A13),
++ PINMUX_IPSR_GPSR(IP1_23_20, FXR_CLKOUT1),
++
++ PINMUX_IPSR_GPSR(IP1_27_24, DU_DB4),
++ PINMUX_IPSR_GPSR(IP1_27_24, A14),
++ PINMUX_IPSR_GPSR(IP1_27_24, FXR_CLKOUT2),
++
++ PINMUX_IPSR_GPSR(IP1_31_28, DU_DB5),
++ PINMUX_IPSR_GPSR(IP1_31_28, A15),
++ PINMUX_IPSR_GPSR(IP1_31_28, FXR_TXENA_N),
++
++ /* IPSR2 */
++ PINMUX_IPSR_GPSR(IP2_3_0, DU_DB6),
++ PINMUX_IPSR_GPSR(IP2_3_0, A16),
++ PINMUX_IPSR_GPSR(IP2_3_0, FXR_TXENB_N),
++
++ PINMUX_IPSR_GPSR(IP2_7_4, DU_DB7),
++ PINMUX_IPSR_GPSR(IP2_7_4, A17),
++ PINMUX_IPSR_GPSR(IP2_7_4, STPWT_EXTFXR),
++
++ PINMUX_IPSR_GPSR(IP2_11_8, DU_DOTCLKOUT),
++ PINMUX_IPSR_MSEL(IP2_11_8, SCIF_CLK_A, SEL_HSCIF0_0),
++ PINMUX_IPSR_GPSR(IP2_11_8, A18),
++
++ PINMUX_IPSR_GPSR(IP2_15_12, DU_EXHSYNC_DU_HSYNC),
++ PINMUX_IPSR_GPSR(IP2_15_12, HRX0),
++ PINMUX_IPSR_GPSR(IP2_15_12, A19),
++ PINMUX_IPSR_GPSR(IP2_15_12, IRQ3),
++
++ PINMUX_IPSR_GPSR(IP2_19_16, DU_EXVSYNC_DU_VSYNC),
++ PINMUX_IPSR_GPSR(IP2_19_16, MSIOF3_SCK),
++ PINMUX_IPSR_GPSR(IP2_19_16, A20),
++
++ PINMUX_IPSR_GPSR(IP2_23_20, DU_EXODDF_DU_ODDF_DISP_CDE),
++ PINMUX_IPSR_GPSR(IP2_23_20, MSIOF3_SYNC),
++ PINMUX_IPSR_GPSR(IP2_23_20, A21),
++
++ PINMUX_IPSR_GPSR(IP2_27_24, IRQ0),
++ PINMUX_IPSR_GPSR(IP2_27_24, CC5_OSCOUT),
++
++ PINMUX_IPSR_GPSR(IP2_31_28, VI0_CLK),
++ PINMUX_IPSR_GPSR(IP2_31_28, MSIOF2_SCK),
++ PINMUX_IPSR_GPSR(IP2_31_28, SCK3),
++ PINMUX_IPSR_GPSR(IP2_31_28, HSCK3),
++
++ /* IPSR3 */
++ PINMUX_IPSR_GPSR(IP3_3_0, VI0_CLKENB),
++ PINMUX_IPSR_GPSR(IP3_3_0, MSIOF2_RXD),
++ PINMUX_IPSR_GPSR(IP3_3_0, RX3),
++ PINMUX_IPSR_GPSR(IP3_3_0, RD_WR_N),
++ PINMUX_IPSR_GPSR(IP3_3_0, HCTS3_N),
++
++ PINMUX_IPSR_GPSR(IP3_7_4, VI0_HSYNC_N),
++ PINMUX_IPSR_GPSR(IP3_7_4, MSIOF2_TXD),
++ PINMUX_IPSR_GPSR(IP3_7_4, TX3),
++ PINMUX_IPSR_GPSR(IP3_7_4, HRTS3_N),
++
++ PINMUX_IPSR_GPSR(IP3_11_8, VI0_VSYNC_N),
++ PINMUX_IPSR_GPSR(IP3_11_8, MSIOF2_SYNC),
++ PINMUX_IPSR_GPSR(IP3_11_8, CTS3_N),
++ PINMUX_IPSR_GPSR(IP3_11_8, HTX3),
++
++ PINMUX_IPSR_GPSR(IP3_15_12, VI0_DATA0),
++ PINMUX_IPSR_GPSR(IP3_15_12, MSIOF2_SS1),
++ PINMUX_IPSR_GPSR(IP3_15_12, RTS3_N_TANS),
++ PINMUX_IPSR_GPSR(IP3_15_12, HRX3),
++
++ PINMUX_IPSR_GPSR(IP3_19_16, VI0_DATA1),
++ PINMUX_IPSR_GPSR(IP3_19_16, MSIOF2_SS2),
++ PINMUX_IPSR_GPSR(IP3_19_16, SCK1),
++ PINMUX_IPSR_MSEL(IP3_19_16, SPEEDIN_A, SEL_RSP_1),
++
++ PINMUX_IPSR_GPSR(IP3_23_20, VI0_DATA2),
++ PINMUX_IPSR_GPSR(IP3_23_20, AVB0_AVTP_PPS),
++ PINMUX_IPSR_GPSR(IP3_23_20, SDA3_A),
++
++ PINMUX_IPSR_GPSR(IP3_27_24, VI0_DATA3),
++ PINMUX_IPSR_GPSR(IP3_27_24, HSCK1),
++ PINMUX_IPSR_GPSR(IP3_27_24, SCL3_A),
++
++ PINMUX_IPSR_GPSR(IP3_31_28, VI0_DATA4),
++ PINMUX_IPSR_GPSR(IP3_31_28, HRTS1_N),
++ PINMUX_IPSR_MSEL(IP3_31_28, RX1_A, SEL_SCIF1_0),
++
++ /* IPSR4 */
++ PINMUX_IPSR_GPSR(IP4_3_0, VI0_DATA5),
++ PINMUX_IPSR_GPSR(IP4_3_0, HCTS1_N),
++ PINMUX_IPSR_MSEL(IP4_3_0, TX1_A, SEL_SCIF1_0),
++
++ PINMUX_IPSR_GPSR(IP4_7_4, VI0_DATA6),
++ PINMUX_IPSR_GPSR(IP4_7_4, HTX1),
++ PINMUX_IPSR_GPSR(IP4_7_4, CTS1_N),
++
++ PINMUX_IPSR_GPSR(IP4_11_8, VI0_DATA7),
++ PINMUX_IPSR_GPSR(IP4_11_8, HRX1),
++ PINMUX_IPSR_GPSR(IP4_11_8, RTS1_N_TANS),
++
++ PINMUX_IPSR_GPSR(IP4_15_12, VI0_DATA8),
++ PINMUX_IPSR_GPSR(IP4_15_12, HSCK2),
++ PINMUX_IPSR_MSEL(IP4_15_12, PWM0_A, SEL_PWM0_0),
++ PINMUX_IPSR_GPSR(IP4_15_12, A22),
++
++ PINMUX_IPSR_GPSR(IP4_19_16, VI0_DATA9),
++ PINMUX_IPSR_GPSR(IP4_19_16, HCTS2_N),
++ PINMUX_IPSR_MSEL(IP4_19_16, PWM1_A, SEL_PWM1_0),
++ PINMUX_IPSR_GPSR(IP4_19_16, A23),
++ PINMUX_IPSR_MSEL(IP4_19_16, FSO_CFE_0_N_B, SEL_RFSO_1),
++
++ PINMUX_IPSR_GPSR(IP4_23_20, VI0_DATA10),
++ PINMUX_IPSR_GPSR(IP4_23_20, HRTS2_N),
++ PINMUX_IPSR_MSEL(IP4_23_20, PWM2_A, SEL_PWM2_0),
++ PINMUX_IPSR_GPSR(IP4_23_20, A24),
++ PINMUX_IPSR_MSEL(IP4_23_20, FSO_CFE_1_N_B, SEL_RFSO_1),
++
++ PINMUX_IPSR_GPSR(IP4_27_24, VI0_DATA11),
++ PINMUX_IPSR_GPSR(IP4_27_24, HTX2),
++ PINMUX_IPSR_MSEL(IP4_27_24, PWM3_A, SEL_PWM3_0),
++ PINMUX_IPSR_GPSR(IP4_27_24, A25),
++ PINMUX_IPSR_MSEL(IP4_27_24, FSO_TOE_N_B, SEL_RFSO_1),
++
++ PINMUX_IPSR_GPSR(IP4_31_28, VI0_FIELD),
++ PINMUX_IPSR_GPSR(IP4_31_28, HRX2),
++ PINMUX_IPSR_MSEL(IP4_31_28, PWM4_A, SEL_PWM4_0),
++ PINMUX_IPSR_GPSR(IP4_31_28, CS1_N_A26),
++ PINMUX_IPSR_GPSR(IP4_31_28, FSCLKST2_N_A),
++
++ /* IPSR5 */
++ PINMUX_IPSR_GPSR(IP5_3_0, VI1_CLK),
++ PINMUX_IPSR_GPSR(IP5_3_0, MSIOF1_RXD),
++ PINMUX_IPSR_GPSR(IP5_3_0, CS0_N),
++
++ PINMUX_IPSR_GPSR(IP5_7_4, VI1_CLKENB),
++ PINMUX_IPSR_GPSR(IP5_7_4, MSIOF1_TXD),
++ PINMUX_IPSR_GPSR(IP5_7_4, D0),
++
++ PINMUX_IPSR_GPSR(IP5_11_8, VI1_HSYNC_N),
++ PINMUX_IPSR_GPSR(IP5_11_8, MSIOF1_SCK),
++ PINMUX_IPSR_GPSR(IP5_11_8, D1),
++
++ PINMUX_IPSR_GPSR(IP5_15_12, VI1_VSYNC_N),
++ PINMUX_IPSR_GPSR(IP5_15_12, MSIOF1_SYNC),
++ PINMUX_IPSR_GPSR(IP5_15_12, D2),
++
++ PINMUX_IPSR_GPSR(IP5_19_16, VI1_DATA0),
++ PINMUX_IPSR_GPSR(IP5_19_16, MSIOF1_SS1),
++ PINMUX_IPSR_GPSR(IP5_19_16, D3),
++
++ PINMUX_IPSR_GPSR(IP5_23_20, VI1_DATA1),
++ PINMUX_IPSR_GPSR(IP5_23_20, MSIOF1_SS2),
++ PINMUX_IPSR_GPSR(IP5_23_20, D4),
++ PINMUX_IPSR_GPSR(IP5_23_20, MMC_CMD),
++
++ PINMUX_IPSR_GPSR(IP5_27_24, VI1_DATA2),
++ PINMUX_IPSR_MSEL(IP5_27_24, CANFD0_TX_B, SEL_CANFD0_1),
++ PINMUX_IPSR_GPSR(IP5_27_24, D5),
++ PINMUX_IPSR_GPSR(IP5_27_24, MMC_D0),
++
++ PINMUX_IPSR_GPSR(IP5_31_28, VI1_DATA3),
++ PINMUX_IPSR_MSEL(IP5_31_28, CANFD0_RX_B, SEL_CANFD0_1),
++ PINMUX_IPSR_GPSR(IP5_31_28, D6),
++ PINMUX_IPSR_GPSR(IP5_31_28, MMC_D1),
++
++ /* IPSR6 */
++ PINMUX_IPSR_GPSR(IP6_3_0, VI1_DATA4),
++ PINMUX_IPSR_MSEL(IP6_3_0, CANFD_CLK_B, SEL_CANFD0_1),
++ PINMUX_IPSR_GPSR(IP6_3_0, D7),
++ PINMUX_IPSR_GPSR(IP6_3_0, MMC_D2),
++
++ PINMUX_IPSR_GPSR(IP6_7_4, VI1_DATA5),
++ PINMUX_IPSR_GPSR(IP6_7_4, SCK4),
++ PINMUX_IPSR_GPSR(IP6_7_4, D8),
++ PINMUX_IPSR_GPSR(IP6_7_4, MMC_D3),
++
++ PINMUX_IPSR_GPSR(IP6_11_8, VI1_DATA6),
++ PINMUX_IPSR_GPSR(IP6_11_8, RX4),
++ PINMUX_IPSR_GPSR(IP6_11_8, D9),
++ PINMUX_IPSR_GPSR(IP6_11_8, MMC_CLK),
++
++ PINMUX_IPSR_GPSR(IP6_15_12, VI1_DATA7),
++ PINMUX_IPSR_GPSR(IP6_15_12, TX4),
++ PINMUX_IPSR_GPSR(IP6_15_12, D10),
++ PINMUX_IPSR_GPSR(IP6_15_12, MMC_D4),
++
++ PINMUX_IPSR_GPSR(IP6_19_16, VI1_DATA8),
++ PINMUX_IPSR_GPSR(IP6_19_16, CTS4_N),
++ PINMUX_IPSR_GPSR(IP6_19_16, D11),
++ PINMUX_IPSR_GPSR(IP6_19_16, MMC_D5),
++
++ PINMUX_IPSR_GPSR(IP6_23_20, VI1_DATA9),
++ PINMUX_IPSR_GPSR(IP6_23_20, RTS4_N_TANS),
++ PINMUX_IPSR_GPSR(IP6_23_20, D12),
++ PINMUX_IPSR_GPSR(IP6_23_20, MMC_D6),
++ PINMUX_IPSR_GPSR(IP6_23_20, SCL3_B),
++
++ PINMUX_IPSR_GPSR(IP6_27_24, VI1_DATA10),
++ PINMUX_IPSR_GPSR(IP6_27_24, D13),
++ PINMUX_IPSR_GPSR(IP6_27_24, MMC_D7),
++ PINMUX_IPSR_GPSR(IP6_27_24, SDA3_B),
++
++ PINMUX_IPSR_GPSR(IP6_31_28, VI1_DATA11),
++ PINMUX_IPSR_GPSR(IP6_31_28, SCL4),
++ PINMUX_IPSR_GPSR(IP6_31_28, IRQ4),
++ PINMUX_IPSR_GPSR(IP6_31_28, D14),
++ PINMUX_IPSR_GPSR(IP6_31_28, MMC_WP),
++
++ /* IPSR7 */
++ PINMUX_IPSR_GPSR(IP7_3_0, VI1_FIELD),
++ PINMUX_IPSR_GPSR(IP7_3_0, SDA4),
++ PINMUX_IPSR_GPSR(IP7_3_0, IRQ5),
++ PINMUX_IPSR_GPSR(IP7_3_0, D15),
++ PINMUX_IPSR_GPSR(IP7_3_0, MMC_CD),
++
++ PINMUX_IPSR_GPSR(IP7_7_4, SCL0),
++ PINMUX_IPSR_GPSR(IP7_7_4, DU_DR0),
++ PINMUX_IPSR_GPSR(IP7_7_4, TPU0TO0),
++ PINMUX_IPSR_GPSR(IP7_7_4, CLKOUT),
++ PINMUX_IPSR_GPSR(IP7_7_4, MSIOF0_RXD),
++
++ PINMUX_IPSR_GPSR(IP7_11_8, SDA0),
++ PINMUX_IPSR_GPSR(IP7_11_8, DU_DR1),
++ PINMUX_IPSR_GPSR(IP7_11_8, TPU0TO1),
++ PINMUX_IPSR_GPSR(IP7_11_8, BS_N),
++ PINMUX_IPSR_GPSR(IP7_11_8, SCK0),
++ PINMUX_IPSR_GPSR(IP7_11_8, MSIOF0_TXD),
++
++ PINMUX_IPSR_GPSR(IP7_15_12, SCL1),
++ PINMUX_IPSR_GPSR(IP7_15_12, DU_DG0),
++ PINMUX_IPSR_GPSR(IP7_15_12, TPU0TO2),
++ PINMUX_IPSR_GPSR(IP7_15_12, RD_N),
++ PINMUX_IPSR_GPSR(IP7_15_12, CTS0_N),
++ PINMUX_IPSR_GPSR(IP7_15_12, MSIOF0_SCK),
++
++ PINMUX_IPSR_GPSR(IP7_19_16, SDA1),
++ PINMUX_IPSR_GPSR(IP7_19_16, DU_DG1),
++ PINMUX_IPSR_GPSR(IP7_19_16, TPU0TO3),
++ PINMUX_IPSR_GPSR(IP7_19_16, WE0_N),
++ PINMUX_IPSR_GPSR(IP7_19_16, RTS0_N_TANS),
++ PINMUX_IPSR_GPSR(IP7_19_16, MSIOF0_SYNC),
++
++ PINMUX_IPSR_GPSR(IP7_23_20, SCL2),
++ PINMUX_IPSR_GPSR(IP7_23_20, DU_DB0),
++ PINMUX_IPSR_MSEL(IP7_23_20, TCLK1_A, SEL_TMU_0),
++ PINMUX_IPSR_GPSR(IP7_23_20, WE1_N),
++ PINMUX_IPSR_GPSR(IP7_23_20, RX0),
++ PINMUX_IPSR_GPSR(IP7_23_20, MSIOF0_SS1),
++
++ PINMUX_IPSR_GPSR(IP7_27_24, SDA2),
++ PINMUX_IPSR_GPSR(IP7_27_24, DU_DB1),
++ PINMUX_IPSR_MSEL(IP7_27_24, TCLK2_A, SEL_TMU_0),
++ PINMUX_IPSR_GPSR(IP7_27_24, EX_WAIT0),
++ PINMUX_IPSR_GPSR(IP7_27_24, TX0),
++ PINMUX_IPSR_GPSR(IP7_27_24, MSIOF0_SS2),
++
++ PINMUX_IPSR_GPSR(IP7_31_28, AVB0_AVTP_CAPTURE),
++ PINMUX_IPSR_GPSR(IP7_31_28, FSCLKST2_N_B),
++
++ /* IPSR8 */
++ PINMUX_IPSR_MSEL(IP8_3_0, CANFD0_TX_A, SEL_CANFD0_0),
++ PINMUX_IPSR_GPSR(IP8_3_0, FXR_TXDA),
++ PINMUX_IPSR_MSEL(IP8_3_0, PWM0_B, SEL_PWM0_1),
++ PINMUX_IPSR_GPSR(IP8_3_0, DU_DISP),
++ PINMUX_IPSR_GPSR(IP8_3_0, FSCLKST2_N_C),
++
++ PINMUX_IPSR_MSEL(IP8_7_4, CANFD0_RX_A, SEL_CANFD0_0),
++ PINMUX_IPSR_GPSR(IP8_7_4, RXDA_EXTFXR),
++ PINMUX_IPSR_MSEL(IP8_7_4, PWM1_B, SEL_PWM1_1),
++ PINMUX_IPSR_GPSR(IP8_7_4, DU_CDE),
++
++ PINMUX_IPSR_GPSR(IP8_11_8, CANFD1_TX),
++ PINMUX_IPSR_GPSR(IP8_11_8, FXR_TXDB),
++ PINMUX_IPSR_MSEL(IP8_11_8, PWM2_B, SEL_PWM2_1),
++ PINMUX_IPSR_MSEL(IP8_11_8, TCLK1_B, SEL_TMU_1),
++ PINMUX_IPSR_MSEL(IP8_11_8, TX1_B, SEL_SCIF1_1),
++
++ PINMUX_IPSR_GPSR(IP8_15_12, CANFD1_RX),
++ PINMUX_IPSR_GPSR(IP8_15_12, RXDB_EXTFXR),
++ PINMUX_IPSR_MSEL(IP8_15_12, PWM3_B, SEL_PWM3_1),
++ PINMUX_IPSR_MSEL(IP8_15_12, TCLK2_B, SEL_TMU_1),
++ PINMUX_IPSR_MSEL(IP8_15_12, RX1_B, SEL_SCIF1_1),
++
++ PINMUX_IPSR_MSEL(IP8_19_16, CANFD_CLK_A, SEL_CANFD0_0),
++ PINMUX_IPSR_GPSR(IP8_19_16, CLK_EXTFXR),
++ PINMUX_IPSR_MSEL(IP8_19_16, PWM4_B, SEL_PWM4_1),
++ PINMUX_IPSR_MSEL(IP8_19_16, SPEEDIN_B, SEL_RSP_0),
++ PINMUX_IPSR_MSEL(IP8_19_16, SCIF_CLK_B, SEL_HSCIF0_1),
++
++ PINMUX_IPSR_GPSR(IP8_23_20, DIGRF_CLKIN),
++ PINMUX_IPSR_GPSR(IP8_23_20, DIGRF_CLKEN_IN),
++
++ PINMUX_IPSR_GPSR(IP8_27_24, DIGRF_CLKOUT),
++ PINMUX_IPSR_GPSR(IP8_27_24, DIGRF_CLKEN_OUT),
++};
++
++static const struct sh_pfc_pin pinmux_pins[] = {
++ PINMUX_GPIO_GP_ALL(),
++};
++
++/* - EtherAVB --------------------------------------------------------------- */
++static const unsigned int avb0_rx_ctrl_pins[] = {
++ /* AVB0_RX_CTL */
++ RCAR_GP_PIN(1, 1),
++};
++static const unsigned int avb0_rx_ctrl_mux[] = {
++ AVB0_RX_CTL_MARK,
++};
++static const unsigned int avb0_rxc_pins[] = {
++ /* AVB0_RXC */
++ RCAR_GP_PIN(1, 2),
++};
++static const unsigned int avb0_rxc_mux[] = {
++ AVB0_RXC_MARK,
++};
++static const unsigned int avb0_rd0_pins[] = {
++ /* AVB0_RD[0] */
++ RCAR_GP_PIN(1, 3),
++};
++static const unsigned int avb0_rd0_mux[] = {
++ AVB0_RD0_MARK,
++};
++static const unsigned int avb0_rd1_pins[] = {
++ /* AVB0_RD[1] */
++ RCAR_GP_PIN(1, 4),
++};
++static const unsigned int avb0_rd1_mux[] = {
++ AVB0_RD1_MARK,
++};
++static const unsigned int avb0_rd2_pins[] = {
++ /* AVB0_RD[2] */
++ RCAR_GP_PIN(1, 5),
++};
++static const unsigned int avb0_rd2_mux[] = {
++ AVB0_RD2_MARK,
++};
++static const unsigned int avb0_rd3_pins[] = {
++ /* AVB0_RD[3] */
++ RCAR_GP_PIN(1, 6),
++};
++static const unsigned int avb0_rd3_mux[] = {
++ AVB0_RD3_MARK,
++};
++static const unsigned int avb0_rd4_pins[] = {
++ /* AVB0_RD[3:0] */
++ RCAR_GP_PIN(1, 3), RCAR_GP_PIN(1, 4),
++ RCAR_GP_PIN(1, 5), RCAR_GP_PIN(1, 6),
++};
++static const unsigned int avb0_rd4_mux[] = {
++ AVB0_RD0_MARK, AVB0_RD1_MARK,
++ AVB0_RD2_MARK, AVB0_RD3_MARK,
++};
++static const unsigned int avb0_tx_ctrl_pins[] = {
++ /* AVB0_TX_CTL */
++ RCAR_GP_PIN(1, 7),
++};
++static const unsigned int avb0_tx_ctrl_mux[] = {
++ AVB0_TX_CTL_MARK,
++};
++static const unsigned int avb0_txc_pins[] = {
++ /* AVB0_TXC */
++ RCAR_GP_PIN(1, 8),
++};
++static const unsigned int avb0_txc_mux[] = {
++ AVB0_TXC_MARK,
++};
++static const unsigned int avb0_td0_pins[] = {
++ /* AVB0_TD[0] */
++ RCAR_GP_PIN(1, 9),
++};
++static const unsigned int avb0_td0_mux[] = {
++ AVB0_TD0_MARK,
++};
++static const unsigned int avb0_td1_pins[] = {
++ /* AVB0_TD[1] */
++ RCAR_GP_PIN(1, 10),
++};
++static const unsigned int avb0_td1_mux[] = {
++ AVB0_TD1_MARK,
++};
++static const unsigned int avb0_td2_pins[] = {
++ /* AVB0_TD[2] */
++ RCAR_GP_PIN(1, 11),
++};
++static const unsigned int avb0_td2_mux[] = {
++ AVB0_TD2_MARK,
++};
++static const unsigned int avb0_td3_pins[] = {
++ /* AVB0_TD[3] */
++ RCAR_GP_PIN(1, 12),
++};
++static const unsigned int avb0_td3_mux[] = {
++ AVB0_TD3_MARK,
++};
++static const unsigned int avb0_td4_pins[] = {
++ /* AVB0_TD[3:0] */
++ RCAR_GP_PIN(1, 9), RCAR_GP_PIN(1, 10),
++ RCAR_GP_PIN(1, 11), RCAR_GP_PIN(1, 12),
++};
++static const unsigned int avb0_td4_mux[] = {
++ AVB0_TD0_MARK, AVB0_TD1_MARK,
++ AVB0_TD2_MARK, AVB0_TD3_MARK,
++};
++static const unsigned int avb0_txcrefclk_pins[] = {
++ /* AVB0_TXCREFCLK */
++ RCAR_GP_PIN(1, 13),
++};
++static const unsigned int avb0_txcrefclk_mux[] = {
++ AVB0_TXCREFCLK_MARK,
++};
++static const unsigned int avb0_mdio_pins[] = {
++ /* AVB0_MDIO */
++ RCAR_GP_PIN(1, 14),
++};
++static const unsigned int avb0_mdio_mux[] = {
++ AVB0_MDIO_MARK,
++};
++static const unsigned int avb0_mdc_pins[] = {
++ /* AVB0_MDC */
++ RCAR_GP_PIN(1, 15),
++};
++static const unsigned int avb0_mdc_mux[] = {
++ AVB0_MDC_MARK,
++};
++static const unsigned int avb0_magic_pins[] = {
++ /* AVB0_MAGIC */
++ RCAR_GP_PIN(1, 16),
++};
++static const unsigned int avb0_magic_mux[] = {
++ AVB0_MAGIC_MARK,
++};
++static const unsigned int avb0_phy_int_pins[] = {
++ /* AVB0_PHY_INT */
++ RCAR_GP_PIN(1, 17),
++};
++static const unsigned int avb0_phy_int_mux[] = {
++ AVB0_PHY_INT_MARK,
++};
++static const unsigned int avb0_link_pins[] = {
++ /* AVB0_LINK */
++ RCAR_GP_PIN(1, 18),
++};
++static const unsigned int avb0_link_mux[] = {
++ AVB0_LINK_MARK,
++};
++static const unsigned int avb0_avtp_match_pins[] = {
++ /* AVB0_AVTP_MATCH */
++ RCAR_GP_PIN(1, 19),
++};
++static const unsigned int avb0_avtp_match_mux[] = {
++ AVB0_AVTP_MATCH_MARK,
++};
++static const unsigned int avb0_avtp_pps_pins[] = {
++ /* AVB0_AVTP_PPS */
++ RCAR_GP_PIN(2, 6),
++};
++static const unsigned int avb0_avtp_pps_mux[] = {
++ AVB0_AVTP_PPS_MARK,
++};
++static const unsigned int avb0_avtp_capture_pins[] = {
++ /* AVB0_AVTP_CAPTURE */
++ RCAR_GP_PIN(1, 20),
++};
++static const unsigned int avb0_avtp_capture_mux[] = {
++ AVB0_AVTP_CAPTURE_MARK,
++};
++
++/* - CANFD0 ----------------------------------------------------------------- */
++static const unsigned int canfd0_data_a_pins[] = {
++ /* TX, RX */
++ RCAR_GP_PIN(1, 21), RCAR_GP_PIN(1, 22),
++};
++static const unsigned int canfd0_data_a_mux[] = {
++ CANFD0_TX_A_MARK, CANFD0_RX_A_MARK,
++};
++static const unsigned int canfd_clk_a_pins[] = {
++ /* CLK */
++ RCAR_GP_PIN(1, 25),
++};
++static const unsigned int canfd_clk_a_mux[] = {
++ CANFD_CLK_A_MARK,
++};
++static const unsigned int canfd0_data_b_pins[] = {
++ /* TX, RX */
++ RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7),
++};
++static const unsigned int canfd0_data_b_mux[] = {
++ CANFD0_TX_B_MARK, CANFD0_RX_B_MARK,
++};
++static const unsigned int canfd_clk_b_pins[] = {
++ /* CLK */
++ RCAR_GP_PIN(3, 8),
++};
++static const unsigned int canfd_clk_b_mux[] = {
++ CANFD_CLK_B_MARK,
++};
++
++/* - CANFD1 ----------------------------------------------------------------- */
++static const unsigned int canfd1_data_pins[] = {
++ /* TX, RX */
++ RCAR_GP_PIN(1, 23), RCAR_GP_PIN(1, 24),
++};
++static const unsigned int canfd1_data_mux[] = {
++ CANFD1_TX_MARK, CANFD1_RX_MARK,
++};
++
++/* - DU --------------------------------------------------------------------- */
++static const unsigned int du_rgb666_pins[] = {
++ /* R[7:0] */
++ RCAR_GP_PIN(0, 5), RCAR_GP_PIN(0, 4), RCAR_GP_PIN(0, 3),
++ RCAR_GP_PIN(0, 2), RCAR_GP_PIN(0, 1), RCAR_GP_PIN(0, 0),
++ /* G[7:0] */
++ RCAR_GP_PIN(0, 11), RCAR_GP_PIN(0, 10), RCAR_GP_PIN(0, 9),
++ RCAR_GP_PIN(0, 8), RCAR_GP_PIN(0, 7), RCAR_GP_PIN(0, 6),
++ /* B[7:0] */
++ RCAR_GP_PIN(0, 17), RCAR_GP_PIN(0, 16), RCAR_GP_PIN(0, 15),
++ RCAR_GP_PIN(0, 14), RCAR_GP_PIN(0, 13), RCAR_GP_PIN(0, 12),
++};
++static const unsigned int du_rgb666_mux[] = {
++ DU_DR7_MARK, DU_DR6_MARK, DU_DR5_MARK, DU_DR4_MARK,
++ DU_DR3_MARK, DU_DR2_MARK,
++ DU_DG7_MARK, DU_DG6_MARK, DU_DG5_MARK, DU_DG4_MARK,
++ DU_DG3_MARK, DU_DG2_MARK,
++ DU_DB7_MARK, DU_DB6_MARK, DU_DB5_MARK, DU_DB4_MARK,
++ DU_DB3_MARK, DU_DB2_MARK,
++};
++static const unsigned int du_clk_out_0_pins[] = {
++ /* CLKOUT0 */
++ RCAR_GP_PIN(0, 18),
++};
++static const unsigned int du_clk_out_0_mux[] = {
++ DU_DOTCLKOUT_MARK,
++};
++static const unsigned int du_clk_out_1_pins[] = {
++ /* CLKOUT1 */
++ RCAR_GP_PIN(0, 18), /* @@ */
++};
++static const unsigned int du_clk_out_1_mux[] = {
++ DU_DOTCLKOUT_MARK,
++};
++static const unsigned int du_sync_pins[] = {
++ /* EXVSYNC/VSYNC, EXHSYNC/HSYNC */
++ RCAR_GP_PIN(0, 20), RCAR_GP_PIN(0, 19),
++};
++static const unsigned int du_sync_mux[] = {
++ DU_EXVSYNC_DU_VSYNC_MARK, DU_EXHSYNC_DU_HSYNC_MARK
++};
++static const unsigned int du_oddf_pins[] = {
++ /* EXDISP/EXODDF/EXCDE */
++ RCAR_GP_PIN(0, 21),
++};
++static const unsigned int du_oddf_mux[] = {
++ DU_EXODDF_DU_ODDF_DISP_CDE_MARK,
++};
++static const unsigned int du_cde_pins[] = {
++ /* CDE */
++ RCAR_GP_PIN(1, 22),
++};
++static const unsigned int du_cde_mux[] = {
++ DU_CDE_MARK,
++};
++static const unsigned int du_disp_pins[] = {
++ /* DISP */
++ RCAR_GP_PIN(1, 21),
++};
++static const unsigned int du_disp_mux[] = {
++ DU_DISP_MARK,
++};
++
++/* - HSCIF0 ----------------------------------------------------------------- */
++static const unsigned int hscif0_data_pins[] = {
++ /* HRX0, HTX0 */
++ RCAR_GP_PIN(0, 19), RCAR_GP_PIN(0, 3),
++};
++static const unsigned int hscif0_data_mux[] = {
++ HRX0_MARK, HTX0_MARK,
++};
++static const unsigned int hscif0_clk_pins[] = {
++ /* HSCK0 */
++ RCAR_GP_PIN(0, 0),
++};
++static const unsigned int hscif0_clk_mux[] = {
++ HSCK0_MARK,
++};
++static const unsigned int hscif0_ctrl_pins[] = {
++ /* HRTS0#, HCTS0# */
++ RCAR_GP_PIN(0, 1), RCAR_GP_PIN(0, 2),
++};
++static const unsigned int hscif0_ctrl_mux[] = {
++ HRTS0_N_MARK, HCTS0_N_MARK,
++};
++
++/* - HSCIF1 ----------------------------------------------------------------- */
++static const unsigned int hscif1_data_pins[] = {
++ /* HRX1, HTX1 */
++ RCAR_GP_PIN(2, 11), RCAR_GP_PIN(2, 10),
++};
++static const unsigned int hscif1_data_mux[] = {
++ HRX1_MARK, HTX1_MARK,
++};
++static const unsigned int hscif1_clk_pins[] = {
++ /* HSCK1 */
++ RCAR_GP_PIN(2, 7),
++};
++static const unsigned int hscif1_clk_mux[] = {
++ HSCK1_MARK,
++};
++static const unsigned int hscif1_ctrl_pins[] = {
++ /* HRTS1#, HCTS1# */
++ RCAR_GP_PIN(2, 8), RCAR_GP_PIN(2, 9),
++};
++static const unsigned int hscif1_ctrl_mux[] = {
++ HRTS1_N_MARK, HCTS1_N_MARK,
++};
++
++/* - HSCIF2 ----------------------------------------------------------------- */
++static const unsigned int hscif2_data_pins[] = {
++ /* HRX2, HTX2 */
++ RCAR_GP_PIN(2, 16), RCAR_GP_PIN(2, 15),
++};
++static const unsigned int hscif2_data_mux[] = {
++ HRX2_MARK, HTX2_MARK,
++};
++static const unsigned int hscif2_clk_pins[] = {
++ /* HSCK2 */
++ RCAR_GP_PIN(2, 12),
++};
++static const unsigned int hscif2_clk_mux[] = {
++ HSCK2_MARK,
++};
++static const unsigned int hscif2_ctrl_pins[] = {
++ /* HRTS2#, HCTS2# */
++ RCAR_GP_PIN(2, 14), RCAR_GP_PIN(2, 13),
++};
++static const unsigned int hscif2_ctrl_mux[] = {
++ HRTS2_N_MARK, HCTS2_N_MARK,
++};
++
++/* - HSCIF3 ----------------------------------------------------------------- */
++static const unsigned int hscif3_data_pins[] = {
++ /* HRX3, HTX3 */
++ RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 3),
++};
++static const unsigned int hscif3_data_mux[] = {
++ HRX3_MARK, HTX3_MARK,
++};
++static const unsigned int hscif3_clk_pins[] = {
++ /* HSCK3 */
++ RCAR_GP_PIN(2, 0),
++};
++static const unsigned int hscif3_clk_mux[] = {
++ HSCK3_MARK,
++};
++static const unsigned int hscif3_ctrl_pins[] = {
++ /* HRTS3#, HCTS3# */
++ RCAR_GP_PIN(2, 2), RCAR_GP_PIN(2, 1),
++};
++static const unsigned int hscif3_ctrl_mux[] = {
++ HRTS3_N_MARK, HCTS3_N_MARK,
++};
++
++/* - SCIF Clock ------------------------------------------------------------- */
++static const unsigned int scif_clk_a_pins[] = {
++ /* SCIF_CLK */
++ RCAR_GP_PIN(0, 18),
++};
++static const unsigned int scif_clk_a_mux[] = {
++ SCIF_CLK_A_MARK,
++};
++static const unsigned int scif_clk_b_pins[] = {
++ /* SCIF_CLK */
++ RCAR_GP_PIN(1, 25),
++};
++static const unsigned int scif_clk_b_mux[] = {
++ SCIF_CLK_B_MARK,
++};
++
++/* - I2C -------------------------------------------------------------------- */
++static const unsigned int i2c0_pins[] = {
++ /* SDA0, SCL0 */
++ RCAR_GP_PIN(4, 1), RCAR_GP_PIN(4, 0),
++};
++static const unsigned int i2c0_mux[] = {
++ SDA0_MARK, SCL0_MARK,
++};
++static const unsigned int i2c1_pins[] = {
++ /* SDA1, SCL1 */
++ RCAR_GP_PIN(4, 3), RCAR_GP_PIN(4, 2),
++};
++static const unsigned int i2c1_mux[] = {
++ SDA1_MARK, SCL1_MARK,
++};
++static const unsigned int i2c2_pins[] = {
++ /* SDA2, SCL2 */
++ RCAR_GP_PIN(4, 5), RCAR_GP_PIN(4, 4),
++};
++static const unsigned int i2c2_mux[] = {
++ SDA2_MARK, SCL2_MARK,
++};
++static const unsigned int i2c3_pins[] = {
++ /* SDA3_A, SCL3_A */
++ RCAR_GP_PIN(2, 6), RCAR_GP_PIN(2, 5),
++};
++static const unsigned int i2c3_mux[] = {
++ SDA3_A_MARK, SCL3_A_MARK,
++};
++static const unsigned int i2c4_pins[] = {
++ /* SDA4, SCL4 */
++ RCAR_GP_PIN(3, 16), RCAR_GP_PIN(3, 15),
++};
++static const unsigned int i2c4_mux[] = {
++ SDA4_MARK, SCL4_MARK,
++};
++
++/* - INTC-EX ---------------------------------------------------------------- */
++static const unsigned int intc_ex_irq0_pins[] = {
++ /* IRQ0 */
++ RCAR_GP_PIN(1, 0),
++};
++static const unsigned int intc_ex_irq0_mux[] = {
++ IRQ0_MARK,
++};
++static const unsigned int intc_ex_irq1_pins[] = {
++ /* IRQ1 */
++ RCAR_GP_PIN(0, 11),
++};
++static const unsigned int intc_ex_irq1_mux[] = {
++ IRQ1_MARK,
++};
++static const unsigned int intc_ex_irq2_pins[] = {
++ /* IRQ2 */
++ RCAR_GP_PIN(0, 12),
++};
++static const unsigned int intc_ex_irq2_mux[] = {
++ IRQ2_MARK,
++};
++static const unsigned int intc_ex_irq3_pins[] = {
++ /* IRQ3 */
++ RCAR_GP_PIN(0, 19),
++};
++static const unsigned int intc_ex_irq3_mux[] = {
++ IRQ3_MARK,
++};
++static const unsigned int intc_ex_irq4_pins[] = {
++ /* IRQ4 */
++ RCAR_GP_PIN(3, 15),
++};
++static const unsigned int intc_ex_irq4_mux[] = {
++ IRQ4_MARK,
++};
++static const unsigned int intc_ex_irq5_pins[] = {
++ /* IRQ5 */
++ RCAR_GP_PIN(3, 16),
++};
++static const unsigned int intc_ex_irq5_mux[] = {
++ IRQ5_MARK,
++};
++
++/* - MSIOF0 ----------------------------------------------------------------- */
++static const unsigned int msiof0_clk_pins[] = {
++ /* SCK */
++ RCAR_GP_PIN(4, 2),
++};
++static const unsigned int msiof0_clk_mux[] = {
++ MSIOF0_SCK_MARK,
++};
++static const unsigned int msiof0_sync_pins[] = {
++ /* SYNC */
++ RCAR_GP_PIN(4, 3),
++};
++static const unsigned int msiof0_sync_mux[] = {
++ MSIOF0_SYNC_MARK,
++};
++static const unsigned int msiof0_ss1_pins[] = {
++ /* SS1 */
++ RCAR_GP_PIN(4, 4),
++};
++static const unsigned int msiof0_ss1_mux[] = {
++ MSIOF0_SS1_MARK,
++};
++static const unsigned int msiof0_ss2_pins[] = {
++ /* SS2 */
++ RCAR_GP_PIN(4, 5),
++};
++static const unsigned int msiof0_ss2_mux[] = {
++ MSIOF0_SS2_MARK,
++};
++static const unsigned int msiof0_txd_pins[] = {
++ /* TXD */
++ RCAR_GP_PIN(4, 1),
++};
++static const unsigned int msiof0_txd_mux[] = {
++ MSIOF0_TXD_MARK,
++};
++static const unsigned int msiof0_rxd_pins[] = {
++ /* RXD */
++ RCAR_GP_PIN(4, 0),
++};
++static const unsigned int msiof0_rxd_mux[] = {
++ MSIOF0_RXD_MARK,
++};
++
++/* - MSIOF1 ----------------------------------------------------------------- */
++static const unsigned int msiof1_clk_pins[] = {
++ /* SCK */
++ RCAR_GP_PIN(3, 2),
++};
++static const unsigned int msiof1_clk_mux[] = {
++ MSIOF1_SCK_MARK,
++};
++static const unsigned int msiof1_sync_pins[] = {
++ /* SYNC */
++ RCAR_GP_PIN(3, 3),
++};
++static const unsigned int msiof1_sync_mux[] = {
++ MSIOF1_SYNC_MARK,
++};
++static const unsigned int msiof1_ss1_pins[] = {
++ /* SS1 */
++ RCAR_GP_PIN(3, 4),
++};
++static const unsigned int msiof1_ss1_mux[] = {
++ MSIOF1_SS1_MARK,
++};
++static const unsigned int msiof1_ss2_pins[] = {
++ /* SS2 */
++ RCAR_GP_PIN(3, 5),
++};
++static const unsigned int msiof1_ss2_mux[] = {
++ MSIOF1_SS2_MARK,
++};
++static const unsigned int msiof1_txd_pins[] = {
++ /* TXD */
++ RCAR_GP_PIN(3, 1),
++};
++static const unsigned int msiof1_txd_mux[] = {
++ MSIOF1_TXD_MARK,
++};
++static const unsigned int msiof1_rxd_pins[] = {
++ /* RXD */
++ RCAR_GP_PIN(3, 0),
++};
++static const unsigned int msiof1_rxd_mux[] = {
++ MSIOF1_RXD_MARK,
++};
++
++/* - MSIOF2 ----------------------------------------------------------------- */
++static const unsigned int msiof2_clk_pins[] = {
++ /* SCK */
++ RCAR_GP_PIN(2, 0),
++};
++static const unsigned int msiof2_clk_mux[] = {
++ MSIOF2_SCK_MARK,
++};
++static const unsigned int msiof2_sync_pins[] = {
++ /* SYNC */
++ RCAR_GP_PIN(2, 3),
++};
++static const unsigned int msiof2_sync_mux[] = {
++ MSIOF2_SYNC_MARK,
++};
++static const unsigned int msiof2_ss1_pins[] = {
++ /* SS1 */
++ RCAR_GP_PIN(2, 4),
++};
++static const unsigned int msiof2_ss1_mux[] = {
++ MSIOF2_SS1_MARK,
++};
++static const unsigned int msiof2_ss2_pins[] = {
++ /* SS2 */
++ RCAR_GP_PIN(2, 5),
++};
++static const unsigned int msiof2_ss2_mux[] = {
++ MSIOF2_SS2_MARK,
++};
++static const unsigned int msiof2_txd_pins[] = {
++ /* TXD */
++ RCAR_GP_PIN(2, 2),
++};
++static const unsigned int msiof2_txd_mux[] = {
++ MSIOF2_TXD_MARK,
++};
++static const unsigned int msiof2_rxd_pins[] = {
++ /* RXD */
++ RCAR_GP_PIN(2, 1),
++};
++static const unsigned int msiof2_rxd_mux[] = {
++ MSIOF2_RXD_MARK,
++};
++
++/* - MSIOF3 ----------------------------------------------------------------- */
++static const unsigned int msiof3_clk_pins[] = {
++ /* SCK */
++ RCAR_GP_PIN(0, 20),
++};
++static const unsigned int msiof3_clk_mux[] = {
++ MSIOF3_SCK_MARK,
++};
++static const unsigned int msiof3_sync_pins[] = {
++ /* SYNC */
++ RCAR_GP_PIN(0, 21),
++};
++static const unsigned int msiof3_sync_mux[] = {
++ MSIOF3_SYNC_MARK,
++};
++static const unsigned int msiof3_ss1_pins[] = {
++ /* SS1 */
++ RCAR_GP_PIN(0, 6),
++};
++static const unsigned int msiof3_ss1_mux[] = {
++ MSIOF3_SS1_MARK,
++};
++static const unsigned int msiof3_ss2_pins[] = {
++ /* SS2 */
++ RCAR_GP_PIN(0, 7),
++};
++static const unsigned int msiof3_ss2_mux[] = {
++ MSIOF3_SS2_MARK,
++};
++static const unsigned int msiof3_txd_pins[] = {
++ /* TXD */
++ RCAR_GP_PIN(0, 5),
++};
++static const unsigned int msiof3_txd_mux[] = {
++ MSIOF3_TXD_MARK,
++};
++static const unsigned int msiof3_rxd_pins[] = {
++ /* RXD */
++ RCAR_GP_PIN(0, 4),
++};
++static const unsigned int msiof3_rxd_mux[] = {
++ MSIOF3_RXD_MARK,
++};
++
++/* - PWM0 ------------------------------------------------------------------- */
++static const unsigned int pwm0_a_pins[] = {
++ /* PWM0 */
++ RCAR_GP_PIN(2, 12),
++};
++static const unsigned int pwm0_a_mux[] = {
++ PWM0_A_MARK,
++};
++static const unsigned int pwm0_b_pins[] = {
++ /* PWM0 */
++ RCAR_GP_PIN(1, 21),
++};
++static const unsigned int pwm0_b_mux[] = {
++ PWM0_B_MARK,
++};
++
++/* - PWM1 ------------------------------------------------------------------- */
++static const unsigned int pwm1_a_pins[] = {
++ /* PWM1 */
++ RCAR_GP_PIN(2, 13),
++};
++static const unsigned int pwm1_a_mux[] = {
++ PWM1_A_MARK,
++};
++static const unsigned int pwm1_b_pins[] = {
++ /* PWM */
++ RCAR_GP_PIN(1, 22),
++};
++static const unsigned int pwm1_b_mux[] = {
++ PWM1_B_MARK,
++};
++
++/* - PWM2 ------------------------------------------------------------------- */
++static const unsigned int pwm2_a_pins[] = {
++ /* PWM2 */
++ RCAR_GP_PIN(2, 14),
++};
++static const unsigned int pwm2_a_mux[] = {
++ PWM2_A_MARK,
++};
++static const unsigned int pwm2_b_pins[] = {
++ /* PWM2 */
++ RCAR_GP_PIN(1, 23),
++};
++static const unsigned int pwm2_b_mux[] = {
++ PWM2_B_MARK,
++};
++
++/* - PWM3 ------------------------------------------------------------------- */
++static const unsigned int pwm3_a_pins[] = {
++ /* PWM3 */
++ RCAR_GP_PIN(2, 15),
++};
++static const unsigned int pwm3_a_mux[] = {
++ PWM3_A_MARK,
++};
++static const unsigned int pwm3_b_pins[] = {
++ /* PWM3 */
++ RCAR_GP_PIN(1, 24),
++};
++static const unsigned int pwm3_b_mux[] = {
++ PWM3_B_MARK,
++};
++
++/* - PWM4 ------------------------------------------------------------------- */
++static const unsigned int pwm4_a_pins[] = {
++ /* PWM4 */
++ RCAR_GP_PIN(2, 16),
++};
++static const unsigned int pwm4_a_mux[] = {
++ PWM4_A_MARK,
++};
++static const unsigned int pwm4_b_pins[] = {
++ /* PWM4 */
++ RCAR_GP_PIN(1, 25),
++};
++static const unsigned int pwm4_b_mux[] = {
++ PWM4_B_MARK,
++};
++/* - SCIF0 ------------------------------------------------------------------ */
++static const unsigned int scif0_data_pins[] = {
++ /* RX, TX */
++ RCAR_GP_PIN(4, 4), RCAR_GP_PIN(4, 5),
++};
++static const unsigned int scif0_data_mux[] = {
++ RX0_MARK, TX0_MARK,
++};
++static const unsigned int scif0_clk_pins[] = {
++ /* SCK */
++ RCAR_GP_PIN(4, 1),
++};
++static const unsigned int scif0_clk_mux[] = {
++ SCK0_MARK,
++};
++#if 0
++static const unsigned int scif0_ctrl_pins[] = {
++ /* RTS, CTS */
++ RCAR_GP_PIN(4, 3), RCAR_GP_PIN(4, 2),
++};
++static const unsigned int scif0_ctrl_mux[] = {
++ RTS0_N_TANS_MARK, CTS0_N_MARK,
++};
++#endif
++/* - SCIF1 ------------------------------------------------------------------ */
++static const unsigned int scif1_data_a_pins[] = {
++ /* RX, TX */
++ RCAR_GP_PIN(2, 8), RCAR_GP_PIN(2, 9),
++};
++static const unsigned int scif1_data_a_mux[] = {
++ RX1_A_MARK, TX1_A_MARK,
++};
++static const unsigned int scif1_clk_pins[] = {
++ /* SCK */
++ RCAR_GP_PIN(2, 5),
++};
++static const unsigned int scif1_clk_mux[] = {
++ SCK1_MARK,
++};
++static const unsigned int scif1_ctrl_pins[] = {
++ /* RTS, CTS */
++ RCAR_GP_PIN(2, 11), RCAR_GP_PIN(2, 10),
++};
++static const unsigned int scif1_ctrl_mux[] = {
++ RTS1_N_TANS_MARK, CTS1_N_MARK,
++};
++static const unsigned int scif1_data_b_pins[] = {
++ /* RX, TX */
++ RCAR_GP_PIN(1, 24), RCAR_GP_PIN(1, 23),
++};
++static const unsigned int scif1_data_b_mux[] = {
++ RX1_B_MARK, TX1_B_MARK,
++};
++
++/* - SCIF3 ------------------------------------------------------------------ */
++static const unsigned int scif3_data_pins[] = {
++ /* RX, TX */
++ RCAR_GP_PIN(2, 1), RCAR_GP_PIN(2, 2),
++};
++static const unsigned int scif3_data_mux[] = {
++ RX3_MARK, TX3_MARK,
++};
++static const unsigned int scif3_clk_pins[] = {
++ /* SCK */
++ RCAR_GP_PIN(2, 0),
++};
++static const unsigned int scif3_clk_mux[] = {
++ SCK3_MARK,
++};
++static const unsigned int scif3_ctrl_pins[] = {
++ /* RTS, CTS */
++ RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 3),
++};
++static const unsigned int scif3_ctrl_mux[] = {
++ RTS3_N_TANS_MARK, CTS3_N_MARK,
++};
++
++/* - SCIF4 ------------------------------------------------------------------ */
++static const unsigned int scif4_data_pins[] = {
++ /* RX, TX */
++ RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 11),
++};
++static const unsigned int scif4_data_mux[] = {
++ RX4_MARK, TX4_MARK,
++};
++static const unsigned int scif4_clk_pins[] = {
++ /* SCK */
++ RCAR_GP_PIN(3, 9),
++};
++static const unsigned int scif4_clk_mux[] = {
++ SCK4_MARK,
++};
++static const unsigned int scif4_ctrl_pins[] = {
++ /* RTS, CTS */
++ RCAR_GP_PIN(3, 13), RCAR_GP_PIN(3, 12),
++};
++static const unsigned int scif4_ctrl_mux[] = {
++ RTS4_N_TANS_MARK, CTS4_N_MARK,
++};
++
++/* - MMC -------------------------------------------------------------------- */
++static const unsigned int mmc_data1_pins[] = {
++ /* D0 */
++ RCAR_GP_PIN(3, 6),
++};
++static const unsigned int mmc_data1_mux[] = {
++ MMC_D0_MARK,
++};
++static const unsigned int mmc_data4_pins[] = {
++ /* D[0:3] */
++ RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7),
++ RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9),
++};
++static const unsigned int mmc_data4_mux[] = {
++ MMC_D0_MARK, MMC_D1_MARK,
++ MMC_D2_MARK, MMC_D3_MARK,
++};
++static const unsigned int mmc_data8_pins[] = {
++ /* D[0:7] */
++ RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7),
++ RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9),
++ RCAR_GP_PIN(3, 11), RCAR_GP_PIN(3, 12),
++ RCAR_GP_PIN(3, 13), RCAR_GP_PIN(3, 14),
++};
++static const unsigned int mmc_data8_mux[] = {
++ MMC_D0_MARK, MMC_D1_MARK,
++ MMC_D2_MARK, MMC_D3_MARK,
++ MMC_D4_MARK, MMC_D5_MARK,
++ MMC_D6_MARK, MMC_D7_MARK,
++};
++static const unsigned int mmc_ctrl_pins[] = {
++ /* CLK, CMD */
++ RCAR_GP_PIN(3,10), RCAR_GP_PIN(3, 5),
++};
++static const unsigned int mmc_ctrl_mux[] = {
++ MMC_CLK_MARK, MMC_CMD_MARK,
++};
++static const unsigned int mmc_cd_pins[] = {
++ /* CD */
++ RCAR_GP_PIN(3, 16),
++};
++static const unsigned int mmc_cd_mux[] = {
++ MMC_CD_MARK,
++};
++static const unsigned int mmc_wp_pins[] = {
++ /* WP */
++ RCAR_GP_PIN(3, 15),
++};
++static const unsigned int mmc_wp_mux[] = {
++ MMC_WP_MARK,
++};
++
++/* - TMU -------------------------------------------------------------------- */
++static const unsigned int tmu_tclk1_a_pins[] = {
++ /* TCLK1 */
++ RCAR_GP_PIN(4, 4),
++};
++static const unsigned int tmu_tclk1_a_mux[] = {
++ TCLK1_A_MARK,
++};
++static const unsigned int tmu_tclk1_b_pins[] = {
++ /* TCLK1 */
++ RCAR_GP_PIN(1, 23),
++};
++static const unsigned int tmu_tclk1_b_mux[] = {
++ TCLK1_B_MARK,
++};
++static const unsigned int tmu_tclk2_a_pins[] = {
++ /* TCLK2 */
++ RCAR_GP_PIN(4, 5),
++};
++static const unsigned int tmu_tclk2_a_mux[] = {
++ TCLK2_A_MARK,
++};
++static const unsigned int tmu_tclk2_b_pins[] = {
++ /* TCLK2 */
++ RCAR_GP_PIN(1, 24),
++};
++static const unsigned int tmu_tclk2_b_mux[] = {
++ TCLK2_B_MARK,
++};
++
++/* - VIN0 ------------------------------------------------------------------- */
++static const unsigned int vin0_data8_pins[] = {
++ RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 5),
++ RCAR_GP_PIN(2, 6), RCAR_GP_PIN(2, 7),
++ RCAR_GP_PIN(2, 8), RCAR_GP_PIN(2, 9),
++ RCAR_GP_PIN(2, 10), RCAR_GP_PIN(2, 11),
++};
++static const unsigned int vin0_data8_mux[] = {
++ VI0_DATA0_MARK, VI0_DATA1_MARK,
++ VI0_DATA2_MARK, VI0_DATA3_MARK,
++ VI0_DATA4_MARK, VI0_DATA5_MARK,
++ VI0_DATA6_MARK, VI0_DATA7_MARK,
++};
++static const unsigned int vin0_data10_pins[] = {
++ RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 5),
++ RCAR_GP_PIN(2, 6), RCAR_GP_PIN(2, 7),
++ RCAR_GP_PIN(2, 8), RCAR_GP_PIN(2, 9),
++ RCAR_GP_PIN(2, 10), RCAR_GP_PIN(2, 11),
++ RCAR_GP_PIN(2, 12), RCAR_GP_PIN(2, 13),
++};
++static const unsigned int vin0_data10_mux[] = {
++ VI0_DATA0_MARK, VI0_DATA1_MARK,
++ VI0_DATA2_MARK, VI0_DATA3_MARK,
++ VI0_DATA4_MARK, VI0_DATA5_MARK,
++ VI0_DATA6_MARK, VI0_DATA7_MARK,
++ VI0_DATA8_MARK, VI0_DATA9_MARK,
++};
++static const unsigned int vin0_data12_pins[] = {
++ RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 5),
++ RCAR_GP_PIN(2, 6), RCAR_GP_PIN(2, 7),
++ RCAR_GP_PIN(2, 8), RCAR_GP_PIN(2, 9),
++ RCAR_GP_PIN(2, 10), RCAR_GP_PIN(2, 11),
++ RCAR_GP_PIN(2, 12), RCAR_GP_PIN(2, 13),
++ RCAR_GP_PIN(2, 14), RCAR_GP_PIN(2, 15),
++};
++static const unsigned int vin0_data12_mux[] = {
++ VI0_DATA0_MARK, VI0_DATA1_MARK,
++ VI0_DATA2_MARK, VI0_DATA3_MARK,
++ VI0_DATA4_MARK, VI0_DATA5_MARK,
++ VI0_DATA6_MARK, VI0_DATA7_MARK,
++ VI0_DATA8_MARK, VI0_DATA9_MARK,
++ VI0_DATA10_MARK, VI0_DATA11_MARK,
++};
++static const unsigned int vin0_sync_pins[] = {
++ /* VSYNC_N, HSYNC_N */
++ RCAR_GP_PIN(2, 3), RCAR_GP_PIN(2, 2),
++};
++static const unsigned int vin0_sync_mux[] = {
++ VI0_HSYNC_N_MARK, VI0_VSYNC_N_MARK,
++};
++static const unsigned int vin0_field_pins[] = {
++ /* FIELD */
++ RCAR_GP_PIN(2, 16),
++};
++static const unsigned int vin0_field_mux[] = {
++ VI0_FIELD_MARK,
++};
++static const unsigned int vin0_clkenb_pins[] = {
++ /* CLKENB */
++ RCAR_GP_PIN(2, 1),
++};
++static const unsigned int vin0_clkenb_mux[] = {
++ VI0_CLKENB_MARK,
++};
++static const unsigned int vin0_clk_pins[] = {
++ /* CLK */
++ RCAR_GP_PIN(2, 0),
++};
++static const unsigned int vin0_clk_mux[] = {
++ VI0_CLK_MARK,
++};
++/* - VIN1 ------------------------------------------------------------------- */
++static const unsigned int vin1_data8_pins[] = {
++ RCAR_GP_PIN(3, 4), RCAR_GP_PIN(3, 5),
++ RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7),
++ RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9),
++ RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 11),
++};
++static const unsigned int vin1_data8_mux[] = {
++ VI1_DATA0_MARK, VI1_DATA1_MARK,
++ VI1_DATA2_MARK, VI1_DATA3_MARK,
++ VI1_DATA4_MARK, VI1_DATA5_MARK,
++ VI1_DATA6_MARK, VI1_DATA7_MARK,
++};
++static const unsigned int vin1_data10_pins[] = {
++ RCAR_GP_PIN(3, 4), RCAR_GP_PIN(3, 5),
++ RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7),
++ RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9),
++ RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 11),
++ RCAR_GP_PIN(3, 12), RCAR_GP_PIN(3, 13),
++};
++static const unsigned int vin1_data10_mux[] = {
++ VI1_DATA0_MARK, VI1_DATA1_MARK,
++ VI1_DATA2_MARK, VI1_DATA3_MARK,
++ VI1_DATA4_MARK, VI1_DATA5_MARK,
++ VI1_DATA6_MARK, VI1_DATA7_MARK,
++ VI1_DATA8_MARK, VI1_DATA9_MARK,
++};
++static const unsigned int vin1_data12_pins[] = {
++ RCAR_GP_PIN(3, 4), RCAR_GP_PIN(3, 5),
++ RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7),
++ RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9),
++ RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 11),
++ RCAR_GP_PIN(3, 12), RCAR_GP_PIN(3, 13),
++ RCAR_GP_PIN(3, 14), RCAR_GP_PIN(3, 15),
++};
++static const unsigned int vin1_data12_mux[] = {
++ VI1_DATA0_MARK, VI1_DATA1_MARK,
++ VI1_DATA2_MARK, VI1_DATA3_MARK,
++ VI1_DATA4_MARK, VI1_DATA5_MARK,
++ VI1_DATA6_MARK, VI1_DATA7_MARK,
++ VI1_DATA8_MARK, VI1_DATA9_MARK,
++ VI1_DATA10_MARK, VI1_DATA11_MARK,
++};
++static const unsigned int vin1_sync_pins[] = {
++ /* VSYNC_N, HSYNC_N */
++ RCAR_GP_PIN(3, 3), RCAR_GP_PIN(3, 2),
++};
++static const unsigned int vin1_sync_mux[] = {
++ VI1_HSYNC_N_MARK, VI1_VSYNC_N_MARK,
++};
++static const unsigned int vin1_field_pins[] = {
++ RCAR_GP_PIN(3, 16),
++};
++static const unsigned int vin1_field_mux[] = {
++ /* FIELD */
++ VI1_FIELD_MARK,
++};
++static const unsigned int vin1_clkenb_pins[] = {
++ RCAR_GP_PIN(3, 1),
++};
++static const unsigned int vin1_clkenb_mux[] = {
++ /* CLKENB */
++ VI1_CLKENB_MARK,
++};
++static const unsigned int vin1_clk_pins[] = {
++ RCAR_GP_PIN(3, 0),
++};
++static const unsigned int vin1_clk_mux[] = {
++ /* CLK */
++ VI1_CLK_MARK,
++};
++
++static const struct sh_pfc_pin_group pinmux_groups[] = {
++ SH_PFC_PIN_GROUP(avb0_rx_ctrl),
++ SH_PFC_PIN_GROUP(avb0_rxc),
++ SH_PFC_PIN_GROUP(avb0_rd0),
++ SH_PFC_PIN_GROUP(avb0_rd1),
++ SH_PFC_PIN_GROUP(avb0_rd2),
++ SH_PFC_PIN_GROUP(avb0_rd3),
++ SH_PFC_PIN_GROUP(avb0_rd4),
++ SH_PFC_PIN_GROUP(avb0_tx_ctrl),
++ SH_PFC_PIN_GROUP(avb0_txc),
++ SH_PFC_PIN_GROUP(avb0_td0),
++ SH_PFC_PIN_GROUP(avb0_td1),
++ SH_PFC_PIN_GROUP(avb0_td2),
++ SH_PFC_PIN_GROUP(avb0_td3),
++ SH_PFC_PIN_GROUP(avb0_td4),
++ SH_PFC_PIN_GROUP(avb0_txcrefclk),
++ SH_PFC_PIN_GROUP(avb0_mdio),
++ SH_PFC_PIN_GROUP(avb0_mdc),
++ SH_PFC_PIN_GROUP(avb0_magic),
++ SH_PFC_PIN_GROUP(avb0_phy_int),
++ SH_PFC_PIN_GROUP(avb0_link),
++ SH_PFC_PIN_GROUP(avb0_avtp_match),
++ SH_PFC_PIN_GROUP(avb0_avtp_pps),
++ SH_PFC_PIN_GROUP(avb0_avtp_capture),
++ SH_PFC_PIN_GROUP(canfd0_data_a),
++ SH_PFC_PIN_GROUP(canfd_clk_a),
++ SH_PFC_PIN_GROUP(canfd0_data_b),
++ SH_PFC_PIN_GROUP(canfd_clk_b),
++ SH_PFC_PIN_GROUP(canfd1_data),
++ SH_PFC_PIN_GROUP(du_rgb666),
++ SH_PFC_PIN_GROUP(du_clk_out_0),
++ SH_PFC_PIN_GROUP(du_clk_out_1),
++ SH_PFC_PIN_GROUP(du_sync),
++ SH_PFC_PIN_GROUP(du_oddf),
++ SH_PFC_PIN_GROUP(du_cde),
++ SH_PFC_PIN_GROUP(du_disp),
++ SH_PFC_PIN_GROUP(hscif0_data),
++ SH_PFC_PIN_GROUP(hscif0_clk),
++ SH_PFC_PIN_GROUP(hscif0_ctrl),
++ SH_PFC_PIN_GROUP(hscif1_data),
++ SH_PFC_PIN_GROUP(hscif1_clk),
++ SH_PFC_PIN_GROUP(hscif1_ctrl),
++ SH_PFC_PIN_GROUP(hscif2_data),
++ SH_PFC_PIN_GROUP(hscif2_clk),
++ SH_PFC_PIN_GROUP(hscif2_ctrl),
++ SH_PFC_PIN_GROUP(hscif3_data),
++ SH_PFC_PIN_GROUP(hscif3_clk),
++ SH_PFC_PIN_GROUP(hscif3_ctrl),
++ SH_PFC_PIN_GROUP(scif_clk_a),
++ SH_PFC_PIN_GROUP(scif_clk_b),
++ SH_PFC_PIN_GROUP(i2c0),
++ SH_PFC_PIN_GROUP(i2c1),
++ SH_PFC_PIN_GROUP(i2c2),
++ SH_PFC_PIN_GROUP(i2c3),
++ SH_PFC_PIN_GROUP(i2c4),
++ SH_PFC_PIN_GROUP(intc_ex_irq0),
++ SH_PFC_PIN_GROUP(intc_ex_irq1),
++ SH_PFC_PIN_GROUP(intc_ex_irq2),
++ SH_PFC_PIN_GROUP(intc_ex_irq3),
++ SH_PFC_PIN_GROUP(intc_ex_irq4),
++ SH_PFC_PIN_GROUP(intc_ex_irq5),
++ SH_PFC_PIN_GROUP(msiof0_clk),
++ SH_PFC_PIN_GROUP(msiof0_sync),
++ SH_PFC_PIN_GROUP(msiof0_ss1),
++ SH_PFC_PIN_GROUP(msiof0_ss2),
++ SH_PFC_PIN_GROUP(msiof0_txd),
++ SH_PFC_PIN_GROUP(msiof0_rxd),
++ SH_PFC_PIN_GROUP(msiof1_clk),
++ SH_PFC_PIN_GROUP(msiof1_sync),
++ SH_PFC_PIN_GROUP(msiof1_ss1),
++ SH_PFC_PIN_GROUP(msiof1_ss2),
++ SH_PFC_PIN_GROUP(msiof1_txd),
++ SH_PFC_PIN_GROUP(msiof1_rxd),
++ SH_PFC_PIN_GROUP(msiof2_clk),
++ SH_PFC_PIN_GROUP(msiof2_sync),
++ SH_PFC_PIN_GROUP(msiof2_ss1),
++ SH_PFC_PIN_GROUP(msiof2_ss2),
++ SH_PFC_PIN_GROUP(msiof2_txd),
++ SH_PFC_PIN_GROUP(msiof2_rxd),
++ SH_PFC_PIN_GROUP(msiof3_clk),
++ SH_PFC_PIN_GROUP(msiof3_sync),
++ SH_PFC_PIN_GROUP(msiof3_ss1),
++ SH_PFC_PIN_GROUP(msiof3_ss2),
++ SH_PFC_PIN_GROUP(msiof3_txd),
++ SH_PFC_PIN_GROUP(msiof3_rxd),
++ SH_PFC_PIN_GROUP(pwm0_a),
++ SH_PFC_PIN_GROUP(pwm0_b),
++ SH_PFC_PIN_GROUP(pwm1_a),
++ SH_PFC_PIN_GROUP(pwm1_b),
++ SH_PFC_PIN_GROUP(pwm2_a),
++ SH_PFC_PIN_GROUP(pwm2_b),
++ SH_PFC_PIN_GROUP(pwm3_a),
++ SH_PFC_PIN_GROUP(pwm3_b),
++ SH_PFC_PIN_GROUP(pwm4_a),
++ SH_PFC_PIN_GROUP(pwm4_b),
++ SH_PFC_PIN_GROUP(scif0_data),
++ //SH_PFC_PIN_GROUP(scif0_clk),
++ //SH_PFC_PIN_GROUP(scif0_ctrl),
++ SH_PFC_PIN_GROUP(scif1_data_a),
++ SH_PFC_PIN_GROUP(scif1_clk),
++ SH_PFC_PIN_GROUP(scif1_ctrl),
++ SH_PFC_PIN_GROUP(scif1_data_b),
++ SH_PFC_PIN_GROUP(scif3_data),
++ SH_PFC_PIN_GROUP(scif3_clk),
++ SH_PFC_PIN_GROUP(scif3_ctrl),
++ SH_PFC_PIN_GROUP(scif4_data),
++ SH_PFC_PIN_GROUP(scif4_clk),
++ SH_PFC_PIN_GROUP(scif4_ctrl),
++ SH_PFC_PIN_GROUP(mmc_data1),
++ SH_PFC_PIN_GROUP(mmc_data4),
++ SH_PFC_PIN_GROUP(mmc_data8),
++ SH_PFC_PIN_GROUP(mmc_ctrl),
++ SH_PFC_PIN_GROUP(mmc_cd),
++ SH_PFC_PIN_GROUP(mmc_wp),
++ SH_PFC_PIN_GROUP(tmu_tclk1_a),
++ SH_PFC_PIN_GROUP(tmu_tclk1_b),
++ SH_PFC_PIN_GROUP(tmu_tclk2_a),
++ SH_PFC_PIN_GROUP(tmu_tclk2_b),
++ SH_PFC_PIN_GROUP(vin0_data8),
++ SH_PFC_PIN_GROUP(vin0_data10),
++ SH_PFC_PIN_GROUP(vin0_data12),
++ SH_PFC_PIN_GROUP(vin0_sync),
++ SH_PFC_PIN_GROUP(vin0_field),
++ SH_PFC_PIN_GROUP(vin0_clkenb),
++ SH_PFC_PIN_GROUP(vin0_clk),
++ SH_PFC_PIN_GROUP(vin1_data8),
++ SH_PFC_PIN_GROUP(vin1_data10),
++ SH_PFC_PIN_GROUP(vin1_data12),
++ SH_PFC_PIN_GROUP(vin1_sync),
++ SH_PFC_PIN_GROUP(vin1_field),
++ SH_PFC_PIN_GROUP(vin1_clkenb),
++ SH_PFC_PIN_GROUP(vin1_clk),
++};
++
++static const char * const avb0_groups[] = {
++ "avb0_rx_ctrl",
++ "avb0_rxc",
++ "avb0_rd1",
++ "avb0_rd4",
++ "avb0_tx_ctrl",
++ "avb0_txc",
++ "avb0_td1",
++ "avb0_td4",
++ "avb0_txcrefclk",
++ "avb0_mdio",
++ "avb0_mdc",
++ "avb0_magic",
++ "avb0_phy_int",
++ "avb0_link",
++ "avb0_avtp_match",
++ "avb0_avtp_pps",
++ "avb0_avtp_capture",
++};
++
++static const char * const canfd0_groups[] = {
++ "canfd0_data_a",
++ "canfd0_clk_a",
++ "canfd0_data_b",
++ "canfd0_clk_b",
++};
++
++static const char * const canfd1_groups[] = {
++ "canfd1_data",
++};
++
++static const char * const du_groups[] = {
++ "du_rgb666",
++ "du_clk_out_0",
++ "du_clk_out_1",
++ "du_sync",
++ "du_oddf",
++ "du_cde",
++ "du_disp",
++};
++
++static const char * const hscif0_groups[] = {
++ "hscif0_data",
++ "hscif0_clk",
++ "hscif0_ctrl",
++};
++
++static const char * const hscif1_groups[] = {
++ "hscif1_data",
++ "hscif1_clk",
++ "hscif1_ctrl",
++};
++
++static const char * const hscif2_groups[] = {
++ "hscif2_data",
++ "hscif2_clk",
++ "hscif2_ctrl",
++};
++
++static const char * const hscif3_groups[] = {
++ "hscif3_data",
++ "hscif3_clk",
++ "hscif3_ctrl",
++};
++
++static const char * const scif_clk_groups[] = {
++ "scif_clk_a",
++ "scif_clk_b",
++};
++
++static const char * const i2c0_groups[] = {
++ "i2c0",
++};
++
++static const char * const i2c1_groups[] = {
++ "i2c1",
++};
++
++static const char * const i2c2_groups[] = {
++ "i2c2",
++};
++
++static const char * const i2c3_groups[] = {
++ "i2c3",
++};
++
++static const char * const i2c4_groups[] = {
++ "i2c4",
++};
++
++static const char * const intc_ex_groups[] = {
++ "intc_ex_irq0",
++ "intc_ex_irq1",
++ "intc_ex_irq2",
++ "intc_ex_irq3",
++ "intc_ex_irq4",
++ "intc_ex_irq5",
++};
++
++static const char * const msiof0_groups[] = {
++ "msiof0_clk",
++ "msiof0_sync",
++ "msiof0_ss1",
++ "msiof0_ss2",
++ "msiof0_txd",
++ "msiof0_rxd",
++};
++
++static const char * const msiof1_groups[] = {
++ "msiof1_clk",
++ "msiof1_sync",
++ "msiof1_ss1",
++ "msiof1_ss2",
++ "msiof1_txd",
++ "msiof1_rxd",
++};
++
++static const char * const msiof2_groups[] = {
++ "msiof2_clk",
++ "msiof2_sync",
++ "msiof2_ss1",
++ "msiof2_ss2",
++ "msiof2_txd",
++ "msiof2_rxd",
++};
++
++static const char * const msiof3_groups[] = {
++ "msiof3_clk",
++ "msiof3_sync",
++ "msiof3_ss1",
++ "msiof3_ss2",
++ "msiof3_txd",
++ "msiof3_rxd",
++};
++
++static const char * const pwm0_groups[] = {
++ "pwm0_a",
++ "pwm0_b",
++};
++
++static const char * const pwm1_groups[] = {
++ "pwm1_a",
++ "pwm1_b",
++};
++
++static const char * const pwm2_groups[] = {
++ "pwm2_a",
++ "pwm2_b",
++};
++
++static const char * const pwm3_groups[] = {
++ "pwm3_a",
++ "pwm3_b",
++};
++
++static const char * const pwm4_groups[] = {
++ "pwm4_a",
++ "pwm4_b",
++};
++
++static const char * const scif0_groups[] = {
++ "scif0_data",
++// "scif0_clk",
++// "scif0_ctl",
++};
++
++static const char * const scif1_groups[] = {
++ "scif1_data_a",
++ "scif1_clk",
++ "scif1_ctl",
++ "scif1_data_b",
++};
++
++static const char * const scif3_groups[] = {
++ "scif3_data",
++ "scif3_clk",
++ "scif3_ctl",
++};
++
++static const char * const scif4_groups[] = {
++ "scif4_data",
++ "scif4_clk",
++ "scif4_ctl",
++};
++
++static const char * const mmc_groups[] = {
++ "mmc_data1",
++ "mmc_data4",
++ "mmc_data8",
++ "mmc_ctrl",
++ "mmc_cd",
++ "mmc_wp",
++};
++
++static const char * const tmu_groups[] = {
++ "tmu_tclk1_a",
++ "tmu_tclk1_b",
++ "tmu_tclk2_a",
++ "tmu_tclk2_b",
++};
++
++static const char * const vin0_groups[] = {
++ "vin0_data8",
++ "vin0_data10",
++ "vin0_data12",
++ "vin0_sync",
++ "vin0_field",
++ "vin0_clkenb",
++ "vin0_clk",
++};
++
++static const char * const vin1_groups[] = {
++ "vin1_data8",
++ "vin1_data10",
++ "vin1_data12",
++ "vin1_sync",
++ "vin1_field",
++ "vin1_clkenb",
++ "vin1_clk",
++};
++
++#define POCCTRL0 0x380
++#define POCCTRL1 0x384
++#define PIN2POCCTRL0_SHIFT(a) ({ \
++ int _gp = (a) >> 5; \
++ int _bit = (a) & 0x1f; \
++ ((_gp == 3) && (_bit < 12)) ? _bit : \
++ ((_gp == 4) && (_bit < 18)) ? _bit + 12 : -1; \
++})
++
++#if 0
++static int r8a7797_get_io_voltage(struct sh_pfc *pfc, unsigned int pin)
++{
++ void __iomem *reg;
++ u32 data, mask;
++ int shift;
++
++ /* Bits in POCCTRL0 are numbered in opposite order to pins */
++ shift = PIN2POCCTRL0_SHIFT(pin);
++
++ if (WARN(shift < 0, "invalid pin %#x", pin))
++ return -EINVAL;
++
++ reg = pfc->windows->virt + POCCTRL0;
++ data = ioread32(reg);
++
++ mask = 0x1 << shift;
++
++ return (data & mask) ? 3300 : 1800;
++}
++
++static int r8a7797_set_io_voltage(struct sh_pfc *pfc, unsigned int pin, u16 mV)
++{
++ void __iomem *reg;
++ u32 data, mask;
++ int shift;
++
++ /* Bits in POCCTRL0 are numbered in opposite order to pins */
++ shift = PIN2POCCTRL0_SHIFT(pin);
++
++ if (WARN(shift < 0, "invalid pin %#x", pin))
++ return -EINVAL;
++
++ if (mV != 1800 && mV != 3300)
++ return -EINVAL;
++
++ reg = pfc->windows->virt + POCCTRL0;
++ data = ioread32(reg);
++
++ mask = 0x1 << shift;
++
++ if (mV == 3300)
++ data |= mask;
++ else
++ data &= ~mask;
++
++
++ iowrite32(~data, pfc->windows->virt +
++ (pfc->info->unlock_reg - pfc->windows->phys));
++ iowrite32(data, reg);
++
++ return 0;
++}
++#endif
++
++static const struct sh_pfc_function pinmux_functions[] = {
++ SH_PFC_FUNCTION(avb0),
++ SH_PFC_FUNCTION(canfd0),
++ SH_PFC_FUNCTION(canfd1),
++ SH_PFC_FUNCTION(du),
++ SH_PFC_FUNCTION(hscif0),
++ SH_PFC_FUNCTION(hscif1),
++ SH_PFC_FUNCTION(hscif2),
++ SH_PFC_FUNCTION(hscif3),
++ SH_PFC_FUNCTION(scif_clk),
++ SH_PFC_FUNCTION(i2c0),
++ SH_PFC_FUNCTION(i2c1),
++ SH_PFC_FUNCTION(i2c2),
++ SH_PFC_FUNCTION(i2c3),
++ SH_PFC_FUNCTION(i2c4),
++ SH_PFC_FUNCTION(intc_ex),
++ SH_PFC_FUNCTION(msiof0),
++ SH_PFC_FUNCTION(msiof1),
++ SH_PFC_FUNCTION(msiof2),
++ SH_PFC_FUNCTION(msiof3),
++ SH_PFC_FUNCTION(pwm0),
++ SH_PFC_FUNCTION(pwm1),
++ SH_PFC_FUNCTION(pwm2),
++ SH_PFC_FUNCTION(pwm3),
++ SH_PFC_FUNCTION(pwm4),
++ SH_PFC_FUNCTION(scif0),
++ SH_PFC_FUNCTION(scif1),
++ SH_PFC_FUNCTION(scif3),
++ SH_PFC_FUNCTION(scif4),
++ SH_PFC_FUNCTION(mmc),
++ SH_PFC_FUNCTION(tmu),
++ SH_PFC_FUNCTION(vin0),
++ SH_PFC_FUNCTION(vin1),
++};
++
++static const struct pinmux_cfg_reg pinmux_config_regs[] = {
++#define F_(x, y) FN_##y
++#define FM(x) FN_##x
++ { PINMUX_CFG_REG("GPSR0", 0xe6060100, 32, 1) {
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ GP_0_21_FN, GPSR0_21,
++ GP_0_20_FN, GPSR0_20,
++ GP_0_19_FN, GPSR0_19,
++ GP_0_18_FN, GPSR0_18,
++ GP_0_17_FN, GPSR0_17,
++ GP_0_16_FN, GPSR0_16,
++ GP_0_15_FN, GPSR0_15,
++ GP_0_14_FN, GPSR0_14,
++ GP_0_13_FN, GPSR0_13,
++ GP_0_12_FN, GPSR0_12,
++ GP_0_11_FN, GPSR0_11,
++ GP_0_10_FN, GPSR0_10,
++ GP_0_9_FN, GPSR0_9,
++ GP_0_8_FN, GPSR0_8,
++ GP_0_7_FN, GPSR0_7,
++ GP_0_6_FN, GPSR0_6,
++ GP_0_5_FN, GPSR0_5,
++ GP_0_4_FN, GPSR0_4,
++ GP_0_3_FN, GPSR0_3,
++ GP_0_2_FN, GPSR0_2,
++ GP_0_1_FN, GPSR0_1,
++ GP_0_0_FN, GPSR0_0, }
++ },
++ { PINMUX_CFG_REG("GPSR1", 0xe6060104, 32, 1) {
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ GP_1_27_FN, GPSR1_27,
++ GP_1_26_FN, GPSR1_26,
++ GP_1_25_FN, GPSR1_25,
++ GP_1_24_FN, GPSR1_24,
++ GP_1_23_FN, GPSR1_23,
++ GP_1_22_FN, GPSR1_22,
++ GP_1_21_FN, GPSR1_21,
++ GP_1_20_FN, GPSR1_20,
++ GP_1_19_FN, GPSR1_19,
++ GP_1_18_FN, GPSR1_18,
++ GP_1_17_FN, GPSR1_17,
++ GP_1_16_FN, GPSR1_16,
++ GP_1_15_FN, GPSR1_15,
++ GP_1_14_FN, GPSR1_14,
++ GP_1_13_FN, GPSR1_13,
++ GP_1_12_FN, GPSR1_12,
++ GP_1_11_FN, GPSR1_11,
++ GP_1_10_FN, GPSR1_10,
++ GP_1_9_FN, GPSR1_9,
++ GP_1_8_FN, GPSR1_8,
++ GP_1_7_FN, GPSR1_7,
++ GP_1_6_FN, GPSR1_6,
++ GP_1_5_FN, GPSR1_5,
++ GP_1_4_FN, GPSR1_4,
++ GP_1_3_FN, GPSR1_3,
++ GP_1_2_FN, GPSR1_2,
++ GP_1_1_FN, GPSR1_1,
++ GP_1_0_FN, GPSR1_0, }
++ },
++ { PINMUX_CFG_REG("GPSR2", 0xe6060108, 32, 1) {
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ GP_2_16_FN, GPSR2_16,
++ GP_2_15_FN, GPSR2_15,
++ GP_2_14_FN, GPSR2_14,
++ GP_2_13_FN, GPSR2_13,
++ GP_2_12_FN, GPSR2_12,
++ GP_2_11_FN, GPSR2_11,
++ GP_2_10_FN, GPSR2_10,
++ GP_2_9_FN, GPSR2_9,
++ GP_2_8_FN, GPSR2_8,
++ GP_2_7_FN, GPSR2_7,
++ GP_2_6_FN, GPSR2_6,
++ GP_2_5_FN, GPSR2_5,
++ GP_2_4_FN, GPSR2_4,
++ GP_2_3_FN, GPSR2_3,
++ GP_2_2_FN, GPSR2_2,
++ GP_2_1_FN, GPSR2_1,
++ GP_2_0_FN, GPSR2_0, }
++ },
++ { PINMUX_CFG_REG("GPSR3", 0xe606010c, 32, 1) {
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ GP_3_16_FN, GPSR3_16,
++ GP_3_15_FN, GPSR3_15,
++ GP_3_14_FN, GPSR3_14,
++ GP_3_13_FN, GPSR3_13,
++ GP_3_12_FN, GPSR3_12,
++ GP_3_11_FN, GPSR3_11,
++ GP_3_10_FN, GPSR3_10,
++ GP_3_9_FN, GPSR3_9,
++ GP_3_8_FN, GPSR3_8,
++ GP_3_7_FN, GPSR3_7,
++ GP_3_6_FN, GPSR3_6,
++ GP_3_5_FN, GPSR3_5,
++ GP_3_4_FN, GPSR3_4,
++ GP_3_3_FN, GPSR3_3,
++ GP_3_2_FN, GPSR3_2,
++ GP_3_1_FN, GPSR3_1,
++ GP_3_0_FN, GPSR3_0, }
++ },
++ { PINMUX_CFG_REG("GPSR4", 0xe6060110, 32, 1) {
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ GP_4_5_FN, GPSR4_5,
++ GP_4_4_FN, GPSR4_4,
++ GP_4_3_FN, GPSR4_3,
++ GP_4_2_FN, GPSR4_2,
++ GP_4_1_FN, GPSR4_1,
++ GP_4_0_FN, GPSR4_0, }
++ },
++ { PINMUX_CFG_REG("GPSR5", 0xe6060114, 32, 1) {
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ 0, 0,
++ GP_5_14_FN, GPSR5_14,
++ GP_5_13_FN, GPSR5_13,
++ GP_5_12_FN, GPSR5_12,
++ GP_5_11_FN, GPSR5_11,
++ GP_5_10_FN, GPSR5_10,
++ GP_5_9_FN, GPSR5_9,
++ GP_5_8_FN, GPSR5_8,
++ GP_5_7_FN, GPSR5_7,
++ GP_5_6_FN, GPSR5_6,
++ GP_5_5_FN, GPSR5_5,
++ GP_5_4_FN, GPSR5_4,
++ GP_5_3_FN, GPSR5_3,
++ GP_5_2_FN, GPSR5_2,
++ GP_5_1_FN, GPSR5_1,
++ GP_5_0_FN, GPSR5_0, }
++ },
++#undef F_
++#undef FM
++
++#define F_(x, y) x,
++#define FM(x) FN_##x,
++ { PINMUX_CFG_REG("IPSR0", 0xe6060200, 32, 4) {
++ IP0_31_28
++ IP0_27_24
++ IP0_23_20
++ IP0_19_16
++ IP0_15_12
++ IP0_11_8
++ IP0_7_4
++ IP0_3_0 }
++ },
++ { PINMUX_CFG_REG("IPSR1", 0xe6060204, 32, 4) {
++ IP1_31_28
++ IP1_27_24
++ IP1_23_20
++ IP1_19_16
++ IP1_15_12
++ IP1_11_8
++ IP1_7_4
++ IP1_3_0 }
++ },
++ { PINMUX_CFG_REG("IPSR2", 0xe6060208, 32, 4) {
++ IP2_31_28
++ IP2_27_24
++ IP2_23_20
++ IP2_19_16
++ IP2_15_12
++ IP2_11_8
++ IP2_7_4
++ IP2_3_0 }
++ },
++ { PINMUX_CFG_REG("IPSR3", 0xe606020c, 32, 4) {
++ IP3_31_28
++ IP3_27_24
++ IP3_23_20
++ IP3_19_16
++ IP3_15_12
++ IP3_11_8
++ IP3_7_4
++ IP3_3_0 }
++ },
++ { PINMUX_CFG_REG("IPSR4", 0xe6060210, 32, 4) {
++ IP4_31_28
++ IP4_27_24
++ IP4_23_20
++ IP4_19_16
++ IP4_15_12
++ IP4_11_8
++ IP4_7_4
++ IP4_3_0 }
++ },
++ { PINMUX_CFG_REG("IPSR5", 0xe6060214, 32, 4) {
++ IP5_31_28
++ IP5_27_24
++ IP5_23_20
++ IP5_19_16
++ IP5_15_12
++ IP5_11_8
++ IP5_7_4
++ IP5_3_0 }
++ },
++ { PINMUX_CFG_REG("IPSR6", 0xe6060218, 32, 4) {
++ IP6_31_28
++ IP6_27_24
++ IP6_23_20
++ IP6_19_16
++ IP6_15_12
++ IP6_11_8
++ IP6_7_4
++ IP6_3_0 }
++ },
++ { PINMUX_CFG_REG("IPSR7", 0xe606021c, 32, 4) {
++ IP7_31_28
++ IP7_27_24
++ IP7_23_20
++ IP7_19_16
++ IP7_15_12
++ IP7_11_8
++ IP7_7_4
++ IP7_3_0 }
++ },
++ { PINMUX_CFG_REG("IPSR8", 0xe6060220, 32, 4) {
++ IP8_31_28
++ IP8_27_24
++ IP8_23_20
++ IP8_19_16
++ IP8_15_12
++ IP8_11_8
++ IP8_7_4
++ IP8_3_0 }
++ },
++#undef F_
++#undef FM
++
++#define F_(x, y) x,
++#define FM(x) FN_##x,
++ { PINMUX_CFG_REG_VAR("MOD_SEL0", 0xe6060500, 32,
++ 4, 4, 4, 4, 1,
++ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) {
++ /* RESERVED 31, 30, 29, 28 */
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ /* RESERVED 27, 26, 25, 24 */
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ /* RESERVED 23, 22, 21, 20 */
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ /* RESERVED 19, 18, 17, 16 */
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ /* RESERVED 15, 14, 13, 12 */
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, /* RESERVED 11 */
++ MOD_SEL0_10
++ MOD_SEL0_9
++ MOD_SEL0_8
++ MOD_SEL0_7
++ MOD_SEL0_6
++ MOD_SEL0_5
++ MOD_SEL0_4
++ MOD_SEL0_3
++ MOD_SEL0_2
++ MOD_SEL0_1
++ MOD_SEL0_0 }
++ },
++ { },
++};
++
++static const struct sh_pfc_soc_operations pinmux_ops = {
++#if 0
++ .get_io_voltage = r8a7797_get_io_voltage,
++ .set_io_voltage = r8a7797_set_io_voltage,
++#endif
++};
++
++const struct sh_pfc_soc_info r8a7797_pinmux_info = {
++ .name = "r8a77970_pfc",
++ .ops = &pinmux_ops,
++ .unlock_reg = 0xe6060000, /* PMMR */
++
++ .function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
++
++ .pins = pinmux_pins,
++ .nr_pins = ARRAY_SIZE(pinmux_pins),
++ .groups = pinmux_groups,
++ .nr_groups = ARRAY_SIZE(pinmux_groups),
++ .functions = pinmux_functions,
++ .nr_functions = ARRAY_SIZE(pinmux_functions),
++
++ .cfg_regs = pinmux_config_regs,
++
++ .pinmux_data = pinmux_data,
++ .pinmux_data_size = ARRAY_SIZE(pinmux_data),
++};
+diff --git a/drivers/pinctrl/sh-pfc/sh_pfc.h b/drivers/pinctrl/sh-pfc/sh_pfc.h
+index c6a1855..a673a00 100644
+--- a/drivers/pinctrl/sh-pfc/sh_pfc.h
++++ b/drivers/pinctrl/sh-pfc/sh_pfc.h
+@@ -269,6 +269,7 @@ struct sh_pfc_soc_info {
+ extern const struct sh_pfc_soc_info r8a7795_pinmux_info;
+ extern const struct sh_pfc_soc_info r8a7795_es1_pinmux_info;
+ extern const struct sh_pfc_soc_info r8a7796_pinmux_info;
++extern const struct sh_pfc_soc_info r8a7797_pinmux_info;
+ extern const struct sh_pfc_soc_info sh7203_pinmux_info;
+ extern const struct sh_pfc_soc_info sh7264_pinmux_info;
+ extern const struct sh_pfc_soc_info sh7269_pinmux_info;
+@@ -374,6 +375,11 @@ struct sh_pfc_soc_info {
+ PORT_GP_CFG_1(bank, 3, fn, sfx, cfg)
+ #define PORT_GP_4(bank, fn, sfx) PORT_GP_CFG_4(bank, fn, sfx, 0)
+
++#define PORT_GP_CFG_6(bank, fn, sfx, cfg) \
++ PORT_GP_CFG_4(bank, fn, sfx, cfg), \
++ PORT_GP_CFG_1(bank, 4, fn, sfx, cfg), PORT_GP_CFG_1(bank, 5, fn, sfx, cfg)
++#define PORT_GP_6(bank, fn, sfx) PORT_GP_CFG_6(bank, fn, sfx, 0)
++
+ #define PORT_GP_CFG_8(bank, fn, sfx, cfg) \
+ PORT_GP_CFG_4(bank, fn, sfx, cfg), \
+ PORT_GP_CFG_1(bank, 4, fn, sfx, cfg), \
+@@ -420,6 +426,12 @@ struct sh_pfc_soc_info {
+ PORT_GP_CFG_1(bank, 17, fn, sfx, cfg)
+ #define PORT_GP_18(bank, fn, sfx) PORT_GP_CFG_18(bank, fn, sfx, 0)
+
++#define PORT_GP_CFG_22(bank, fn, sfx, cfg) \
++ PORT_GP_CFG_18(bank, fn, sfx, cfg), \
++ PORT_GP_CFG_1(bank, 18, fn, sfx, cfg), PORT_GP_CFG_1(bank, 19, fn, sfx, cfg), \
++ PORT_GP_CFG_1(bank, 20, fn, sfx, cfg), PORT_GP_CFG_1(bank, 21, fn, sfx, cfg)
++#define PORT_GP_22(bank, fn, sfx) PORT_GP_CFG_22(bank, fn, sfx, 0)
++
+ #define PORT_GP_CFG_23(bank, fn, sfx, cfg) \
+ PORT_GP_CFG_18(bank, fn, sfx, cfg), \
+ PORT_GP_CFG_1(bank, 18, fn, sfx, cfg), \
+diff --git a/drivers/soc/renesas/Makefile b/drivers/soc/renesas/Makefile
+index 504fb05..df143fe 100644
+--- a/drivers/soc/renesas/Makefile
++++ b/drivers/soc/renesas/Makefile
+@@ -16,11 +16,14 @@ obj-$(CONFIG_ARCH_R8A7793) += rcar-sysc.o r8a7791-sysc.o
+ obj-$(CONFIG_ARCH_R8A7794) += rcar-sysc.o r8a7794-sysc.o
+ obj-$(CONFIG_ARCH_R8A7795) += rcar-sysc.o r8a7795-sysc.o
+ obj-$(CONFIG_ARCH_R8A7796) += rcar-sysc.o r8a7796-sysc.o
++obj-$(CONFIG_ARCH_R8A7797) += rcar-sysc.o r8a7797-sysc.o
+
+ obj-$(CONFIG_ARCH_R8A7795) += rcar-avs.o
+ obj-$(CONFIG_ARCH_R8A7796) += rcar-avs.o
++obj-$(CONFIG_ARCH_R8A7797) += rcar-avs.o
+ # EMS for R-Car Gen3
+ obj-$(CONFIG_ARCH_R8A7795) += rcar_ems_ctrl.o
+ obj-$(CONFIG_ARCH_R8A7796) += rcar_ems_ctrl.o
++obj-$(CONFIG_ARCH_R8A7797) += rcar_ems_ctrl.o
+
+ obj-$(CONFIG_RCAR_DDR_BACKUP) += s2ram_ddr_backup.o
+diff --git a/drivers/soc/renesas/r8a7797-sysc.c b/drivers/soc/renesas/r8a7797-sysc.c
+new file mode 100644
+index 0000000..b71bdedb
+--- /dev/null
++++ b/drivers/soc/renesas/r8a7797-sysc.c
+@@ -0,0 +1,39 @@
++/*
++ * Renesas R-Car V3M System Controller
++ *
++ * Copyright (C) 2016 Glider bvba
++ *
++ * 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; version 2 of the License.
++ */
++
++#include <linux/bug.h>
++#include <linux/kernel.h>
++
++#include <dt-bindings/power/r8a7797-sysc.h>
++
++#include "rcar-sysc.h"
++
++static const struct rcar_sysc_area r8a7797_areas[] __initconst = {
++ { "always-on", 0, 0, R8A7797_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
++ { "ca53-scu", 0x140, 0, R8A7797_PD_CA53_SCU, R8A7797_PD_ALWAYS_ON,
++ PD_SCU },
++ { "ca53-cpu0", 0x200, 0, R8A7797_PD_CA53_CPU0, R8A7797_PD_CA53_SCU,
++ PD_CPU_NOCR },
++ { "ca53-cpu1", 0x200, 1, R8A7797_PD_CA53_CPU1, R8A7797_PD_CA53_SCU,
++ PD_CPU_NOCR },
++ { "cr7", 0x240, 0, R8A7797_PD_CR7, R8A7797_PD_ALWAYS_ON },
++ { "a3ir", 0x180, 0, R8A7797_PD_A3IR, R8A7797_PD_ALWAYS_ON },
++ { "a2ir0", 0x400, 0, R8A7797_PD_A2IR0, R8A7797_PD_ALWAYS_ON },
++ { "a2ir1", 0x400, 1, R8A7797_PD_A2IR1, R8A7797_PD_A2IR0 },
++ { "a2ir2", 0x400, 2, R8A7797_PD_A2IR2, R8A7797_PD_A2IR0 },
++ { "a2ir3", 0x400, 3, R8A7797_PD_A2IR3, R8A7797_PD_A2IR0 },
++ { "a2sc0", 0x400, 4, R8A7797_PD_A2SC0, R8A7797_PD_ALWAYS_ON },
++ { "a2sc1", 0x400, 5, R8A7797_PD_A2SC1, R8A7797_PD_A2SC0 },
++};
++
++const struct rcar_sysc_info r8a7797_sysc_info __initconst = {
++ .areas = r8a7797_areas,
++ .num_areas = ARRAY_SIZE(r8a7797_areas),
++};
+diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c
+index 042500a..e6165b6 100644
+--- a/drivers/soc/renesas/rcar-sysc.c
++++ b/drivers/soc/renesas/rcar-sysc.c
+@@ -320,6 +320,9 @@ static void __init rcar_sysc_pd_setup(struct rcar_sysc_pd *pd)
+ #ifdef CONFIG_ARCH_R8A7796
+ { .compatible = "renesas,r8a7796-sysc", .data = &r8a7796_sysc_info },
+ #endif
++#ifdef CONFIG_ARCH_R8A7797
++ { .compatible = "renesas,r8a7797-sysc", .data = &r8a7797_sysc_info },
++#endif
+ { /* sentinel */ }
+ };
+
+diff --git a/drivers/soc/renesas/rcar-sysc.h b/drivers/soc/renesas/rcar-sysc.h
+index f6e842e..e7980d5 100644
+--- a/drivers/soc/renesas/rcar-sysc.h
++++ b/drivers/soc/renesas/rcar-sysc.h
+@@ -59,4 +59,5 @@ struct rcar_sysc_info {
+ extern const struct rcar_sysc_info r8a7794_sysc_info;
+ extern const struct rcar_sysc_info r8a7795_sysc_info;
+ extern const struct rcar_sysc_info r8a7796_sysc_info;
++extern const struct rcar_sysc_info r8a7797_sysc_info;
+ #endif /* __SOC_RENESAS_RCAR_SYSC_H__ */
+diff --git a/drivers/soc/renesas/rcar_ems_ctrl.c b/drivers/soc/renesas/rcar_ems_ctrl.c
+index ca9af73..388c570 100644
+--- a/drivers/soc/renesas/rcar_ems_ctrl.c
++++ b/drivers/soc/renesas/rcar_ems_ctrl.c
+@@ -24,11 +24,17 @@
+ #include <linux/pm_runtime.h>
+ #include <linux/spinlock.h>
+ #include <linux/thermal.h>
++#include <linux/sys_soc.h>
+
+ #include <linux/soc/renesas/rcar_ems_ctrl.h>
+
+ #define EMS_THERMAL_ZONE_MAX 10
+
++static const struct soc_device_attribute r8a7797[] = {
++ { .soc_id = "r8a7797" },
++ { }
++};
++
+ static void rcar_ems_monitor(struct work_struct *ws);
+ static DECLARE_DELAYED_WORK(rcar_ems_monitor_work, rcar_ems_monitor);
+
+@@ -268,6 +274,10 @@ static int __init rcar_ems_cpu_shutdown_init(void)
+
+ for_each_online_cpu(cpu) {
+ tmp_node = of_get_cpu_node(cpu, NULL);
++ if (soc_device_match(r8a7797)) {
++ if (!of_device_is_compatible(tmp_node, "arm,cortex-a53"))
++ continue;
++ }
+ if (!of_device_is_compatible(tmp_node, "arm,cortex-a57"))
+ continue;
+ for (i = 0; i < total_target_cpu; i++) {
+diff --git a/drivers/soc/renesas/renesas-soc.c b/drivers/soc/renesas/renesas-soc.c
+index 5cab1b5..9d6fdb0 100644
+--- a/drivers/soc/renesas/renesas-soc.c
++++ b/drivers/soc/renesas/renesas-soc.c
+@@ -134,6 +134,11 @@ struct renesas_soc {
+ .id = 0x52,
+ };
+
++static const struct renesas_soc soc_rcar_v3m __initconst __maybe_unused = {
++ .family = &fam_rcar_gen3,
++ .id = 0x54,
++};
++
+ static const struct renesas_soc soc_shmobile_ag5 __initconst __maybe_unused = {
+ .family = &fam_shmobile,
+ .id = 0x37,
+@@ -183,6 +188,9 @@ struct renesas_soc {
+ #ifdef CONFIG_ARCH_R8A7796
+ { .compatible = "renesas,r8a7796", .data = &soc_rcar_m3_w },
+ #endif
++#ifdef CONFIG_ARCH_R8A7797
++ { .compatible = "renesas,r8a7797", .data = &soc_rcar_v3m },
++#endif
+ #ifdef CONFIG_ARCH_SH73A0
+ { .compatible = "renesas,sh73a0", .data = &soc_shmobile_ag5 },
+ #endif
+diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c
+index 996869e..3281dc7 100644
+--- a/drivers/spi/spi-sh-msiof.c
++++ b/drivers/spi/spi-sh-msiof.c
+@@ -215,7 +215,8 @@ static int msiof_rcar_is_gen3(struct device *dev)
+ struct device_node *node = dev->of_node;
+
+ return of_device_is_compatible(node, "renesas,msiof-r8a7795") ||
+- of_device_is_compatible(node, "renesas,msiof-r8a7796");
++ of_device_is_compatible(node, "renesas,msiof-r8a7796") ||
++ of_device_is_compatible(node, "renesas,msiof-r8a7797");
+ }
+
+ static u32 sh_msiof_read(struct sh_msiof_spi_priv *p, int reg_offs)
+@@ -1188,6 +1189,7 @@ static int sh_msiof_transfer_one(struct spi_master *master,
+ { .compatible = "renesas,msiof-r8a7794", .data = &r8a779x_data },
+ { .compatible = "renesas,msiof-r8a7795", .data = &r8a779x_data },
+ { .compatible = "renesas,msiof-r8a7796", .data = &r8a779x_data },
++ { .compatible = "renesas,msiof-r8a7797", .data = &r8a779x_data },
+ {},
+ };
+ MODULE_DEVICE_TABLE(of, sh_msiof_match);
+diff --git a/drivers/thermal/rcar_gen3_thermal.c b/drivers/thermal/rcar_gen3_thermal.c
+index 39763c7..07b1a2e 100644
+--- a/drivers/thermal/rcar_gen3_thermal.c
++++ b/drivers/thermal/rcar_gen3_thermal.c
+@@ -385,6 +385,30 @@ static int rcar_gen3_r8a7795_thermal_init(struct rcar_thermal_priv *priv)
+ return 0;
+ }
+
++/* @@ transitional */
++static int rcar_gen3_r8a7797_thermal_init(struct rcar_thermal_priv *priv)
++{
++#if 0
++ unsigned long flags;
++ unsigned long reg_val;
++
++ spin_lock_irqsave(&priv->lock, flags);
++ rcar_thermal_write(priv, REG_GEN3_THCTR, 0x0);
++ udelay(1000);
++ rcar_thermal_write(priv, REG_GEN3_IRQCTL, 0x3F);
++ rcar_thermal_write(priv, REG_GEN3_IRQEN,
++ IRQ_TEMP1_BIT | IRQ_TEMPD2_BIT);
++ rcar_thermal_write(priv, REG_GEN3_THCTR, CTCTL | THCNTSEN(BIT_LEN_12));
++ reg_val = rcar_thermal_read(priv, REG_GEN3_THCTR);
++ reg_val &= ~CTCTL;
++ reg_val |= THSST;
++ rcar_thermal_write(priv, REG_GEN3_THCTR, reg_val);
++
++ spin_unlock_irqrestore(&priv->lock, flags);
++#endif
++ return 0;
++}
++
+ /*
+ * Interrupt
+ */
+@@ -466,9 +490,14 @@ static int rcar_gen3_thermal_remove(struct platform_device *pdev)
+ .thermal_init = rcar_gen3_r8a7796_thermal_init,
+ };
+
++static const struct rcar_thermal_data r8a7797_data = {
++ .thermal_init = rcar_gen3_r8a7797_thermal_init,
++};
++
+ static const struct of_device_id rcar_thermal_dt_ids[] = {
+ { .compatible = "renesas,thermal-r8a7795", .data = &r8a7795_data},
+ { .compatible = "renesas,thermal-r8a7796", .data = &r8a7796_data},
++ { .compatible = "renesas,thermal-r8a7797", .data = &r8a7797_data},
+ {},
+ };
+ MODULE_DEVICE_TABLE(of, rcar_thermal_dt_ids);
+diff --git a/include/dt-bindings/clock/r8a7797-cpg-mssr.h b/include/dt-bindings/clock/r8a7797-cpg-mssr.h
+new file mode 100644
+index 0000000..ae6b3af
+--- /dev/null
++++ b/include/dt-bindings/clock/r8a7797-cpg-mssr.h
+@@ -0,0 +1,48 @@
++/*
++ * Copyright (C) 2016 Renesas Electronics Corp.
++ *
++ * 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.
++ */
++#ifndef __DT_BINDINGS_CLOCK_R8A7797_CPG_MSSR_H__
++#define __DT_BINDINGS_CLOCK_R8A7797_CPG_MSSR_H__
++
++#include <dt-bindings/clock/renesas-cpg-mssr.h>
++
++/* r8a7797 CPG Core Clocks */
++#define R8A7797_CLK_Z2 0
++#define R8A7797_CLK_ZR 1
++#define R8A7797_CLK_ZTR 2
++#define R8A7797_CLK_ZTRD2 3
++#define R8A7797_CLK_ZT 4
++#define R8A7797_CLK_ZX 5
++#define R8A7797_CLK_S1D1 6
++#define R8A7797_CLK_S1D2 7
++#define R8A7797_CLK_S1D4 8
++#define R8A7797_CLK_S2D1 9
++#define R8A7797_CLK_S2D2 10
++#define R8A7797_CLK_S2D4 11
++#define R8A7797_CLK_LB 12
++#define R8A7797_CLK_CL 13
++#define R8A7797_CLK_ZB3 14
++#define R8A7797_CLK_ZB3D2 15
++#define R8A7797_CLK_DDR 16
++#define R8A7797_CLK_CR 17
++#define R8A7797_CLK_CRD2 18
++#define R8A7797_CLK_SD0H 19
++#define R8A7797_CLK_SD0 20
++#define R8A7797_CLK_RPC 21
++#define R8A7797_CLK_RPCD2 22
++#define R8A7797_CLK_MSO 23
++#define R8A7797_CLK_CANFD 24
++#define R8A7797_CLK_CSI0 25
++#define R8A7797_CLK_CSIREF 26
++#define R8A7797_CLK_FRAY 27
++#define R8A7797_CLK_CP 28
++#define R8A7797_CLK_CPEX 29
++#define R8A7797_CLK_R 30
++#define R8A7797_CLK_OSC 31
++
++#endif /* __DT_BINDINGS_CLOCK_R8A7797_CPG_MSSR_H__ */
+diff --git a/include/dt-bindings/power/r8a7797-sysc.h b/include/dt-bindings/power/r8a7797-sysc.h
+new file mode 100644
+index 0000000..5aef212
+--- /dev/null
++++ b/include/dt-bindings/power/r8a7797-sysc.h
+@@ -0,0 +1,32 @@
++/*
++ * Copyright (C) 2016 Glider bvba
++ *
++ * 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; version 2 of the License.
++ */
++#ifndef __DT_BINDINGS_POWER_R8A7797_SYSC_H__
++#define __DT_BINDINGS_POWER_R8A7797_SYSC_H__
++
++/*
++ * These power domain indices match the numbers of the interrupt bits
++ * representing the power areas in the various Interrupt Registers
++ * (e.g. SYSCISR, Interrupt Status Register)
++ */
++
++#define R8A7797_PD_CA53_CPU0 5
++#define R8A7797_PD_CA53_CPU1 6
++#define R8A7797_PD_CR7 13
++#define R8A7797_PD_CA53_SCU 21
++#define R8A7797_PD_A2IR0 23
++#define R8A7797_PD_A3IR 24
++#define R8A7797_PD_A2IR1 27
++#define R8A7797_PD_A2IR2 28
++#define R8A7797_PD_A2IR3 29
++#define R8A7797_PD_A2SC0 30
++#define R8A7797_PD_A2SC1 31
++
++/* Always-on power area */
++#define R8A7797_PD_ALWAYS_ON 32
++
++#endif /* __DT_BINDINGS_POWER_R8A7797_SYSC_H__ */
+--
+1.9.1
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0019-Revert-media-v4l2-async-remove-unneeded-.registered_.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0019-Revert-media-v4l2-async-remove-unneeded-.registered_.patch
new file mode 100644
index 0000000..72c22f5
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0019-Revert-media-v4l2-async-remove-unneeded-.registered_.patch
@@ -0,0 +1,54 @@
+From 050637736af144f4bfb096f5f47120c477349732 Mon Sep 17 00:00:00 2001
+From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+Date: Sun, 14 May 2017 15:23:57 +0300
+Subject: [PATCH] Revert "[media] v4l2-async: remove unneeded .registered_async
+ callback"
+
+This reverts commit a53d2f299dc83340c695e153363a2f21641d5f58.
+---
+ drivers/media/v4l2-core/v4l2-async.c | 7 +++++++
+ include/media/v4l2-subdev.h | 3 +++
+ 2 files changed, 10 insertions(+)
+
+diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
+index 5bada20..a4b224d 100644
+--- a/drivers/media/v4l2-core/v4l2-async.c
++++ b/drivers/media/v4l2-core/v4l2-async.c
+@@ -119,6 +119,13 @@ static int v4l2_async_test_notify(struct v4l2_async_notifier *notifier,
+ return ret;
+ }
+
++ ret = v4l2_subdev_call(sd, core, registered_async);
++ if (ret < 0 && ret != -ENOIOCTLCMD) {
++ if (notifier->unbind)
++ notifier->unbind(notifier, sd, asd);
++ return ret;
++ }
++
+ if (list_empty(&notifier->waiting) && notifier->complete)
+ return notifier->complete(notifier);
+
+diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
+index cf778c5..269904d 100644
+--- a/include/media/v4l2-subdev.h
++++ b/include/media/v4l2-subdev.h
+@@ -184,6 +184,8 @@ struct v4l2_subdev_io_pin_config {
+ * for it to be warned when the value of a control changes.
+ *
+ * @unsubscribe_event: remove event subscription from the control framework.
++ *
++ * @registered_async: the subdevice has been registered async.
+ */
+ struct v4l2_subdev_core_ops {
+ int (*log_status)(struct v4l2_subdev *sd);
+@@ -209,6 +211,7 @@ struct v4l2_subdev_core_ops {
+ struct v4l2_event_subscription *sub);
+ int (*unsubscribe_event)(struct v4l2_subdev *sd, struct v4l2_fh *fh,
+ struct v4l2_event_subscription *sub);
++ int (*registered_async)(struct v4l2_subdev *sd);
+ };
+
+ /**
+--
+1.9.1
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0020-ti-st-add-device-tree-support.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0020-ti-st-add-device-tree-support.patch
new file mode 100644
index 0000000..fff9a40
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0020-ti-st-add-device-tree-support.patch
@@ -0,0 +1,236 @@
+From 36122fec4390663b5c05d5836beb977ba2c09a68 Mon Sep 17 00:00:00 2001
+From: Eyal Reizer <eyalr@ti.com>
+Date: Thu, 23 May 2013 17:11:14 +0300
+Subject: [PATCH 099/104] ti-st: add device tree support
+
+When using device tree, driver configuration data need to be read from
+device node.
+Add support for getting the platform data information from the device
+tree information stored in the .dtb file in case it exists.
+
+Change-Id: I74f7f869fc257a057edb9f35c5fd8cbafb810164
+Signed-off-by: Eyal Reizer <eyalr@ti.com>
+Signed-off-by: bvijay <bvijay@ti.com>
+Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com>
+---
+ drivers/misc/ti-st/st_kim.c | 92 +++++++++++++++++++++++++++++++++++++++----
+ drivers/misc/ti-st/st_ll.c | 19 ++++++++-
+ 2 files changed, 102 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c
+index 71b6455..a36db89 100644
+--- a/drivers/misc/ti-st/st_kim.c
++++ b/drivers/misc/ti-st/st_kim.c
+@@ -43,6 +43,9 @@ static struct platform_device *st_kim_devices[MAX_ST_DEVICES];
+ /**********************************************************************/
+ /* internal functions */
+
++struct ti_st_plat_data *dt_pdata;
++static struct ti_st_plat_data *get_platform_data(struct device *dev);
++
+ /**
+ * st_get_plat_device -
+ * function which returns the reference to the platform device
+@@ -464,7 +467,12 @@ long st_kim_start(void *kim_data)
+ struct kim_data_s *kim_gdata = (struct kim_data_s *)kim_data;
+
+ pr_info(" %s", __func__);
+- pdata = kim_gdata->kim_pdev->dev.platform_data;
++ if (kim_gdata->kim_pdev->dev.of_node) {
++ pr_debug("use device tree data");
++ pdata = dt_pdata;
++ } else {
++ pdata = kim_gdata->kim_pdev->dev.platform_data;
++ }
+
+ do {
+ /* platform specific enabling code here */
+@@ -524,12 +532,17 @@ long st_kim_stop(void *kim_data)
+ {
+ long err = 0;
+ struct kim_data_s *kim_gdata = (struct kim_data_s *)kim_data;
+- struct ti_st_plat_data *pdata =
+- kim_gdata->kim_pdev->dev.platform_data;
++ struct ti_st_plat_data *pdata;
+ struct tty_struct *tty = kim_gdata->core_data->tty;
+
+ reinit_completion(&kim_gdata->ldisc_installed);
+
++ if (kim_gdata->kim_pdev->dev.of_node) {
++ pr_debug("use device tree data");
++ pdata = dt_pdata;
++ } else
++ pdata = kim_gdata->kim_pdev->dev.platform_data;
++
+ if (tty) { /* can be called before ldisc is installed */
+ /* Flush any pending characters in the driver and discipline. */
+ tty_ldisc_flush(tty);
+@@ -721,13 +734,53 @@ static const struct file_operations list_debugfs_fops = {
+ * board-*.c file
+ */
+
++static const struct of_device_id kim_of_match[] = {
++{
++ .compatible = "kim",
++ },
++ {}
++};
++MODULE_DEVICE_TABLE(of, kim_of_match);
++
++static struct ti_st_plat_data *get_platform_data(struct device *dev)
++{
++ struct device_node *np = dev->of_node;
++ const u32 *dt_property;
++ int len;
++
++ dt_pdata = kzalloc(sizeof(*dt_pdata), GFP_KERNEL);
++
++ if (!dt_pdata)
++ pr_err("Can't allocate device_tree platform data\n");
++
++ dt_property = of_get_property(np, "dev_name", &len);
++ if (dt_property)
++ memcpy(&dt_pdata->dev_name, dt_property, len);
++ of_property_read_u32(np, "nshutdown_gpio",
++ (u32 *)&dt_pdata->nshutdown_gpio);
++ of_property_read_u32(np, "flow_cntrl", (u32 *)&dt_pdata->flow_cntrl);
++ of_property_read_u32(np, "baud_rate", (u32 *)&dt_pdata->baud_rate);
++
++ return dt_pdata;
++}
++
+ static struct dentry *kim_debugfs_dir;
+ static int kim_probe(struct platform_device *pdev)
+ {
+ struct kim_data_s *kim_gdata;
+- struct ti_st_plat_data *pdata = pdev->dev.platform_data;
++ struct ti_st_plat_data *pdata;
+ int err;
+
++ if (pdev->dev.of_node)
++ pdata = get_platform_data(&pdev->dev);
++ else
++ pdata = pdev->dev.platform_data;
++
++ if (pdata == NULL) {
++ dev_err(&pdev->dev, "Platform Data is missing\n");
++ return -ENXIO;
++ }
++
+ if ((pdev->id != -1) && (pdev->id < MAX_ST_DEVICES)) {
+ /* multiple devices could exist */
+ st_kim_devices[pdev->id] = pdev;
+@@ -808,9 +861,16 @@ err_core_init:
+ static int kim_remove(struct platform_device *pdev)
+ {
+ /* free the GPIOs requested */
+- struct ti_st_plat_data *pdata = pdev->dev.platform_data;
++ struct ti_st_plat_data *pdata;
+ struct kim_data_s *kim_gdata;
+
++ if (pdev->dev.of_node) {
++ pr_debug("use device tree data");
++ pdata = dt_pdata;
++ } else {
++ pdata = pdev->dev.platform_data;
++ }
++
+ kim_gdata = platform_get_drvdata(pdev);
+
+ /* Free the Bluetooth/FM/GPIO
+@@ -828,12 +888,22 @@ static int kim_remove(struct platform_device *pdev)
+
+ kfree(kim_gdata);
+ kim_gdata = NULL;
++ kfree(dt_pdata);
++ dt_pdata = NULL;
++
+ return 0;
+ }
+
+ static int kim_suspend(struct platform_device *pdev, pm_message_t state)
+ {
+- struct ti_st_plat_data *pdata = pdev->dev.platform_data;
++ struct ti_st_plat_data *pdata;
++
++ if (pdev->dev.of_node) {
++ pr_debug("use device tree data");
++ pdata = dt_pdata;
++ } else {
++ pdata = pdev->dev.platform_data;
++ }
+
+ if (pdata->suspend)
+ return pdata->suspend(pdev, state);
+@@ -843,7 +913,14 @@ static int kim_suspend(struct platform_device *pdev, pm_message_t state)
+
+ static int kim_resume(struct platform_device *pdev)
+ {
+- struct ti_st_plat_data *pdata = pdev->dev.platform_data;
++ struct ti_st_plat_data *pdata;
++
++ if (pdev->dev.of_node) {
++ pr_debug("use device tree data");
++ pdata = dt_pdata;
++ } else {
++ pdata = pdev->dev.platform_data;
++ }
+
+ if (pdata->resume)
+ return pdata->resume(pdev);
+@@ -860,6 +937,7 @@ static struct platform_driver kim_platform_driver = {
+ .resume = kim_resume,
+ .driver = {
+ .name = "kim",
++ .of_match_table = of_match_ptr(kim_of_match),
+ },
+ };
+
+diff --git a/drivers/misc/ti-st/st_ll.c b/drivers/misc/ti-st/st_ll.c
+index 93b4d67..644f00e 100644
+--- a/drivers/misc/ti-st/st_ll.c
++++ b/drivers/misc/ti-st/st_ll.c
+@@ -25,7 +25,10 @@
+ #include <linux/platform_device.h>
+ #include <linux/ti_wilink_st.h>
+
++extern struct ti_st_plat_data *dt_pdata;
++
+ /**********************************************************************/
++
+ /* internal functions */
+ static void send_ll_cmd(struct st_data_s *st_data,
+ unsigned char cmd)
+@@ -53,7 +56,13 @@ static void ll_device_want_to_sleep(struct st_data_s *st_data)
+
+ /* communicate to platform about chip asleep */
+ kim_data = st_data->kim_data;
+- pdata = kim_data->kim_pdev->dev.platform_data;
++ if (kim_data->kim_pdev->dev.of_node) {
++ pr_debug("use device tree data");
++ pdata = dt_pdata;
++ } else {
++ pdata = kim_data->kim_pdev->dev.platform_data;
++ }
++
+ if (pdata->chip_asleep)
+ pdata->chip_asleep(NULL);
+ }
+@@ -86,7 +95,13 @@ static void ll_device_want_to_wakeup(struct st_data_s *st_data)
+
+ /* communicate to platform about chip wakeup */
+ kim_data = st_data->kim_data;
+- pdata = kim_data->kim_pdev->dev.platform_data;
++ if (kim_data->kim_pdev->dev.of_node) {
++ pr_debug("use device tree data");
++ pdata = dt_pdata;
++ } else {
++ pdata = kim_data->kim_pdev->dev.platform_data;
++ }
++
+ if (pdata->chip_awake)
+ pdata->chip_awake(NULL);
+ }
+--
+1.7.10.4
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0021-btwilink-add-minimal-device-tree-support.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0021-btwilink-add-minimal-device-tree-support.patch
new file mode 100644
index 0000000..b628784
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0021-btwilink-add-minimal-device-tree-support.patch
@@ -0,0 +1,54 @@
+From ce021cc0ed5fe1f8068edb41996d05ebe5e11954 Mon Sep 17 00:00:00 2001
+From: Eyal Reizer <eyalr@ti.com>
+Date: Thu, 23 May 2013 17:15:21 +0300
+Subject: [PATCH 100/104] btwilink: add minimal device tree support
+
+Add minimal device tree support to the btwilink driver that is used
+for binding bluetooth with the ti-st shared transport driver.
+
+Change-Id: I301c49d29046f20f8868bebb14347e82c12c8140
+Signed-off-by: Eyal Reizer <eyalr@ti.com>
+Signed-off-by: bvijay <bvijay@ti.com>
+Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com>
+---
+ drivers/bluetooth/btwilink.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/drivers/bluetooth/btwilink.c b/drivers/bluetooth/btwilink.c
+index 24a652f..a369bf7 100644
+--- a/drivers/bluetooth/btwilink.c
++++ b/drivers/bluetooth/btwilink.c
+@@ -30,6 +30,7 @@
+
+ #include <linux/ti_wilink_st.h>
+ #include <linux/module.h>
++#include <linux/of.h>
+
+ /* Bluetooth Driver Version */
+ #define VERSION "1.0"
+@@ -273,6 +274,14 @@ static int ti_st_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
+ return 0;
+ }
+
++static const struct of_device_id btwilink_of_match[] = {
++{
++ .compatible = "btwilink",
++ },
++ {}
++};
++MODULE_DEVICE_TABLE(of, btwilink_of_match);
++
+ static int bt_ti_probe(struct platform_device *pdev)
+ {
+ static struct ti_st *hst;
+@@ -336,6 +345,7 @@ static struct platform_driver btwilink_driver = {
+ .remove = bt_ti_remove,
+ .driver = {
+ .name = "btwilink",
++ .of_match_table = of_match_ptr(btwilink_of_match),
+ },
+ };
+
+--
+1.7.10.4
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0022-ASoC-Modify-check-condition-of-multiple-bindings-of-.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0022-ASoC-Modify-check-condition-of-multiple-bindings-of-.patch
new file mode 100644
index 0000000..7b08da4
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0022-ASoC-Modify-check-condition-of-multiple-bindings-of-.patch
@@ -0,0 +1,42 @@
+From 2fc4f16b075264fae016ea3db1f1f81d30cb0ab6 Mon Sep 17 00:00:00 2001
+From: Andrey Gusakov <andrey.gusakov@cogentembedded.com>
+Date: Tue, 13 Dec 2016 18:08:39 +0300
+Subject: [PATCH 102/104] ASoC: Modify check condition of multiple bindings of
+ components
+
+https://patchwork.kernel.org/patch/7385501/
+...and some more hacks to bind one component (with several DAIs)
+to more than one sound card.
+
+Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com>
+---
+ sound/soc/soc-core.c | 6 ++++--
+ 2 files changed, 4 insertions(+), 14 deletions(-)
+
+diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
+index 16369ca..899d013 100644
+--- a/sound/soc/soc-core.c
++++ b/sound/soc/soc-core.c
+@@ -1373,7 +1373,8 @@ static int soc_probe_component(struct snd_soc_card *card,
+ return 0;
+
+ if (component->card) {
+- if (component->card != card) {
++ if (component->card != card &&
++ component->registered_as_component) {
+ dev_err(component->dev,
+ "Trying to bind component to card \"%s\" but is already bound to card \"%s\"\n",
+ card->name, component->card->name);
+@@ -3049,7 +3050,8 @@ int snd_soc_register_component(struct device *dev,
+ goto err_free;
+
+ cmpnt->ignore_pmdown_time = true;
+- cmpnt->registered_as_component = true;
++ if (num_dai == 1)
++ cmpnt->registered_as_component = true;
+
+ ret = snd_soc_register_dais(cmpnt, dai_drv, num_dai, true);
+ if (ret < 0) {
+--
+1.7.10.4
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0023-ASoC-add-dummy-Si468x-driver.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0023-ASoC-add-dummy-Si468x-driver.patch
new file mode 100644
index 0000000..fa27dc1
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0023-ASoC-add-dummy-Si468x-driver.patch
@@ -0,0 +1,123 @@
+From 8829efb30ecbecde33a266ddaed25a74cebbbaf2 Mon Sep 17 00:00:00 2001
+From: Andrey Gusakov <andrey.gusakov@cogentembedded.com>
+Date: Tue, 13 Dec 2016 18:07:13 +0300
+Subject: [PATCH 103/104] ASoC: add dummy Si468x driver
+
+
+Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com>
+---
+ sound/soc/codecs/Kconfig | 3 +++
+ sound/soc/codecs/Makefile | 2 ++
+ sound/soc/codecs/si468x.c | 66 +++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 71 insertions(+)
+ create mode 100644 sound/soc/codecs/si468x.c
+
+diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
+index 4d82a58..264fe79 100644
+--- a/sound/soc/codecs/Kconfig
++++ b/sound/soc/codecs/Kconfig
+@@ -588,6 +588,9 @@ config SND_SOC_PCM3168A_SPI
+ select SND_SOC_PCM3168A
+ select REGMAP_SPI
+
++config SND_SOC_SI468X
++ tristate "Dummy sound driver for Si468x radio"
++
+ config SND_SOC_PCM5102A
+ tristate
+
+diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
+index 0f548fd3..71a6c2f 100644
+--- a/sound/soc/codecs/Makefile
++++ b/sound/soc/codecs/Makefile
+@@ -116,6 +116,7 @@ snd-soc-sigmadsp-objs := sigmadsp.o
+ snd-soc-sigmadsp-i2c-objs := sigmadsp-i2c.o
+ snd-soc-sigmadsp-regmap-objs := sigmadsp-regmap.o
+ snd-soc-si476x-objs := si476x.o
++snd-soc-si468x-objs := si468x.o
+ snd-soc-sirf-audio-codec-objs := sirf-audio-codec.o
+ snd-soc-sn95031-objs := sn95031.o
+ snd-soc-spdif-tx-objs := spdif_transmitter.o
+@@ -328,6 +329,7 @@ obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o
+ obj-$(CONFIG_SND_SOC_SIGMADSP_I2C) += snd-soc-sigmadsp-i2c.o
+ obj-$(CONFIG_SND_SOC_SIGMADSP_REGMAP) += snd-soc-sigmadsp-regmap.o
+ obj-$(CONFIG_SND_SOC_SI476X) += snd-soc-si476x.o
++obj-$(CONFIG_SND_SOC_SI468X) += snd-soc-si468x.o
+ obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o
+ obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif-rx.o snd-soc-spdif-tx.o
+ obj-$(CONFIG_SND_SOC_SSM2518) += snd-soc-ssm2518.o
+diff --git a/sound/soc/codecs/si468x.c b/sound/soc/codecs/si468x.c
+new file mode 100644
+index 0000000..18b099f
+--- /dev/null
++++ b/sound/soc/codecs/si468x.c
+@@ -0,0 +1,66 @@
++/*
++ * Dummy sound driver for Si468x DAB/FM/AM chips
++ * Copyright 2016 Andrey Gusakov <andrey.gusakov@cogentembedded.com>
++ *
++ * Based on: Driver for the DFBM-CS320 bluetooth module
++ * Copyright 2011 Lars-Peter Clausen <lars@metafoo.de>
++ *
++ * 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/init.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++
++#include <sound/soc.h>
++
++static struct snd_soc_dai_driver si468x_dai = {
++ .name = "si468x-pcm",
++ .capture = {
++ .channels_min = 2,
++ .channels_max = 2,
++ .rates = SNDRV_PCM_RATE_48000,
++ .formats = SNDRV_PCM_FMTBIT_S16_LE,
++ },
++};
++
++static struct snd_soc_codec_driver soc_codec_dev_si468x;
++
++static int si468x_probe(struct platform_device *pdev)
++{
++ return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_si468x,
++ &si468x_dai, 1);
++}
++
++static int si468x_remove(struct platform_device *pdev)
++{
++ snd_soc_unregister_codec(&pdev->dev);
++
++ return 0;
++}
++
++static const struct of_device_id si468x_of_match[] = {
++ { .compatible = "si,si468x-pcm", },
++ { }
++};
++MODULE_DEVICE_TABLE(of, si468x_of_match);
++
++static struct platform_driver si468x_driver = {
++ .driver = {
++ .name = "si468x",
++ .of_match_table = si468x_of_match,
++ .owner = THIS_MODULE,
++ },
++ .probe = si468x_probe,
++ .remove = si468x_remove,
++};
++
++module_platform_driver(si468x_driver);
++
++MODULE_AUTHOR("Andrey Gusakov <andrey.gusakov@cogentembedded.com>");
++MODULE_DESCRIPTION("ASoC Si468x radio chip driver");
++MODULE_LICENSE("GPL");
+--
+1.7.10.4
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0030-Gen3-LVDS-cameras.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0030-Gen3-LVDS-cameras.patch
new file mode 100644
index 0000000..f927db2
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0030-Gen3-LVDS-cameras.patch
@@ -0,0 +1,6491 @@
+From 7a6b0c38e5e1502f309b89b16fad8c70645e1221 Mon Sep 17 00:00:00 2001
+From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+Date: Sun, 14 May 2017 15:20:01 +0300
+Subject: [PATCH] Gen3: LVDS cameras
+
+This add Gen3 LVDS cameras support:
+- deserializers: MAX9286, TI964, TI953, TI960
+- cameras: 10635, ov490+ov10640, ov495+OV2775
+
+Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+---
+ drivers/media/i2c/soc_camera/Kconfig | 47 +
+ drivers/media/i2c/soc_camera/Makefile | 7 +
+ drivers/media/i2c/soc_camera/max9286_max9271.c | 562 +++++++++++
+ drivers/media/i2c/soc_camera/max9286_max9271.h | 196 ++++
+ drivers/media/i2c/soc_camera/ov10635.c | 751 ++++++++++++++
+ drivers/media/i2c/soc_camera/ov10635.h | 1139 ++++++++++++++++++++++
+ drivers/media/i2c/soc_camera/ov10635_debug.h | 54 +
+ drivers/media/i2c/soc_camera/ov106xx.c | 95 ++
+ drivers/media/i2c/soc_camera/ov490_ov10640.c | 963 ++++++++++++++++++
+ drivers/media/i2c/soc_camera/ov490_ov10640.h | 33 +
+ drivers/media/i2c/soc_camera/ov495_ov2775.c | 670 +++++++++++++
+ drivers/media/i2c/soc_camera/ov495_ov2775.h | 18 +
+ drivers/media/i2c/soc_camera/ti954_ti9x3.c | 414 ++++++++
+ drivers/media/i2c/soc_camera/ti964_ti9x3.c | 382 ++++++++
+ drivers/media/i2c/soc_camera/ti9x4_ti9x3.h | 108 ++
+ drivers/media/platform/soc_camera/rcar_csi2.c | 253 +++--
+ drivers/media/platform/soc_camera/rcar_vin.c | 159 ++-
+ drivers/media/platform/soc_camera/soc_camera.c | 17 +-
+ drivers/media/platform/soc_camera/soc_mediabus.c | 16 +
+ include/media/drv-intf/soc_mediabus.h | 3 +
+ include/media/soc_camera.h | 1 +
+ 21 files changed, 5781 insertions(+), 107 deletions(-)
+ create mode 100644 drivers/media/i2c/soc_camera/max9286_max9271.c
+ create mode 100644 drivers/media/i2c/soc_camera/max9286_max9271.h
+ create mode 100644 drivers/media/i2c/soc_camera/ov10635.c
+ create mode 100644 drivers/media/i2c/soc_camera/ov10635.h
+ create mode 100644 drivers/media/i2c/soc_camera/ov10635_debug.h
+ create mode 100644 drivers/media/i2c/soc_camera/ov106xx.c
+ create mode 100644 drivers/media/i2c/soc_camera/ov490_ov10640.c
+ create mode 100644 drivers/media/i2c/soc_camera/ov490_ov10640.h
+ create mode 100644 drivers/media/i2c/soc_camera/ov495_ov2775.c
+ create mode 100644 drivers/media/i2c/soc_camera/ov495_ov2775.h
+ create mode 100644 drivers/media/i2c/soc_camera/ti954_ti9x3.c
+ create mode 100644 drivers/media/i2c/soc_camera/ti964_ti9x3.c
+ create mode 100644 drivers/media/i2c/soc_camera/ti9x4_ti9x3.h
+
+diff --git a/drivers/media/i2c/soc_camera/Kconfig b/drivers/media/i2c/soc_camera/Kconfig
+index 7704bcf..82da59f 100644
+--- a/drivers/media/i2c/soc_camera/Kconfig
++++ b/drivers/media/i2c/soc_camera/Kconfig
+@@ -6,6 +6,53 @@ config SOC_CAMERA_IMX074
+ help
+ This driver supports IMX074 cameras from Sony
+
++config SOC_CAMERA_MAX9286_MAX9271
++ tristate "max9286-max9271 GMSL support"
++ depends on SOC_CAMERA && I2C
++ help
++ This is a MAXIM max9286-max9271 GMSL driver
++
++config SOC_CAMERA_OV106XX
++ tristate "ov106xx camera support"
++ depends on SOC_CAMERA && SOC_CAMERA_MAX9286_MAX9271 && I2C
++ help
++ This is a runtime detected OmniVision ov10635 or ov490-ov10640
++ or ov495-ov2775 sensors camera driver
++
++if !SOC_CAMERA_OV106XX
++
++config SOC_CAMERA_OV10635
++ tristate "ov10635 camera support"
++ depends on SOC_CAMERA && SOC_CAMERA_MAX9286_MAX9271 && I2C
++ help
++ This is an OmniVision ov10635 sensor camera driver
++
++config SOC_CAMERA_OV490_OV10640
++ tristate "ov490-ov10640 camera support"
++ depends on SOC_CAMERA && SOC_CAMERA_MAX9286_MAX9271 && I2C
++ help
++ This is an OmniVision ov490-ov10640 sensor camera driver
++
++config SOC_CAMERA_OV495_OV2775
++ tristate "ov495-ov2775 camera support"
++ depends on SOC_CAMERA && I2C
++ help
++ This is an OmniVision ov495-ov2775 sensor camera driver
++
++endif
++
++config SOC_CAMERA_TI964_TI9X3
++ tristate "ti964-ti9x3 FPDLinkIII support"
++ depends on SOC_CAMERA && I2C
++ help
++ This is an Texas Instruments ti964-ti9X3 FPDLinkIII driver
++
++config SOC_CAMERA_TI954_TI9X3
++ tristate "ti954-ti9X3 FPDLinkIII support"
++ depends on SOC_CAMERA && I2C
++ help
++ This is an Texas Instruments ti954-ti9X3 FPDLinkIII driver
++
+ config SOC_CAMERA_MT9M001
+ tristate "mt9m001 support"
+ depends on SOC_CAMERA && I2C
+diff --git a/drivers/media/i2c/soc_camera/Makefile b/drivers/media/i2c/soc_camera/Makefile
+index 6f994f9..7d4c1ab 100644
+--- a/drivers/media/i2c/soc_camera/Makefile
++++ b/drivers/media/i2c/soc_camera/Makefile
+@@ -1,8 +1,15 @@
+ obj-$(CONFIG_SOC_CAMERA_IMX074) += imx074.o
++obj-$(CONFIG_SOC_CAMERA_MAX9286_MAX9271) += max9286_max9271.o
++obj-$(CONFIG_SOC_CAMERA_TI964_TI9X3) += ti964_ti9x3.o
++obj-$(CONFIG_SOC_CAMERA_TI954_TI9X3) += ti954_ti9x3.o
+ obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o
+ obj-$(CONFIG_SOC_CAMERA_MT9T031) += mt9t031.o
+ obj-$(CONFIG_SOC_CAMERA_MT9T112) += mt9t112.o
+ obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o
++obj-$(CONFIG_SOC_CAMERA_OV10635) += ov10635.o
++obj-$(CONFIG_SOC_CAMERA_OV490_OV10640) += ov490_ov10640.o
++obj-$(CONFIG_SOC_CAMERA_OV495_OV2775) += ov495_ov2775.o
++obj-$(CONFIG_SOC_CAMERA_OV106XX) += ov106xx.o
+ obj-$(CONFIG_SOC_CAMERA_OV2640) += ov2640.o
+ obj-$(CONFIG_SOC_CAMERA_OV5642) += ov5642.o
+ obj-$(CONFIG_SOC_CAMERA_OV6650) += ov6650.o
+diff --git a/drivers/media/i2c/soc_camera/max9286_max9271.c b/drivers/media/i2c/soc_camera/max9286_max9271.c
+new file mode 100644
+index 0000000..1261e45
+--- /dev/null
++++ b/drivers/media/i2c/soc_camera/max9286_max9271.c
+@@ -0,0 +1,562 @@
++/*
++ * MAXIM max9286-max9271 GMSL driver
++ *
++ * Copyright (C) 2015-2017 Cogent Embedded, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++
++#include <linux/delay.h>
++#include <linux/i2c.h>
++#include <linux/module.h>
++#include <linux/of_gpio.h>
++#include <linux/videodev2.h>
++#include <linux/notifier.h>
++
++#include <media/v4l2-common.h>
++#include <media/v4l2-device.h>
++#include <media/v4l2-of.h>
++#include <media/v4l2-subdev.h>
++
++#include "max9286_max9271.h"
++
++#define MAXIM_I2C_I2C_SPEED_837KHZ (0x7 << 2) /* 837kbps */
++#define MAXIM_I2C_I2C_SPEED_533KHZ (0x6 << 2) /* 533kbps */
++#define MAXIM_I2C_I2C_SPEED_339KHZ (0x5 << 2) /* 339 kbps */
++#define MAXIM_I2C_I2C_SPEED_173KHZ (0x4 << 2) /* 174kbps */
++#define MAXIM_I2C_I2C_SPEED_105KHZ (0x3 << 2) /* 105 kbps */
++#define MAXIM_I2C_I2C_SPEED_085KHZ (0x2 << 2) /* 84.7 kbps */
++#define MAXIM_I2C_I2C_SPEED_028KHZ (0x1 << 2) /* 28.3 kbps */
++#define MAXIM_I2C_I2C_SPEED MAXIM_I2C_I2C_SPEED_339KHZ
++
++struct max9286_max9271_priv {
++ struct v4l2_subdev sd[4];
++ struct device_node *sd_of_node[4];
++ int des_addr;
++ int des_quirk_addr; /* second MAX9286 on the same I2C bus */
++ int links;
++ int links_mask;
++ int lanes;
++ int csi_rate;
++ const char *fsync_mode;
++ int fsync_period;
++ char pclk_rising_edge;
++ int gpio_resetb;
++ int active_low_resetb;
++ int timeout;
++ atomic_t use_count;
++ u32 csi2_outord;
++ struct i2c_client *client;
++ int max9271_addr_map[4];
++};
++
++static int force_conf_link;
++
++static __init int max9286_max9271_force_conf_link(char *str)
++{
++ /* force configuration link */
++ /* used only if robust firmware flashing required (f.e. recovery) */
++ force_conf_link = 1;
++ return 0;
++}
++early_param("force_conf_link", max9286_max9271_force_conf_link);
++
++static void max9286_max9271_preinit(struct i2c_client *client, int addr)
++{
++ client->addr = addr; /* MAX9286-CAMx I2C */
++ reg8_write(client, 0x0a, 0x00); /* disable reverse control for all cams */
++ reg8_write(client, 0x00, 0x00); /* disable all GMSL links [0:3] */
++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */
++}
++
++static void max9286_max9271_postinit(struct i2c_client *client, int addr)
++{
++ struct max9286_max9271_priv *priv = i2c_get_clientdata(client);
++
++ client->addr = addr; /* MAX9286 I2C */
++ reg8_write(client, 0x0a, 0x00); /* disable reverse control for all cams */
++ reg8_write(client, 0x00, 0xe0 | priv->links_mask); /* enable GMSL link for CAMs */
++ reg8_write(client, 0x0b, priv->csi2_outord); /* CSI2 output order */
++ reg8_write(client, 0x15, 0x9b); /* enable CSI output, VC is set accordingly to Link number, BIT7 magic must be set */
++ reg8_write(client, 0x1b, priv->links_mask); /* enable equalizer for CAMs */
++ usleep_range(5000, 5500); /* wait 2ms after any change of reverse channel settings */
++
++ /* wait for sensor firmware up (f.e. ov490) if we did sensor reset */
++ if (priv->gpio_resetb >= 1 && priv->gpio_resetb <= 5)
++ mdelay(300);
++}
++
++static int max9286_max9271_reverse_channel_setup(struct i2c_client *client, int idx)
++{
++ struct max9286_max9271_priv *priv = i2c_get_clientdata(client);
++ u8 val = 0;
++ int timeout = priv->timeout;
++ int ret = 0;
++
++ /* Reverse channel enable */
++ client->addr = priv->des_addr; /* MAX9286-CAMx I2C */
++ reg8_write(client, 0x3f, 0x4f); /* enable custom reverse channel & first pulse length */
++ reg8_write(client, 0x34, 0xa2 | MAXIM_I2C_I2C_SPEED); /* enable artificial ACKs, I2C speed set */
++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */
++ reg8_write(client, 0x00, 0xe0 | BIT(idx)); /* enable GMSL link for CAMx */
++ reg8_write(client, 0x0a, 0x11 << idx); /* enable reverse control for CAMx */
++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */
++
++ for (;;) {
++ client->addr = priv->des_addr; /* MAX9286-CAMx I2C */
++ reg8_write(client, 0x3b, 0x1e); /* first pulse length rise time changed from 300ns to 200ns, amplitude 100mV */
++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */
++
++ client->addr = 0x40; /* MAX9271-CAMx I2C */
++ reg8_write(client, 0x08, 0x1); /* reverse channel receiver high threshold enable */
++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */
++
++ client->addr = priv->des_addr; /* MAX9286-CAMx I2C */
++ reg8_write(client, 0x3b, 0x19); /* reverse channel increase amplitude 170mV to compensate high threshold enabled */
++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */
++
++ client->addr = 0x40; /* MAX9271-CAMx I2C */
++ reg8_write(client, 0x04, 0x43); /* wake-up, enable reverse_control/conf_link */
++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */
++
++ client->addr = 0x40; /* MAX9271-CAMx I2C */
++ reg8_read(client, 0x1e, &val); /* read max9271 ID */
++ if (val == MAX9271_ID || --timeout == 0)
++ break;
++
++ /* Check if already initialized (after reboot/reset ?) */
++ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C */
++ reg8_read(client, 0x1e, &val); /* read max9271 ID */
++ if (val == MAX9271_ID) {
++ reg8_write(client, 0x04, 0x43); /* enable reverse_control/conf_link */
++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */
++ ret = -EADDRINUSE;
++ break;
++ }
++ }
++
++ if (!timeout) {
++ ret = -ETIMEDOUT;
++ goto out;
++ }
++
++ priv->links_mask |= BIT(idx);
++ priv->csi2_outord &= ~(0x3 << (idx * 2));
++ priv->csi2_outord |= ((hweight8(priv->links_mask) - 1) << (idx * 2));
++
++out:
++ dev_info(&client->dev, "link%d MAX9271 %sat 0x%x %s\n", idx,
++ ret == -EADDRINUSE ? "already " : "", priv->max9271_addr_map[idx],
++ ret == -ETIMEDOUT ? "not found: timeout GMSL link establish" : "");
++
++ return ret;
++}
++
++static void max9286_max9271_initial_setup(struct i2c_client *client)
++{
++ struct max9286_max9271_priv *priv = i2c_get_clientdata(client);
++
++ /* Initial setup */
++ client->addr = priv->des_addr; /* MAX9286-CAMx I2C */
++ reg8_write(client, 0x15, 0x13); /* disable CSI output, VC is set accordingly to Link number */
++ reg8_write(client, 0x69, 0x0f); /* mask CSI forwarding from all links */
++ switch (priv->lanes) {
++ case 1:
++ reg8_write(client, 0x12, 0x33); /* enable CSI-2 Lane D0, DBL mode, YUV422 8-bit*/
++ break;
++ case 2:
++ reg8_write(client, 0x12, 0x73); /* enable CSI-2 Lanes D0,D1, DBL mode, YUV422 8-bit*/
++ break;
++ case 3:
++ reg8_write(client, 0x12, 0xd3); /* enable CSI-2 Lanes D0-D2, DBL mode, YUV422 8-bit*/
++ break;
++ case 4:
++ reg8_write(client, 0x12, 0xf3); /* enable CSI-2 Lanes D0-D3, DBL mode, YUV422 8-bit*/
++ break;
++ default:
++ dev_err(&client->dev, "CSI2 lanes number is invalid (%d)\n", priv->lanes);
++ }
++
++ if (strcmp(priv->fsync_mode, "manual") == 0) {
++ reg8_write(client, 0x06, priv->fsync_period & 0xff);
++ reg8_write(client, 0x07, (priv->fsync_period >> 8) & 0xff);
++ reg8_write(client, 0x08, priv->fsync_period >> 16);
++ reg8_write(client, 0x01, 0x00); /* manual: FRAMESYNC set manually via [0x06:0x08] regs */
++ } else if (strcmp(priv->fsync_mode, "automatic") == 0) {
++ reg8_write(client, 0x01, 0x02); /* automatic: FRAMESYNC taken from the slowest Link */
++ } else if (strcmp(priv->fsync_mode, "semi-automatic") == 0) {
++ reg8_write(client, 0x01, 0x01); /* semi-automatic: FRAMESYNC taken from the slowest Link */
++ } else if (strcmp(priv->fsync_mode, "external") == 0) {
++ reg8_write(client, 0x01, 0xc0); /* ECU (aka MCU) based FrameSync using GPI-to-GPO */
++ }
++
++ reg8_write(client, 0x63, 0); /* disable overlap window */
++ reg8_write(client, 0x64, 0);
++ reg8_write(client, 0x0c, 0x89); /* enable HS/VS encoding, use D14/15 for HS/VS, invert VS */
++}
++
++static void max9286_max9271_gmsl_link_setup(struct i2c_client *client, int idx)
++{
++ struct max9286_max9271_priv *priv = i2c_get_clientdata(client);
++
++ /* GMSL setup */
++ client->addr = 0x40; /* MAX9271-CAMx I2C */
++ reg8_write(client, 0x0d, 0x22 | MAXIM_I2C_I2C_SPEED); /* disable artificial ACK, I2C speed set */
++ reg8_write(client, 0x07, 0x84 | (priv->pclk_rising_edge ? 0 : 0x10)); /* RAW/YUV, PCLK edge, HS/VS encoding enabled */
++ usleep_range(2000, 2500); /* wait 2ms */
++ reg8_write(client, 0x02, 0xff); /* spread spectrum +-4%, pclk range automatic, Gbps automatic */
++ usleep_range(2000, 2500); /* wait 2ms */
++
++ client->addr = priv->des_addr; /* MAX9286-CAMx I2C */
++ reg8_write(client, 0x34, 0x22 | MAXIM_I2C_I2C_SPEED); /* disable artificial ACK, I2C speed set */
++ usleep_range(2000, 2500); /* wait 2ms */
++
++ /* I2C translator setup */
++ client->addr = 0x40; /* MAX9271-CAMx I2C */
++// reg8_write(client, 0x09, maxim_map[2][idx] << 1); /* SENSOR I2C translated - must be set by sensor driver */
++// reg8_write(client, 0x0A, 0x30 << 1); /* SENSOR I2C native - must be set by sensor driver */
++ reg8_write(client, 0x0B, BROADCAST << 1); /* broadcast I2C */
++ reg8_write(client, 0x0C, priv->max9271_addr_map[idx] << 1); /* MAX9271-CAMx I2C new */
++ /* I2C addresse change */
++ reg8_write(client, 0x01, priv->des_addr << 1); /* MAX9286 I2C */
++ reg8_write(client, 0x00, priv->max9271_addr_map[idx] << 1); /* MAX9271-CAM0 I2C new */
++ usleep_range(2000, 2500); /* wait 2ms */
++ /* put MAX9271 in configuration link state */
++ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C new */
++ reg8_write(client, 0x04, 0x43); /* enable reverse_control/conf_link */
++ usleep_range(2000, 2500); /* wait 2ms */
++#ifdef MAXIM_DUMP
++ client->addr = priv->des_addr; /* MAX9286-CAMx I2C */
++ maxim_max927x_dump_regs(client);
++ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C new */
++ maxim_max927x_dump_regs(client);
++#endif
++ if (priv->gpio_resetb >= 1 && priv->gpio_resetb <= 5) {
++ /* get out from sensor reset */
++ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C new */
++ reg8_write(client, 0x0f, (0xfe & ~BIT(priv->gpio_resetb)) |
++ (priv->active_low_resetb ? 0 : BIT(priv->gpio_resetb))); /* set GPIOn value to reset */
++ reg8_write(client, 0x0e, 0x42 | BIT(priv->gpio_resetb)); /* set GPIOn direction output */
++ usleep_range(2000, 2500); /* wait 2ms */
++ reg8_write(client, 0x0f, (0xfe & ~BIT(priv->gpio_resetb)) |
++ (priv->active_low_resetb ? BIT(priv->gpio_resetb) : 0)); /* set GPIOn value to un-reset */
++ usleep_range(2000, 2500); /* wait 2ms */
++ }
++}
++
++static int max9286_max9271_initialize(struct i2c_client *client)
++{
++ struct max9286_max9271_priv *priv = i2c_get_clientdata(client);
++ int idx, ret;
++
++ dev_info(&client->dev, "LINKs=%d, LANES=%d, FSYNC mode=%s, FSYNC period=%d, PCLK edge=%s\n",
++ priv->links, priv->lanes, priv->fsync_mode, priv->fsync_period,
++ priv->pclk_rising_edge ? "rising" : "falling");
++
++ if (priv->des_quirk_addr)
++ max9286_max9271_preinit(client, priv->des_quirk_addr);
++
++ max9286_max9271_preinit(client, priv->des_addr);
++ max9286_max9271_initial_setup(client);
++
++ for (idx = 0; idx < priv->links; idx++) {
++ ret = max9286_max9271_reverse_channel_setup(client, idx);
++ if (ret)
++ continue;
++ max9286_max9271_gmsl_link_setup(client, idx);
++ }
++
++ max9286_max9271_postinit(client, priv->des_addr);
++
++ client->addr = priv->des_addr;
++
++ return 0;
++}
++
++#ifdef CONFIG_VIDEO_ADV_DEBUG
++static int max9286_max9271_g_register(struct v4l2_subdev *sd,
++ struct v4l2_dbg_register *reg)
++{
++ struct max9286_max9271_priv *priv = v4l2_get_subdevdata(sd);
++ struct i2c_client *client = priv->client;
++ int ret;
++ u8 val = 0;
++
++ ret = reg8_read(client, (u8)reg->reg, &val);
++ if (ret < 0)
++ return ret;
++
++ reg->val = val;
++ reg->size = sizeof(u8);
++
++ return 0;
++}
++
++static int max9286_max9271_s_register(struct v4l2_subdev *sd,
++ const struct v4l2_dbg_register *reg)
++{
++ struct max9286_max9271_priv *priv = v4l2_get_subdevdata(sd);
++ struct i2c_client *client = priv->client;
++
++ return reg8_write(client, (u8)reg->reg, (u8)reg->val);
++}
++#endif
++
++static int max9286_max9271_s_power(struct v4l2_subdev *sd, int on)
++{
++ struct max9286_max9271_priv *priv = v4l2_get_subdevdata(sd);
++ struct i2c_client *client = priv->client;
++
++ if (on) {
++ if (atomic_inc_return(&priv->use_count) == 1)
++ reg8_write(client, 0x69, priv->links_mask ^ 0x0f); /* unmask CSI forwarding from detected links */
++ } else {
++ if (atomic_dec_return(&priv->use_count) == 0)
++ reg8_write(client, 0x69, 0x0f); /* mask CSI forwarding from all links */
++ }
++
++ return 0;
++}
++
++static int max9286_max9271_registered_async(struct v4l2_subdev *sd)
++{
++ struct max9286_max9271_priv *priv = v4l2_get_subdevdata(sd);
++ struct i2c_client *client = priv->client;
++ int idx, tmp_addr;
++
++ /* switch to GMSL serial_link for streaming video */
++ tmp_addr = client->addr;
++ idx = sd->grp_id;
++
++ client->addr = priv->des_addr; /* MAX9286 I2C */
++ reg8_write(client, 0x0a, 0x11 << idx); /* enable reverse/forward control for CAMx */
++
++ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx */
++ reg8_write(client, 0x04, force_conf_link ? 0x43 : 0x83); /* enable reverse_control/serial_link */
++ usleep_range(2000, 2500); /* wait 2ms after changing reverse_control */
++
++ client->addr = priv->des_addr; /* MAX9286 I2C */
++ reg8_write(client, 0x0a, (priv->links_mask << 4) | priv->links_mask); /* enable reverse/forward control for all CAMs */
++
++ client->addr = tmp_addr;
++
++ return 0;
++}
++
++static struct v4l2_subdev_core_ops max9286_max9271_subdev_core_ops = {
++#ifdef CONFIG_VIDEO_ADV_DEBUG
++ .g_register = max9286_max9271_g_register,
++ .s_register = max9286_max9271_s_register,
++#endif
++ .s_power = max9286_max9271_s_power,
++ .registered_async = max9286_max9271_registered_async,
++};
++
++static struct v4l2_subdev_ops max9286_max9271_subdev_ops = {
++ .core = &max9286_max9271_subdev_core_ops,
++};
++
++static int max9286_max9271_parse_dt(struct i2c_client *client)
++{
++ struct max9286_max9271_priv *priv = i2c_get_clientdata(client);
++ struct device_node *np = client->dev.of_node;
++ struct device_node *endpoint = NULL;
++ struct property *prop;
++ int err, pwen, i;
++ int sensor_delay, gpio0 = 1, gpio1 = 1;
++ char fsync_mode_default[20] = "manual"; /* manual, automatic, semi-automatic, external */
++ u8 val = 0;
++
++ if (of_property_read_u32(np, "maxim,links", &priv->links))
++ priv->links = 4;
++
++ if (of_property_read_u32(np, "maxim,lanes", &priv->lanes))
++ priv->lanes = 4;
++
++ pwen = of_get_gpio(np, 0);
++ if (pwen > 0) {
++ err = gpio_request_one(pwen, GPIOF_OUT_INIT_HIGH, dev_name(&client->dev));
++ if (err)
++ dev_err(&client->dev, "cannot request PWEN gpio %d: %d\n", pwen, err);
++ else
++ mdelay(250);
++ }
++
++ reg8_read(client, 0x1e, &val); /* read max9286 ID */
++ if (val != MAX9286_ID) {
++ prop = of_find_property(np, "reg", NULL);
++ if (prop)
++ of_remove_property(np, prop);
++ return -ENODEV;
++ }
++
++ if (!of_property_read_u32(np, "maxim,gpio0", &gpio0) ||
++ !of_property_read_u32(np, "maxim,gpio1", &gpio1))
++ reg8_write(client, 0x0f, 0x08 | (gpio1 << 1) | gpio0);
++
++ if (of_property_read_u32(np, "maxim,resetb-gpio", &priv->gpio_resetb)) {
++ priv->gpio_resetb = -1;
++ } else {
++ if (of_property_read_bool(np, "maxim,resetb-active-high"))
++ priv->active_low_resetb = false;
++ else
++ priv->active_low_resetb = true;
++ }
++
++ if (!of_property_read_u32(np, "maxim,sensor_delay", &sensor_delay))
++ mdelay(sensor_delay);
++
++ if (of_property_read_string(np, "maxim,fsync-mode", &priv->fsync_mode))
++ priv->fsync_mode = fsync_mode_default;
++
++ if (of_property_read_u32(np, "maxim,fsync-period", &priv->fsync_period))
++ priv->fsync_period = 3200000; /* 96MHz/30fps */
++ priv->pclk_rising_edge = true;
++ if (of_property_read_bool(np, "maxim,pclk-falling-edge"))
++ priv->pclk_rising_edge = false;
++ if (of_property_read_u32(np, "maxim,timeout", &priv->timeout))
++ priv->timeout = 100;
++ if (of_property_read_u32(np, "maxim,i2c-quirk", &priv->des_quirk_addr))
++ priv->des_quirk_addr = 0;
++
++ for (i = 0; i < priv->links; i++) {
++ endpoint = of_graph_get_next_endpoint(np, endpoint);
++ if (!endpoint)
++ break;
++
++ of_node_put(endpoint);
++
++ if (of_property_read_u32(endpoint, "max9271-addr", &priv->max9271_addr_map[i])) {
++ dev_err(&client->dev, "max9271-addr not set\n");
++ return -EINVAL;
++ }
++
++ priv->sd_of_node[i] = endpoint;
++ }
++
++ return 0;
++}
++
++static void max9286_max9271_setup_remote_endpoint(struct i2c_client *client)
++{
++ struct max9286_max9271_priv *priv = i2c_get_clientdata(client);
++ struct device_node *np = client->dev.of_node;
++ struct device_node *endpoint = NULL, *rendpoint = NULL;
++ int i;
++ struct property *csi_rate_prop, *dvp_order_prop;
++
++ for (i = 0; ; i++) {
++ endpoint = of_graph_get_next_endpoint(np, endpoint);
++ if (!endpoint)
++ break;
++
++ of_node_put(endpoint);
++
++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0);
++ if (!rendpoint)
++ continue;
++
++ csi_rate_prop = of_find_property(endpoint, "csi-rate", NULL);
++ if (csi_rate_prop) {
++ /* CSI2_RATE = PCLK*sizeof(YUV8)*links/lanes */
++ priv->csi_rate = cpu_to_be32(100 * 8 * hweight8(priv->links_mask) / priv->lanes);
++ csi_rate_prop->value = &priv->csi_rate;
++ of_update_property(rendpoint, csi_rate_prop);
++ }
++
++ dvp_order_prop = of_find_property(endpoint, "dvp-order", NULL);
++ if (dvp_order_prop)
++ of_update_property(rendpoint, dvp_order_prop);
++ }
++}
++
++static int max9286_max9271_probe(struct i2c_client *client,
++ const struct i2c_device_id *did)
++{
++ struct max9286_max9271_priv *priv;
++ int err, i;
++
++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ i2c_set_clientdata(client, priv);
++ priv->des_addr = client->addr;
++ priv->client = client;
++ atomic_set(&priv->use_count, 0);
++ priv->csi2_outord = 0xff;
++
++ err = max9286_max9271_parse_dt(client);
++ if (err)
++ goto out;
++
++ err = max9286_max9271_initialize(client);
++ if (err < 0)
++ goto out;
++
++ max9286_max9271_setup_remote_endpoint(client);
++
++ for (i = 0; i < 4; i++) {
++ v4l2_subdev_init(&priv->sd[i], &max9286_max9271_subdev_ops);
++ priv->sd[i].owner = client->dev.driver->owner;
++ priv->sd[i].dev = &client->dev;
++ priv->sd[i].grp_id = i;
++ v4l2_set_subdevdata(&priv->sd[i], priv);
++ priv->sd[i].of_node = priv->sd_of_node[i];
++
++ snprintf(priv->sd[i].name, V4L2_SUBDEV_NAME_SIZE, "%s.%d %d-%04x",
++ client->dev.driver->name, i, i2c_adapter_id(client->adapter),
++ client->addr);
++
++ err = v4l2_async_register_subdev(&priv->sd[i]);
++ if (err < 0)
++ goto out;
++ }
++
++out:
++ return err;
++}
++
++static int max9286_max9271_remove(struct i2c_client *client)
++{
++ struct max9286_max9271_priv *priv = i2c_get_clientdata(client);
++ int i;
++
++ for (i = 0; i < 4; i++) {
++ v4l2_async_unregister_subdev(&priv->sd[i]);
++ v4l2_device_unregister_subdev(&priv->sd[i]);
++ }
++
++ return 0;
++}
++
++static const struct of_device_id max9286_max9271_dt_ids[] = {
++ { .compatible = "maxim,max9286-max9271" },
++ {},
++};
++MODULE_DEVICE_TABLE(of, max9286_max9271_dt_ids);
++
++static const struct i2c_device_id max9286_max9271_id[] = {
++ { "max9286_max9271", 0 },
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, max9286_max9271_id);
++
++static struct i2c_driver max9286_max9271_i2c_driver = {
++ .driver = {
++ .name = "max9286_max9271",
++ .of_match_table = of_match_ptr(max9286_max9271_dt_ids),
++ },
++ .probe = max9286_max9271_probe,
++ .remove = max9286_max9271_remove,
++ .id_table = max9286_max9271_id,
++};
++
++module_i2c_driver(max9286_max9271_i2c_driver);
++
++MODULE_DESCRIPTION("GMSL driver for MAX9286-MAX9271");
++MODULE_AUTHOR("Vladimir Barinov");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/i2c/soc_camera/max9286_max9271.h b/drivers/media/i2c/soc_camera/max9286_max9271.h
+new file mode 100644
+index 0000000..87c040b
+--- /dev/null
++++ b/drivers/media/i2c/soc_camera/max9286_max9271.h
+@@ -0,0 +1,196 @@
++/*
++ * MAXIM max9286-max9271 GMSL driver include file
++ *
++ * Copyright (C) 2015-2017 Cogent Embedded, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++
++#ifndef _MAX9286_MAX9271_H
++#define _MAX9286_MAX9271_H
++
++//#define DEBUG
++#ifdef DEBUG
++//#define WRITE_VERIFY
++#define MAXIM_DUMP
++#undef dev_dbg
++#define dev_dbg dev_info
++#endif
++
++#define REG8_NUM_RETRIES 1 /* number of read/write retries */
++#define REG16_NUM_RETRIES 10 /* number of read/write retries */
++#define MAX9271_ID 0x9
++#define MAX9286_ID 0x40
++#define BROADCAST 0x6f
++
++static inline int reg8_read(struct i2c_client *client, u8 reg, u8 *val)
++{
++ int ret, retries;
++
++ for (retries = REG8_NUM_RETRIES; retries; retries--) {
++ ret = i2c_smbus_read_byte_data(client, reg);
++ if (!(ret < 0))
++ break;
++ }
++
++ if (ret < 0) {
++ dev_dbg(&client->dev,
++ "read fail: chip 0x%x register 0x%x: %d\n",
++ client->addr, reg, ret);
++ } else {
++ *val = ret;
++ }
++
++ return ret < 0 ? ret : 0;
++}
++
++static inline int reg8_write(struct i2c_client *client, u8 reg, u8 val)
++{
++ int ret, retries;
++
++ for (retries = REG8_NUM_RETRIES; retries; retries--) {
++ ret = i2c_smbus_write_byte_data(client, reg, val);
++ if (!(ret < 0))
++ break;
++ }
++
++ if (ret < 0) {
++ dev_dbg(&client->dev,
++ "write fail: chip 0x%x register 0x%x: %d\n",
++ client->addr, reg, ret);
++ } else {
++#ifdef WRITE_VERIFY
++ u8 val2;
++ reg8_read(client, reg, &val2);
++ if (val != val2)
++ dev_err(&client->dev,
++ "write verify mismatch: chip 0x%x reg=0x%x "
++ "0x%x->0x%x\n", client->addr, reg, val, val2);
++#endif
++ }
++
++ return ret < 0 ? ret : 0;
++}
++
++static inline int reg16_read(struct i2c_client *client, u16 reg, u8 *val)
++{
++ int ret, retries;
++ u8 buf[2] = {reg >> 8, reg & 0xff};
++
++ for (retries = REG16_NUM_RETRIES; retries; retries--) {
++ ret = i2c_master_send(client, buf, 2);
++ if (ret == 2) {
++ ret = i2c_master_recv(client, buf, 1);
++ if (ret == 1)
++ break;
++ }
++ }
++
++ if (ret < 0) {
++ dev_dbg(&client->dev,
++ "read fail: chip 0x%x register 0x%x: %d\n",
++ client->addr, reg, ret);
++ } else {
++ *val = buf[0];
++ }
++
++ return ret < 0 ? ret : 0;
++}
++
++static inline int reg16_write(struct i2c_client *client, u16 reg, u8 val)
++{
++ int ret, retries;
++ u8 buf[3] = {reg >> 8, reg & 0xff, val};
++
++ for (retries = REG16_NUM_RETRIES; retries; retries--) {
++ ret = i2c_master_send(client, buf, 3);
++ if (ret == 3)
++ break;
++ }
++
++ if (ret < 0) {
++ dev_dbg(&client->dev,
++ "write fail: chip 0x%x register 0x%x: %d\n",
++ client->addr, reg, ret);
++ } else {
++#ifdef WRITE_VERIFY
++ u8 val2;
++ reg16_read(client, reg, &val2);
++ if (val != val2)
++ dev_err(&client->dev,
++ "write verify mismatch: chip 0x%x reg=0x%x "
++ "0x%x->0x%x\n", client->addr, reg, val, val2);
++#endif
++ }
++
++ return ret < 0 ? ret : 0;
++}
++
++#ifdef MAXIM_DUMP
++static void maxim_ovsensor_dump_regs(struct i2c_client *client)
++{
++ int ret, i;
++ u8 val = 0;
++ u16 regs[] = {0x300a, 0x300b, 0x300c};
++
++ dev_dbg(&client->dev, "dump regs 0x%x\n", client->addr);
++
++ for (i = 0; i < sizeof(regs) / 2; i++) {
++ ret = reg16_read(client, regs[i], &val);
++ if (ret < 0)
++ dev_err(&client->dev,
++ "read fail: chip 0x%x register 0x%02x: %d\n",
++ client->addr, regs[i], ret);
++ printk("0x%02x -> 0x%x\n", regs[i], val);
++ }
++}
++
++static void maxim_ov10635_dump_format_regs(struct i2c_client *client)
++{
++ int ret, i;
++ u8 val;
++ u16 regs[] = {0x3003, 0x3004, 0x4300,
++ 0x4605, 0x3621, 0x3702, 0x3703, 0x3704,
++ 0x3802, 0x3803, 0x3806, 0x3807, 0x3808, 0x3809, 0x380a,
++ 0x380b, 0x380c, 0x380d, 0x380e, 0x380f,
++ 0x4606, 0x4607, 0x460a, 0x460b,
++ 0xc488, 0xc489, 0xc48a, 0xc48b,
++ 0xc4cc, 0xc4cd, 0xc4ce, 0xc4cf, 0xc512, 0xc513,
++ 0xc518, 0xc519, 0xc51a, 0xc51b,
++ };
++
++ dev_dbg(&client->dev, "dump regs 0x%x\n", client->addr);
++
++ for (i = 0; i < sizeof(regs) / 2; i++) {
++ ret = reg16_read(client, regs[i], &val);
++ if (ret < 0)
++ dev_err(&client->dev,
++ "read fail: chip 0x%x register 0x%02x: %d\n",
++ client->addr, regs[i], ret);
++ printk("0x%02x -> 0x%x\n", regs[i], val);
++ }
++}
++
++static void maxim_max927x_dump_regs(struct i2c_client *client)
++{
++ int ret;
++ u8 reg;
++
++ dev_dbg(&client->dev, "dump regs 0x%x\n", client->addr);
++
++ for (reg = 0; reg < 0x20; reg++) {
++ ret = i2c_smbus_read_byte_data(client, reg);
++ if (ret < 0)
++ dev_err(&client->dev,
++ "read fail: chip 0x%x register 0x%x: %d\n",
++ client->addr, reg, ret);
++ printk("0x%02x ", ret);
++ if (((reg + 1) % 0x10) == 0)
++ printk("\n");
++ }
++}
++#endif /* MAXIM_DUMP */
++#endif /* _MAX9286_MAX9271_H */
+diff --git a/drivers/media/i2c/soc_camera/ov10635.c b/drivers/media/i2c/soc_camera/ov10635.c
+new file mode 100644
+index 0000000..fd72396
+--- /dev/null
++++ b/drivers/media/i2c/soc_camera/ov10635.c
+@@ -0,0 +1,751 @@
++/*
++ * OmniVision ov10635 sensor camera driver
++ *
++ * Copyright (C) 2015-2017 Cogent Embedded, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++
++#include <linux/delay.h>
++#include <linux/init.h>
++#include <linux/i2c.h>
++#include <linux/module.h>
++#include <linux/videodev2.h>
++
++#include <media/soc_camera.h>
++#include <media/v4l2-common.h>
++#include <media/v4l2-ctrls.h>
++#include <media/v4l2-of.h>
++
++#include "max9286_max9271.h"
++#include "ov10635.h"
++
++#define OV10635_I2C_ADDR 0x30
++
++#define OV10635_PID 0x300a
++#define OV10635_VER 0x300b
++#define OV10635_VERSION_REG 0xa635
++#define OV10635_VERSION(pid, ver) (((pid) << 8) | ((ver) & 0xff))
++
++struct ov10635_priv {
++ struct v4l2_subdev sd;
++ struct v4l2_ctrl_handler hdl;
++ struct media_pad pad;
++ struct v4l2_rect rect;
++ int subsampling;
++ int fps_denominator;
++ int init_complete;
++ u8 id[6];
++ int dvp_order;
++ /* serializers */
++ int max9286_addr;
++ int max9271_addr;
++ int ti964_addr;
++ int ti954_addr;
++ int ti9x3_addr;
++ int port;
++ int gpio_resetb;
++ int gpio_fsin;
++};
++
++static inline struct ov10635_priv *to_ov10635(const struct i2c_client *client)
++{
++ return container_of(i2c_get_clientdata(client), struct ov10635_priv, sd);
++}
++
++static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
++{
++ return &container_of(ctrl->handler, struct ov10635_priv, hdl)->sd;
++}
++
++static void ov10635_s_port(struct i2c_client *client, int fwd_en)
++{
++ struct ov10635_priv *priv = to_ov10635(client);
++ int tmp_addr;
++
++ if (priv->max9286_addr) {
++ tmp_addr = client->addr;
++ client->addr = priv->max9286_addr; /* Deserializer I2C address */
++ reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */
++ client->addr = tmp_addr;
++ };
++}
++
++static int ov10635_set_regs(struct i2c_client *client,
++ const struct ov10635_reg *regs, int nr_regs)
++{
++ int i;
++
++ for (i = 0; i < nr_regs; i++) {
++ if (reg16_write(client, regs[i].reg, regs[i].val)) {
++ usleep_range(100, 150); /* wait 100ns */
++ reg16_write(client, regs[i].reg, regs[i].val);
++ }
++ }
++
++ return 0;
++}
++
++static int ov10635_s_stream(struct v4l2_subdev *sd, int enable)
++{
++ return 0;
++}
++
++static int ov10635_set_window(struct v4l2_subdev *sd, int subsampling)
++{
++ struct i2c_client *client = v4l2_get_subdevdata(sd);
++ struct ov10635_priv *priv = to_ov10635(client);
++
++ /* disable clocks */
++ reg16_write(client, 0x302e, 0x00);
++ reg16_write(client, 0x301b, 0xff);
++ reg16_write(client, 0x301c, 0xff);
++ reg16_write(client, 0x301a, 0xff);
++
++ /* setup resolution */
++ reg16_write(client, 0x3808, priv->rect.width >> 8);
++ reg16_write(client, 0x3809, priv->rect.width & 0xff);
++ reg16_write(client, 0x380a, priv->rect.height >> 8);
++ reg16_write(client, 0x380b, priv->rect.height & 0xff);
++
++ /* enable/disable subsampling */
++ reg16_write(client, 0x5005, subsampling ? 0x89 : 0x08);
++ reg16_write(client, 0x3007, subsampling ? 0x02 : 0x01);
++ reg16_write(client, 0x4004, subsampling ? 0x02 : 0x04);
++
++#if 0 /* This is implemented in VIN via SOC_CAMERA layer, hence skip */
++ /* horiz crop start */
++ reg16_write(client, 0x3800, priv->rect.left >> 8);
++ reg16_write(client, 0x3801, priv->rect.left & 0xff);
++ /* horiz crop end */
++ reg16_write(client, 0x3804, (priv->rect.left + priv->rect.width + 1) >> 8);
++ reg16_write(client, 0x3805, (priv->rect.left + priv->rect.width + 1) & 0xff);
++ /* vert crop start */
++ reg16_write(client, 0x3802, priv->rect.top >> 8);
++ reg16_write(client, 0x3803, priv->rect.top & 0xff);
++ /* vert crop end */
++ reg16_write(client, 0x3806, (priv->rect.top + priv->rect.height + 1) >> 8);
++ reg16_write(client, 0x3807, (priv->rect.top + priv->rect.height + 1) & 0xff);
++#endif
++ /* enable clocks */
++ reg16_write(client, 0x301b, 0xf0);
++ reg16_write(client, 0x301c, 0xf0);
++ reg16_write(client, 0x301a, 0xf0);
++ reg16_write(client, 0x302e, 0x01);
++
++ return 0;
++};
++
++static int ov10635_get_fmt(struct v4l2_subdev *sd,
++ struct v4l2_subdev_pad_config *cfg,
++ struct v4l2_subdev_format *format)
++{
++ struct v4l2_mbus_framefmt *mf = &format->format;
++ struct i2c_client *client = v4l2_get_subdevdata(sd);
++ struct ov10635_priv *priv = to_ov10635(client);
++
++ if (format->pad)
++ return -EINVAL;
++
++ mf->width = priv->rect.width;
++ mf->height = priv->rect.height;
++ mf->code = MEDIA_BUS_FMT_YUYV8_2X8;
++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M;
++ mf->field = V4L2_FIELD_NONE;
++
++ return 0;
++}
++
++static int ov10635_set_fmt(struct v4l2_subdev *sd,
++ struct v4l2_subdev_pad_config *cfg,
++ struct v4l2_subdev_format *format)
++{
++ struct v4l2_mbus_framefmt *mf = &format->format;
++
++ mf->code = MEDIA_BUS_FMT_YUYV8_2X8;
++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M;
++ mf->field = V4L2_FIELD_NONE;
++
++ if (format->which == V4L2_SUBDEV_FORMAT_TRY)
++ cfg->try_fmt = *mf;
++
++ return 0;
++}
++
++static int ov10635_enum_mbus_code(struct v4l2_subdev *sd,
++ struct v4l2_subdev_pad_config *cfg,
++ struct v4l2_subdev_mbus_code_enum *code)
++{
++ if (code->pad || code->index > 0)
++ return -EINVAL;
++
++ code->code = MEDIA_BUS_FMT_YUYV8_2X8;
++
++ return 0;
++}
++
++static int ov10635_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
++{
++ struct i2c_client *client = v4l2_get_subdevdata(sd);
++ struct ov10635_priv *priv = to_ov10635(client);
++
++ memcpy(edid->edid, priv->id, 6);
++
++ edid->edid[6] = 0xff;
++ edid->edid[7] = client->addr;
++ edid->edid[8] = OV10635_VERSION_REG >> 8;
++ edid->edid[9] = OV10635_VERSION_REG & 0xff;
++
++ return 0;
++}
++
++static int ov10635_set_selection(struct v4l2_subdev *sd,
++ struct v4l2_subdev_pad_config *cfg,
++ struct v4l2_subdev_selection *sel)
++{
++ struct v4l2_rect *rect = &sel->r;
++ struct i2c_client *client = v4l2_get_subdevdata(sd);
++ struct ov10635_priv *priv = to_ov10635(client);
++ int subsampling = 0;
++
++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE ||
++ sel->target != V4L2_SEL_TGT_CROP)
++ return -EINVAL;
++
++ rect->left = ALIGN(rect->left, 2);
++ rect->top = ALIGN(rect->top, 2);
++ rect->width = ALIGN(rect->width, 2);
++ rect->height = ALIGN(rect->height, 2);
++
++ if ((rect->left + rect->width > OV10635_MAX_WIDTH) ||
++ (rect->top + rect->height > OV10635_MAX_HEIGHT))
++ *rect = priv->rect;
++
++ if (rect->width == OV10635_MAX_WIDTH / 2 &&
++ rect->height == OV10635_MAX_HEIGHT / 2)
++ subsampling = 1;
++
++ priv->rect.left = rect->left;
++ priv->rect.top = rect->top;
++ priv->rect.width = rect->width;
++ priv->rect.height = rect->height;
++
++ /* change window only for subsampling, crop is done by VIN */
++ if (subsampling != priv->subsampling) {
++ ov10635_set_window(sd, subsampling);
++ priv->subsampling = subsampling;
++ }
++
++ return 0;
++}
++
++static int ov10635_get_selection(struct v4l2_subdev *sd,
++ struct v4l2_subdev_pad_config *cfg,
++ struct v4l2_subdev_selection *sel)
++{
++ struct i2c_client *client = v4l2_get_subdevdata(sd);
++ struct ov10635_priv *priv = to_ov10635(client);
++
++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
++ return -EINVAL;
++
++ switch (sel->target) {
++ case V4L2_SEL_TGT_CROP_BOUNDS:
++ sel->r.left = 0;
++ sel->r.top = 0;
++ sel->r.width = OV10635_MAX_WIDTH;
++ sel->r.height = OV10635_MAX_HEIGHT;
++ return 0;
++ case V4L2_SEL_TGT_CROP_DEFAULT:
++ sel->r.left = 0;
++ sel->r.top = 0;
++ sel->r.width = OV10635_MAX_WIDTH;
++ sel->r.height = OV10635_MAX_HEIGHT;
++ return 0;
++ case V4L2_SEL_TGT_CROP:
++ sel->r = priv->rect;
++ return 0;
++ default:
++ return -EINVAL;
++ }
++}
++
++static int ov10635_g_mbus_config(struct v4l2_subdev *sd,
++ struct v4l2_mbus_config *cfg)
++{
++ cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 |
++ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
++ cfg->type = V4L2_MBUS_CSI2;
++
++ return 0;
++}
++
++static int ov10635_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
++{
++ struct i2c_client *client = v4l2_get_subdevdata(sd);
++ struct ov10635_priv *priv = to_ov10635(client);
++ struct v4l2_captureparm *cp = &parms->parm.capture;
++
++ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
++ return -EINVAL;
++
++ memset(cp, 0, sizeof(struct v4l2_captureparm));
++ cp->capability = V4L2_CAP_TIMEPERFRAME;
++ cp->timeperframe.numerator = 1;
++ cp->timeperframe.denominator = priv->fps_denominator;
++
++ return 0;
++}
++
++static int ov10635_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
++{
++ struct i2c_client *client = v4l2_get_subdevdata(sd);
++ struct ov10635_priv *priv = to_ov10635(client);
++ struct v4l2_captureparm *cp = &parms->parm.capture;
++ int ret = 0;
++
++ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
++ return -EINVAL;
++ if (cp->extendedmode != 0)
++ return -EINVAL;
++
++ if (priv->fps_denominator != cp->timeperframe.denominator) {
++ switch (cp->timeperframe.denominator) {
++ case 5:
++ ret = ov10635_set_regs(client, ov10635_regs_5fps,
++ ARRAY_SIZE(ov10635_regs_5fps));
++ break;
++ case 10:
++ ret = ov10635_set_regs(client, ov10635_regs_10fps,
++ ARRAY_SIZE(ov10635_regs_10fps));
++ break;
++ case 15:
++ ret = ov10635_set_regs(client, ov10635_regs_15fps,
++ ARRAY_SIZE(ov10635_regs_15fps));
++ break;
++ case 30:
++ ret = ov10635_set_regs(client, ov10635_regs_30fps,
++ ARRAY_SIZE(ov10635_regs_30fps));
++ break;
++ default:
++ ret = -EINVAL;
++ goto out;
++ }
++
++ priv->fps_denominator = cp->timeperframe.denominator;
++ }
++
++out:
++ return ret;
++}
++
++#ifdef CONFIG_VIDEO_ADV_DEBUG
++static int ov10635_g_register(struct v4l2_subdev *sd,
++ struct v4l2_dbg_register *reg)
++{
++ struct i2c_client *client = v4l2_get_subdevdata(sd);
++ int ret;
++ u8 val = 0;
++
++ ret = reg16_read(client, (u16)reg->reg, &val);
++ if (ret < 0)
++ return ret;
++
++ reg->val = val;
++ reg->size = sizeof(u16);
++
++ return 0;
++}
++
++static int ov10635_s_register(struct v4l2_subdev *sd,
++ const struct v4l2_dbg_register *reg)
++{
++ struct i2c_client *client = v4l2_get_subdevdata(sd);
++
++ return reg16_write(client, (u16)reg->reg, (u8)reg->val);
++}
++#endif
++
++static struct v4l2_subdev_core_ops ov10635_core_ops = {
++#ifdef CONFIG_VIDEO_ADV_DEBUG
++ .g_register = ov10635_g_register,
++ .s_register = ov10635_s_register,
++#endif
++};
++
++static int ov10635_s_ctrl(struct v4l2_ctrl *ctrl)
++{
++ struct v4l2_subdev *sd = to_sd(ctrl);
++ struct i2c_client *client = v4l2_get_subdevdata(sd);
++ struct ov10635_priv *priv = to_ov10635(client);
++ int ret = -EINVAL;
++ u8 val = 0;
++
++ if (!priv->init_complete)
++ return 0;
++
++ switch (ctrl->id) {
++ case V4L2_CID_BRIGHTNESS:
++ /* AEC/AGC target */
++ ret = reg16_write(client, 0xc46a, ctrl->val);
++ break;
++ case V4L2_CID_CONTRAST:
++ udelay(100);
++ ret = ov10635_set_regs(client, &ov10635_regs_contrast[ctrl->val][0], 18);
++ break;
++ case V4L2_CID_SATURATION:
++ ret = reg16_write(client, 0xc316, ctrl->val);
++ break;
++ case V4L2_CID_HUE:
++ /* CMX ? */
++ ret = 0;
++ break;
++ case V4L2_CID_GAMMA:
++ ret = reg16_write(client, 0xc4be, ctrl->val >> 8);
++ ret |= reg16_write(client, 0xc4bf, ctrl->val & 0xff);
++ break;
++ case V4L2_CID_AUTOGAIN:
++ /* automatic gain/exposure */
++ ret = reg16_write(client, 0x56d0, !ctrl->val);
++ break;
++ case V4L2_CID_GAIN:
++ /* manual gain */
++ ret = reg16_write(client, 0x3504, 0);
++ ret |= reg16_write(client, 0x56d1, ctrl->val >> 8);
++ ret |= reg16_write(client, 0x56d2, ctrl->val & 0xff);
++ ret |= reg16_write(client, 0x3504, 1); /* validate gain */
++ break;
++ case V4L2_CID_EXPOSURE:
++ /* manual exposure */
++ ret = reg16_write(client, 0x3504, 0);
++ ret |= reg16_write(client, 0x56d5, ctrl->val >> 8);
++ ret |= reg16_write(client, 0x56d6, ctrl->val & 0xff);
++ ret |= reg16_write(client, 0x3504, 1); /* validate exposure */
++ break;
++ case V4L2_CID_HFLIP:
++ ret = reg16_read(client, 0x381d, &val);
++ if (ret < 0)
++ goto out;
++ if (ctrl->val)
++ val |= 0x3;
++ else
++ val &= ~0x3;
++ ret = reg16_write(client, 0x381d, val);
++ break;
++ case V4L2_CID_VFLIP:
++ ret = reg16_read(client, 0x381c, &val);
++ if (ctrl->val)
++ val |= 0xc0;
++ else
++ val &= ~0xc0;
++ ret = reg16_write(client, 0x381c, val);
++ break;
++ }
++
++out:
++ return ret;
++}
++
++static const struct v4l2_ctrl_ops ov10635_ctrl_ops = {
++ .s_ctrl = ov10635_s_ctrl,
++};
++
++static struct v4l2_subdev_video_ops ov10635_video_ops = {
++ .s_stream = ov10635_s_stream,
++ .g_mbus_config = ov10635_g_mbus_config,
++ .g_parm = ov10635_g_parm,
++ .s_parm = ov10635_s_parm,
++};
++
++static const struct v4l2_subdev_pad_ops ov10635_subdev_pad_ops = {
++ .get_edid = ov10635_get_edid,
++ .enum_mbus_code = ov10635_enum_mbus_code,
++ .get_selection = ov10635_get_selection,
++ .set_selection = ov10635_set_selection,
++ .get_fmt = ov10635_get_fmt,
++ .set_fmt = ov10635_set_fmt,
++};
++
++static struct v4l2_subdev_ops ov10635_subdev_ops = {
++ .core = &ov10635_core_ops,
++ .video = &ov10635_video_ops,
++ .pad = &ov10635_subdev_pad_ops,
++};
++
++static void ov10635_otp_id_read(struct i2c_client *client)
++{
++ struct ov10635_priv *priv = to_ov10635(client);
++ int i;
++
++ /* read camera id from OTP memory */
++ reg16_write(client, 0x3d10, 1);
++
++ usleep_range(15000, 16000); /* wait 15ms */
++
++ for (i = 0; i < 6; i++)
++ reg16_read(client, 0x3d00 + i, &priv->id[i]);
++}
++
++static ssize_t ov10635_otp_id_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct v4l2_subdev *sd = i2c_get_clientdata(to_i2c_client(dev));
++ struct i2c_client *client = v4l2_get_subdevdata(sd);
++ struct ov10635_priv *priv = to_ov10635(client);
++
++ return snprintf(buf, 32, "%02x:%02x:%02x:%02x:%02x:%02x\n",
++ priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]);
++}
++
++static DEVICE_ATTR(otp_id_ov10635, S_IRUGO, ov10635_otp_id_show, NULL);
++
++static int ov10635_initialize(struct i2c_client *client)
++{
++ struct ov10635_priv *priv = to_ov10635(client);
++ u8 pid = 0, ver = 0;
++ int ret = 0;
++
++ ov10635_s_port(client, 1);
++
++ /* check and show product ID and manufacturer ID */
++ reg16_read(client, OV10635_PID, &pid);
++ reg16_read(client, OV10635_VER, &ver);
++
++ if (OV10635_VERSION(pid, ver) != OV10635_VERSION_REG) {
++ dev_dbg(&client->dev, "Product ID error %x:%x\n", pid, ver);
++ ret = -ENODEV;
++ goto out;
++ }
++
++ /* s/w reset sensor */
++ reg16_write(client, 0x103, 0x1);
++ udelay(100);
++ /* Program wizard registers */
++ ov10635_set_regs(client, ov10635_regs_wizard, ARRAY_SIZE(ov10635_regs_wizard));
++ /* Set DVP bit swap */
++ reg16_write(client, 0x4709, priv->dvp_order << 4);
++ /* Read OTP IDs */
++ ov10635_otp_id_read(client);
++
++ dev_info(&client->dev, "ov10635 Product ID %x Manufacturer ID %x OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n",
++ pid, ver, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]);
++
++out:
++ ov10635_s_port(client, 0);
++
++ return ret;
++}
++
++static int ov10635_parse_dt(struct device_node *np, struct ov10635_priv *priv)
++{
++ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd);
++ int i;
++ struct device_node *endpoint = NULL, *rendpoint = NULL;
++ int tmp_addr = 0;
++
++ for (i = 0; ; i++) {
++ endpoint = of_graph_get_next_endpoint(np, endpoint);
++ if (!endpoint)
++ break;
++
++ of_node_put(endpoint);
++
++ of_property_read_u32(endpoint, "dvp-order", &priv->dvp_order);
++
++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0);
++ if (!rendpoint)
++ continue;
++
++ if (!of_property_read_u32(rendpoint, "max9271-addr", &priv->max9271_addr) &&
++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->max9286_addr) &&
++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port))
++ break;
++
++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) &&
++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti964-ti9x3") &&
++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti964_addr) &&
++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port))
++ break;
++
++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) &&
++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti954-ti9x3") &&
++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti954_addr) &&
++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port))
++ break;
++ }
++
++ if (!priv->max9286_addr && !priv->ti964_addr && !priv->ti954_addr) {
++ dev_err(&client->dev, "deserializer does not present\n");
++ return -EINVAL;
++ }
++
++ ov10635_s_port(client, 1);
++
++ /* setup I2C translator address */
++ tmp_addr = client->addr;
++ if (priv->max9286_addr) {
++ client->addr = priv->max9271_addr; /* Serializer I2C address */
++
++ reg8_write(client, 0x09, tmp_addr << 1); /* Sensor translated I2C address */
++ reg8_write(client, 0x0A, OV10635_I2C_ADDR << 1); /* Sensor native I2C address */
++ usleep_range(2000, 2500); /* wait 2ms */
++ };
++
++ if (priv->ti964_addr) {
++ client->addr = priv->ti964_addr; /* Deserializer I2C address */
++
++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */
++ usleep_range(2000, 2500); /* wait 2ms */
++ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */
++ reg8_write(client, 0x5d, OV10635_I2C_ADDR << 1); /* Sensor native I2C address */
++
++ reg8_write(client, 0x6e, 0xa9); /* GPIO0 - resetb, GPIO1 - fsin */
++ udelay(100);
++ }
++
++ if (priv->ti954_addr) {
++ client->addr = priv->ti954_addr; /* Deserializer I2C address */
++
++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */
++ usleep_range(2000, 2500); /* wait 2ms */
++ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */
++ reg8_write(client, 0x5d, OV10635_I2C_ADDR << 1); /* Sensor native I2C address */
++
++ reg8_write(client, 0x6e, 0xa9); /* GPIO0 - resetb, GPIO1 - fsin */
++ udelay(100);
++ }
++ client->addr = tmp_addr;
++
++ return 0;
++}
++
++static int ov10635_probe(struct i2c_client *client,
++ const struct i2c_device_id *did)
++{
++ struct ov10635_priv *priv;
++ int ret;
++
++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ v4l2_i2c_subdev_init(&priv->sd, client, &ov10635_subdev_ops);
++ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
++ priv->rect.left = 0;
++ priv->rect.top = 0;
++ priv->rect.width = OV10635_MAX_WIDTH;
++ priv->rect.height = OV10635_MAX_HEIGHT;
++ priv->fps_denominator = 30;
++
++ v4l2_ctrl_handler_init(&priv->hdl, 4);
++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops,
++ V4L2_CID_BRIGHTNESS, 0, 0xff, 1, 0x30);
++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops,
++ V4L2_CID_CONTRAST, 0, 4, 1, 2);
++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops,
++ V4L2_CID_SATURATION, 0, 0xff, 1, 0xff);
++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops,
++ V4L2_CID_HUE, 0, 255, 1, 0);
++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops,
++ V4L2_CID_GAMMA, 0, 0xffff, 1, 0x233);
++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops,
++ V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops,
++ V4L2_CID_GAIN, 0, 0x3ff, 1, 0x10);
++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops,
++ V4L2_CID_EXPOSURE, 0, 0xffff, 1, 0x80);
++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops,
++ V4L2_CID_HFLIP, 0, 1, 1, 0);
++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops,
++ V4L2_CID_VFLIP, 0, 1, 1, 0);
++ priv->sd.ctrl_handler = &priv->hdl;
++
++ ret = priv->hdl.error;
++ if (ret)
++ goto cleanup;
++
++ v4l2_ctrl_handler_setup(&priv->hdl);
++
++ priv->pad.flags = MEDIA_PAD_FL_SOURCE;
++ priv->sd.entity.flags |= MEDIA_ENT_F_CAM_SENSOR;
++ ret = media_entity_pads_init(&priv->sd.entity, 1, &priv->pad);
++ if (ret < 0)
++ goto cleanup;
++
++ ret = ov10635_parse_dt(client->dev.of_node, priv);
++ if (ret)
++ goto cleanup;
++
++ ret = ov10635_initialize(client);
++ if (ret < 0)
++ goto cleanup;
++
++ ret = v4l2_async_register_subdev(&priv->sd);
++ if (ret)
++ goto cleanup;
++
++ if (device_create_file(&client->dev, &dev_attr_otp_id_ov10635) != 0) {
++ dev_err(&client->dev, "sysfs otp_id entry creation failed\n");
++ goto cleanup;
++ }
++
++ priv->init_complete = 1;
++
++ return 0;
++
++cleanup:
++ media_entity_cleanup(&priv->sd.entity);
++ v4l2_ctrl_handler_free(&priv->hdl);
++ v4l2_device_unregister_subdev(&priv->sd);
++#ifdef CONFIG_SOC_CAMERA_OV10635
++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n",
++ client->addr, client->adapter->name);
++#endif
++ return ret;
++}
++
++static int ov10635_remove(struct i2c_client *client)
++{
++ struct ov10635_priv *priv = i2c_get_clientdata(client);
++
++ device_remove_file(&client->dev, &dev_attr_otp_id_ov10635);
++ v4l2_async_unregister_subdev(&priv->sd);
++ media_entity_cleanup(&priv->sd.entity);
++ v4l2_ctrl_handler_free(&priv->hdl);
++ v4l2_device_unregister_subdev(&priv->sd);
++
++ return 0;
++}
++
++#ifdef CONFIG_SOC_CAMERA_OV10635
++static const struct i2c_device_id ov10635_id[] = {
++ { "ov10635", 0 },
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, ov10635_id);
++
++static const struct of_device_id ov10635_of_ids[] = {
++ { .compatible = "ovti,ov10635", },
++ { }
++};
++MODULE_DEVICE_TABLE(of, ov10635_of_ids);
++
++static struct i2c_driver ov10635_i2c_driver = {
++ .driver = {
++ .name = "ov10635",
++ .of_match_table = ov10635_of_ids,
++ },
++ .probe = ov10635_probe,
++ .remove = ov10635_remove,
++ .id_table = ov10635_id,
++};
++
++module_i2c_driver(ov10635_i2c_driver);
++
++MODULE_DESCRIPTION("SoC Camera driver for OV10635");
++MODULE_AUTHOR("Vladimir Barinov");
++MODULE_LICENSE("GPL");
++#endif
+diff --git a/drivers/media/i2c/soc_camera/ov10635.h b/drivers/media/i2c/soc_camera/ov10635.h
+new file mode 100644
+index 0000000..66cc490
+--- /dev/null
++++ b/drivers/media/i2c/soc_camera/ov10635.h
+@@ -0,0 +1,1139 @@
++/*
++ * OmniVision ov10635 sensor camera wizard 1280x800@30/UYVY/BT601/8bit
++ *
++ * Copyright (C) 2015-2017 Cogent Embedded, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++
++//#define OV10635_DISPLAY_PATTERN
++
++#define OV10635_SENSOR_WIDTH 1312
++#define OV10635_SENSOR_HEIGHT 814
++
++#define OV10635_MAX_WIDTH 1280
++#define OV10635_MAX_HEIGHT 800
++
++//#define OV10635_PCLK_96MHZ
++#define OV10635_PCLK_88MHZ
++
++#if defined(OV10635_PCLK_96MHZ)
++/* VTS=PCLK/FPS/HTS/2 (=96MHz/30/1600/2) */
++ #define OV10635_HTS 1600
++ #define OV10635_VTS 1000 /* fps=30 */
++#elif defined(OV10635_PCLK_88MHZ)
++/* VTS=PCLK/FPS/HTS/2 (=88MHz/1572/30/2) */
++ #define OV10635_HTS 1572
++ #define OV10635_VTS 933 /* fps=29.9998 */
++#else
++ #error PCLK not defined
++#endif
++
++struct ov10635_reg {
++ u16 reg;
++ u8 val;
++};
++
++static const struct ov10635_reg ov10635_regs_wizard[] = {
++//{0x0103, 0x01},
++{0x300C, 0x61},
++{0x300C, 0x61},
++{0x300C, 0x61},
++{0x300C, 0x61},
++{0x300C, 0x61},
++{0x300C, 0x61},
++{0x300C, 0x61},
++{0x300C, 0x61},
++{0x300C, 0x61},
++{0x300C, 0x61},
++{0x300C, 0x61},
++{0x300C, 0x61},
++{0x300C, 0x61},
++{0x300C, 0x61},
++{0x300C, 0x61},
++{0x300C, 0x61},
++{0x300C, 0x61},
++{0x300C, 0x61},
++{0x300C, 0x61},
++{0x300C, 0x61},
++{0x300C, 0x61},
++{0x300C, 0x61},
++{0x300C, 0x61},
++{0x301B, 0xFF},
++{0x301C, 0xFF},
++{0x301A, 0xFF},
++{0x3011, 0x42},
++{0x6900, 0x0C},
++{0x6901, 0x19},
++{0x3503, 0x10},
++{0x3025, 0x03},
++#if defined(OV10635_PCLK_96MHZ)
++{0x3003, 0x20},
++{0x3004, 0x21},
++#elif defined(OV10635_PCLK_88MHZ)
++{0x3003, 0x16},
++{0x3004, 0x30},
++#endif
++{0x3005, 0x40},
++{0x3006, 0x91},
++{0x3600, 0x74},
++{0x3601, 0x2B},
++{0x3612, 0x00},
++{0x3611, 0x67},
++{0x3633, 0xCA},
++{0x3602, 0xAF},
++{0x3603, 0x04},
++{0x3630, 0x28},
++{0x3631, 0x16},
++{0x3714, 0x10},
++{0x371D, 0x01},
++{0x4300, 0x3A},
++{0x3007, 0x01},
++{0x3024, 0x03},
++{0x3020, 0x0A},
++{0x3702, 0x0D},
++{0x3703, 0x20},
++{0x3704, 0x15},
++{0x3709, 0xA8},
++{0x370C, 0xC7},
++{0x370D, 0x80},
++{0x3712, 0x00},
++{0x3713, 0x20},
++{0x3715, 0x04},
++{0x381D, 0x40},
++{0x381C, 0x00},
++{0x3822, 0x50},
++{0x3824, 0x10},
++{0x3815, 0x8C},
++{0x3804, 0x05},
++{0x3805, 0x1F},
++{0x3800, 0x00},
++{0x3801, 0x00},
++{0x3806, 0x03},
++{0x3807, 0x28},
++{0x3802, 0x00},
++{0x3803, 0x07},
++{0x3808, 0x05},
++{0x3809, 0x00},
++{0x380A, 0x03},
++{0x380B, 0x20},
++{0x380C, OV10635_HTS >> 8},
++{0x380D, OV10635_HTS & 0xff},
++{0x380E, OV10635_VTS >> 8},
++{0x380F, OV10635_VTS & 0xff},
++{0x3813, 0x02},
++{0x3811, 0x08},
++{0x381F, 0x0C},
++{0x3819, 0x04},
++{0x3804, 0x01},
++{0x3805, 0x00},
++{0x3828, 0x03},
++{0x3829, 0x10},
++{0x382A, 0x10},
++{0x3621, 0x63},
++{0x5005, 0x08},
++{0x56D5, 0x00},
++{0x56D6, 0x80},
++{0x56D7, 0x00},
++{0x56D8, 0x00},
++{0x56D9, 0x00},
++{0x56DA, 0x80},
++{0x56DB, 0x00},
++{0x56DC, 0x00},
++{0x56E8, 0x00},
++{0x56E9, 0x7F},
++{0x56EA, 0x00},
++{0x56EB, 0x7F},
++{0x5100, 0x00},
++{0x5101, 0x80},
++{0x5102, 0x00},
++{0x5103, 0x80},
++{0x5104, 0x00},
++{0x5105, 0x80},
++{0x5106, 0x00},
++{0x5107, 0x80},
++{0x5108, 0x00},
++{0x5109, 0x00},
++{0x510A, 0x00},
++{0x510B, 0x00},
++{0x510C, 0x00},
++{0x510D, 0x00},
++{0x510E, 0x00},
++{0x510F, 0x00},
++{0x5110, 0x00},
++{0x5111, 0x80},
++{0x5112, 0x00},
++{0x5113, 0x80},
++{0x5114, 0x00},
++{0x5115, 0x80},
++{0x5116, 0x00},
++{0x5117, 0x80},
++{0x5118, 0x00},
++{0x5119, 0x00},
++{0x511A, 0x00},
++{0x511B, 0x00},
++{0x511C, 0x00},
++{0x511D, 0x00},
++{0x511E, 0x00},
++{0x511F, 0x00},
++{0x56D0, 0x00},
++{0x5006, 0x04},
++{0x5608, 0x05},
++{0x52D7, 0x06},
++{0x528D, 0x08},
++{0x5293, 0x12},
++{0x52D3, 0x12},
++{0x5288, 0x06},
++{0x5289, 0x20},
++{0x52C8, 0x06},
++{0x52C9, 0x20},
++{0x52CD, 0x04},
++{0x5381, 0x00},
++{0x5382, 0xFF},
++{0x5589, 0x76},
++{0x558A, 0x47},
++{0x558B, 0xEF},
++{0x558C, 0xC9},
++{0x558D, 0x49},
++{0x558E, 0x30},
++{0x558F, 0x67},
++{0x5590, 0x3F},
++{0x5591, 0xF0},
++{0x5592, 0x10},
++{0x55A2, 0x6D},
++{0x55A3, 0x55},
++{0x55A4, 0xC3},
++{0x55A5, 0xB5},
++{0x55A6, 0x43},
++{0x55A7, 0x38},
++{0x55A8, 0x5F},
++{0x55A9, 0x4B},
++{0x55AA, 0xF0},
++{0x55AB, 0x10},
++{0x5581, 0x52},
++{0x5300, 0x01},
++{0x5301, 0x00},
++{0x5302, 0x00},
++{0x5303, 0x0E},
++{0x5304, 0x00},
++{0x5305, 0x0E},
++{0x5306, 0x00},
++{0x5307, 0x36},
++{0x5308, 0x00},
++{0x5309, 0xD9},
++{0x530A, 0x00},
++{0x530B, 0x0F},
++{0x530C, 0x00},
++{0x530D, 0x2C},
++{0x530E, 0x00},
++{0x530F, 0x59},
++{0x5310, 0x00},
++{0x5311, 0x7B},
++{0x5312, 0x00},
++{0x5313, 0x22},
++{0x5314, 0x00},
++{0x5315, 0xD5},
++{0x5316, 0x00},
++{0x5317, 0x13},
++{0x5318, 0x00},
++{0x5319, 0x18},
++{0x531A, 0x00},
++{0x531B, 0x26},
++{0x531C, 0x00},
++{0x531D, 0xDC},
++{0x531E, 0x00},
++{0x531F, 0x02},
++{0x5320, 0x00},
++{0x5321, 0x24},
++{0x5322, 0x00},
++{0x5323, 0x56},
++{0x5324, 0x00},
++{0x5325, 0x85},
++{0x5326, 0x00},
++{0x5327, 0x20},
++{0x5609, 0x01},
++{0x560A, 0x40},
++{0x560B, 0x01},
++{0x560C, 0x40},
++{0x560D, 0x00},
++{0x560E, 0xFA},
++{0x560F, 0x00},
++{0x5610, 0xFA},
++{0x5611, 0x02},
++{0x5612, 0x80},
++{0x5613, 0x02},
++{0x5614, 0x80},
++{0x5615, 0x01},
++{0x5616, 0x2C},
++{0x5617, 0x01},
++{0x5618, 0x2C},
++{0x563B, 0x01},
++{0x563C, 0x01},
++{0x563D, 0x01},
++{0x563E, 0x01},
++{0x563F, 0x03},
++{0x5640, 0x03},
++{0x5641, 0x03},
++{0x5642, 0x05},
++{0x5643, 0x09},
++{0x5644, 0x05},
++{0x5645, 0x05},
++{0x5646, 0x05},
++{0x5647, 0x05},
++{0x5651, 0x00},
++{0x5652, 0x80},
++{0x521A, 0x01},
++{0x521B, 0x03},
++{0x521C, 0x06},
++{0x521D, 0x0A},
++{0x521E, 0x0E},
++{0x521F, 0x12},
++{0x5220, 0x16},
++{0x5223, 0x02},
++{0x5225, 0x04},
++{0x5227, 0x08},
++{0x5229, 0x0C},
++{0x522B, 0x12},
++{0x522D, 0x18},
++{0x522F, 0x1E},
++{0x5241, 0x04},
++{0x5242, 0x01},
++{0x5243, 0x03},
++{0x5244, 0x06},
++{0x5245, 0x0A},
++{0x5246, 0x0E},
++{0x5247, 0x12},
++{0x5248, 0x16},
++{0x524A, 0x03},
++{0x524C, 0x04},
++{0x524E, 0x08},
++{0x5250, 0x0C},
++{0x5252, 0x12},
++{0x5254, 0x18},
++{0x5256, 0x1E},
++{0x4606, (2*OV10635_HTS) >> 8}, /* fifo_line_length = 2*hts */
++{0x4607, (2*OV10635_HTS) & 0xff},
++{0x460a, (2*(OV10635_HTS-OV10635_MAX_WIDTH)) >> 8}, /* fifo_hsync_start = 2*(hts - xres) */
++{0x460b, (2*(OV10635_HTS-OV10635_MAX_WIDTH)) & 0xff },
++{0x460C, 0x00},
++{0x4620, 0x0E},
++#if 0
++{0x4700, 0x02}, // BT656: mode is acceptable but artefact lines on left/bottom due to BT656 SAV/EAV are parsed as image data
++#else
++{0x4700, 0x04}, // BT601: 0x08 is also accaptable as HS/VS mode
++#endif
++{0x4701, 0x00},
++{0x4702, 0x01},
++{0x4004, 0x04},
++{0x4005, 0x18},
++{0x4001, 0x06},
++{0x4050, 0x22},
++{0x4051, 0x24},
++{0x4052, 0x02},
++{0x4057, 0x9C},
++{0x405A, 0x00},
++{0x4202, 0x02},
++{0x3023, 0x10},
++{0x0100, 0x01},
++{0x0100, 0x01},
++{0x6F10, 0x07},
++{0x6F11, 0x82},
++{0x6F12, 0x04},
++{0x6F13, 0x00},
++{0xD000, 0x19},
++{0xD001, 0xA0},
++{0xD002, 0x00},
++{0xD003, 0x01},
++{0xD004, 0xA9},
++{0xD005, 0xAD},
++{0xD006, 0x10},
++{0xD007, 0x40},
++{0xD008, 0x44},
++{0xD009, 0x00},
++{0xD00A, 0x68},
++{0xD00B, 0x00},
++{0xD00C, 0x15},
++{0xD00D, 0x00},
++{0xD00E, 0x00},
++{0xD00F, 0x00},
++{0xD040, 0x9C},
++{0xD041, 0x21},
++{0xD042, 0xFF},
++{0xD043, 0xF8},
++{0xD044, 0xD4},
++{0xD045, 0x01},
++{0xD046, 0x48},
++{0xD047, 0x00},
++{0xD048, 0xD4},
++{0xD049, 0x01},
++{0xD04A, 0x50},
++{0xD04B, 0x04},
++{0xD04C, 0x18},
++{0xD04D, 0x60},
++{0xD04E, 0x00},
++{0xD04F, 0x01},
++{0xD050, 0xA8},
++{0xD051, 0x63},
++{0xD052, 0x02},
++{0xD053, 0xA4},
++{0xD054, 0x85},
++{0xD055, 0x43},
++{0xD056, 0x00},
++{0xD057, 0x00},
++{0xD058, 0x18},
++{0xD059, 0x60},
++{0xD05A, 0x00},
++{0xD05B, 0x01},
++{0xD05C, 0xA8},
++{0xD05D, 0x63},
++{0xD05E, 0x03},
++{0xD05F, 0xF0},
++{0xD060, 0x98},
++{0xD061, 0xA3},
++{0xD062, 0x00},
++{0xD063, 0x00},
++{0xD064, 0x8C},
++{0xD065, 0x6A},
++{0xD066, 0x00},
++{0xD067, 0x6E},
++{0xD068, 0xE5},
++{0xD069, 0x85},
++{0xD06A, 0x18},
++{0xD06B, 0x00},
++{0xD06C, 0x10},
++{0xD06D, 0x00},
++{0xD06E, 0x00},
++{0xD06F, 0x10},
++{0xD070, 0x9C},
++{0xD071, 0x80},
++{0xD072, 0x00},
++{0xD073, 0x03},
++{0xD074, 0x18},
++{0xD075, 0x60},
++{0xD076, 0x00},
++{0xD077, 0x01},
++{0xD078, 0xA8},
++{0xD079, 0x63},
++{0xD07A, 0x07},
++{0xD07B, 0x80},
++{0xD07C, 0x07},
++{0xD07D, 0xFF},
++{0xD07E, 0xF9},
++{0xD07F, 0x03},
++{0xD080, 0x8C},
++{0xD081, 0x63},
++{0xD082, 0x00},
++{0xD083, 0x00},
++{0xD084, 0xA5},
++{0xD085, 0x6B},
++{0xD086, 0x00},
++{0xD087, 0xFF},
++{0xD088, 0x18},
++{0xD089, 0x80},
++{0xD08A, 0x00},
++{0xD08B, 0x01},
++{0xD08C, 0xA8},
++{0xD08D, 0x84},
++{0xD08E, 0x01},
++{0xD08F, 0x04},
++{0xD090, 0xE1},
++{0xD091, 0x6B},
++{0xD092, 0x58},
++{0xD093, 0x00},
++{0xD094, 0x94},
++{0xD095, 0x6A},
++{0xD096, 0x00},
++{0xD097, 0x70},
++{0xD098, 0xE1},
++{0xD099, 0x6B},
++{0xD09A, 0x20},
++{0xD09B, 0x00},
++{0xD09C, 0x95},
++{0xD09D, 0x6B},
++{0xD09E, 0x00},
++{0xD09F, 0x00},
++{0xD0A0, 0xE4},
++{0xD0A1, 0x8B},
++{0xD0A2, 0x18},
++{0xD0A3, 0x00},
++{0xD0A4, 0x0C},
++{0xD0A5, 0x00},
++{0xD0A6, 0x00},
++{0xD0A7, 0x23},
++{0xD0A8, 0x15},
++{0xD0A9, 0x00},
++{0xD0AA, 0x00},
++{0xD0AB, 0x00},
++{0xD0AC, 0x18},
++{0xD0AD, 0x60},
++{0xD0AE, 0x80},
++{0xD0AF, 0x06},
++{0xD0B0, 0xA8},
++{0xD0B1, 0x83},
++{0xD0B2, 0x40},
++{0xD0B3, 0x08},
++{0xD0B4, 0xA8},
++{0xD0B5, 0xE3},
++{0xD0B6, 0x38},
++{0xD0B7, 0x2A},
++{0xD0B8, 0xA8},
++{0xD0B9, 0xC3},
++{0xD0BA, 0x40},
++{0xD0BB, 0x09},
++{0xD0BC, 0xA8},
++{0xD0BD, 0xA3},
++{0xD0BE, 0x38},
++{0xD0BF, 0x29},
++{0xD0C0, 0x8C},
++{0xD0C1, 0x65},
++{0xD0C2, 0x00},
++{0xD0C3, 0x00},
++{0xD0C4, 0xD8},
++{0xD0C5, 0x04},
++{0xD0C6, 0x18},
++{0xD0C7, 0x00},
++{0xD0C8, 0x8C},
++{0xD0C9, 0x67},
++{0xD0CA, 0x00},
++{0xD0CB, 0x00},
++{0xD0CC, 0xD8},
++{0xD0CD, 0x06},
++{0xD0CE, 0x18},
++{0xD0CF, 0x00},
++{0xD0D0, 0x18},
++{0xD0D1, 0x60},
++{0xD0D2, 0x80},
++{0xD0D3, 0x06},
++{0xD0D4, 0xA8},
++{0xD0D5, 0xE3},
++{0xD0D6, 0x67},
++{0xD0D7, 0x02},
++{0xD0D8, 0xA9},
++{0xD0D9, 0x03},
++{0xD0DA, 0x67},
++{0xD0DB, 0x03},
++{0xD0DC, 0xA8},
++{0xD0DD, 0xC3},
++{0xD0DE, 0x3D},
++{0xD0DF, 0x05},
++{0xD0E0, 0x8C},
++{0xD0E1, 0x66},
++{0xD0E2, 0x00},
++{0xD0E3, 0x00},
++{0xD0E4, 0xB8},
++{0xD0E5, 0x63},
++{0xD0E6, 0x00},
++{0xD0E7, 0x18},
++{0xD0E8, 0xB8},
++{0xD0E9, 0x63},
++{0xD0EA, 0x00},
++{0xD0EB, 0x98},
++{0xD0EC, 0xBC},
++{0xD0ED, 0x03},
++{0xD0EE, 0x00},
++{0xD0EF, 0x00},
++{0xD0F0, 0x10},
++{0xD0F1, 0x00},
++{0xD0F2, 0x00},
++{0xD0F3, 0x16},
++{0xD0F4, 0xB8},
++{0xD0F5, 0x83},
++{0xD0F6, 0x00},
++{0xD0F7, 0x19},
++{0xD0F8, 0x8C},
++{0xD0F9, 0x67},
++{0xD0FA, 0x00},
++{0xD0FB, 0x00},
++{0xD0FC, 0xB8},
++{0xD0FD, 0xA4},
++{0xD0FE, 0x00},
++{0xD0FF, 0x98},
++{0xD100, 0xB8},
++{0xD101, 0x83},
++{0xD102, 0x00},
++{0xD103, 0x08},
++{0xD104, 0x8C},
++{0xD105, 0x68},
++{0xD106, 0x00},
++{0xD107, 0x00},
++{0xD108, 0xE0},
++{0xD109, 0x63},
++{0xD10A, 0x20},
++{0xD10B, 0x04},
++{0xD10C, 0xE0},
++{0xD10D, 0x65},
++{0xD10E, 0x18},
++{0xD10F, 0x00},
++{0xD110, 0xA4},
++{0xD111, 0x83},
++{0xD112, 0xFF},
++{0xD113, 0xFF},
++{0xD114, 0xB8},
++{0xD115, 0x64},
++{0xD116, 0x00},
++{0xD117, 0x48},
++{0xD118, 0xD8},
++{0xD119, 0x07},
++{0xD11A, 0x18},
++{0xD11B, 0x00},
++{0xD11C, 0xD8},
++{0xD11D, 0x08},
++{0xD11E, 0x20},
++{0xD11F, 0x00},
++{0xD120, 0x9C},
++{0xD121, 0x60},
++{0xD122, 0x00},
++{0xD123, 0x00},
++{0xD124, 0xD8},
++{0xD125, 0x06},
++{0xD126, 0x18},
++{0xD127, 0x00},
++{0xD128, 0x00},
++{0xD129, 0x00},
++{0xD12A, 0x00},
++{0xD12B, 0x08},
++{0xD12C, 0x15},
++{0xD12D, 0x00},
++{0xD12E, 0x00},
++{0xD12F, 0x00},
++{0xD130, 0x8C},
++{0xD131, 0x6A},
++{0xD132, 0x00},
++{0xD133, 0x76},
++{0xD134, 0xBC},
++{0xD135, 0x23},
++{0xD136, 0x00},
++{0xD137, 0x00},
++{0xD138, 0x13},
++{0xD139, 0xFF},
++{0xD13A, 0xFF},
++{0xD13B, 0xE6},
++{0xD13C, 0x18},
++{0xD13D, 0x60},
++{0xD13E, 0x80},
++{0xD13F, 0x06},
++{0xD140, 0x03},
++{0xD141, 0xFF},
++{0xD142, 0xFF},
++{0xD143, 0xDD},
++{0xD144, 0xA8},
++{0xD145, 0x83},
++{0xD146, 0x40},
++{0xD147, 0x08},
++{0xD148, 0x85},
++{0xD149, 0x21},
++{0xD14A, 0x00},
++{0xD14B, 0x00},
++{0xD14C, 0x85},
++{0xD14D, 0x41},
++{0xD14E, 0x00},
++{0xD14F, 0x04},
++{0xD150, 0x44},
++{0xD151, 0x00},
++{0xD152, 0x48},
++{0xD153, 0x00},
++{0xD154, 0x9C},
++{0xD155, 0x21},
++{0xD156, 0x00},
++{0xD157, 0x08},
++{0x6F0E, 0x03},
++{0x6F0F, 0x00},
++{0x460E, 0x08},
++{0x460F, 0x01},
++{0x4610, 0x00},
++{0x4611, 0x01},
++{0x4612, 0x00},
++{0x4613, 0x01},
++{0x4605, 0x08}, // 8bit
++//{0x4709, 0x10}, // swap data bits order [9:0] -> [0:9]
++{0x4608, 0x00},
++{0x4609, 0x08},
++{0x6804, 0x00},
++{0x6805, 0x06},
++{0x6806, 0x00},
++{0x5120, 0x00},
++{0x3510, 0x00},
++{0x3504, 0x00},
++{0x6800, 0x00},
++{0x6F0D, 0x01},
++{0x4708, 0x01}, // PCLK rising edge
++{0x5000, 0xFF},
++{0x5001, 0xBF},
++{0x5002, 0x7E},
++#ifdef OV10635_DISPLAY_PATTERN
++{0x503d, 0x80},
++#else
++{0x503D, 0x00},
++#endif
++{0xC450, 0x01}, /* AA mode */
++{0xC452, 0x04},
++{0xC453, 0x00},
++{0xC454, 0x00},
++{0xC455, 0x01},
++{0xC456, 0x01},
++{0xC457, 0x00},
++{0xC458, 0x00},
++{0xC459, 0x00},
++{0xC45B, 0x00},
++{0xC45C, 0x01},
++{0xC45D, 0x00},
++{0xC45E, 0x00},
++{0xC45F, 0x00},
++{0xC460, 0x00},
++{0xC461, 0x01},
++{0xC462, 0x01},
++{0xC464, 0x03},
++{0xC465, 0x00},
++{0xC466, 0x8A},
++{0xC467, 0x00},
++{0xC468, 0x86},
++{0xC469, 0x00},
++{0xC46A, 0x30},
++{0xC46B, 0x50},
++{0xC46C, 0x30},
++{0xC46D, 0x28},
++{0xC46E, 0x60},
++{0xC46F, 0x40},
++{0xC47C, 0x01},
++{0xC47D, 0x38},
++{0xC47E, 0x00},
++{0xC47F, 0x00},
++{0xC480, 0x00},
++{0xC481, 0xFF},
++{0xC482, 0x00},
++{0xC483, 0x40},
++{0xC484, 0x00},
++{0xC485, 0x18},
++{0xC486, 0x00},
++{0xC487, 0x18},
++{0xC488, (OV10635_VTS-8)*16 >> 8},
++{0xC489, (OV10635_VTS-8)*16 & 0xff},
++{0xC48A, (OV10635_VTS-8)*16 >> 8},
++{0xC48B, (OV10635_VTS-8)*16 & 0xff},
++{0xC48C, 0x00},
++{0xC48D, 0x04},
++{0xC48E, 0x00},
++{0xC48F, 0x04},
++{0xC490, 0x03},
++{0xC492, 0x20},
++{0xC493, 0x08},
++{0xC498, 0x02},
++{0xC499, 0x00},
++{0xC49A, 0x02},
++{0xC49B, 0x00},
++{0xC49C, 0x02},
++{0xC49D, 0x00},
++{0xC49E, 0x02},
++{0xC49F, 0x60},
++{0xC4A0, 0x03},
++{0xC4A1, 0x00},
++{0xC4A2, 0x04},
++{0xC4A3, 0x00},
++{0xC4A4, 0x00},
++{0xC4A5, 0x10},
++{0xC4A6, 0x00},
++{0xC4A7, 0x40},
++{0xC4A8, 0x00},
++{0xC4A9, 0x80},
++{0xC4AA, 0x0D},
++{0xC4AB, 0x00},
++{0xC4AC, 0x0F},
++{0xC4AD, 0xC0},
++{0xC4B4, 0x01},
++{0xC4B5, 0x01},
++{0xC4B6, 0x00},
++{0xC4B7, 0x01},
++{0xC4B8, 0x00},
++{0xC4B9, 0x01},
++{0xC4BA, 0x01},
++{0xC4BB, 0x00},
++{0xC4BC, 0x01},
++{0xC4BD, 0x60},
++{0xC4BE, 0x02},
++{0xC4BF, 0x33},
++{0xC4C8, 0x03},
++{0xC4C9, 0xD0},
++{0xC4CA, 0x0E},
++{0xC4CB, 0x00},
++{0xC4CC, 0x0E},
++{0xC4CD, 0x51},
++{0xC4CE, 0x0E},
++{0xC4CF, 0x51},
++{0xC4D0, 0x04},
++{0xC4D1, 0x80},
++{0xC4E0, 0x04},
++{0xC4E1, 0x02},
++{0xC4E2, 0x01},
++{0xC4E4, 0x10},
++{0xC4E5, 0x20},
++{0xC4E6, 0x30},
++{0xC4E7, 0x40},
++{0xC4E8, 0x50},
++{0xC4E9, 0x60},
++{0xC4EA, 0x70},
++{0xC4EB, 0x80},
++{0xC4EC, 0x90},
++{0xC4ED, 0xA0},
++{0xC4EE, 0xB0},
++{0xC4EF, 0xC0},
++{0xC4F0, 0xD0},
++{0xC4F1, 0xE0},
++{0xC4F2, 0xF0},
++{0xC4F3, 0x80},
++{0xC4F4, 0x00},
++{0xC4F5, 0x20},
++{0xC4F6, 0x02},
++{0xC4F7, 0x00},
++{0xC4F8, 0x00},
++{0xC4F9, 0x00},
++{0xC4FA, 0x00},
++{0xC4FB, 0x01},
++{0xC4FC, 0x01},
++{0xC4FD, 0x00},
++{0xC4FE, 0x04},
++{0xC4FF, 0x02},
++{0xC500, 0x48},
++{0xC501, 0x74},
++{0xC502, 0x58},
++{0xC503, 0x80},
++{0xC504, 0x05},
++{0xC505, 0x80},
++{0xC506, 0x03},
++{0xC507, 0x80},
++{0xC508, 0x01},
++{0xC509, 0xC0},
++{0xC50A, 0x01},
++{0xC50B, 0xA0},
++{0xC50C, 0x01},
++{0xC50D, 0x2C},
++{0xC50E, 0x01},
++{0xC50F, 0x0A},
++{0xC510, 0x00},
++{0xC511, 0x00},
++{0xC512, 0xE5},
++{0xC513, 0x14},
++{0xC514, 0x04},
++{0xC515, 0x00},
++{0xC518, OV10635_VTS >> 8},
++{0xC519, OV10635_VTS & 0xff},
++{0xC51A, OV10635_HTS >> 8},
++{0xC51B, OV10635_HTS & 0xff},
++{0xC2E0, 0x00},
++{0xC2E1, 0x51},
++{0xC2E2, 0x00},
++{0xC2E3, 0xD6},
++{0xC2E4, 0x01},
++{0xC2E5, 0x5E},
++{0xC2E9, 0x01},
++{0xC2EA, 0x7A},
++{0xC2EB, 0x90},
++{0xC2ED, 0x00},
++{0xC2EE, 0x7A},
++{0xC2EF, 0x64},
++{0xC308, 0x00},
++{0xC309, 0x00},
++{0xC30A, 0x00},
++{0xC30C, 0x00},
++{0xC30D, 0x01},
++{0xC30E, 0x00},
++{0xC30F, 0x00},
++{0xC310, 0x01},
++{0xC311, 0x60},
++{0xC312, 0xFF},
++{0xC313, 0x08},
++{0xC314, 0x01},
++{0xC315, 0x00}, /* min saturation gain */
++{0xC316, 0xFF}, /* max saturation gain */
++{0xC317, 0x0B},
++{0xC318, 0x00},
++{0xC319, 0x0C},
++{0xC31A, 0x00},
++{0xC31B, 0xE0},
++{0xC31C, 0x00},
++{0xC31D, 0x14},
++{0xC31E, 0x00},
++{0xC31F, 0xC5},
++{0xC320, 0xFF},
++{0xC321, 0x4B},
++{0xC322, 0xFF},
++{0xC323, 0xF0},
++{0xC324, 0xFF},
++{0xC325, 0xE8},
++{0xC326, 0x00},
++{0xC327, 0x46},
++{0xC328, 0xFF},
++{0xC329, 0xD2},
++{0xC32A, 0xFF},
++{0xC32B, 0xE4},
++{0xC32C, 0xFF},
++{0xC32D, 0xBB},
++{0xC32E, 0x00},
++{0xC32F, 0x61},
++{0xC330, 0xFF},
++{0xC331, 0xF9},
++{0xC332, 0x00},
++{0xC333, 0xD9},
++{0xC334, 0x00},
++{0xC335, 0x2E},
++{0xC336, 0x00},
++{0xC337, 0xB1},
++{0xC338, 0xFF},
++{0xC339, 0x64},
++{0xC33A, 0xFF},
++{0xC33B, 0xEB},
++{0xC33C, 0xFF},
++{0xC33D, 0xE8},
++{0xC33E, 0x00},
++{0xC33F, 0x48},
++{0xC340, 0xFF},
++{0xC341, 0xD0},
++{0xC342, 0xFF},
++{0xC343, 0xED},
++{0xC344, 0xFF},
++{0xC345, 0xAD},
++{0xC346, 0x00},
++{0xC347, 0x66},
++{0xC348, 0x01},
++{0xC349, 0x00},
++{0x6700, 0x04},
++{0x6701, 0x7B},
++{0x6702, 0xFD},
++{0x6703, 0xF9},
++{0x6704, 0x3D},
++{0x6705, 0x71},
++{0x6706, 0x78},
++{0x6708, 0x05},
++{0x6F06, 0x6F},
++{0x6F07, 0x00},
++{0x6F0A, 0x6F},
++{0x6F0B, 0x00},
++{0x6F00, 0x03},
++{0xC34C, 0x01},
++{0xC34D, 0x00},
++{0xC34E, 0x46},
++{0xC34F, 0x55},
++{0xC350, 0x00},
++{0xC351, 0x40},
++{0xC352, 0x00},
++{0xC353, 0xFF},
++{0xC354, 0x04},
++{0xC355, 0x08},
++{0xC356, 0x01},
++{0xC357, 0xEF},
++{0xC358, 0x30},
++{0xC359, 0x01},
++{0xC35A, 0x64},
++{0xC35B, 0x46},
++{0xC35C, 0x00},
++{0x3042, 0xF0},
++{0x3042, 0xF0},
++{0x3042, 0xF0},
++{0x3042, 0xF0},
++{0x3042, 0xF0},
++{0x3042, 0xF0},
++{0x3042, 0xF0},
++{0x3042, 0xF0},
++{0x3042, 0xF0},
++{0x3042, 0xF0},
++{0x3042, 0xF0},
++{0x3042, 0xF0},
++{0x3042, 0xF0},
++{0x3042, 0xF0},
++{0x3042, 0xF0},
++{0x3042, 0xF0},
++{0x3042, 0xF0},
++{0x3042, 0xF0},
++{0x3042, 0xF0},
++{0x3042, 0xF0},
++{0x3042, 0xF0},
++{0x3042, 0xF0},
++{0x3042, 0xF0},
++{0x3042, 0xF0},
++{0x3042, 0xF0},
++{0x3042, 0xF0},
++{0xC261, 0x01},
++{0x301B, 0xF0},
++{0x301C, 0xF0},
++{0x301A, 0xF0},
++{0x6F00, 0xC3},
++{0xC46A, 0x30},
++{0xC46D, 0x20},
++{0xC464, 0x84},
++{0xC465, 0x00},
++{0x6F00, 0x03},
++{0x6F00, 0x43},
++{0x381C, 0x00},
++{0x381D, 0x40},
++{0xC454, 0x01},
++{0x6F00, 0xC3},
++{0xC454, 0x00},
++{0xC4B1, 0x02},
++{0xC4B2, 0x01},
++{0xC4B3, 0x03},
++{0x6F00, 0x03},
++{0x6F00, 0x43},
++/* enable FSIN (FRAMESYNC input) functionality */
++{0x3832, 0x00},
++{0x3833, 0x10},
++{0x3834, 0x00},
++{0x3835, 0x10},
++{0x302E, 0x01},
++};
++
++static const struct ov10635_reg ov10635_regs_30fps[] = {
++/* disable clocks */
++{0x301b, 0xff},
++{0x301c, 0xff},
++{0x301a, 0xff},
++/* clk = 24Mhz/2*32/2(1+1)=96Mhz, 30fps */
++{0x3003, 0x20},
++{0x3004, 0x21},
++/* enable clocks */
++{0x301b, 0xf0},
++{0x301c, 0xf0},
++{0x301a, 0xf0},
++};
++
++static const struct ov10635_reg ov10635_regs_15fps[] = {
++/* disable clocks */
++{0x301b, 0xff},
++{0x301c, 0xff},
++{0x301a, 0xff},
++/* clk = 24Mhz/2*32/2(1+3)=48Mhz, 15fps */
++{0x3003, 0x20},
++{0x3004, 0x23},
++/* enable clocks */
++{0x301b, 0xf0},
++{0x301c, 0xf0},
++{0x301a, 0xf0},
++};
++
++static const struct ov10635_reg ov10635_regs_10fps[] = {
++/* disable clocks */
++{0x301b, 0xff},
++{0x301c, 0xff},
++{0x301a, 0xff},
++/* clk = 24Mhz/2*32/2(1+5)=32Mhz, 10fps */
++{0x3003, 0x20},
++{0x3004, 0x25},
++/* enable clocks */
++{0x301b, 0xf0},
++{0x301c, 0xf0},
++{0x301a, 0xf0},
++};
++
++static const struct ov10635_reg ov10635_regs_5fps[] = {
++/* disable clocks */
++{0x301b, 0xff},
++{0x301c, 0xff},
++{0x301a, 0xff},
++/* clk = 24Mhz/4*32/2(1+5)=96Mhz, 5fps */
++{0x3003, 0x20},
++{0x3004, 0x45},
++/* enable clocks */
++{0x301b, 0xf0},
++{0x301c, 0xf0},
++{0x301a, 0xf0},
++};
++
++static const struct ov10635_reg ov10635_regs_contrast[5][18] = {
++{
++ {0x6f00, 0xc3},
++ {0xc4e4, 0x20},
++ {0xc4e5, 0x40},
++ {0xc4e6, 0x60},
++ {0xc4e7, 0x80},
++ {0xc4e8, 0xa0},
++ {0xc4e9, 0xb4},
++ {0xc4ea, 0xc0},
++ {0xc4eb, 0xcb},
++ {0xc4ec, 0xd5},
++ {0xc4ed, 0xde},
++ {0xc4ee, 0xe6},
++ {0xc4ef, 0xed},
++ {0xc4f0, 0xf3},
++ {0xc4f1, 0xf8},
++ {0xc4f2, 0xfc},
++ {0x6f00, 0x03},
++ {0x6f00, 0x43},
++}, {
++ {0x6f00, 0xc3},
++ {0xc4e4, 0x18},
++ {0xc4e5, 0x30},
++ {0xc4e6, 0x48},
++ {0xc4e7, 0x60},
++ {0xc4e8, 0x78},
++ {0xc4e9, 0x90},
++ {0xc4ea, 0xa4},
++ {0xc4eb, 0xb4},
++ {0xc4ec, 0xc2},
++ {0xc4ed, 0xcf},
++ {0xc4ee, 0xdb},
++ {0xc4ef, 0xe5},
++ {0xc4f0, 0xee},
++ {0xc4f1, 0xf6},
++ {0xc4f2, 0xfc},
++ {0x6f00, 0x03},
++ {0x6f00, 0x43},
++}, {
++ {0x6f00, 0xc3},
++ {0xc4e4, 0x10},
++ {0xc4e5, 0x20},
++ {0xc4e6, 0x30},
++ {0xc4e7, 0x40},
++ {0xc4e8, 0x50},
++ {0xc4e9, 0x60},
++ {0xc4ea, 0x70},
++ {0xc4eb, 0x80},
++ {0xc4ec, 0x90},
++ {0xc4ed, 0xa0},
++ {0xc4ee, 0xb0},
++ {0xc4ef, 0xc0},
++ {0xc4f0, 0xd0},
++ {0xc4f1, 0xe0},
++ {0xc4f2, 0xf0},
++ {0x6f00, 0x03},
++ {0x6f00, 0x43},
++}, {
++ {0x6f00, 0xc3},
++ {0xc4e4, 0x0c},
++ {0xc4e5, 0x18},
++ {0xc4e6, 0x24},
++ {0xc4e7, 0x30},
++ {0xc4e8, 0x3c},
++ {0xc4e9, 0x48},
++ {0xc4ea, 0x54},
++ {0xc4eb, 0x62},
++ {0xc4ec, 0x72},
++ {0xc4ed, 0x84},
++ {0xc4ee, 0x94},
++ {0xc4ef, 0xa6},
++ {0xc4f0, 0xb9},
++ {0xc4f1, 0xcd},
++ {0xc4f2, 0xe2},
++ {0x6f00, 0x03},
++ {0x6f00, 0x43},
++}, {
++ {0x6f00, 0xc3},
++ {0xc4e4, 0x06},
++ {0xc4e5, 0x0d},
++ {0xc4e6, 0x15},
++ {0xc4e7, 0x1e},
++ {0xc4e8, 0x28},
++ {0xc4e9, 0x32},
++ {0xc4ea, 0x3c},
++ {0xc4eb, 0x48},
++ {0xc4ec, 0x56},
++ {0xc4ed, 0x66},
++ {0xc4ee, 0x78},
++ {0xc4ef, 0x8c},
++ {0xc4f0, 0xa2},
++ {0xc4f1, 0xba},
++ {0xc4f2, 0xd4},
++ {0x6f00, 0x03},
++ {0x6f00, 0x43},
++}
++};
+diff --git a/drivers/media/i2c/soc_camera/ov10635_debug.h b/drivers/media/i2c/soc_camera/ov10635_debug.h
+new file mode 100644
+index 0000000..4c3515a
+--- /dev/null
++++ b/drivers/media/i2c/soc_camera/ov10635_debug.h
+@@ -0,0 +1,54 @@
++
++#if 0
++{0x4700, 0x02}, // BT656
++{0x381d, 0x40}, // mirror off
++{0x381c, 0x00}, // flip off
++{0x4300, 0x3a}, // YUV: UYVY
++{0x4708, 0x00}, // PCLK rising edge
++
++// clk = 24Mhz/3*22/2= 88Mhz
++{0x3003, 0x16},
++{0x3004, 0x30},
++#endif
++
++#define WIDTH 1280
++#define HEIGHT 720
++
++// DVP frame size
++{0x3808, WIDTH >> 8},
++{0x3809, WIDTH & 0xff},
++{0x380a, HEIGHT >> 8},
++{0x380b, HEIGHT & 0xff},
++
++{0x3802, ((814 - HEIGHT)/2) >> 8}, // vert crop start
++{0x3803, ((814 - HEIGHT)/2) & 0xff},
++{0x3806, ((814 - HEIGHT)/2 + HEIGHT + 1) >> 8}, // vert crop end
++{0x3807, ((814 - HEIGHT)/2 + HEIGHT + 1) & 0xff},
++
++#if 0
++#define HTS 0x6f6 // got from above table 1782
++#define VTS (0x2ec+80) // got from above table 748 + 80
++
++{0x380c, HTS >> 8}, // hts
++{0x380d, HTS & 0xff},
++{0x380e, VTS >> 8}, // vts
++{0x380f, VTS & 0xff},
++
++// fifo
++{0x4606, (2*HTS) >> 8}, // fifo_line_length = 2*hts
++{0x4607, (2*HTS) & 0xff},
++{0x460a, (2*(HTS-1280)) >> 8}, // fifo_hsync_start = 2*(hts - xres)
++{0x460b, (2*(HTS-1280)) & 0xff },
++
++// exposure
++{0xC488, (VTS-8)*16 >> 8},
++{0xC489, (VTS-8)*16 & 0xff},
++{0xC48A, (VTS-8)*16 >> 8},
++{0xC48B, (VTS-8)*16 & 0xff},
++
++// vts/hts
++{0xC518, VTS >> 8},
++{0xC519, VTS & 0xff},
++{0xC51A, HTS >> 8},
++{0xC51B, HTS & 0xff},
++#endif
+diff --git a/drivers/media/i2c/soc_camera/ov106xx.c b/drivers/media/i2c/soc_camera/ov106xx.c
+new file mode 100644
+index 0000000..0079bb2
+--- /dev/null
++++ b/drivers/media/i2c/soc_camera/ov106xx.c
+@@ -0,0 +1,95 @@
++/*
++ * OmniVision ov10635/ov490-ov10640/ov495-ov2775 sensor camera driver
++ *
++ * Copyright (C) 2016-2017 Cogent Embedded, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++
++#include "ov10635.c"
++#include "ov490_ov10640.c"
++#include "ov495_ov2775.c"
++
++static enum {
++ ID_OV10635,
++ ID_OV490_OV10640,
++ ID_OV495_OV2775,
++} chip_id;
++
++static int ov106xx_probe(struct i2c_client *client,
++ const struct i2c_device_id *did)
++{
++ int ret;
++ chip_id = -EINVAL;
++
++ ret = ov10635_probe(client, did);
++ if (!ret) {
++ chip_id = ID_OV10635;
++ goto out;
++ }
++
++ ret = ov490_probe(client, did);
++ if (!ret) {
++ chip_id = ID_OV490_OV10640;
++ goto out;
++ }
++
++ ret = ov495_probe(client, did);
++ if (!ret) {
++ chip_id = ID_OV495_OV2775;
++ goto out;
++ }
++
++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n",
++ client->addr, client->adapter->name);
++out:
++ return ret;
++}
++
++static int ov106xx_remove(struct i2c_client *client)
++{
++ switch (chip_id) {
++ case ID_OV10635:
++ ov10635_remove(client);
++ break;
++ case ID_OV490_OV10640:
++ ov490_remove(client);
++ break;
++ case ID_OV495_OV2775:
++ ov495_remove(client);
++ break;
++ };
++
++ return 0;
++}
++
++static const struct i2c_device_id ov106xx_id[] = {
++ { "ov106xx", 0 },
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, ov106xx_id);
++
++static const struct of_device_id ov106xx_of_ids[] = {
++ { .compatible = "ovti,ov106xx", },
++ { }
++};
++MODULE_DEVICE_TABLE(of, ov106xx_of_ids);
++
++static struct i2c_driver ov106xx_i2c_driver = {
++ .driver = {
++ .name = "ov106xx",
++ .of_match_table = ov106xx_of_ids,
++ },
++ .probe = ov106xx_probe,
++ .remove = ov106xx_remove,
++ .id_table = ov106xx_id,
++};
++
++module_i2c_driver(ov106xx_i2c_driver);
++
++MODULE_DESCRIPTION("SoC Camera driver for OV10635 or OV490/OV10640 or OV495/OV2775");
++MODULE_AUTHOR("Vladimir Barinov");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/i2c/soc_camera/ov490_ov10640.c b/drivers/media/i2c/soc_camera/ov490_ov10640.c
+new file mode 100644
+index 0000000..dfd410a
+--- /dev/null
++++ b/drivers/media/i2c/soc_camera/ov490_ov10640.c
+@@ -0,0 +1,963 @@
++/*
++ * OmniVision ov490-ov10640 sensor camera driver
++ *
++ * Copyright (C) 2016-2017 Cogent Embedded, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++
++#include <linux/delay.h>
++#include <linux/init.h>
++#include <linux/i2c.h>
++#include <linux/module.h>
++#include <linux/videodev2.h>
++
++#include <media/soc_camera.h>
++#include <media/v4l2-common.h>
++#include <media/v4l2-ctrls.h>
++#include <media/v4l2-of.h>
++
++#include "max9286_max9271.h"
++#include "ov490_ov10640.h"
++
++#define OV490_I2C_ADDR 0x24
++
++#define OV490_PID 0x300a
++#define OV490_VER 0x300b
++#define OV490_VERSION_REG 0x0490
++#define OV490_VERSION(pid, ver) (((pid) << 8) | ((ver) & 0xff))
++#define OV490_REV 0x0007
++
++#define OV490_ISP_HSIZE_LOW 0x60
++#define OV490_ISP_HSIZE_HIGH 0x61
++#define OV490_ISP_VSIZE_LOW 0x62
++#define OV490_ISP_VSIZE_HIGH 0x63
++
++struct ov490_priv {
++ struct v4l2_subdev sd;
++ struct v4l2_ctrl_handler hdl;
++ struct media_pad pad;
++ struct v4l2_rect rect;
++ int max_width;
++ int max_height;
++ char is_fixed_sensor;
++ int init_complete;
++ u8 id[6];
++ int exposure;
++ int gain;
++ int autogain;
++ int dvp_order;
++ /* serializers */
++ int max9286_addr;
++ int max9271_addr;
++ int ti964_addr;
++ int ti954_addr;
++ int ti9x3_addr;
++ int port;
++ int gpio_resetb;
++ int gpio_fsin;
++
++};
++
++static int force_conf_link;
++
++static __init int ov490_force_conf_link(char *str)
++{
++ /* force configuration link */
++ /* used only if robust firmware flashing required (f.e. recovery) */
++ force_conf_link = 1;
++ return 0;
++}
++early_param("force_conf_link", ov490_force_conf_link);
++
++static inline struct ov490_priv *to_ov490(const struct i2c_client *client)
++{
++ return container_of(i2c_get_clientdata(client), struct ov490_priv, sd);
++}
++
++static void ov490_s_port(struct i2c_client *client, int fwd_en)
++{
++ struct ov490_priv *priv = to_ov490(client);
++ int tmp_addr;
++
++ if (priv->max9286_addr) {
++ tmp_addr = client->addr;
++ client->addr = priv->max9286_addr; /* Deserializer I2C address */
++ reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */
++ usleep_range(2000, 2500); /* wait 2ms */
++ client->addr = tmp_addr;
++ };
++}
++
++static int ov490_set_regs(struct i2c_client *client,
++ const struct ov490_reg *regs, int nr_regs)
++{
++ int i;
++
++ for (i = 0; i < nr_regs; i++) {
++ if (reg16_write(client, regs[i].reg, regs[i].val)) {
++ usleep_range(100, 150); /* wait 100 us */
++ reg16_write(client, regs[i].reg, regs[i].val);
++ }
++ }
++
++ return 0;
++}
++
++static int ov490_s_stream(struct v4l2_subdev *sd, int enable)
++{
++ return 0;
++}
++
++static int ov490_get_fmt(struct v4l2_subdev *sd,
++ struct v4l2_subdev_pad_config *cfg,
++ struct v4l2_subdev_format *format)
++{
++ struct v4l2_mbus_framefmt *mf = &format->format;
++ struct i2c_client *client = v4l2_get_subdevdata(sd);
++ struct ov490_priv *priv = to_ov490(client);
++
++ if (format->pad)
++ return -EINVAL;
++
++ mf->width = priv->rect.width;
++ mf->height = priv->rect.height;
++ mf->code = MEDIA_BUS_FMT_YUYV8_2X8;
++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M;
++ mf->field = V4L2_FIELD_NONE;
++
++ return 0;
++}
++
++static int ov490_set_fmt(struct v4l2_subdev *sd,
++ struct v4l2_subdev_pad_config *cfg,
++ struct v4l2_subdev_format *format)
++{
++ struct v4l2_mbus_framefmt *mf = &format->format;
++
++ mf->code = MEDIA_BUS_FMT_YUYV8_2X8;
++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M;
++ mf->field = V4L2_FIELD_NONE;
++
++ if (format->which == V4L2_SUBDEV_FORMAT_TRY)
++ cfg->try_fmt = *mf;
++
++ return 0;
++}
++
++static int ov490_enum_mbus_code(struct v4l2_subdev *sd,
++ struct v4l2_subdev_pad_config *cfg,
++ struct v4l2_subdev_mbus_code_enum *code)
++{
++ if (code->pad || code->index > 0)
++ return -EINVAL;
++
++ code->code = MEDIA_BUS_FMT_YUYV8_2X8;
++
++ return 0;
++}
++
++static int ov490_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
++{
++ struct i2c_client *client = v4l2_get_subdevdata(sd);
++ struct ov490_priv *priv = to_ov490(client);
++
++ memcpy(edid->edid, priv->id, 6);
++
++ edid->edid[6] = 0xff;
++ edid->edid[7] = client->addr;
++ edid->edid[8] = OV490_VERSION_REG >> 8;
++ edid->edid[9] = OV490_VERSION_REG & 0xff;
++
++ return 0;
++}
++
++static int ov490_set_selection(struct v4l2_subdev *sd,
++ struct v4l2_subdev_pad_config *cfg,
++ struct v4l2_subdev_selection *sel)
++{
++ struct v4l2_rect *rect = &sel->r;
++ struct i2c_client *client = v4l2_get_subdevdata(sd);
++ struct ov490_priv *priv = to_ov490(client);
++
++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE ||
++ sel->target != V4L2_SEL_TGT_CROP)
++ return -EINVAL;
++
++ rect->left = ALIGN(rect->left, 2);
++ rect->top = ALIGN(rect->top, 2);
++ rect->width = ALIGN(rect->width, 2);
++ rect->height = ALIGN(rect->height, 2);
++
++ if ((rect->left + rect->width > priv->max_width) ||
++ (rect->top + rect->height > priv->max_height))
++ *rect = priv->rect;
++
++ priv->rect.left = rect->left;
++ priv->rect.top = rect->top;
++ priv->rect.width = rect->width;
++ priv->rect.height = rect->height;
++
++ return 0;
++}
++
++static int ov490_get_selection(struct v4l2_subdev *sd,
++ struct v4l2_subdev_pad_config *cfg,
++ struct v4l2_subdev_selection *sel)
++{
++ struct i2c_client *client = v4l2_get_subdevdata(sd);
++ struct ov490_priv *priv = to_ov490(client);
++
++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
++ return -EINVAL;
++
++ switch (sel->target) {
++ case V4L2_SEL_TGT_CROP_BOUNDS:
++ sel->r.left = 0;
++ sel->r.top = 0;
++ sel->r.width = priv->max_width;
++ sel->r.height = priv->max_height;
++ return 0;
++ case V4L2_SEL_TGT_CROP_DEFAULT:
++ sel->r.left = 0;
++ sel->r.top = 0;
++ sel->r.width = priv->max_width;
++ sel->r.height = priv->max_height;
++ return 0;
++ case V4L2_SEL_TGT_CROP:
++ sel->r = priv->rect;
++ return 0;
++ default:
++ return -EINVAL;
++ }
++}
++
++static int ov490_g_mbus_config(struct v4l2_subdev *sd,
++ struct v4l2_mbus_config *cfg)
++{
++ cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 |
++ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
++ cfg->type = V4L2_MBUS_CSI2;
++
++ return 0;
++}
++
++#ifdef CONFIG_VIDEO_ADV_DEBUG
++static int ov490_g_register(struct v4l2_subdev *sd,
++ struct v4l2_dbg_register *reg)
++{
++ struct i2c_client *client = v4l2_get_subdevdata(sd);
++ int ret;
++ u8 val = 0;
++
++ ret = reg16_read(client, (u16)reg->reg, &val);
++ if (ret < 0)
++ return ret;
++
++ reg->val = val;
++ reg->size = sizeof(u16);
++
++ return 0;
++}
++
++static int ov490_s_register(struct v4l2_subdev *sd,
++ const struct v4l2_dbg_register *reg)
++{
++ struct i2c_client *client = v4l2_get_subdevdata(sd);
++ int ret;
++
++ ret = reg16_write(client, (u16)reg->reg, (u8)reg->val);
++ if ((u8)reg->reg == 0xFFFD)
++ usleep_range(100, 150); /* wait 100 us */
++ if ((u8)reg->reg == 0xFFFE)
++ usleep_range(100, 150); /* wait 100 us */
++ return ret;
++}
++#endif
++
++static struct v4l2_subdev_core_ops ov490_core_ops = {
++#ifdef CONFIG_VIDEO_ADV_DEBUG
++ .g_register = ov490_g_register,
++ .s_register = ov490_s_register,
++#endif
++};
++
++static int ov490_s_gamma(int a, int ref)
++{
++ if ((a + ref) > 0xff)
++ return 0xff;
++
++ if ((a + ref) < 0)
++ return 0;
++
++ return a + ref;
++}
++
++static int ov490_s_ctrl(struct v4l2_ctrl *ctrl)
++{
++ struct v4l2_subdev *sd = to_sd(ctrl);
++ struct i2c_client *client = v4l2_get_subdevdata(sd);
++ struct ov490_priv *priv = to_ov490(client);
++ int ret = -EINVAL;
++
++ if (!priv->init_complete)
++ return 0;
++
++ switch (ctrl->id) {
++ case V4L2_CID_BRIGHTNESS:
++ /* SDE (rough) brightness */
++ ret = reg16_write(client, 0xFFFD, 0x80);
++ ret |= reg16_write(client, 0xFFFE, 0x19);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x5000, 0x00);
++ ret |= reg16_write(client, 0x5001, ctrl->val);
++ ret |= reg16_write(client, 0xFFFE, 0x80);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x00C0, 0xf1);
++ break;
++ case V4L2_CID_CONTRAST:
++ ret = reg16_write(client, 0xFFFD, 0x80);
++ ret |= reg16_write(client, 0xFFFE, 0x19);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x5000, ctrl->val);
++ ret |= reg16_write(client, 0xFFFE, 0x80);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x00C0, 0xfd);
++ break;
++ case V4L2_CID_SATURATION:
++ ret = reg16_write(client, 0xFFFD, 0x80);
++ ret |= reg16_write(client, 0xFFFE, 0x19);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x5000, ctrl->val);
++ ret |= reg16_write(client, 0xFFFE, 0x80);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x00C0, 0xf3);
++ break;
++ case V4L2_CID_HUE:
++ ret = reg16_write(client, 0xFFFD, 0x80);
++ ret |= reg16_write(client, 0xFFFE, 0x19);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x5000, ctrl->val);
++ ret |= reg16_write(client, 0xFFFE, 0x80);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x00C0, 0xf5);
++ break;
++ case V4L2_CID_GAMMA:
++ ret = reg16_write(client, 0xFFFD, 0x80);
++ ret |= reg16_write(client, 0xFFFE, 0x19);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x5000, ov490_s_gamma(ctrl->val, 0x12));
++ ret |= reg16_write(client, 0x5001, ov490_s_gamma(ctrl->val, 0x20));
++ ret |= reg16_write(client, 0x5002, ov490_s_gamma(ctrl->val, 0x3b));
++ ret |= reg16_write(client, 0x5003, ov490_s_gamma(ctrl->val, 0x5d));
++ ret |= reg16_write(client, 0x5004, ov490_s_gamma(ctrl->val, 0x6a));
++ ret |= reg16_write(client, 0x5005, ov490_s_gamma(ctrl->val, 0x76));
++ ret |= reg16_write(client, 0x5006, ov490_s_gamma(ctrl->val, 0x81));
++ ret |= reg16_write(client, 0x5007, ov490_s_gamma(ctrl->val, 0x8b));
++ ret |= reg16_write(client, 0x5008, ov490_s_gamma(ctrl->val, 0x96));
++ ret |= reg16_write(client, 0x5009, ov490_s_gamma(ctrl->val, 0x9e));
++ ret |= reg16_write(client, 0x500a, ov490_s_gamma(ctrl->val, 0xae));
++ ret |= reg16_write(client, 0x500b, ov490_s_gamma(ctrl->val, 0xbc));
++ ret |= reg16_write(client, 0x500c, ov490_s_gamma(ctrl->val, 0xcf));
++ ret |= reg16_write(client, 0x500d, ov490_s_gamma(ctrl->val, 0xde));
++ ret |= reg16_write(client, 0x500e, ov490_s_gamma(ctrl->val, 0xec));
++ ret |= reg16_write(client, 0xFFFE, 0x80);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x00C0, 0xf9);
++ break;
++ case V4L2_CID_SHARPNESS:
++ ret = reg16_write(client, 0xFFFD, 0x80);
++ ret |= reg16_write(client, 0xFFFE, 0x19);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x5000, ctrl->val);
++ ret |= reg16_write(client, 0xFFFE, 0x80);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x00C0, 0xfb);
++ break;
++ case V4L2_CID_AUTOGAIN:
++ case V4L2_CID_GAIN:
++ case V4L2_CID_EXPOSURE:
++ if (ctrl->id == V4L2_CID_AUTOGAIN)
++ priv->autogain = ctrl->val;
++ if (ctrl->id == V4L2_CID_GAIN)
++ priv->gain = ctrl->val;
++ if (ctrl->id == V4L2_CID_EXPOSURE)
++ priv->exposure = ctrl->val;
++
++ ret = reg16_write(client, 0xFFFD, 0x80);
++ ret |= reg16_write(client, 0xFFFE, 0x19);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x5000, !priv->autogain);
++ ret |= reg16_write(client, 0x5001, priv->exposure >> 8);
++ ret |= reg16_write(client, 0x5002, priv->exposure & 0xff);
++ ret |= reg16_write(client, 0x5003, priv->exposure >> 8);
++ ret |= reg16_write(client, 0x5004, priv->exposure & 0xff);
++ ret |= reg16_write(client, 0x5005, priv->exposure >> 8);
++ ret |= reg16_write(client, 0x5006, priv->exposure & 0xff);
++ ret |= reg16_write(client, 0x5007, priv->gain >> 8);
++ ret |= reg16_write(client, 0x5008, priv->gain & 0xff);
++ ret |= reg16_write(client, 0x5009, priv->gain >> 8);
++ ret |= reg16_write(client, 0x500a, priv->gain & 0xff);
++ ret |= reg16_write(client, 0x500b, priv->gain >> 8);
++ ret |= reg16_write(client, 0x500c, priv->gain & 0xff);
++ ret |= reg16_write(client, 0xFFFE, 0x80);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x00C0, 0xea);
++ break;
++ case V4L2_CID_HFLIP:
++#if 1
++ ret = reg16_write(client, 0xFFFD, 0x80);
++ ret |= reg16_write(client, 0xFFFE, 0x19);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x5000, ctrl->val);
++ ret |= reg16_write(client, 0x5001, 0x00);
++ ret |= reg16_write(client, 0xFFFE, 0x80);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x00C0, 0xdc);
++#else
++ ret = reg16_write(client, 0xFFFD, 0x80);
++ ret |= reg16_write(client, 0xFFFE, 0x19);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x5000, 0x01); // read 0x3128
++ ret |= reg16_write(client, 0x5001, 0x31);
++ ret |= reg16_write(client, 0x5002, 0x28);
++ ret |= reg16_write(client, 0xFFFE, 0x80);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x00C0, 0xc1);
++ ret |= reg16_write(client, 0xFFFE, 0x19);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_read(client, 0x5000, &val);
++ val &= ~(0x1 << 0);
++ val |= (ctrl->val << 0);
++ ret |= reg16_write(client, 0xFFFE, 0x19);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x5000, 0x00); // write 0x3128
++ ret |= reg16_write(client, 0x5001, 0x31);
++ ret |= reg16_write(client, 0x5002, 0x28);
++ ret |= reg16_write(client, 0x5003, val);
++ ret |= reg16_write(client, 0xFFFE, 0x80);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x00C0, 0xc1);
++
++ ret |= reg16_write(client, 0xFFFE, 0x19);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x5000, 0x01); // read 0x3291
++ ret |= reg16_write(client, 0x5001, 0x32);
++ ret |= reg16_write(client, 0x5002, 0x91);
++ ret |= reg16_write(client, 0xFFFE, 0x80);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x00C0, 0xc1);
++ ret |= reg16_write(client, 0xFFFE, 0x19);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_read(client, 0x5000, &val);
++ val &= ~(0x1 << 1);
++ val |= (ctrl->val << 1);
++ ret |= reg16_write(client, 0xFFFE, 0x19);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x5000, 0x00); // write 0x3291
++ ret |= reg16_write(client, 0x5001, 0x32);
++ ret |= reg16_write(client, 0x5002, 0x91);
++ ret |= reg16_write(client, 0x5003, val);
++ ret |= reg16_write(client, 0xFFFE, 0x80);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x00C0, 0xc1);
++
++ ret |= reg16_write(client, 0xFFFE, 0x19);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x5000, 0x01); // read 0x3090
++ ret |= reg16_write(client, 0x5001, 0x30);
++ ret |= reg16_write(client, 0x5002, 0x90);
++ ret |= reg16_write(client, 0xFFFE, 0x80);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x00C0, 0xc1);
++ ret |= reg16_write(client, 0xFFFE, 0x19);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_read(client, 0x5000, &val);
++ val &= ~(0x1 << 2);
++ val |= (ctrl->val << 2);
++ ret |= reg16_write(client, 0xFFFE, 0x19);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x5000, 0x00); // write 0x3090
++ ret |= reg16_write(client, 0x5001, 0x30);
++ ret |= reg16_write(client, 0x5002, 0x90);
++ ret |= reg16_write(client, 0x5003, val);
++ ret |= reg16_write(client, 0xFFFE, 0x80);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x00C0, 0xc1);
++#endif
++ break;
++ case V4L2_CID_VFLIP:
++#if 1
++ ret = reg16_write(client, 0xFFFD, 0x80);
++ ret |= reg16_write(client, 0xFFFE, 0x19);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x5000, ctrl->val);
++ ret |= reg16_write(client, 0x5001, 0x01);
++ ret |= reg16_write(client, 0xFFFE, 0x80);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x00C0, 0xdc);
++#else
++ ret = reg16_write(client, 0xFFFD, 0x80);
++ ret |= reg16_write(client, 0xFFFE, 0x19);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x5000, 0x01); // read 0x3128
++ ret |= reg16_write(client, 0x5001, 0x31);
++ ret |= reg16_write(client, 0x5002, 0x28);
++ ret |= reg16_write(client, 0xFFFE, 0x80);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x00C0, 0xc1);
++ ret |= reg16_write(client, 0xFFFE, 0x19);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_read(client, 0x5000, &val);
++ val &= ~(0x1 << 1);
++ val |= (ctrl->val << 1);
++ ret |= reg16_write(client, 0xFFFE, 0x19);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x5000, 0x00); // write 0x3128
++ ret |= reg16_write(client, 0x5001, 0x31);
++ ret |= reg16_write(client, 0x5002, 0x28);
++ ret |= reg16_write(client, 0x5003, val);
++ ret |= reg16_write(client, 0xFFFE, 0x80);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x00C0, 0xc1);
++
++ ret |= reg16_write(client, 0xFFFE, 0x19);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x5000, 0x01); // read 0x3291
++ ret |= reg16_write(client, 0x5001, 0x32);
++ ret |= reg16_write(client, 0x5002, 0x91);
++ ret |= reg16_write(client, 0xFFFE, 0x80);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x00C0, 0xc1);
++ ret |= reg16_write(client, 0xFFFE, 0x19);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_read(client, 0x5000, &val);
++ val &= ~(0x1 << 2);
++ val |= (ctrl->val << 2);
++ ret |= reg16_write(client, 0xFFFE, 0x19);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x5000, 0x00); // write 0x3291
++ ret |= reg16_write(client, 0x5001, 0x32);
++ ret |= reg16_write(client, 0x5002, 0x91);
++ ret |= reg16_write(client, 0x5003, val);
++ ret |= reg16_write(client, 0xFFFE, 0x80);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x00C0, 0xc1);
++
++ ret |= reg16_write(client, 0xFFFE, 0x19);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x5000, 0x01); // read 0x3090
++ ret |= reg16_write(client, 0x5001, 0x30);
++ ret |= reg16_write(client, 0x5002, 0x90);
++ ret |= reg16_write(client, 0xFFFE, 0x80);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x00C0, 0xc1);
++ ret |= reg16_write(client, 0xFFFE, 0x19);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_read(client, 0x5000, &val);
++ val &= ~(0x1 << 3);
++ val |= (ctrl->val << 3);
++ ret |= reg16_write(client, 0xFFFE, 0x19);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x5000, 0x00); // write 0x3090
++ ret |= reg16_write(client, 0x5001, 0x30);
++ ret |= reg16_write(client, 0x5002, 0x90);
++ ret |= reg16_write(client, 0x5003, val);
++ ret |= reg16_write(client, 0xFFFE, 0x80);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x00C0, 0xc1);
++#endif
++ break;
++ }
++
++ return ret;
++}
++
++static const struct v4l2_ctrl_ops ov490_ctrl_ops = {
++ .s_ctrl = ov490_s_ctrl,
++};
++
++static struct v4l2_subdev_video_ops ov490_video_ops = {
++ .s_stream = ov490_s_stream,
++ .g_mbus_config = ov490_g_mbus_config,
++};
++
++static const struct v4l2_subdev_pad_ops ov490_subdev_pad_ops = {
++ .get_edid = ov490_get_edid,
++ .enum_mbus_code = ov490_enum_mbus_code,
++ .get_selection = ov490_get_selection,
++ .set_selection = ov490_set_selection,
++ .get_fmt = ov490_get_fmt,
++ .set_fmt = ov490_set_fmt,
++};
++
++static struct v4l2_subdev_ops ov490_subdev_ops = {
++ .core = &ov490_core_ops,
++ .video = &ov490_video_ops,
++ .pad = &ov490_subdev_pad_ops,
++};
++
++static void ov490_otp_id_read(struct i2c_client *client)
++{
++ struct ov490_priv *priv = to_ov490(client);
++ int i;
++
++#if 0
++ /* read camera id from ov490 OTP memory */
++ reg16_write(client, 0xFFFD, 0x80);
++ reg16_write(client, 0xFFFE, 0x28);
++ usleep_range(100, 150); /* wait 100 us */
++ reg16_write(client, 0xE084, 0x40); /* manual mode, bank#0 */
++ reg16_write(client, 0xE081, 1); /* start OTP read */
++
++ usleep_range(25000, 26000); /* wait 25 ms */
++
++ for (i = 0; i < 6; i++)
++ reg16_read(client, 0xe000 + i + 4, &priv->id[i]);
++#else
++ /* read camera id from ov10640 OTP memory */
++ reg16_write(client, 0xFFFD, 0x80);
++ usleep_range(100, 150); /* wait 100 us */
++ reg16_write(client, 0xFFFE, 0x19);
++ usleep_range(100, 150); /* wait 100 us */
++ reg16_write(client, 0x5000, 0x00); /* write 0x349C -> 1 */
++ reg16_write(client, 0x5001, 0x34);
++ reg16_write(client, 0x5002, 0x9C);
++ reg16_write(client, 0x5003, 1);
++ reg16_write(client, 0xFFFE, 0x80);
++ usleep_range(100, 150); /* wait 100 us */
++ reg16_write(client, 0x00C0, 0xc1);
++
++ usleep_range(25000, 25500); /* wait 25 ms */
++
++ for (i = 0; i < 6; i++) {
++ reg16_write(client, 0xFFFE, 0x19);
++ usleep_range(100, 150); /* wait 100 us */
++ reg16_write(client, 0x5000, 0x01); /* read (0x349E + i) */
++ reg16_write(client, 0x5001, 0x34);
++ reg16_write(client, 0x5002, 0x9e + i + 6); /* first 6 bytes are equal on all ov10640 */
++ reg16_write(client, 0xFFFE, 0x80);
++ usleep_range(100, 150); /* wait 100 us */
++ reg16_write(client, 0x00C0, 0xc1);
++ reg16_write(client, 0xFFFE, 0x19);
++ usleep_range(1000, 1500); /* wait 1 ms */
++ reg16_read(client, 0x5000, &priv->id[i]);
++ }
++#endif
++}
++
++static ssize_t ov490_otp_id_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct v4l2_subdev *sd = i2c_get_clientdata(to_i2c_client(dev));
++ struct i2c_client *client = v4l2_get_subdevdata(sd);
++ struct ov490_priv *priv = to_ov490(client);
++
++ return snprintf(buf, 32, "%02x:%02x:%02x:%02x:%02x:%02x\n",
++ priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]);
++}
++
++static DEVICE_ATTR(otp_id_ov490, S_IRUGO, ov490_otp_id_show, NULL);
++
++static int ov490_initialize(struct i2c_client *client)
++{
++ struct ov490_priv *priv = to_ov490(client);
++ u8 val = 0;
++ u8 pid = 0, ver = 0, rev = 0;
++ int ret = 0;
++
++ if (priv->is_fixed_sensor) {
++ dev_info(&client->dev, "ov490/ov10640 fixed-sensor res %dx%d\n", priv->max_width, priv->max_height);
++ return 0;
++ }
++
++ ov490_s_port(client, 1);
++
++ /* check and show product ID and manufacturer ID */
++ reg16_write(client, 0xFFFD, 0x80);
++ reg16_write(client, 0xFFFE, 0x80);
++ usleep_range(100, 150); /* wait 100 us */
++ reg16_read(client, OV490_PID, &pid);
++ reg16_read(client, OV490_VER, &ver);
++ reg16_read(client, OV490_REV, &rev);
++
++ if (OV490_VERSION(pid, ver) != OV490_VERSION_REG) {
++ dev_dbg(&client->dev, "Product ID error %x:%x\n", pid, ver);
++ ret = -ENODEV;
++ goto err;
++ }
++
++ if (unlikely(force_conf_link))
++ goto out;
++
++ /* read resolution used by current firmware */
++ reg16_write(client, 0xFFFD, 0x80);
++ reg16_write(client, 0xFFFE, 0x82);
++ usleep_range(100, 150); /* wait 100 us */
++ reg16_read(client, OV490_ISP_HSIZE_HIGH, &val);
++ priv->max_width = val;
++ reg16_read(client, OV490_ISP_HSIZE_LOW, &val);
++ priv->max_width = (priv->max_width << 8) | val;
++ reg16_read(client, OV490_ISP_VSIZE_HIGH, &val);
++ priv->max_height = val;
++ reg16_read(client, OV490_ISP_VSIZE_LOW, &val);
++ priv->max_height = (priv->max_height << 8) | val;
++ /* Program wizard registers */
++ ov490_set_regs(client, ov490_regs_wizard, ARRAY_SIZE(ov490_regs_wizard));
++ /* Set DVP bit swap */
++ reg16_write(client, 0xFFFD, 0x80);
++ reg16_write(client, 0xFFFE, 0x28);
++ usleep_range(100, 150); /* wait 100 us */
++ reg16_write(client, 0x6009, priv->dvp_order << 4);
++ /* Read OTP IDs */
++ ov490_otp_id_read(client);
++
++out:
++ dev_info(&client->dev, "ov490/ov10640 Product ID %x Manufacturer ID %x, rev 1%x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n",
++ pid, ver, 0xa + rev, priv->max_width, priv->max_height, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]);
++err:
++ ov490_s_port(client, 0);
++
++ return ret;
++}
++
++static int ov490_parse_dt(struct device_node *np, struct ov490_priv *priv)
++{
++ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd);
++ int err, i;
++ const char *fixed_sensor;
++ struct device_node *endpoint = NULL, *rendpoint = NULL;
++ int tmp_addr = 0;
++
++ for (i = 0; ; i++) {
++ endpoint = of_graph_get_next_endpoint(np, endpoint);
++ if (!endpoint)
++ break;
++
++ of_node_put(endpoint);
++
++ of_property_read_u32(endpoint, "dvp-order", &priv->dvp_order);
++
++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0);
++ if (!rendpoint)
++ continue;
++
++ if (!of_property_read_u32(rendpoint, "max9271-addr", &priv->max9271_addr) &&
++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->max9286_addr) &&
++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port))
++ break;
++
++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) &&
++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti964-ti9x3") &&
++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti964_addr) &&
++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port))
++ break;
++
++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) &&
++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti954-ti9x3") &&
++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti954_addr) &&
++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port))
++ break;
++ }
++
++ if (!priv->max9286_addr && !priv->ti964_addr && !priv->ti954_addr) {
++ dev_err(&client->dev, "deserializer does not present\n");
++ return -EINVAL;
++ }
++
++ ov490_s_port(client, 1);
++
++ /* setup I2C translator address */
++ tmp_addr = client->addr;
++ if (priv->max9286_addr) {
++ client->addr = priv->max9271_addr; /* Serializer I2C address */
++
++ reg8_write(client, 0x09, tmp_addr << 1); /* Sensor translated I2C address */
++ reg8_write(client, 0x0A, OV490_I2C_ADDR << 1); /* Sensor native I2C address */
++ usleep_range(2000, 2500); /* wait 2ms */
++ };
++ if (priv->ti964_addr) {
++ client->addr = priv->ti964_addr; /* Deserializer I2C address */
++
++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */
++ usleep_range(2000, 2500); /* wait 2ms */
++ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */
++ reg8_write(client, 0x5d, OV490_I2C_ADDR << 1); /* Sensor native I2C address */
++
++ reg8_write(client, 0x6e, 0x9a); /* GPIO0 - fsin, GPIO1 - resetb */
++ /* TODO: why too long? move logic to workqueue? */
++ mdelay(350); /* time needed to boot all sensor IPs */
++ }
++ if (priv->ti954_addr) {
++ client->addr = priv->ti954_addr; /* Deserializer I2C address */
++
++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */
++ usleep_range(2000, 2500); /* wait 2ms */
++ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */
++ reg8_write(client, 0x5d, OV490_I2C_ADDR << 1); /* Sensor native I2C address */
++
++ reg8_write(client, 0x6e, 0x9a); /* GPIO0 - fsin, GPIO1 - resetb */
++ /* TODO: why too long? move logic to workqueue? */
++ mdelay(350); /* time needed to boot all sensor IPs */
++ }
++ client->addr = tmp_addr;
++
++ err = of_property_read_string(np, "maxim,fixed-sensor", &fixed_sensor);
++ if (err)
++ return 0;
++
++ if (strcmp(fixed_sensor, "ov490") == 0) {
++ err = of_property_read_u32(np, "maxim,width", &priv->max_width);
++ if (err) {
++ dev_err(&client->dev, "maxim,width must be set for fixed-sensor\n");
++ goto out;
++ }
++
++ err = of_property_read_u32(np, "maxim,height", &priv->max_height);
++ if (err) {
++ dev_err(&client->dev, "maxim,height must be set for fixed-sensor\n");
++ goto out;
++ }
++
++ priv->is_fixed_sensor = true;
++ }
++
++out:
++ return err;
++}
++
++static int ov490_probe(struct i2c_client *client,
++ const struct i2c_device_id *did)
++{
++ struct ov490_priv *priv;
++ int ret;
++
++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ v4l2_i2c_subdev_init(&priv->sd, client, &ov490_subdev_ops);
++ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
++
++ priv->exposure = 0x100;
++ priv->gain = 0x100;
++ priv->autogain = 1;
++ v4l2_ctrl_handler_init(&priv->hdl, 4);
++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops,
++ V4L2_CID_BRIGHTNESS, 0, 16, 1, 7);
++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops,
++ V4L2_CID_CONTRAST, 0, 16, 1, 7);
++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops,
++ V4L2_CID_SATURATION, 0, 7, 1, 2);
++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops,
++ V4L2_CID_HUE, 0, 23, 1, 12);
++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops,
++ V4L2_CID_GAMMA, -128, 128, 1, 0);
++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops,
++ V4L2_CID_SHARPNESS, 0, 10, 1, 3);
++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops,
++ V4L2_CID_AUTOGAIN, 0, 1, 1, priv->autogain);
++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops,
++ V4L2_CID_GAIN, 0, 0xffff, 1, priv->gain);
++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops,
++ V4L2_CID_EXPOSURE, 0, 0xffff, 1, priv->exposure);
++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops,
++ V4L2_CID_HFLIP, 0, 1, 1, 1);
++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops,
++ V4L2_CID_VFLIP, 0, 1, 1, 0);
++ priv->sd.ctrl_handler = &priv->hdl;
++
++ ret = priv->hdl.error;
++ if (ret)
++ goto cleanup;
++
++ v4l2_ctrl_handler_setup(&priv->hdl);
++
++ priv->pad.flags = MEDIA_PAD_FL_SOURCE;
++ priv->sd.entity.flags |= MEDIA_ENT_F_CAM_SENSOR;
++ ret = media_entity_pads_init(&priv->sd.entity, 1, &priv->pad);
++ if (ret < 0)
++ goto cleanup;
++
++ ret = ov490_parse_dt(client->dev.of_node, priv);
++ if (ret)
++ goto cleanup;
++
++ ret = ov490_initialize(client);
++ if (ret < 0)
++ goto cleanup;
++
++ priv->rect.left = 0;
++ priv->rect.top = 0;
++ priv->rect.width = priv->max_width;
++ priv->rect.height = priv->max_height;
++
++ ret = v4l2_async_register_subdev(&priv->sd);
++ if (ret)
++ goto cleanup;
++
++ if (device_create_file(&client->dev, &dev_attr_otp_id_ov490) != 0) {
++ dev_err(&client->dev, "sysfs otp_id entry creation failed\n");
++ goto cleanup;
++ }
++
++ priv->init_complete = 1;
++
++ return 0;
++
++cleanup:
++ media_entity_cleanup(&priv->sd.entity);
++ v4l2_ctrl_handler_free(&priv->hdl);
++ v4l2_device_unregister_subdev(&priv->sd);
++#ifdef CONFIG_SOC_CAMERA_OV490_OV10640
++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n",
++ client->addr, client->adapter->name);
++#endif
++ return ret;
++}
++
++static int ov490_remove(struct i2c_client *client)
++{
++ struct ov490_priv *priv = i2c_get_clientdata(client);
++
++ device_remove_file(&client->dev, &dev_attr_otp_id_ov490);
++ v4l2_async_unregister_subdev(&priv->sd);
++ media_entity_cleanup(&priv->sd.entity);
++ v4l2_ctrl_handler_free(&priv->hdl);
++ v4l2_device_unregister_subdev(&priv->sd);
++
++ return 0;
++}
++
++#ifdef CONFIG_SOC_CAMERA_OV490_OV10640
++static const struct i2c_device_id ov490_id[] = {
++ { "ov490-ov10640", 0 },
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, ov490_id);
++
++static const struct of_device_id ov490_of_ids[] = {
++ { .compatible = "ovti,ov490-ov10640", },
++ { }
++};
++MODULE_DEVICE_TABLE(of, ov490_of_ids);
++
++static struct i2c_driver ov490_i2c_driver = {
++ .driver = {
++ .name = "ov490-ov10640",
++ .of_match_table = ov490_of_ids,
++ },
++ .probe = ov490_probe,
++ .remove = ov490_remove,
++ .id_table = ov490_id,
++};
++
++module_i2c_driver(ov490_i2c_driver);
++
++MODULE_DESCRIPTION("SoC Camera driver for OV490-OV10640");
++MODULE_AUTHOR("Vladimir Barinov");
++MODULE_LICENSE("GPL");
++#endif
+diff --git a/drivers/media/i2c/soc_camera/ov490_ov10640.h b/drivers/media/i2c/soc_camera/ov490_ov10640.h
+new file mode 100644
+index 0000000..86e6524
+--- /dev/null
++++ b/drivers/media/i2c/soc_camera/ov490_ov10640.h
+@@ -0,0 +1,33 @@
++/*
++ * OmniVision ov490-ov10640 sensor camera wizard 1280x1080@30/UYVY/BT601/8bit
++ *
++ * Copyright (C) 2016-2017 Cogent Embedded, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++
++struct ov490_reg {
++ u16 reg;
++ u8 val;
++};
++
++static const struct ov490_reg ov490_regs_wizard[] = {
++/* The following registers should match firmware */
++{0xfffd, 0x80},
++{0xfffe, 0x82},
++{0x0071, 0x11},
++{0x0075, 0x11},
++{0xfffe, 0x29},
++{0x6010, 0x01},
++{0x4017, 0x00},
++{0xfffe, 0x28},
++{0x6000, 0x04},
++{0x6004, 0x00},
++{0x6008, 0x00}, // PCLK polarity - useless due to silicon bug -> use 0x808000bb register
++{0xfffe, 0x80},
++{0x0091, 0x00},
++{0x00bb, 0x1d}, // bit[3]=0 - PCLK polarity workaround
++};
+diff --git a/drivers/media/i2c/soc_camera/ov495_ov2775.c b/drivers/media/i2c/soc_camera/ov495_ov2775.c
+new file mode 100644
+index 0000000..3f55778
+--- /dev/null
++++ b/drivers/media/i2c/soc_camera/ov495_ov2775.c
+@@ -0,0 +1,670 @@
++/*
++ * OmniVision ov495-ov2775 sensor camera driver
++ *
++ * Copyright (C) 2017 Cogent Embedded, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++
++#include <linux/delay.h>
++#include <linux/init.h>
++#include <linux/i2c.h>
++#include <linux/module.h>
++#include <linux/videodev2.h>
++
++#include <media/soc_camera.h>
++#include <media/v4l2-common.h>
++#include <media/v4l2-ctrls.h>
++#include <media/v4l2-of.h>
++
++#include "ov495_ov2775.h"
++
++#define OV495_I2C_ADDR 0x24
++
++#define OV495_PID 0x300a
++#define OV495_VER 0x300b
++#define OV495_VERSION_REG 0x0495
++#define OV495_VERSION(pid, ver) (((pid) << 8) | ((ver) & 0xff))
++#define OV495_REV 0x0007
++
++#define OV495_ISP_HSIZE_LOW 0x60
++#define OV495_ISP_HSIZE_HIGH 0x61
++#define OV495_ISP_VSIZE_LOW 0x62
++#define OV495_ISP_VSIZE_HIGH 0x63
++
++struct ov495_priv {
++ struct v4l2_subdev sd;
++ struct v4l2_ctrl_handler hdl;
++ struct media_pad pad;
++ struct v4l2_rect rect;
++ int max_width;
++ int max_height;
++ int init_complete;
++ u8 id[6];
++ int exposure;
++ int gain;
++ int autogain;
++ int dvp_order;
++ /* serializers */
++ int max9286_addr;
++ int max9271_addr;
++ int ti960_addr;
++ int ti954_addr;
++ int ti9x3_addr;
++ int port;
++ int gpio_resetb;
++ int gpio_fsin;
++
++};
++
++static int force_conf_link;
++
++static __init int ov495_force_conf_link(char *str)
++{
++ /* force configuration link */
++ /* used only if robust firmware flashing required (f.e. recovery) */
++ force_conf_link = 1;
++ return 0;
++}
++early_param("force_conf_link", ov495_force_conf_link);
++
++static inline struct ov495_priv *to_ov495(const struct i2c_client *client)
++{
++ return container_of(i2c_get_clientdata(client), struct ov495_priv, sd);
++}
++
++static int ov495_set_regs(struct i2c_client *client,
++ const struct ov495_reg *regs, int nr_regs)
++{
++ int i;
++
++ for (i = 0; i < nr_regs; i++) {
++ if (reg16_write(client, regs[i].reg, regs[i].val)) {
++ usleep_range(100, 150); /* wait 100 us */
++ reg16_write(client, regs[i].reg, regs[i].val);
++ }
++ }
++
++ return 0;
++}
++
++static int ov495_s_stream(struct v4l2_subdev *sd, int enable)
++{
++ return 0;
++}
++
++static int ov495_get_fmt(struct v4l2_subdev *sd,
++ struct v4l2_subdev_pad_config *cfg,
++ struct v4l2_subdev_format *format)
++{
++ struct v4l2_mbus_framefmt *mf = &format->format;
++ struct i2c_client *client = v4l2_get_subdevdata(sd);
++ struct ov495_priv *priv = to_ov495(client);
++
++ if (format->pad)
++ return -EINVAL;
++
++ mf->width = priv->rect.width;
++ mf->height = priv->rect.height;
++ mf->code = MEDIA_BUS_FMT_YUYV8_2X8;
++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M;
++ mf->field = V4L2_FIELD_NONE;
++
++ return 0;
++}
++
++static int ov495_set_fmt(struct v4l2_subdev *sd,
++ struct v4l2_subdev_pad_config *cfg,
++ struct v4l2_subdev_format *format)
++{
++ struct v4l2_mbus_framefmt *mf = &format->format;
++
++ mf->code = MEDIA_BUS_FMT_YUYV8_2X8;
++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M;
++ mf->field = V4L2_FIELD_NONE;
++
++ if (format->which == V4L2_SUBDEV_FORMAT_TRY)
++ cfg->try_fmt = *mf;
++
++ return 0;
++}
++
++static int ov495_enum_mbus_code(struct v4l2_subdev *sd,
++ struct v4l2_subdev_pad_config *cfg,
++ struct v4l2_subdev_mbus_code_enum *code)
++{
++ if (code->pad || code->index > 0)
++ return -EINVAL;
++
++ code->code = MEDIA_BUS_FMT_YUYV8_2X8;
++
++ return 0;
++}
++
++static int ov495_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
++{
++ struct i2c_client *client = v4l2_get_subdevdata(sd);
++ struct ov495_priv *priv = to_ov495(client);
++
++ memcpy(edid->edid, priv->id, 6);
++
++ edid->edid[6] = 0xff;
++ edid->edid[7] = client->addr;
++ edid->edid[8] = OV495_VERSION_REG >> 8;
++ edid->edid[9] = OV495_VERSION_REG & 0xff;
++
++ return 0;
++}
++
++static int ov495_set_selection(struct v4l2_subdev *sd,
++ struct v4l2_subdev_pad_config *cfg,
++ struct v4l2_subdev_selection *sel)
++{
++ struct v4l2_rect *rect = &sel->r;
++ struct i2c_client *client = v4l2_get_subdevdata(sd);
++ struct ov495_priv *priv = to_ov495(client);
++
++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE ||
++ sel->target != V4L2_SEL_TGT_CROP)
++ return -EINVAL;
++
++ rect->left = ALIGN(rect->left, 2);
++ rect->top = ALIGN(rect->top, 2);
++ rect->width = ALIGN(rect->width, 2);
++ rect->height = ALIGN(rect->height, 2);
++
++ if ((rect->left + rect->width > priv->max_width) ||
++ (rect->top + rect->height > priv->max_height))
++ *rect = priv->rect;
++
++ priv->rect.left = rect->left;
++ priv->rect.top = rect->top;
++ priv->rect.width = rect->width;
++ priv->rect.height = rect->height;
++
++ return 0;
++}
++
++static int ov495_get_selection(struct v4l2_subdev *sd,
++ struct v4l2_subdev_pad_config *cfg,
++ struct v4l2_subdev_selection *sel)
++{
++ struct i2c_client *client = v4l2_get_subdevdata(sd);
++ struct ov495_priv *priv = to_ov495(client);
++
++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
++ return -EINVAL;
++
++ switch (sel->target) {
++ case V4L2_SEL_TGT_CROP_BOUNDS:
++ sel->r.left = 0;
++ sel->r.top = 0;
++ sel->r.width = priv->max_width;
++ sel->r.height = priv->max_height;
++ return 0;
++ case V4L2_SEL_TGT_CROP_DEFAULT:
++ sel->r.left = 0;
++ sel->r.top = 0;
++ sel->r.width = priv->max_width;
++ sel->r.height = priv->max_height;
++ return 0;
++ case V4L2_SEL_TGT_CROP:
++ sel->r = priv->rect;
++ return 0;
++ default:
++ return -EINVAL;
++ }
++}
++
++static int ov495_g_mbus_config(struct v4l2_subdev *sd,
++ struct v4l2_mbus_config *cfg)
++{
++ cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 |
++ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
++ cfg->type = V4L2_MBUS_CSI2;
++
++ return 0;
++}
++
++#ifdef CONFIG_VIDEO_ADV_DEBUG
++static int ov495_g_register(struct v4l2_subdev *sd,
++ struct v4l2_dbg_register *reg)
++{
++ struct i2c_client *client = v4l2_get_subdevdata(sd);
++ int ret;
++ u8 val = 0;
++
++ ret = reg16_read(client, (u16)reg->reg, &val);
++ if (ret < 0)
++ return ret;
++
++ reg->val = val;
++ reg->size = sizeof(u16);
++
++ return 0;
++}
++
++static int ov495_s_register(struct v4l2_subdev *sd,
++ const struct v4l2_dbg_register *reg)
++{
++ struct i2c_client *client = v4l2_get_subdevdata(sd);
++ int ret;
++
++ ret = reg16_write(client, (u16)reg->reg, (u8)reg->val);
++ if ((u8)reg->reg == 0xFFFD)
++ usleep_range(100, 150); /* wait 100 us */
++ if ((u8)reg->reg == 0xFFFE)
++ usleep_range(100, 150); /* wait 100 us */
++ return ret;
++}
++#endif
++
++static struct v4l2_subdev_core_ops ov495_core_ops = {
++#ifdef CONFIG_VIDEO_ADV_DEBUG
++ .g_register = ov495_g_register,
++ .s_register = ov495_s_register,
++#endif
++};
++
++static int ov495_s_ctrl(struct v4l2_ctrl *ctrl)
++{
++ struct v4l2_subdev *sd = to_sd(ctrl);
++ struct i2c_client *client = v4l2_get_subdevdata(sd);
++ struct ov495_priv *priv = to_ov495(client);
++ int ret = -EINVAL;
++
++ if (!priv->init_complete)
++ return 0;
++
++ switch (ctrl->id) {
++ case V4L2_CID_BRIGHTNESS:
++ break;
++ case V4L2_CID_CONTRAST:
++ break;
++ case V4L2_CID_SATURATION:
++ break;
++ case V4L2_CID_HUE:
++ break;
++ case V4L2_CID_GAMMA:
++ break;
++ case V4L2_CID_SHARPNESS:
++ break;
++ case V4L2_CID_AUTOGAIN:
++ case V4L2_CID_GAIN:
++ case V4L2_CID_EXPOSURE:
++ break;
++ case V4L2_CID_HFLIP:
++ ret = reg16_write(client, 0x3516, 0x00);
++ ret |= reg16_write(client, 0x0ffc, 0x00);
++ ret |= reg16_write(client, 0x0500, ctrl->val);
++ ret |= reg16_write(client, 0x0501, 0x00);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x30C0, 0xdc);
++ ret |= reg16_write(client, 0x3516, 0x01);
++ break;
++ case V4L2_CID_VFLIP:
++ ret = reg16_write(client, 0x3516, 0x00);
++ ret |= reg16_write(client, 0x0ffc, 0x00);
++ ret |= reg16_write(client, 0x0500, ctrl->val);
++ ret |= reg16_write(client, 0x0501, 0x01);
++ usleep_range(100, 150); /* wait 100 us */
++ ret |= reg16_write(client, 0x30C0, 0xdc);
++ ret |= reg16_write(client, 0x3516, 0x01);
++ break;
++ }
++
++ return ret;
++}
++
++static const struct v4l2_ctrl_ops ov495_ctrl_ops = {
++ .s_ctrl = ov495_s_ctrl,
++};
++
++static struct v4l2_subdev_video_ops ov495_video_ops = {
++ .s_stream = ov495_s_stream,
++ .g_mbus_config = ov495_g_mbus_config,
++};
++
++static const struct v4l2_subdev_pad_ops ov495_subdev_pad_ops = {
++ .get_edid = ov495_get_edid,
++ .enum_mbus_code = ov495_enum_mbus_code,
++ .get_selection = ov495_get_selection,
++ .set_selection = ov495_set_selection,
++ .get_fmt = ov495_get_fmt,
++ .set_fmt = ov495_set_fmt,
++};
++
++static struct v4l2_subdev_ops ov495_subdev_ops = {
++ .core = &ov495_core_ops,
++ .video = &ov495_video_ops,
++ .pad = &ov495_subdev_pad_ops,
++};
++
++static void ov495_otp_id_read(struct i2c_client *client)
++{
++#if 0
++ struct ov495_priv *priv = to_ov495(client);
++ int i;
++
++ /* read camera id from ov495 OTP memory */
++ reg16_write(client, 0xFFFD, 0x80);
++ reg16_write(client, 0xFFFE, 0x28);
++ usleep_range(100, 150); /* wait 100 us */
++ reg16_write(client, 0xE084, 0x40); /* manual mode, bank#0 */
++ reg16_write(client, 0xE081, 1); /* start OTP read */
++
++ usleep_range(25000, 26000); /* wait 25 ms */
++
++ for (i = 0; i < 6; i++)
++ reg16_read(client, 0xe000 + i + 4, &priv->id[i]);
++#else
++#if 0
++ /* read camera id from ov2775 OTP memory */
++ reg16_write(client, 0xFFFD, 0x80);
++ usleep_range(100, 150); /* wait 100 us */
++ reg16_write(client, 0xFFFE, 0x19);
++ usleep_range(100, 150); /* wait 100 us */
++ reg16_write(client, 0x5000, 0x00); /* write 0x349C -> 1 */
++ reg16_write(client, 0x5001, 0x34);
++ reg16_write(client, 0x5002, 0x9C);
++ reg16_write(client, 0x5003, 1);
++ reg16_write(client, 0xFFFE, 0x80);
++ usleep_range(100, 150); /* wait 100 us */
++ reg16_write(client, 0x00C0, 0xc1);
++
++ usleep_range(25000, 25500); /* wait 25 ms */
++
++ for (i = 0; i < 6; i++) {
++ reg16_write(client, 0xFFFE, 0x19);
++ usleep_range(100, 150); /* wait 100 us */
++ reg16_write(client, 0x5000, 0x01); /* read (0x349E + i) */
++ reg16_write(client, 0x5001, 0x34);
++ reg16_write(client, 0x5002, 0x9e + i + 6); /* first 6 bytes are equal on all ov2775 */
++ reg16_write(client, 0xFFFE, 0x80);
++ usleep_range(100, 150); /* wait 100 us */
++ reg16_write(client, 0x00C0, 0xc1);
++ reg16_write(client, 0xFFFE, 0x19);
++ usleep_range(1000, 1500); /* wait 1 ms */
++ reg16_read(client, 0x5000, &priv->id[i]);
++ }
++#endif
++#endif
++}
++
++static ssize_t ov495_otp_id_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct v4l2_subdev *sd = i2c_get_clientdata(to_i2c_client(dev));
++ struct i2c_client *client = v4l2_get_subdevdata(sd);
++ struct ov495_priv *priv = to_ov495(client);
++
++ return snprintf(buf, 32, "%02x:%02x:%02x:%02x:%02x:%02x\n",
++ priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]);
++}
++
++static DEVICE_ATTR(otp_id_ov495, S_IRUGO, ov495_otp_id_show, NULL);
++
++static int ov495_initialize(struct i2c_client *client)
++{
++ struct ov495_priv *priv = to_ov495(client);
++ u8 pid = 0, ver = 0, rev = 0;
++ int ret = 0;
++
++ /* check and show product ID and manufacturer ID */
++ reg16_write(client, 0xFFFD, 0x80);
++ reg16_write(client, 0xFFFE, 0x80);
++ usleep_range(100, 150); /* wait 100 us */
++ reg16_read(client, OV495_PID, &pid);
++ reg16_read(client, OV495_VER, &ver);
++ reg16_read(client, OV495_REV, &rev);
++
++ if (OV495_VERSION(pid, ver) != OV495_VERSION_REG) {
++ dev_err(&client->dev, "Product ID error %x:%x\n", pid, ver);
++ ret = -ENODEV;
++ goto err;
++ }
++
++ if (unlikely(force_conf_link))
++ goto out;
++
++#if 0
++ /* read resolution used by current firmware */
++ reg16_write(client, 0xFFFD, 0x80);
++ reg16_write(client, 0xFFFE, 0x82);
++ usleep_range(100, 150); /* wait 100 us */
++ reg16_read(client, OV495_ISP_HSIZE_HIGH, &val);
++ priv->max_width = val;
++ reg16_read(client, OV495_ISP_HSIZE_LOW, &val);
++ priv->max_width = (priv->max_width << 8) | val;
++ reg16_read(client, OV495_ISP_VSIZE_HIGH, &val);
++ priv->max_height = val;
++ reg16_read(client, OV495_ISP_VSIZE_LOW, &val);
++ priv->max_height = (priv->max_height << 8) | val;
++#else
++ priv->max_width = 1920;
++ priv->max_height = 1080;
++#endif
++
++ /* set virtual channel */
++ reg16_write(client, 0x3516, 0x0); /* unlock write */
++ reg16_write(client, 0xFFFD, 0x80);
++ reg16_write(client, 0xFFFE, 0x20);
++ reg16_write(client, 0x8017, 0x1e | (priv->port << 6));
++ reg16_write(client, 0x3516, 0x1); /* lock write */
++
++ /* Program wizard registers */
++ ov495_set_regs(client, ov495_regs_wizard, ARRAY_SIZE(ov495_regs_wizard));
++ /* Read OTP IDs */
++ ov495_otp_id_read(client);
++
++out:
++ dev_info(&client->dev, "ov495/ov2775 Product ID %x Manufacturer ID %x, rev 1%x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n",
++ pid, ver, 0xa + rev, priv->max_width, priv->max_height, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]);
++err:
++ return ret;
++}
++
++static int ov495_parse_dt(struct device_node *np, struct ov495_priv *priv)
++{
++ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd);
++ int i;
++ struct device_node *endpoint = NULL, *rendpoint = NULL;
++ int tmp_addr = 0;
++
++ for (i = 0; ; i++) {
++ endpoint = of_graph_get_next_endpoint(np, endpoint);
++ if (!endpoint)
++ break;
++
++ of_node_put(endpoint);
++
++ of_property_read_u32(endpoint, "dvp-order", &priv->dvp_order);
++
++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0);
++ if (!rendpoint)
++ continue;
++
++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) &&
++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti964-ti9x3") &&
++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti960_addr) &&
++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port))
++ break;
++
++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) &&
++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti954-ti9x3") &&
++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti954_addr) &&
++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port))
++ break;
++ }
++
++ if (!priv->ti960_addr && !priv->ti954_addr) {
++ dev_err(&client->dev, "deserializer does not present\n");
++ return -EINVAL;
++ }
++
++ /* setup I2C translator address */
++ tmp_addr = client->addr;
++ if (priv->ti960_addr) {
++ client->addr = priv->ti960_addr; /* Deserializer I2C address */
++
++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */
++ usleep_range(2000, 2500); /* wait 2ms */
++ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */
++ reg8_write(client, 0x5d, OV495_I2C_ADDR << 1); /* Sensor native I2C address */
++
++ reg8_write(client, 0x6e, 0x9a); /* GPIO0 - fsin, GPIO1 - resetb */
++ /* TODO: why too long? move logic to workqueue? */
++ mdelay(350); /* time needed to boot all sensor IPs */
++ }
++ if (priv->ti954_addr) {
++ client->addr = priv->ti954_addr; /* Deserializer I2C address */
++
++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */
++ usleep_range(2000, 2500); /* wait 2ms */
++ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */
++ reg8_write(client, 0x5d, OV495_I2C_ADDR << 1); /* Sensor native I2C address */
++
++ reg8_write(client, 0x6e, 0x9a); /* GPIO0 - fsin, GPIO1 - resetb */
++ /* TODO: why too long? move logic to workqueue? */
++ mdelay(350); /* time needed to boot all sensor IPs */
++ }
++ client->addr = tmp_addr;
++
++ return 0;
++}
++
++static int ov495_probe(struct i2c_client *client,
++ const struct i2c_device_id *did)
++{
++ struct ov495_priv *priv;
++ int ret;
++
++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ v4l2_i2c_subdev_init(&priv->sd, client, &ov495_subdev_ops);
++ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
++
++ priv->exposure = 0x100;
++ priv->gain = 0x100;
++ priv->autogain = 1;
++ v4l2_ctrl_handler_init(&priv->hdl, 4);
++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops,
++ V4L2_CID_BRIGHTNESS, 0, 16, 1, 7);
++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops,
++ V4L2_CID_CONTRAST, 0, 16, 1, 7);
++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops,
++ V4L2_CID_SATURATION, 0, 7, 1, 2);
++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops,
++ V4L2_CID_HUE, 0, 23, 1, 12);
++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops,
++ V4L2_CID_GAMMA, -128, 128, 1, 0);
++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops,
++ V4L2_CID_SHARPNESS, 0, 10, 1, 3);
++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops,
++ V4L2_CID_AUTOGAIN, 0, 1, 1, priv->autogain);
++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops,
++ V4L2_CID_GAIN, 0, 0xffff, 1, priv->gain);
++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops,
++ V4L2_CID_EXPOSURE, 0, 0xffff, 1, priv->exposure);
++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops,
++ V4L2_CID_HFLIP, 0, 1, 1, 0);
++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops,
++ V4L2_CID_VFLIP, 0, 1, 1, 0);
++ priv->sd.ctrl_handler = &priv->hdl;
++
++ ret = priv->hdl.error;
++ if (ret)
++ goto cleanup;
++
++ v4l2_ctrl_handler_setup(&priv->hdl);
++
++ priv->pad.flags = MEDIA_PAD_FL_SOURCE;
++ priv->sd.entity.flags |= MEDIA_ENT_F_CAM_SENSOR;
++ ret = media_entity_pads_init(&priv->sd.entity, 1, &priv->pad);
++ if (ret < 0)
++ goto cleanup;
++
++ ret = ov495_parse_dt(client->dev.of_node, priv);
++ if (ret)
++ goto cleanup;
++
++ ret = ov495_initialize(client);
++ if (ret < 0)
++ goto cleanup;
++
++ priv->rect.left = 0;
++ priv->rect.top = 0;
++ priv->rect.width = priv->max_width;
++ priv->rect.height = priv->max_height;
++
++ ret = v4l2_async_register_subdev(&priv->sd);
++ if (ret)
++ goto cleanup;
++
++ if (device_create_file(&client->dev, &dev_attr_otp_id_ov495) != 0) {
++ dev_err(&client->dev, "sysfs otp_id entry creation failed\n");
++ goto cleanup;
++ }
++
++ priv->init_complete = 1;
++
++ return 0;
++
++cleanup:
++ media_entity_cleanup(&priv->sd.entity);
++ v4l2_ctrl_handler_free(&priv->hdl);
++ v4l2_device_unregister_subdev(&priv->sd);
++#ifdef CONFIG_SOC_CAMERA_OV495_OV2775
++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n",
++ client->addr, client->adapter->name);
++#endif
++ return ret;
++}
++
++static int ov495_remove(struct i2c_client *client)
++{
++ struct ov495_priv *priv = i2c_get_clientdata(client);
++
++ device_remove_file(&client->dev, &dev_attr_otp_id_ov495);
++ v4l2_async_unregister_subdev(&priv->sd);
++ media_entity_cleanup(&priv->sd.entity);
++ v4l2_ctrl_handler_free(&priv->hdl);
++ v4l2_device_unregister_subdev(&priv->sd);
++
++ return 0;
++}
++
++#ifdef CONFIG_SOC_CAMERA_OV495_OV2775
++static const struct i2c_device_id ov495_id[] = {
++ { "ov495-ov2775", 0 },
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, ov495_id);
++
++static const struct of_device_id ov495_of_ids[] = {
++ { .compatible = "ovti,ov495-ov2775", },
++ { }
++};
++MODULE_DEVICE_TABLE(of, ov495_of_ids);
++
++static struct i2c_driver ov495_i2c_driver = {
++ .driver = {
++ .name = "ov495-ov2775",
++ .of_match_table = ov495_of_ids,
++ },
++ .probe = ov495_probe,
++ .remove = ov495_remove,
++ .id_table = ov495_id,
++};
++
++module_i2c_driver(ov495_i2c_driver);
++
++MODULE_DESCRIPTION("SoC Camera driver for OV495-OV2775");
++MODULE_AUTHOR("Vladimir Barinov");
++MODULE_LICENSE("GPL");
++#endif
+diff --git a/drivers/media/i2c/soc_camera/ov495_ov2775.h b/drivers/media/i2c/soc_camera/ov495_ov2775.h
+new file mode 100644
+index 0000000..dc6ad86
+--- /dev/null
++++ b/drivers/media/i2c/soc_camera/ov495_ov2775.h
+@@ -0,0 +1,18 @@
++/*
++ * OmniVision ov495-ov2775 sensor camera wizard 1280x1080@30/UYVY/BT601/8bit
++ *
++ * Copyright (C) 2017 Cogent Embedded, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++
++struct ov495_reg {
++ u16 reg;
++ u8 val;
++};
++
++static const struct ov495_reg ov495_regs_wizard[] = {
++};
+diff --git a/drivers/media/i2c/soc_camera/ti954_ti9x3.c b/drivers/media/i2c/soc_camera/ti954_ti9x3.c
+new file mode 100644
+index 0000000..81babce
+--- /dev/null
++++ b/drivers/media/i2c/soc_camera/ti954_ti9x3.c
+@@ -0,0 +1,414 @@
++/*
++ * TI ti954-(ti913/ti953) FPDLinkIII driver
++ *
++ * Copyright (C) 2017 Cogent Embedded, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++
++#include <linux/delay.h>
++#include <linux/i2c.h>
++#include <linux/module.h>
++#include <linux/of_gpio.h>
++#include <linux/videodev2.h>
++#include <linux/notifier.h>
++
++#include <media/v4l2-common.h>
++#include <media/v4l2-device.h>
++#include <media/v4l2-of.h>
++#include <media/v4l2-subdev.h>
++
++#include "ti9x4_ti9x3.h"
++
++struct ti954_ti9x3_priv {
++ struct v4l2_subdev sd[4];
++ struct device_node *sd_of_node[4];
++ int des_addr;
++ int links;
++ int lanes;
++ int csi_rate;
++ const char *forwarding_mode;
++ const char *cable_mode;
++ atomic_t use_count;
++ struct i2c_client *client;
++ int ti9x3_addr_map[4];
++ char chip_id[6];
++ int xtal_gpio;
++};
++
++static int indirect_write(struct i2c_client *client, unsigned int page, u8 reg, u8 val)
++{
++ if (page > 7)
++ return -EINVAL;
++
++ reg8_write(client, 0xb0, page << 2);
++ reg8_write(client, 0xb1, reg);
++ reg8_write(client, 0xb2, val);
++
++ return 0;
++}
++
++#if 0
++static int indirect_read(struct i2c_client *client, unsigned int page, u8 reg, u8 *val)
++{
++ if (page > 7)
++ return -EINVAL;
++
++ reg8_write(client, 0xb0, page << 2);
++ reg8_write(client, 0xb1, reg);
++ reg8_read(client, 0xb2, val);
++
++ return 0;
++}
++#endif
++
++static void ti954_ti9x3_read_chipid(struct i2c_client *client)
++{
++ struct ti954_ti9x3_priv *priv = i2c_get_clientdata(client);
++
++ /* Chip ID */
++ reg8_read(client, 0xf1, &priv->chip_id[0]);
++ reg8_read(client, 0xf2, &priv->chip_id[1]);
++ reg8_read(client, 0xf3, &priv->chip_id[2]);
++ reg8_read(client, 0xf4, &priv->chip_id[3]);
++ reg8_read(client, 0xf5, &priv->chip_id[4]);
++ priv->chip_id[5] = '\0';
++}
++
++static void ti954_ti9x3_initial_setup(struct i2c_client *client)
++{
++ struct ti954_ti9x3_priv *priv = i2c_get_clientdata(client);
++
++ /* Initial setup */
++ client->addr = priv->des_addr; /* TI954 I2C */
++ reg8_write(client, 0x08, 0x1c); /* I2C glitch filter depth */
++ reg8_write(client, 0x0a, 0x79); /* I2C high pulse width */
++ reg8_write(client, 0x0b, 0x79); /* I2C low pulse width */
++ reg8_write(client, 0x0d, 0xb9); /* VDDIO 3.3V */
++ switch (priv->csi_rate) {
++ case 1600: /* REFCLK = 25MHZ */
++ case 1450: /* REFCLK = 22.5MHZ */
++ reg8_write(client, 0x1f, 0x00); /* CSI rate 1.5/1.6Gbps */
++ break;
++ case 800: /* REFCLK = 25MHZ */
++ reg8_write(client, 0x1f, 0x02); /* CSI rate 800Mbps */
++ break;
++ case 400: /* REFCLK = 25MHZ */
++ reg8_write(client, 0x1f, 0x03); /* CSI rate 400Mbps */
++ break;
++ default:
++ dev_err(&client->dev, "unsupported CSI rate %d\n", priv->csi_rate);
++ }
++
++ if (strcmp(priv->forwarding_mode, "round-robin") == 0) {
++ reg8_write(client, 0x21, 0x01); /* Round Robin forwarding enable */
++ } else if (strcmp(priv->forwarding_mode, "synchronized") == 0) {
++ reg8_write(client, 0x21, 0x44); /* Basic Syncronized forwarding enable (FrameSync must be enabled!!) */
++ }
++
++ reg8_write(client, 0x32, 0x01); /* Select TX (CSI) port 0 */
++ reg8_write(client, 0x33, ((priv->lanes - 1) ^ 0x3) << 4); /* disable CSI output, set CSI lane count, non-continuous CSI mode */
++ reg8_write(client, 0x20, 0xf0); /* disable port forwarding */
++#if 1
++ /* FrameSync setup for REFCLK=25MHz, FPS=30: period_counts=1/FPS*25MHz =1/30*25Mhz =833333 -> FS_TIME=833333 */
++ /* FrameSync setup for REFCLK=22.5MHz, FPS=30: period_counts=1/FPS*22.5Mhz=1/30*22.5Mhz=750000 -> FS_TIME=750000 */
++ #define FS_TIME (priv->csi_rate == 1450 ? 750000 : 833333)
++ reg8_write(client, 0x1a, FS_TIME >> 16); /* FrameSync time 24bit */
++ reg8_write(client, 0x1b, (FS_TIME >> 8) & 0xff);
++ reg8_write(client, 0x1c, FS_TIME & 0xff);
++ reg8_write(client, 0x18, 0x43); /* Enable FrameSync, 50/50 mode, Frame clock from 25MHz */
++#else
++ /* FrameSync setup for 30FPS: period_counts=1/FPS/12mks=1/30/12e-6=2777 -> HI=2, LO=2775 FPS=30.008 */
++ reg8_write(client, 0x19, 2 >> 8); /* FrameSync high time MSB */
++ reg8_write(client, 0x1a, 2 >> 16); /* FrameSync high time LSB */
++ reg8_write(client, 0x1b, 2775 & 0xff); /* FrameSync low time MSB */
++ reg8_write(client, 0x1c, 2775 & 0xff); /* FrameSync low time LSB */
++ reg8_write(client, 0x18, 0x01); /* Enable FrameSync, HI/LO mode, Frame clock from port0 */
++#endif
++}
++
++//#define SENSOR_ID 0x30 // ov10635
++//#define SENSOR_ID 0x24 // ov490
++
++static void ti954_ti9x3_fpdlink3_setup(struct i2c_client *client, int idx)
++{
++ struct ti954_ti9x3_priv *priv = i2c_get_clientdata(client);
++
++ /* FPDLinkIII setup */
++ client->addr = priv->des_addr; /* TI954 I2C */
++ reg8_write(client, 0x4c, (idx << 4) | (1 << idx)); /* Select RX port number */
++ usleep_range(2000, 2500); /* wait 2ms */
++ reg8_write(client, 0x58, 0x58); /* Back channel: pass-through/backchannel/CRC enable, Freq=2.5Mbps */
++ reg8_write(client, 0x5c, priv->ti9x3_addr_map[idx] << 1); /* TI9X3 I2C addr */
++// reg8_write(client, 0x5d, SENSOR_ID << 1); /* SENSOR I2C native - must be set by sensor driver */
++// reg8_write(client, 0x65, (0x60 + idx) << 1); /* SENSOR I2C translated - must be set by sensor driver */
++ if (strcmp(priv->cable_mode, "coax") == 0) {
++ reg8_write(client, 0x6d, 0x7f); /* Coax, RAW10 */
++ } else if (strcmp(priv->cable_mode, "stp") == 0) {
++ reg8_write(client, 0x6d, 0x78); /* STP, CSI */
++ }
++ reg8_write(client, 0x70, (idx << 6) | 0x1e); /* CSI data type: yuv422 8-bit, assign VC */
++ reg8_write(client, 0x7c, 0x81); /* BIT(7) - magic to Use RAW10 as 8-bit mode */
++ reg8_write(client, 0x6e, 0x99); /* Backchannel GPIO0/GPIO1 set high */
++}
++
++static int ti954_ti9x3_initialize(struct i2c_client *client)
++{
++ struct ti954_ti9x3_priv *priv = i2c_get_clientdata(client);
++ int idx;
++
++ dev_info(&client->dev, "LINKs=%d, LANES=%d, FORWARDING=%s, CABLE=%s, ID=%s\n",
++ priv->links, priv->lanes, priv->forwarding_mode, priv->cable_mode, priv->chip_id);
++
++ ti954_ti9x3_initial_setup(client);
++
++ for (idx = 0; idx < priv->links; idx++)
++ ti954_ti9x3_fpdlink3_setup(client, idx);
++
++ client->addr = priv->des_addr;
++
++ return 0;
++}
++
++#ifdef CONFIG_VIDEO_ADV_DEBUG
++static int ti954_ti9x3_g_register(struct v4l2_subdev *sd,
++ struct v4l2_dbg_register *reg)
++{
++ struct ti954_ti9x3_priv *priv = v4l2_get_subdevdata(sd);
++ struct i2c_client *client = priv->client;
++ int ret;
++ u8 val = 0;
++
++ ret = reg8_read(client, (u8)reg->reg, &val);
++ if (ret < 0)
++ return ret;
++
++ reg->val = val;
++ reg->size = sizeof(u8);
++
++ return 0;
++}
++
++static int ti954_ti9x3_s_register(struct v4l2_subdev *sd,
++ const struct v4l2_dbg_register *reg)
++{
++ struct ti954_ti9x3_priv *priv = v4l2_get_subdevdata(sd);
++ struct i2c_client *client = priv->client;
++
++ return reg8_write(client, (u8)reg->reg, (u8)reg->val);
++}
++#endif
++
++static int ti954_ti9x3_s_power(struct v4l2_subdev *sd, int on)
++{
++ struct ti954_ti9x3_priv *priv = v4l2_get_subdevdata(sd);
++ struct i2c_client *client = priv->client;
++
++ if (on) {
++ if (atomic_inc_return(&priv->use_count) == 1)
++ reg8_write(client, 0x20, 0x00); /* enable port forwarding to CSI */
++ } else {
++ if (atomic_dec_return(&priv->use_count) == 0)
++ reg8_write(client, 0x20, 0xf0); /* disable port forwarding to CSI */
++ }
++
++ return 0;
++}
++
++static int ti954_ti9x3_registered_async(struct v4l2_subdev *sd)
++{
++ struct ti954_ti9x3_priv *priv = v4l2_get_subdevdata(sd);
++ struct i2c_client *client = priv->client;
++
++ reg8_write(client, 0x33, ((priv->lanes - 1) ^ 0x3) << 4 | 0x1); /* enable CSI output, set CSI lane count, non-continuous CSI mode */
++
++ return 0;
++}
++
++static struct v4l2_subdev_core_ops ti954_ti9x3_subdev_core_ops = {
++#ifdef CONFIG_VIDEO_ADV_DEBUG
++ .g_register = ti954_ti9x3_g_register,
++ .s_register = ti954_ti9x3_s_register,
++#endif
++ .s_power = ti954_ti9x3_s_power,
++ .registered_async = ti954_ti9x3_registered_async,
++};
++
++static struct v4l2_subdev_ops ti954_ti9x3_subdev_ops = {
++ .core = &ti954_ti9x3_subdev_core_ops,
++};
++
++static int ti954_ti9x3_parse_dt(struct i2c_client *client)
++{
++ struct ti954_ti9x3_priv *priv = i2c_get_clientdata(client);
++ struct device_node *np = client->dev.of_node;
++ struct device_node *endpoint = NULL, *rendpoint = NULL;
++ struct property *prop;
++ int err, i;
++ int sensor_delay;
++ char forwarding_mode_default[20] = "round-robin"; /* round-robin, synchronized */
++ char cable_mode_default[5] = "coax"; /* coax, stp */
++ struct property *csi_rate_prop, *dvp_order_prop;
++ u8 val = 0;
++
++ if (of_property_read_u32(np, "ti,links", &priv->links))
++ priv->links = 2;
++
++ if (of_property_read_u32(np, "ti,lanes", &priv->lanes))
++ priv->lanes = 4;
++
++ priv->xtal_gpio = of_get_gpio(np, 0);
++ if (priv->xtal_gpio > 0) {
++ err = gpio_request_one(priv->xtal_gpio, GPIOF_OUT_INIT_LOW, dev_name(&client->dev));
++ if (err)
++ dev_err(&client->dev, "cannot request XTAL gpio %d: %d\n", priv->xtal_gpio, err);
++ else
++ mdelay(250);
++ }
++
++ reg8_read(client, 0x00, &val); /* read TI954 I2C address */
++ if (val != (priv->des_addr << 1)) {
++ prop = of_find_property(np, "reg", NULL);
++ if (prop)
++ of_remove_property(np, prop);
++ return -ENODEV;
++ }
++
++ ti954_ti9x3_read_chipid(client);
++
++ indirect_write(client, 7, 0x15, 0x30);
++ gpio_set_value(priv->xtal_gpio, 1);
++ usleep_range(5000, 5500); /* wait 5ms */
++ indirect_write(client, 7, 0x15, 0);
++
++ if (!of_property_read_u32(np, "ti,sensor_delay", &sensor_delay))
++ mdelay(sensor_delay);
++
++ err = of_property_read_string(np, "ti,forwarding-mode", &priv->forwarding_mode);
++ if (err)
++ priv->forwarding_mode = forwarding_mode_default;
++
++ err = of_property_read_string(np, "ti,cable-mode", &priv->cable_mode);
++ if (err)
++ priv->cable_mode = cable_mode_default;
++
++ for (i = 0; ; i++) {
++ endpoint = of_graph_get_next_endpoint(np, endpoint);
++ if (!endpoint)
++ break;
++
++ of_node_put(endpoint);
++
++ if (i < priv->links) {
++ if (of_property_read_u32(endpoint, "ti9x3-addr", &priv->ti9x3_addr_map[i])) {
++ dev_err(&client->dev, "ti9x3-addr not set\n");
++ return -EINVAL;
++ }
++ priv->sd_of_node[i] = endpoint;
++ }
++
++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0);
++ if (!rendpoint)
++ continue;
++
++ csi_rate_prop = of_find_property(endpoint, "csi-rate", NULL);
++ if (csi_rate_prop) {
++ of_property_read_u32(endpoint, "csi-rate", &priv->csi_rate);
++ of_update_property(rendpoint, csi_rate_prop);
++ }
++
++ dvp_order_prop = of_find_property(endpoint, "dvp-order", NULL);
++ if (dvp_order_prop)
++ of_update_property(rendpoint, dvp_order_prop);
++ }
++
++ return 0;
++}
++
++static int ti954_ti9x3_probe(struct i2c_client *client,
++ const struct i2c_device_id *did)
++{
++ struct ti954_ti9x3_priv *priv;
++ int err, i;
++
++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ i2c_set_clientdata(client, priv);
++ priv->des_addr = client->addr;
++ priv->client = client;
++ atomic_set(&priv->use_count, 0);
++
++ err = ti954_ti9x3_parse_dt(client);
++ if (err)
++ goto out;
++
++ err = ti954_ti9x3_initialize(client);
++ if (err < 0)
++ goto out;
++
++ for (i = 0; i < priv->links; i++) {
++ v4l2_subdev_init(&priv->sd[i], &ti954_ti9x3_subdev_ops);
++ priv->sd[i].owner = client->dev.driver->owner;
++ priv->sd[i].dev = &client->dev;
++ priv->sd[i].grp_id = i;
++ v4l2_set_subdevdata(&priv->sd[i], priv);
++ priv->sd[i].of_node = priv->sd_of_node[i];
++
++ snprintf(priv->sd[i].name, V4L2_SUBDEV_NAME_SIZE, "%s %d-%04x",
++ client->dev.driver->name, i2c_adapter_id(client->adapter),
++ client->addr);
++
++ err = v4l2_async_register_subdev(&priv->sd[i]);
++ if (err < 0)
++ goto out;
++ }
++
++out:
++ return err;
++}
++
++static int ti954_ti9x3_remove(struct i2c_client *client)
++{
++ struct ti954_ti9x3_priv *priv = i2c_get_clientdata(client);
++ int i;
++
++ for (i = 0; i < priv->links; i++) {
++ v4l2_async_unregister_subdev(&priv->sd[i]);
++ v4l2_device_unregister_subdev(&priv->sd[i]);
++ }
++
++ return 0;
++}
++
++static const struct of_device_id ti954_ti9x3_dt_ids[] = {
++ { .compatible = "ti,ti954-ti9x3" },
++ {},
++};
++MODULE_DEVICE_TABLE(of, ti954_ti9x3_dt_ids);
++
++static const struct i2c_device_id ti954_ti9x3_id[] = {
++ { "ti954_ti9x3", 0 },
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, ti954_ti9x3_id);
++
++static struct i2c_driver ti954_ti9x3_i2c_driver = {
++ .driver = {
++ .name = "ti954_ti9x3",
++ .of_match_table = of_match_ptr(ti954_ti9x3_dt_ids),
++ },
++ .probe = ti954_ti9x3_probe,
++ .remove = ti954_ti9x3_remove,
++ .id_table = ti954_ti9x3_id,
++};
++
++module_i2c_driver(ti954_ti9x3_i2c_driver);
++
++MODULE_DESCRIPTION("FPDLinkIII driver for TI954-TI9X3");
++MODULE_AUTHOR("Vladimir Barinov");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/i2c/soc_camera/ti964_ti9x3.c b/drivers/media/i2c/soc_camera/ti964_ti9x3.c
+new file mode 100644
+index 0000000..e66e639
+--- /dev/null
++++ b/drivers/media/i2c/soc_camera/ti964_ti9x3.c
+@@ -0,0 +1,382 @@
++/*
++ * TI (ti964/ti960)-(ti913/ti953) FPDLinkIII driver
++ *
++ * Copyright (C) 2017 Cogent Embedded, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++
++#include <linux/delay.h>
++#include <linux/i2c.h>
++#include <linux/module.h>
++#include <linux/of_gpio.h>
++#include <linux/videodev2.h>
++#include <linux/notifier.h>
++
++#include <media/v4l2-common.h>
++#include <media/v4l2-device.h>
++#include <media/v4l2-of.h>
++#include <media/v4l2-subdev.h>
++
++#include "ti9x4_ti9x3.h"
++
++struct ti964_ti9x3_priv {
++ struct v4l2_subdev sd[4];
++ struct device_node *sd_of_node[4];
++ int des_addr;
++ int links;
++ int lanes;
++ int csi_rate;
++ const char *forwarding_mode;
++ const char *cable_mode;
++ atomic_t use_count;
++ struct i2c_client *client;
++ int ti9x3_addr_map[4];
++ char chip_id[6];
++};
++
++static void ti964_ti9x3_read_chipid(struct i2c_client *client)
++{
++ struct ti964_ti9x3_priv *priv = i2c_get_clientdata(client);
++
++ /* Chip ID */
++ reg8_read(client, 0xf1, &priv->chip_id[0]);
++ reg8_read(client, 0xf2, &priv->chip_id[1]);
++ reg8_read(client, 0xf3, &priv->chip_id[2]);
++ reg8_read(client, 0xf4, &priv->chip_id[3]);
++ reg8_read(client, 0xf5, &priv->chip_id[4]);
++ priv->chip_id[5] = '\0';
++}
++
++static void ti964_ti9x3_initial_setup(struct i2c_client *client)
++{
++ struct ti964_ti9x3_priv *priv = i2c_get_clientdata(client);
++
++ /* Initial setup */
++ client->addr = priv->des_addr; /* TI964 I2C */
++ reg8_write(client, 0x08, 0x1c); /* I2C glitch filter depth */
++ reg8_write(client, 0x0a, 0x79); /* I2C high pulse width */
++ reg8_write(client, 0x0b, 0x79); /* I2C low pulse width */
++ reg8_write(client, 0x0d, 0xb9); /* VDDIO 3.3V */
++ switch (priv->csi_rate) {
++ case 1600: /* REFCLK = 25MHZ */
++ case 1450: /* REFCLK = 22.5MHZ */
++ reg8_write(client, 0x1f, 0x00); /* CSI rate 1.5/1.6Gbps */
++ break;
++ case 800: /* REFCLK = 25MHZ */
++ reg8_write(client, 0x1f, 0x02); /* CSI rate 800Mbps */
++ break;
++ case 400: /* REFCLK = 25MHZ */
++ reg8_write(client, 0x1f, 0x03); /* CSI rate 400Mbps */
++ break;
++ default:
++ dev_err(&client->dev, "unsupported CSI rate %d\n", priv->csi_rate);
++ }
++
++ if (strcmp(priv->forwarding_mode, "round-robin") == 0) {
++ reg8_write(client, 0x21, 0x01); /* Round Robin forwarding enable */
++ } else if (strcmp(priv->forwarding_mode, "synchronized") == 0) {
++ reg8_write(client, 0x21, 0x44); /* Basic Syncronized forwarding enable (FrameSync must be enabled!!) */
++ }
++
++ reg8_write(client, 0x32, 0x01); /* Select TX (CSI) port 0 */
++ reg8_write(client, 0x33, ((priv->lanes - 1) ^ 0x3) << 4); /* disable CSI output, set CSI lane count, non-continuous CSI mode */
++ reg8_write(client, 0x20, 0xf0); /* disable port forwarding */
++#if 1
++ /* FrameSync setup for REFCLK=25MHz, FPS=30: period_counts=1/FPS*25MHz =1/30*25Mhz =833333 -> FS_TIME=833333 */
++ /* FrameSync setup for REFCLK=22.5MHz, FPS=30: period_counts=1/FPS*22.5Mhz=1/30*22.5Mhz=750000 -> FS_TIME=750000 */
++ #define FS_TIME (priv->csi_rate == 1450 ? 750000 : 833333)
++ reg8_write(client, 0x1a, FS_TIME >> 16); /* FrameSync time 24bit */
++ reg8_write(client, 0x1b, (FS_TIME >> 8) & 0xff);
++ reg8_write(client, 0x1c, FS_TIME & 0xff);
++ reg8_write(client, 0x18, 0x43); /* Enable FrameSync, 50/50 mode, Frame clock from 25MHz */
++#else
++ /* FrameSync setup for 30FPS: period_counts=1/FPS/12mks=1/30/12e-6=2777 -> HI=2, LO=2775 FPS=30.008 */
++ reg8_write(client, 0x19, 2 >> 8); /* FrameSync high time MSB */
++ reg8_write(client, 0x1a, 2 >> 16); /* FrameSync high time LSB */
++ reg8_write(client, 0x1b, 2775 & 0xff); /* FrameSync low time MSB */
++ reg8_write(client, 0x1c, 2775 & 0xff); /* FrameSync low time LSB */
++ reg8_write(client, 0x18, 0x01); /* Enable FrameSync, HI/LO mode, Frame clock from port0 */
++#endif
++}
++
++//#define SENSOR_ID 0x30 // ov10635
++//#define SENSOR_ID 0x24 // ov490
++
++static void ti964_ti9x3_fpdlink3_setup(struct i2c_client *client, int idx)
++{
++ struct ti964_ti9x3_priv *priv = i2c_get_clientdata(client);
++
++ /* FPDLinkIII setup */
++ client->addr = priv->des_addr; /* TI964 I2C */
++ reg8_write(client, 0x4c, (idx << 4) | (1 << idx)); /* Select RX port number */
++ usleep_range(2000, 2500); /* wait 2ms */
++ reg8_write(client, 0x58, 0x58); /* Back channel: pass-through/backchannel/CRC enable, Freq=2.5Mbps */
++ reg8_write(client, 0x5c, priv->ti9x3_addr_map[idx] << 1); /* TI9X3 I2C addr */
++// reg8_write(client, 0x5d, SENSOR_ID << 1); /* SENSOR I2C native - must be set by sensor driver */
++// reg8_write(client, 0x65, (0x60 + idx) << 1); /* SENSOR I2C translated - must be set by sensor driver */
++ if (strcmp(priv->cable_mode, "coax") == 0) {
++ reg8_write(client, 0x6d, 0x7f); /* Coax, RAW10 */
++ } else if (strcmp(priv->cable_mode, "stp") == 0) {
++ reg8_write(client, 0x6d, 0x78); /* STP, CSI */
++ }
++ reg8_write(client, 0x70, (idx << 6) | 0x1e); /* CSI data type: yuv422 8-bit, assign VC */
++ reg8_write(client, 0x7c, 0x81); /* BIT(7) - magic to Use RAW10 as 8-bit mode */
++ reg8_write(client, 0x6e, 0x99); /* Backchannel GPIO0/GPIO1 set high */
++}
++
++static int ti964_ti9x3_initialize(struct i2c_client *client)
++{
++ struct ti964_ti9x3_priv *priv = i2c_get_clientdata(client);
++ int idx;
++
++ dev_info(&client->dev, "LINKs=%d, LANES=%d, FORWARDING=%s, CABLE=%s, ID=%s\n",
++ priv->links, priv->lanes, priv->forwarding_mode, priv->cable_mode, priv->chip_id);
++
++ ti964_ti9x3_initial_setup(client);
++
++ for (idx = 0; idx < priv->links; idx++)
++ ti964_ti9x3_fpdlink3_setup(client, idx);
++
++ client->addr = priv->des_addr;
++
++ return 0;
++}
++
++#ifdef CONFIG_VIDEO_ADV_DEBUG
++static int ti964_ti9x3_g_register(struct v4l2_subdev *sd,
++ struct v4l2_dbg_register *reg)
++{
++ struct ti964_ti9x3_priv *priv = v4l2_get_subdevdata(sd);
++ struct i2c_client *client = priv->client;
++ int ret;
++ u8 val = 0;
++
++ ret = reg8_read(client, (u8)reg->reg, &val);
++ if (ret < 0)
++ return ret;
++
++ reg->val = val;
++ reg->size = sizeof(u8);
++
++ return 0;
++}
++
++static int ti964_ti9x3_s_register(struct v4l2_subdev *sd,
++ const struct v4l2_dbg_register *reg)
++{
++ struct ti964_ti9x3_priv *priv = v4l2_get_subdevdata(sd);
++ struct i2c_client *client = priv->client;
++
++ return reg8_write(client, (u8)reg->reg, (u8)reg->val);
++}
++#endif
++
++static int ti964_ti9x3_s_power(struct v4l2_subdev *sd, int on)
++{
++ struct ti964_ti9x3_priv *priv = v4l2_get_subdevdata(sd);
++ struct i2c_client *client = priv->client;
++
++ if (on) {
++ if (atomic_inc_return(&priv->use_count) == 1)
++ reg8_write(client, 0x20, 0x00); /* enable port forwarding to CSI */
++ } else {
++ if (atomic_dec_return(&priv->use_count) == 0)
++ reg8_write(client, 0x20, 0xf0); /* disable port forwarding to CSI */
++ }
++
++ return 0;
++}
++
++static int ti964_ti9x3_registered_async(struct v4l2_subdev *sd)
++{
++ struct ti964_ti9x3_priv *priv = v4l2_get_subdevdata(sd);
++ struct i2c_client *client = priv->client;
++
++ reg8_write(client, 0x33, ((priv->lanes - 1) ^ 0x3) << 4 | 0x1); /* enable CSI output, set CSI lane count, non-continuous CSI mode */
++
++ return 0;
++}
++
++static struct v4l2_subdev_core_ops ti964_ti9x3_subdev_core_ops = {
++#ifdef CONFIG_VIDEO_ADV_DEBUG
++ .g_register = ti964_ti9x3_g_register,
++ .s_register = ti964_ti9x3_s_register,
++#endif
++ .s_power = ti964_ti9x3_s_power,
++ .registered_async = ti964_ti9x3_registered_async,
++};
++
++static struct v4l2_subdev_ops ti964_ti9x3_subdev_ops = {
++ .core = &ti964_ti9x3_subdev_core_ops,
++};
++
++static int ti964_ti9x3_parse_dt(struct i2c_client *client)
++{
++ struct ti964_ti9x3_priv *priv = i2c_get_clientdata(client);
++ struct device_node *np = client->dev.of_node;
++ struct device_node *endpoint = NULL, *rendpoint = NULL;
++ struct property *prop;
++ int err, pwen, i;
++ int sensor_delay;
++ char forwarding_mode_default[20] = "round-robin"; /* round-robin, synchronized */
++ char cable_mode_default[5] = "coax"; /* coax, stp */
++ struct property *csi_rate_prop, *dvp_order_prop;
++ u8 val = 0;
++
++ if (of_property_read_u32(np, "ti,links", &priv->links))
++ priv->links = 4;
++
++ if (of_property_read_u32(np, "ti,lanes", &priv->lanes))
++ priv->lanes = 4;
++
++ pwen = of_get_gpio(np, 0);
++ if (pwen > 0) {
++ err = gpio_request_one(pwen, GPIOF_OUT_INIT_HIGH, dev_name(&client->dev));
++ if (err)
++ dev_err(&client->dev, "cannot request PWEN gpio %d: %d\n", pwen, err);
++ else
++ mdelay(250);
++ }
++
++ reg8_read(client, 0x00, &val); /* read TI964 I2C address */
++ if (val != (priv->des_addr << 1)) {
++ prop = of_find_property(np, "reg", NULL);
++ if (prop)
++ of_remove_property(np, prop);
++ return -ENODEV;
++ }
++
++ ti964_ti9x3_read_chipid(client);
++
++ if (!of_property_read_u32(np, "ti,sensor_delay", &sensor_delay))
++ mdelay(sensor_delay);
++
++ err = of_property_read_string(np, "ti,forwarding-mode", &priv->forwarding_mode);
++ if (err)
++ priv->forwarding_mode = forwarding_mode_default;
++
++ err = of_property_read_string(np, "ti,cable-mode", &priv->cable_mode);
++ if (err)
++ priv->cable_mode = cable_mode_default;
++
++ for (i = 0; ; i++) {
++ endpoint = of_graph_get_next_endpoint(np, endpoint);
++ if (!endpoint)
++ break;
++
++ of_node_put(endpoint);
++
++ if (i < priv->links) {
++ if (of_property_read_u32(endpoint, "ti9x3-addr", &priv->ti9x3_addr_map[i])) {
++ dev_err(&client->dev, "ti9x3-addr not set\n");
++ return -EINVAL;
++ }
++ priv->sd_of_node[i] = endpoint;
++ }
++
++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0);
++ if (!rendpoint)
++ continue;
++
++ csi_rate_prop = of_find_property(endpoint, "csi-rate", NULL);
++ if (csi_rate_prop) {
++ of_property_read_u32(endpoint, "csi-rate", &priv->csi_rate);
++ of_update_property(rendpoint, csi_rate_prop);
++ }
++
++ dvp_order_prop = of_find_property(endpoint, "dvp-order", NULL);
++ if (dvp_order_prop)
++ of_update_property(rendpoint, dvp_order_prop);
++ }
++
++ return 0;
++}
++
++static int ti964_ti9x3_probe(struct i2c_client *client,
++ const struct i2c_device_id *did)
++{
++ struct ti964_ti9x3_priv *priv;
++ int err, i;
++
++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ i2c_set_clientdata(client, priv);
++ priv->des_addr = client->addr;
++ priv->client = client;
++ atomic_set(&priv->use_count, 0);
++
++ err = ti964_ti9x3_parse_dt(client);
++ if (err)
++ goto out;
++
++ err = ti964_ti9x3_initialize(client);
++ if (err < 0)
++ goto out;
++
++ for (i = 0; i < priv->links; i++) {
++ v4l2_subdev_init(&priv->sd[i], &ti964_ti9x3_subdev_ops);
++ priv->sd[i].owner = client->dev.driver->owner;
++ priv->sd[i].dev = &client->dev;
++ priv->sd[i].grp_id = i;
++ v4l2_set_subdevdata(&priv->sd[i], priv);
++ priv->sd[i].of_node = priv->sd_of_node[i];
++
++ snprintf(priv->sd[i].name, V4L2_SUBDEV_NAME_SIZE, "%s %d-%04x",
++ client->dev.driver->name, i2c_adapter_id(client->adapter),
++ client->addr);
++
++ err = v4l2_async_register_subdev(&priv->sd[i]);
++ if (err < 0)
++ goto out;
++ }
++
++out:
++ return err;
++}
++
++static int ti964_ti9x3_remove(struct i2c_client *client)
++{
++ struct ti964_ti9x3_priv *priv = i2c_get_clientdata(client);
++ int i;
++
++ for (i = 0; i < priv->links; i++) {
++ v4l2_async_unregister_subdev(&priv->sd[i]);
++ v4l2_device_unregister_subdev(&priv->sd[i]);
++ }
++
++ return 0;
++}
++
++static const struct of_device_id ti964_ti9x3_dt_ids[] = {
++ { .compatible = "ti,ti964-ti9x3" },
++ {},
++};
++MODULE_DEVICE_TABLE(of, ti964_ti9x3_dt_ids);
++
++static const struct i2c_device_id ti964_ti9x3_id[] = {
++ { "ti964_ti9x3", 0 },
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, ti964_ti9x3_id);
++
++static struct i2c_driver ti964_ti9x3_i2c_driver = {
++ .driver = {
++ .name = "ti964_ti9x3",
++ .of_match_table = of_match_ptr(ti964_ti9x3_dt_ids),
++ },
++ .probe = ti964_ti9x3_probe,
++ .remove = ti964_ti9x3_remove,
++ .id_table = ti964_ti9x3_id,
++};
++
++module_i2c_driver(ti964_ti9x3_i2c_driver);
++
++MODULE_DESCRIPTION("FPDLinkIII driver for TI964-TI9X3");
++MODULE_AUTHOR("Vladimir Barinov");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/i2c/soc_camera/ti9x4_ti9x3.h b/drivers/media/i2c/soc_camera/ti9x4_ti9x3.h
+new file mode 100644
+index 0000000..0cee5f1
+--- /dev/null
++++ b/drivers/media/i2c/soc_camera/ti9x4_ti9x3.h
+@@ -0,0 +1,108 @@
++/*
++ * TI FPDLinkIII driver include file
++ *
++ * Copyright (C) 2017 Cogent Embedded, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++
++#ifndef _TI9X4_H
++#define _TI9X4_H
++
++//#define DEBUG
++#ifdef DEBUG
++#undef dev_dbg
++#define dev_dbg dev_info
++#endif
++
++#define MAXIM_NUM_RETRIES 1 /* number of read/write retries */
++#define BROADCAST 0x6f
++
++static inline int reg8_read(struct i2c_client *client, u8 reg, u8 *val)
++{
++ int ret, retries;
++
++ for (retries = MAXIM_NUM_RETRIES; retries; retries--) {
++ ret = i2c_smbus_read_byte_data(client, reg);
++ if (!(ret < 0))
++ break;
++ }
++
++ if (ret < 0) {
++ dev_dbg(&client->dev,
++ "read fail: chip 0x%x register 0x%x: %d\n",
++ client->addr, reg, ret);
++ } else {
++ *val = ret;
++ }
++
++ return ret < 0 ? ret : 0;
++}
++
++static inline int reg8_write(struct i2c_client *client, u8 reg, u8 val)
++{
++ int ret, retries;
++
++ for (retries = MAXIM_NUM_RETRIES; retries; retries--) {
++ ret = i2c_smbus_write_byte_data(client, reg, val);
++ if (!(ret < 0))
++ break;
++ }
++
++ if (ret < 0) {
++ dev_dbg(&client->dev,
++ "write fail: chip 0x%x register 0x%x: %d\n",
++ client->addr, reg, ret);
++ }
++
++ return ret < 0 ? ret : 0;
++}
++
++static inline int reg16_read(struct i2c_client *client, u16 reg, u8 *val)
++{
++ int ret, retries;
++ u8 buf[2] = {reg >> 8, reg & 0xff};
++
++ for (retries = MAXIM_NUM_RETRIES; retries; retries--) {
++ ret = i2c_master_send(client, buf, 2);
++ if (ret == 2) {
++ ret = i2c_master_recv(client, buf, 1);
++ if (ret == 1)
++ break;
++ }
++ }
++
++ if (ret < 0) {
++ dev_dbg(&client->dev,
++ "read fail: chip 0x%x register 0x%x: %d\n",
++ client->addr, reg, ret);
++ } else {
++ *val = buf[0];
++ }
++
++ return ret < 0 ? ret : 0;
++}
++
++static inline int reg16_write(struct i2c_client *client, u16 reg, u8 val)
++{
++ int ret, retries;
++ u8 buf[3] = {reg >> 8, reg & 0xff, val};
++
++ for (retries = MAXIM_NUM_RETRIES; retries; retries--) {
++ ret = i2c_master_send(client, buf, 3);
++ if (ret == 3)
++ break;
++ }
++
++ if (ret < 0) {
++ dev_dbg(&client->dev,
++ "write fail: chip 0x%x register 0x%x: %d\n",
++ client->addr, reg, ret);
++ }
++
++ return ret < 0 ? ret : 0;
++}
++#endif /* _TI9X4_H */
+diff --git a/drivers/media/platform/soc_camera/rcar_csi2.c b/drivers/media/platform/soc_camera/rcar_csi2.c
+index 7373ac3..b3bc810 100644
+--- a/drivers/media/platform/soc_camera/rcar_csi2.c
++++ b/drivers/media/platform/soc_camera/rcar_csi2.c
+@@ -37,8 +37,9 @@
+
+ #include <media/v4l2-of.h>
+
++//#define RCAR_CSI2_DUMP
++
+ #define DRV_NAME "rcar_csi2"
+-#define CONNECT_SLAVE_NAME "adv7482"
+ #define VC_MAX_CHANNEL 4
+
+ #define RCAR_CSI2_TREF 0x00
+@@ -63,6 +64,7 @@
+
+ #define RCAR_CSI2_LINKCNT 0x48
+ #define RCAR_CSI2_LSWAP 0x4C
++#define RCAR_CSI2_PHTW 0x50
+ #define RCAR_CSI2_PHTC 0x58
+ #define RCAR_CSI2_PHYPLL 0x68
+
+@@ -106,6 +108,9 @@
+ #define RCAR_CSI2_LSWAP_L0SEL_PLANE2 (2 << 0)
+ #define RCAR_CSI2_LSWAP_L0SEL_PLANE3 (3 << 0)
+
++#define RCAR_CSI2_PHTW_DWEN (1 << 24)
++#define RCAR_CSI2_PHTW_CWEN (1 << 8)
++
+ #define RCAR_CSI2_PHTC_TESTCLR (1 << 0)
+
+ /* interrupt status registers */
+@@ -179,6 +184,7 @@ struct rcar_csi2_link_config {
+ unsigned char lanes;
+ unsigned long vcdt;
+ unsigned long vcdt2;
++ unsigned int csi_rate;
+ };
+
+ #define INIT_RCAR_CSI2_LINK_CONFIG(m) \
+@@ -192,8 +198,7 @@ struct rcar_csi_irq_counter_log {
+ };
+
+ struct rcar_csi2 {
+- struct v4l2_subdev subdev;
+- struct v4l2_mbus_framefmt *mf;
++ struct v4l2_subdev subdev[4];
+ unsigned int irq;
+ unsigned long mipi_flags;
+ void __iomem *base;
+@@ -205,7 +210,9 @@ struct rcar_csi2 {
+ unsigned int field;
+ unsigned int code;
+ unsigned int lanes;
++ unsigned int csi_rate;
+ spinlock_t lock;
++ atomic_t use_count;
+ };
+
+ #define RCAR_CSI_80MBPS 0
+@@ -251,6 +258,89 @@ struct rcar_csi2 {
+ #define RCAR_CSI_1400MBPS 40
+ #define RCAR_CSI_1450MBPS 41
+ #define RCAR_CSI_1500MBPS 42
++#define RCAR_CSI_NUMRATES 43
++
++#define RCAR_CSI2_PHxM0(i) (0xf0 + i * 0x08)
++#define RCAR_CSI2_PHxM1(i) (0xf4 + i * 0x08)
++#define RCAR_CSI2_PHRM(i) (0x110 + i * 0x04)
++#define RCAR_CSI2_PHCM(i) (0x120 + i * 0x04)
++#define RCAR_CSI2_SERCCNT 0x140
++#define RCAR_CSI2_SSERCCNT 0x144
++#define RCAR_CSI2_ECCCM 0x148
++#define RCAR_CSI2_ECECM 0x14c
++#define RCAR_CSI2_CRCECM 0x150
++#define RCAR_CSI2_LCNT(i) (0x160 + i * 0x04)
++#define RCAR_CSI2_LCNTM(i) (0x168 + i * 0x04)
++#define RCAR_CSI2_FCNTM 0x170
++#define RCAR_CSI2_FCNTM2 0x174
++#define RCAR_CSI2_VINSM(i) (0x190 + i * 0x04)
++#define RCAR_CSI2_PHM(i) (0x1C0 + i * 0x04)
++
++#define RCAR_CSI2_INTSTATE_ALL 0x3FFFFCDD
++
++#ifdef RCAR_CSI2_DUMP
++static void rcar_sci2_debug_show(struct rcar_csi2 *priv)
++{
++ int i;
++ u32 reg0, reg1;
++
++ printk("Debug registers:\n");
++ printk("FCNTM : 0x%08x\n", ioread32(priv->base + RCAR_CSI2_FCNTM));
++ printk("FCNTM2: 0x%08x\n", ioread32(priv->base + RCAR_CSI2_FCNTM2));
++
++ for (i = 0; i < 4; i++) {
++ reg0 = ioread32(priv->base + RCAR_CSI2_PHxM0(i));
++ reg1 = ioread32(priv->base + RCAR_CSI2_PHxM1(i));
++
++ printk("Packet header %d: dt: 0x%02x, vc: %d, wc: %d, cnt: %d\n",
++ i,
++ reg0 & 0x3F, (reg0 >> 6) & 0x03, (reg0 >> 8) & 0xffff,
++ reg1 & 0xffff);
++ }
++ for (i = 0; i < 3; i++) {
++ reg0 = ioread32(priv->base + RCAR_CSI2_PHRM(i));
++
++ printk("Packet header R %d dt: 0x%02x, vc: %d, wc: %d, ecc: 0x%02x\n",
++ i,
++ reg0 & 0x3F, (reg0 >> 6) & 0x03, (reg0 >> 8) & 0xffff,
++ (reg0 >> 24) & 0xff);
++ }
++ for (i = 0; i < 2; i++) {
++ reg0 = ioread32(priv->base + RCAR_CSI2_PHCM(i));
++
++ printk("Packet header C %d: dt: 0x%02x, vc: %d, wc: %d, cal_parity: 0x%02x\n",
++ i,
++ reg0 & 0x3F, (reg0 >> 6) & 0x03, (reg0 >> 8) & 0xffff,
++ (reg0 >> 24) & 0xff);
++ }
++ for (i = 0; i < 8; i++) {
++ reg0 = ioread32(priv->base + RCAR_CSI2_PHM(i));
++
++ printk("Packet header Monitor %d: dt: 0x%02x, vc: %d, wc: %d, ecc: 0x%02x\n",
++ i + 1,
++ reg0 & 0x3F, (reg0 >> 6) & 0x03, (reg0 >> 8) & 0xffff,
++ (reg0 >> 24) & 0xff);
++ }
++ for (i = 0; i < 3; i++)
++ printk("VINSM%d: 0x%08x\n", i, ioread32(priv->base + RCAR_CSI2_VINSM(i)));
++ printk("SERCCNT: %d\n",
++ ioread32(priv->base + RCAR_CSI2_SERCCNT));
++ printk("SSERCCNT: %d\n",
++ ioread32(priv->base + RCAR_CSI2_SSERCCNT));
++ printk("ECCCM: %d\n",
++ ioread32(priv->base + RCAR_CSI2_ECCCM));
++ printk("ECECM: %d\n",
++ ioread32(priv->base + RCAR_CSI2_ECECM));
++ printk("CRCECM: %d\n",
++ ioread32(priv->base + RCAR_CSI2_CRCECM));
++ for (i = 0; i < 2; i++)
++ printk("LCNT%d: 0x%08x\n", i, ioread32(priv->base + RCAR_CSI2_LCNT(i)));
++ for (i = 0; i < 2; i++)
++ printk("LCNTM%d: 0x%08x\n", i, ioread32(priv->base + RCAR_CSI2_LCNTM(i)));
++}
++#else
++#define rcar_sci2_debug_show(args)
++#endif /* RCAR_CSI2_DUMP */
+
+ static int rcar_csi2_set_phy_freq(struct rcar_csi2 *priv)
+ {
+@@ -276,47 +366,22 @@ static int rcar_csi2_set_phy_freq(struct rcar_csi2 *priv)
+ 0x0B, 0x1B, 0x2B, 0x3B, 0x0C, /* 35-39 */
+ 0x1C, 0x2C, 0x3C /* 40-42 */
+ };
++ const uint32_t const csi2_rate_range[43] = {
++ 80, 90, 100, 110, 120, /* 0-4 */
++ 130, 140, 150, 160, 170, /* 5-9 */
++ 180, 190, 205, 220, 235, /* 10-14 */
++ 250, 275, 300, 325, 350, /* 15-19 */
++ 400, 450, 500, 550, 600, /* 20-24 */
++ 650, 700, 750, 800, 850, /* 25-29 */
++ 900, 950, 1000, 1050, 1100, /* 30-34 */
++ 1150, 1200, 1250, 1300, 1350, /* 35-39 */
++ 1400, 1450, 1500 /* 40-42 */
++ };
+ uint32_t bps_per_lane = RCAR_CSI_190MBPS;
+
+- dev_dbg(&priv->pdev->dev, "Input size (%dx%d%c)\n",
+- priv->mf->width, priv->mf->height,
+- (priv->mf->field == V4L2_FIELD_NONE) ? 'p' : 'i');
+-
+- switch (priv->lanes) {
+- case 1:
+- bps_per_lane = RCAR_CSI_400MBPS;
+- break;
+- case 4:
+- if (priv->mf->field == V4L2_FIELD_NONE) {
+- if ((priv->mf->width == 1920) &&
+- (priv->mf->height == 1080))
+- bps_per_lane = RCAR_CSI_900MBPS;
+- else if ((priv->mf->width == 1280) &&
+- (priv->mf->height == 720))
+- bps_per_lane = RCAR_CSI_450MBPS;
+- else if ((priv->mf->width == 720) &&
+- (priv->mf->height == 480))
+- bps_per_lane = RCAR_CSI_190MBPS;
+- else if ((priv->mf->width == 720) &&
+- (priv->mf->height == 576))
+- bps_per_lane = RCAR_CSI_190MBPS;
+- else if ((priv->mf->width == 640) &&
+- (priv->mf->height == 480))
+- bps_per_lane = RCAR_CSI_100MBPS;
+- else
+- goto error;
+- } else {
+- if ((priv->mf->width == 1920) &&
+- (priv->mf->height == 1080))
+- bps_per_lane = RCAR_CSI_450MBPS;
+- else
+- goto error;
+- }
+- break;
+- default:
+- dev_err(&priv->pdev->dev, "ERROR: lanes is invalid (%d)\n",
+- priv->lanes);
+- return -EINVAL;
++ for (bps_per_lane = 0; bps_per_lane < RCAR_CSI_NUMRATES; bps_per_lane++) {
++ if (priv->csi_rate <= csi2_rate_range[bps_per_lane])
++ break;
+ }
+
+ dev_dbg(&priv->pdev->dev, "bps_per_lane (%d)\n", bps_per_lane);
+@@ -329,12 +394,6 @@ static int rcar_csi2_set_phy_freq(struct rcar_csi2 *priv)
+ iowrite32(hs_freq_range[bps_per_lane] << 16,
+ priv->base + RCAR_CSI2_PHYPLL);
+ return 0;
+-
+-error:
+- dev_err(&priv->pdev->dev, "Not support resolution (%dx%d%c)\n",
+- priv->mf->width, priv->mf->height,
+- (priv->mf->field == V4L2_FIELD_NONE) ? 'p' : 'i');
+- return -EINVAL;
+ }
+
+ static irqreturn_t rcar_csi2_irq(int irq, void *data)
+@@ -392,6 +451,16 @@ static int rcar_csi2_hwinit(struct rcar_csi2 *priv)
+ iowrite32(0x0001000f, priv->base + RCAR_CSI2_FLD);
+ tmp |= 0x1;
+ break;
++ case 2:
++ /* First field number setting */
++ iowrite32(0x0001000f, priv->base + RCAR_CSI2_FLD);
++ tmp |= 0x3;
++ break;
++ case 3:
++ /* First field number setting */
++ iowrite32(0x0001000f, priv->base + RCAR_CSI2_FLD);
++ tmp |= 0x7;
++ break;
+ case 4:
+ /* First field number setting */
+ iowrite32(0x0002000f, priv->base + RCAR_CSI2_FLD);
+@@ -469,32 +538,22 @@ static int rcar_csi2_hwinit(struct rcar_csi2 *priv)
+
+ static int rcar_csi2_s_power(struct v4l2_subdev *sd, int on)
+ {
+- struct rcar_csi2 *priv = container_of(sd, struct rcar_csi2, subdev);
+- struct v4l2_subdev *tmp_sd;
+- struct v4l2_subdev_format fmt = {
+- .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+- };
+- struct v4l2_mbus_framefmt *mf = &fmt.format;
++ struct rcar_csi2 *priv = v4l2_get_subdevdata(sd);
+ int ret = 0;
+
+ if (on) {
+- v4l2_device_for_each_subdev(tmp_sd, sd->v4l2_dev) {
+- if (strncmp(tmp_sd->name, CONNECT_SLAVE_NAME,
+- sizeof(CONNECT_SLAVE_NAME) - 1) == 0) {
+- v4l2_subdev_call(tmp_sd, pad, get_fmt,
+- NULL, &fmt);
+- if (ret < 0)
+- return ret;
+- }
++ if (atomic_inc_return(&priv->use_count) == 1) {
++ pm_runtime_get_sync(&priv->pdev->dev);
++ ret = rcar_csi2_hwinit(priv);
++ if (ret < 0)
++ return ret;
+ }
+- priv->mf = mf;
+- pm_runtime_get_sync(&priv->pdev->dev);
+- ret = rcar_csi2_hwinit(priv);
+- if (ret < 0)
+- return ret;
+ } else {
+- rcar_csi2_hwdeinit(priv);
+- pm_runtime_put_sync(&priv->pdev->dev);
++ if (atomic_dec_return(&priv->use_count) == 0) {
++ rcar_sci2_debug_show(priv);
++ rcar_csi2_hwdeinit(priv);
++ pm_runtime_put_sync(&priv->pdev->dev);
++ }
+ }
+
+ return ret;
+@@ -543,18 +602,19 @@ static int rcar_csi2_parse_dt(struct device_node *np,
+ return -EINVAL;
+
+ v4l2_of_parse_endpoint(endpoint, &bus_cfg);
++ ret = of_property_read_u32(endpoint, "csi-rate", &config->csi_rate);
++ if (ret < 0) {
++ printk(KERN_ERR "csi-rate not set\n");
++ return ret;
++ }
+ of_node_put(endpoint);
+
+ config->lanes = bus_cfg.bus.mipi_csi2.num_data_lanes;
+
+- ret = of_property_read_string(np, "adi,input-interface", &str);
+- if (ret < 0)
+- return ret;
+-
+ vc_np = of_get_child_by_name(np, "virtual,channel");
+
+- config->vcdt = 0;
+- config->vcdt2 = 0;
++ config->vcdt = 0x81008000;
++ config->vcdt2 = 0x83008200;
+ for (i = 0; i < VC_MAX_CHANNEL; i++) {
+ sprintf(csi_name, "csi2_vc%d", i);
+
+@@ -573,6 +633,8 @@ static int rcar_csi2_parse_dt(struct device_node *np,
+ config->vcdt |= (0x24 << (i * 16));
+ else if (!strcmp(str, "ycbcr422"))
+ config->vcdt |= (0x1e << (i * 16));
++ else if (!strcmp(str, "raw8"))
++ config->vcdt |= (0x2a << (i * 16));
+ else
+ config->vcdt |= 0;
+
+@@ -587,6 +649,8 @@ static int rcar_csi2_parse_dt(struct device_node *np,
+ config->vcdt2 |= (0x24 << (j * 16));
+ else if (!strcmp(str, "ycbcr422"))
+ config->vcdt2 |= (0x1e << (j * 16));
++ else if (!strcmp(str, "raw8"))
++ config->vcdt2 |= (0x2a << (j * 16));
+ else
+ config->vcdt2 |= 0;
+
+@@ -608,6 +672,7 @@ static int rcar_csi2_probe(struct platform_device *pdev)
+ /* Platform data specify the PHY, lanes, ECC, CRC */
+ struct rcar_csi2_pdata *pdata;
+ struct rcar_csi2_link_config link_config;
++ int i;
+
+ dev_dbg(&pdev->dev, "CSI2 probed.\n");
+
+@@ -618,12 +683,7 @@ static int rcar_csi2_probe(struct platform_device *pdev)
+ if (ret)
+ return ret;
+
+- if (link_config.lanes == 4)
+- dev_info(&pdev->dev,
+- "Detected rgb888 in rcar_csi2_parse_dt\n");
+- else
+- dev_info(&pdev->dev,
+- "Detected YCbCr422 in rcar_csi2_parse_dt\n");
++ dev_info(&pdev->dev, "Data lanes %d, link freq %d\n", link_config.lanes, link_config.csi_rate);
+ } else {
+ pdata = pdev->dev.platform_data;
+ if (!pdata)
+@@ -655,23 +715,27 @@ static int rcar_csi2_probe(struct platform_device *pdev)
+ return ret;
+
+ priv->pdev = pdev;
+- priv->subdev.owner = THIS_MODULE;
+- priv->subdev.dev = &pdev->dev;
+ priv->lanes = link_config.lanes;
+ priv->vcdt = link_config.vcdt;
+ priv->vcdt2 = link_config.vcdt2;
++ priv->csi_rate = link_config.csi_rate;
++ atomic_set(&priv->use_count, 0);
+
+- platform_set_drvdata(pdev, &priv->subdev);
++ platform_set_drvdata(pdev, priv);
+
+- v4l2_subdev_init(&priv->subdev, &rcar_csi2_subdev_ops);
+- v4l2_set_subdevdata(&priv->subdev, &pdev->dev);
++ for (i= 0; i < 4; i++) {
++ priv->subdev[i].owner = THIS_MODULE;
++ priv->subdev[i].dev = &pdev->dev;
++ v4l2_subdev_init(&priv->subdev[i], &rcar_csi2_subdev_ops);
++ v4l2_set_subdevdata(&priv->subdev[i], priv);
+
+- snprintf(priv->subdev.name, V4L2_SUBDEV_NAME_SIZE, "rcar_csi2.%s",
+- dev_name(&pdev->dev));
++ snprintf(priv->subdev[i].name, V4L2_SUBDEV_NAME_SIZE, "rcar_csi2.%s",
++ dev_name(&pdev->dev));
+
+- ret = v4l2_async_register_subdev(&priv->subdev);
+- if (ret < 0)
+- return ret;
++ ret = v4l2_async_register_subdev(&priv->subdev[i]);
++ if (ret < 0)
++ return ret;
++ }
+
+ spin_lock_init(&priv->lock);
+
+@@ -684,10 +748,11 @@ static int rcar_csi2_probe(struct platform_device *pdev)
+
+ static int rcar_csi2_remove(struct platform_device *pdev)
+ {
+- struct v4l2_subdev *subdev = platform_get_drvdata(pdev);
+- struct rcar_csi2 *priv = container_of(subdev, struct rcar_csi2, subdev);
++ struct rcar_csi2 *priv = platform_get_drvdata(pdev);
++ int i;
+
+- v4l2_async_unregister_subdev(&priv->subdev);
++ for (i= 0; i < 4; i++)
++ v4l2_async_unregister_subdev(&priv->subdev[i]);
+ pm_runtime_disable(&pdev->dev);
+
+ return 0;
+diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c
+index 74fb005..f5c2528 100644
+--- a/drivers/media/platform/soc_camera/rcar_vin.c
++++ b/drivers/media/platform/soc_camera/rcar_vin.c
+@@ -106,6 +106,7 @@
+ #define VNMC_INF_YUV8_BT601 (1 << 16)
+ #define VNMC_INF_YUV10_BT656 (2 << 16)
+ #define VNMC_INF_YUV10_BT601 (3 << 16)
++#define VNMC_INF_RAW8 (4 << 16)
+ #define VNMC_INF_YUV16 (5 << 16)
+ #define VNMC_INF_RGB888 (6 << 16)
+ #define VNMC_INF_MASK (7 << 16)
+@@ -138,6 +139,7 @@
+ #define VNINTS_FOS (1 << 0)
+
+ /* Video n Data Mode Register bits */
++#define VNDMR_YMODE_Y8 (1 << 12)
+ #define VNDMR_EXRGB (1 << 8)
+ #define VNDMR_BPSM (1 << 4)
+ #define VNDMR_DTMD_YCSEP (1 << 1)
+@@ -408,6 +410,7 @@ enum csi2_fmt {
+ RCAR_CSI_FMT_NONE = -1,
+ RCAR_CSI_RGB888,
+ RCAR_CSI_YCBCR422,
++ RCAR_CSI_RAW8,
+ };
+
+ struct vin_coeff {
+@@ -773,10 +776,13 @@ struct rcar_vin_priv {
+ enum csi2_fmt csi_fmt;
+ enum virtual_ch vc;
+ bool csi_sync;
++ bool deser_sync;
+
+ struct rcar_vin_async_client *async_client;
+ /* Asynchronous CSI2 linking */
+ struct v4l2_subdev *csi2_sd;
++ /* Asynchronous Deserializer linking */
++ struct v4l2_subdev *deser_sd;
+ /* Synchronous probing compatibility */
+ struct platform_device *csi2_pdev;
+
+@@ -989,6 +995,9 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv)
+ VNMC_INF_YUV10_BT656 : VNMC_INF_YUV10_BT601;
+ input_is_yuv = true;
+ break;
++ case MEDIA_BUS_FMT_SBGGR8_1X8:
++ vnmc |= VNMC_INF_RAW8 | VNMC_BPS;
++ break;
+ default:
+ break;
+ }
+@@ -1021,6 +1030,10 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv)
+ dmr = 0;
+ output_is_yuv = true;
+ break;
++ case V4L2_PIX_FMT_GREY:
++ dmr = VNDMR_DTMD_YCSEP | VNDMR_YMODE_Y8;
++ output_is_yuv = true;
++ break;
+ case V4L2_PIX_FMT_ARGB555:
+ dmr = VNDMR_DTMD_ARGB;
+ break;
+@@ -1043,6 +1056,9 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv)
+
+ dmr = VNDMR_EXRGB | VNDMR_DTMD_ARGB;
+ break;
++ case V4L2_PIX_FMT_SBGGR8:
++ dmr = 0;
++ break;
+ default:
+ goto e_format;
+ }
+@@ -1061,7 +1077,8 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv)
+ else
+ vnmc |= VNMC_DPINE;
+
+- if ((icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_NV12)
++ if ((icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_NV12) &&
++ (icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_SBGGR8)
+ && is_scaling(cam))
+ vnmc |= VNMC_SCLE;
+ }
+@@ -1211,6 +1228,10 @@ static void rcar_vin_videobuf_queue(struct vb2_buffer *vb)
+ */
+ static void rcar_vin_wait_stop_streaming(struct rcar_vin_priv *priv)
+ {
++ /* update the status if hardware is not stopped */
++ if (ioread32(priv->base + VNMS_REG) & VNMS_CA)
++ priv->state = RUNNING;
++
+ while (priv->state != STOPPED) {
+ /* issue stop if running */
+ if (priv->state == RUNNING)
+@@ -1361,6 +1382,31 @@ static struct v4l2_subdev *find_csi2(struct rcar_vin_priv *pcdev)
+ return NULL;
+ }
+
++static struct v4l2_subdev *find_deser(struct rcar_vin_priv *pcdev)
++{
++ struct v4l2_subdev *sd;
++ char name[] = "max9286_max9271";
++ char name2[] = "ti964_ti9x3";
++ char name3[] = "ti954_ti9x3";
++
++ v4l2_device_for_each_subdev(sd, &pcdev->ici.v4l2_dev) {
++ if (!strncmp(name, sd->name, sizeof(name) - 1)) {
++ pcdev->deser_sd = sd;
++ return sd;
++ }
++ if (!strncmp(name2, sd->name, sizeof(name2) - 1)) {
++ pcdev->deser_sd = sd;
++ return sd;
++ }
++ if (!strncmp(name3, sd->name, sizeof(name3) - 1)) {
++ pcdev->deser_sd = sd;
++ return sd;
++ }
++ }
++
++ return NULL;
++}
++
+ static int rcar_vin_add_device(struct soc_camera_device *icd)
+ {
+ struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+@@ -1375,7 +1421,8 @@ static int rcar_vin_add_device(struct soc_camera_device *icd)
+ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 ||
+ priv->chip == RCAR_V3M) {
+ struct v4l2_subdev *csi2_sd = find_csi2(priv);
+- int ret;
++ struct v4l2_subdev *deser_sd = find_deser(priv);
++ int ret = 0;
+
+ if (csi2_sd) {
+ csi2_sd->grp_id = soc_camera_grp_id(icd);
+@@ -1390,6 +1437,18 @@ static int rcar_vin_add_device(struct soc_camera_device *icd)
+ if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
+ return ret;
+ }
++ if (deser_sd) {
++ v4l2_set_subdev_hostdata(deser_sd, icd);
++
++ ret = v4l2_subdev_call(deser_sd, core, s_power, 1);
++ priv->deser_sync = true;
++
++ if (ret < 0 && ret != -EINVAL)
++ priv->deser_sync = false;
++
++ if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
++ return ret;
++ }
+ /*
+ * -ENODEV is special:
+ * either csi2_sd == NULL or the CSI-2 driver
+@@ -1417,6 +1476,7 @@ static void rcar_vin_remove_device(struct soc_camera_device *icd)
+ struct rcar_vin_priv *priv = ici->priv;
+ struct vb2_v4l2_buffer *vbuf;
+ struct v4l2_subdev *csi2_sd = find_csi2(priv);
++ struct v4l2_subdev *deser_sd = find_deser(priv);
+ int i;
+
+ /* disable capture, disable interrupts */
+@@ -1443,6 +1503,8 @@ static void rcar_vin_remove_device(struct soc_camera_device *icd)
+
+ if ((csi2_sd) && (priv->csi_sync))
+ v4l2_subdev_call(csi2_sd, core, s_power, 0);
++ if ((deser_sd) && (priv->deser_sync))
++ v4l2_subdev_call(deser_sd, core, s_power, 0);
+
+ dev_dbg(icd->parent, "R-Car VIN driver detached from camera %d\n",
+ icd->devnum);
+@@ -1621,13 +1683,17 @@ static int rcar_vin_set_rect(struct soc_camera_device *icd)
+
+ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 ||
+ priv->chip == RCAR_V3M) {
+- if ((icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_NV12)
++ if ((icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_NV12) &&
++ (icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_SBGGR8)
+ && is_scaling(cam)) {
+ ret = rcar_vin_uds_set(priv, cam);
+ if (ret < 0)
+ return ret;
+ }
+- if (is_scaling(cam) ||
++ if (icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_SBGGR8)
++ iowrite32(ALIGN(cam->out_width / 2, 0x10),
++ priv->base + VNIS_REG);
++ else if (is_scaling(cam) ||
+ (icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_NV16) ||
+ (icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_NV12))
+ iowrite32(ALIGN(cam->out_width, 0x20),
+@@ -1868,6 +1934,14 @@ static bool rcar_vin_packing_supported(const struct soc_mbus_pixelfmt *fmt)
+ .layout = SOC_MBUS_LAYOUT_PACKED,
+ },
+ {
++ .fourcc = V4L2_PIX_FMT_GREY,
++ .name = "GREY8",
++ .bits_per_sample = 8,
++ .packing = SOC_MBUS_PACKING_NONE,
++ .order = SOC_MBUS_ORDER_LE,
++ .layout = SOC_MBUS_LAYOUT_PACKED,
++ },
++ {
+ .fourcc = V4L2_PIX_FMT_RGB565,
+ .name = "RGB565",
+ .bits_per_sample = 16,
+@@ -1899,6 +1973,14 @@ static bool rcar_vin_packing_supported(const struct soc_mbus_pixelfmt *fmt)
+ .order = SOC_MBUS_ORDER_LE,
+ .layout = SOC_MBUS_LAYOUT_PACKED,
+ },
++ {
++ .fourcc = V4L2_PIX_FMT_SBGGR8,
++ .name = "Bayer 8 BGGR",
++ .bits_per_sample = 8,
++ .packing = SOC_MBUS_PACKING_NONE,
++ .order = SOC_MBUS_ORDER_LE,
++ .layout = SOC_MBUS_LAYOUT_PACKED,
++ },
+ };
+
+ static int rcar_vin_get_formats(struct soc_camera_device *icd, unsigned int idx,
+@@ -2012,6 +2094,7 @@ static int rcar_vin_get_formats(struct soc_camera_device *icd, unsigned int idx,
+ case MEDIA_BUS_FMT_YUYV8_2X8:
+ case MEDIA_BUS_FMT_YUYV10_2X10:
+ case MEDIA_BUS_FMT_RGB888_1X24:
++ case MEDIA_BUS_FMT_SBGGR8_1X8:
+ if (cam->extra_fmt)
+ break;
+
+@@ -2218,12 +2301,14 @@ static int rcar_vin_set_fmt(struct soc_camera_device *icd,
+ case V4L2_PIX_FMT_ABGR32:
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_YUYV:
++ case V4L2_PIX_FMT_GREY:
+ case V4L2_PIX_FMT_RGB565:
+ case V4L2_PIX_FMT_ARGB555:
+ case V4L2_PIX_FMT_NV16:
+ can_scale = true;
+ break;
+ case V4L2_PIX_FMT_NV12:
++ case V4L2_PIX_FMT_SBGGR8:
+ default:
+ can_scale = false;
+ break;
+@@ -2316,7 +2401,8 @@ static int rcar_vin_try_fmt(struct soc_camera_device *icd,
+ /* odd number clipping by pixel post clip processing, */
+ /* it is outputted to a memory per even pixels. */
+ if ((pixfmt == V4L2_PIX_FMT_NV16) || (pixfmt == V4L2_PIX_FMT_NV12) ||
+- (pixfmt == V4L2_PIX_FMT_YUYV) || (pixfmt == V4L2_PIX_FMT_UYVY))
++ (pixfmt == V4L2_PIX_FMT_YUYV) || (pixfmt == V4L2_PIX_FMT_UYVY) ||
++ (pixfmt == V4L2_PIX_FMT_GREY))
+ v4l_bound_align_image(&pix->width, 5, priv->max_width, 1,
+ &pix->height, 2, priv->max_height, 0, 0);
+ else
+@@ -2486,6 +2572,19 @@ static int rcar_vin_cropcap(struct soc_camera_device *icd,
+ }
+ #endif
+
++static int rcar_vin_get_edid(struct soc_camera_device *icd,
++ struct v4l2_edid *edid)
++{
++ struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
++ int ret;
++
++ ret = v4l2_subdev_call(sd, pad, get_edid, edid);
++ if (ret < 0)
++ return ret;
++
++ return 0;
++}
++
+ static struct soc_camera_host_ops rcar_vin_host_ops = {
+ .owner = THIS_MODULE,
+ .add = rcar_vin_add_device,
+@@ -2504,6 +2603,7 @@ static int rcar_vin_cropcap(struct soc_camera_device *icd,
+ .get_selection = rcar_vin_get_selection,
+ .cropcap = rcar_vin_cropcap,
+ #endif
++ .get_edid = rcar_vin_get_edid,
+ };
+
+ #ifdef CONFIG_OF
+@@ -2524,7 +2624,7 @@ static int rcar_vin_cropcap(struct soc_camera_device *icd,
+ MODULE_DEVICE_TABLE(of, rcar_vin_of_table);
+ #endif
+
+-#define MAP_MAX_NUM 32
++#define MAP_MAX_NUM 128
+ static DECLARE_BITMAP(device_map, MAP_MAX_NUM);
+ static DEFINE_MUTEX(list_lock);
+
+@@ -2714,7 +2814,11 @@ static int rcar_vin_probe(struct platform_device *pdev)
+ const char *str;
+ unsigned int i;
+ struct device_node *epn = NULL, *ren = NULL;
++ struct device_node *csi2_ren = NULL, *max9286_ren = NULL, *ti964_ren = NULL, *ti954_ren = NULL;
+ bool csi_use = false;
++ bool max9286_use = false;
++ bool ti964_use = false;
++ bool ti954_use = false;
+
+ match = of_match_device(of_match_ptr(rcar_vin_of_table), &pdev->dev);
+
+@@ -2741,13 +2845,27 @@ static int rcar_vin_probe(struct platform_device *pdev)
+ dev_dbg(&pdev->dev, "node name:%s\n",
+ of_node_full_name(ren->parent));
+
+- if (strcmp(ren->parent->name, "csi2") == 0)
++ if (strcmp(ren->parent->name, "csi2") == 0) {
++ csi2_ren = ren;
+ csi_use = true;
++ }
+
+- of_node_put(ren);
++ if (strcmp(ren->parent->name, "max9286-max9271") == 0) {
++ max9286_ren = of_parse_phandle(epn, "remote-endpoint", 0);
++ max9286_use = true;
++ }
+
+- if (i)
+- break;
++ if (strcmp(ren->parent->name, "ti964-ti9x3") == 0) {
++ ti964_ren = of_parse_phandle(epn, "remote-endpoint", 0);
++ ti964_use = true;
++ }
++
++ if (strcmp(ren->parent->name, "ti954-ti9x3") == 0) {
++ ti954_ren = of_parse_phandle(epn, "remote-endpoint", 0);
++ ti954_use = true;
++ }
++
++ of_node_put(ren);
+ }
+
+ ret = v4l2_of_parse_endpoint(np, &ep);
+@@ -2799,6 +2917,7 @@ static int rcar_vin_probe(struct platform_device *pdev)
+ priv->ici.drv_name = dev_name(&pdev->dev);
+ priv->ici.ops = &rcar_vin_host_ops;
+ priv->csi_sync = false;
++ priv->deser_sync = false;
+
+ priv->pdata_flags = pdata_flags;
+ if (!match) {
+@@ -2983,7 +3102,25 @@ static int rcar_vin_probe(struct platform_device *pdev)
+ goto cleanup;
+
+ if (csi_use) {
+- ret = rcar_vin_soc_of_bind(priv, &priv->ici, epn, ren->parent);
++ ret = rcar_vin_soc_of_bind(priv, &priv->ici, epn, csi2_ren->parent);
++ if (ret)
++ goto cleanup;
++ }
++
++ if (max9286_use) {
++ ret = rcar_vin_soc_of_bind(priv, &priv->ici, epn, max9286_ren);
++ if (ret)
++ goto cleanup;
++ }
++
++ if (ti964_use) {
++ ret = rcar_vin_soc_of_bind(priv, &priv->ici, epn, ti964_ren);
++ if (ret)
++ goto cleanup;
++ }
++
++ if (ti954_use) {
++ ret = rcar_vin_soc_of_bind(priv, &priv->ici, epn, ti954_ren);
+ if (ret)
+ goto cleanup;
+ }
+diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c
+index edd1c1d..54f4c9d 100644
+--- a/drivers/media/platform/soc_camera/soc_camera.c
++++ b/drivers/media/platform/soc_camera/soc_camera.c
+@@ -49,7 +49,7 @@
+ (icd)->vb_vidq.streaming : \
+ vb2_is_streaming(&(icd)->vb2_vidq))
+
+-#define MAP_MAX_NUM 32
++#define MAP_MAX_NUM 128
+ static DECLARE_BITMAP(device_map, MAP_MAX_NUM);
+ static LIST_HEAD(hosts);
+ static LIST_HEAD(devices);
+@@ -1106,6 +1106,18 @@ static int soc_camera_s_parm(struct file *file, void *fh,
+ return -ENOIOCTLCMD;
+ }
+
++static int soc_camera_g_edid(struct file *file, void *fh,
++ struct v4l2_edid *edid)
++{
++ struct soc_camera_device *icd = file->private_data;
++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
++
++ if (ici->ops->get_edid)
++ return ici->ops->get_edid(icd, edid);
++
++ return -ENOIOCTLCMD;
++}
++
+ static int soc_camera_probe(struct soc_camera_host *ici,
+ struct soc_camera_device *icd);
+
+@@ -1664,7 +1676,7 @@ static void scan_of_host(struct soc_camera_host *ici)
+ of_node_put(ren);
+
+ if (i) {
+- dev_err(dev, "multiple subdevices aren't supported yet!\n");
++ dev_dbg(dev, "multiple subdevices aren't supported yet!\n");
+ break;
+ }
+ }
+@@ -2077,6 +2089,7 @@ static int soc_camera_device_register(struct soc_camera_device *icd)
+ .vidioc_s_selection = soc_camera_s_selection,
+ .vidioc_g_parm = soc_camera_g_parm,
+ .vidioc_s_parm = soc_camera_s_parm,
++ .vidioc_g_edid = soc_camera_g_edid,
+ };
+
+ static int video_dev_create(struct soc_camera_device *icd)
+diff --git a/drivers/media/platform/soc_camera/soc_mediabus.c b/drivers/media/platform/soc_camera/soc_mediabus.c
+index e3e665e..84754a4 100644
+--- a/drivers/media/platform/soc_camera/soc_mediabus.c
++++ b/drivers/media/platform/soc_camera/soc_mediabus.c
+@@ -57,6 +57,16 @@
+ .layout = SOC_MBUS_LAYOUT_PACKED,
+ },
+ }, {
++ .code = MEDIA_BUS_FMT_YUYV10_2X10,
++ .fmt = {
++ .fourcc = V4L2_PIX_FMT_YUYV,
++ .name = "YUYV",
++ .bits_per_sample = 10,
++ .packing = SOC_MBUS_PACKING_2X10_PADHI,
++ .order = SOC_MBUS_ORDER_LE,
++ .layout = SOC_MBUS_LAYOUT_PACKED,
++ },
++}, {
+ .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE,
+ .fmt = {
+ .fourcc = V4L2_PIX_FMT_RGB555,
+@@ -403,6 +413,10 @@ int soc_mbus_samples_per_pixel(const struct soc_mbus_pixelfmt *mf,
+ *numerator = 2;
+ *denominator = 1;
+ return 0;
++ case SOC_MBUS_PACKING_2X10_PADHI:
++ *numerator = 3;
++ *denominator = 1;
++ return 0;
+ case SOC_MBUS_PACKING_1_5X8:
+ *numerator = 3;
+ *denominator = 2;
+@@ -428,6 +442,8 @@ s32 soc_mbus_bytes_per_line(u32 width, const struct soc_mbus_pixelfmt *mf)
+ case SOC_MBUS_PACKING_2X8_PADLO:
+ case SOC_MBUS_PACKING_EXTEND16:
+ return width * 2;
++ case SOC_MBUS_PACKING_2X10_PADHI:
++ return width * 3;
+ case SOC_MBUS_PACKING_1_5X8:
+ return width * 3 / 2;
+ case SOC_MBUS_PACKING_VARIABLE:
+diff --git a/include/media/drv-intf/soc_mediabus.h b/include/media/drv-intf/soc_mediabus.h
+index 2ff7737..e5f3f53 100644
+--- a/include/media/drv-intf/soc_mediabus.h
++++ b/include/media/drv-intf/soc_mediabus.h
+@@ -21,6 +21,8 @@
+ * @SOC_MBUS_PACKING_2X8_PADHI: 16 bits transferred in 2 8-bit samples, in the
+ * possibly incomplete byte high bits are padding
+ * @SOC_MBUS_PACKING_2X8_PADLO: as above, but low bits are padding
++ * @SOC_MBUS_PACKING_2X10_PADHI:20 bits transferred in 2 10-bit samples. The
++ * high bits are padding
+ * @SOC_MBUS_PACKING_EXTEND16: sample width (e.g., 10 bits) has to be extended
+ * to 16 bits
+ * @SOC_MBUS_PACKING_VARIABLE: compressed formats with variable packing
+@@ -33,6 +35,7 @@ enum soc_mbus_packing {
+ SOC_MBUS_PACKING_NONE,
+ SOC_MBUS_PACKING_2X8_PADHI,
+ SOC_MBUS_PACKING_2X8_PADLO,
++ SOC_MBUS_PACKING_2X10_PADHI,
+ SOC_MBUS_PACKING_EXTEND16,
+ SOC_MBUS_PACKING_VARIABLE,
+ SOC_MBUS_PACKING_1_5X8,
+diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h
+index 1a15c3e..dad1ed8 100644
+--- a/include/media/soc_camera.h
++++ b/include/media/soc_camera.h
+@@ -125,6 +125,7 @@ struct soc_camera_host_ops {
+ int (*set_parm)(struct soc_camera_device *, struct v4l2_streamparm *);
+ int (*enum_framesizes)(struct soc_camera_device *, struct v4l2_frmsizeenum *);
+ unsigned int (*poll)(struct file *, poll_table *);
++ int (*get_edid)(struct soc_camera_device *, struct v4l2_edid *);
+ };
+
+ #define SOCAM_SENSOR_INVERT_PCLK (1 << 0)
+--
+1.9.1
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0031-arm64-dts-r8a7795-es1-salvator-x-view-add-ADAS-board.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0031-arm64-dts-r8a7795-es1-salvator-x-view-add-ADAS-board.patch
new file mode 100644
index 0000000..ddcff1d
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0031-arm64-dts-r8a7795-es1-salvator-x-view-add-ADAS-board.patch
@@ -0,0 +1,588 @@
+From c4d2ada2089db7db1a059af37f371f6e2df213f4 Mon Sep 17 00:00:00 2001
+From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+Date: Wed, 4 Jan 2017 10:37:23 +0300
+Subject: [PATCH] arm64: dts: r8a7795-es1-salvator-x-view: add ADAS board
+
+Salvator-X.View board on R8A7795 ES1.x SoC
+
+Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+---
+ arch/arm64/boot/dts/renesas/Makefile | 3 +
+ .../dts/renesas/r8a7795-es1-salvator-x-view.dts | 552 +++++++++++++++++++++
+ 2 files changed, 555 insertions(+)
+ create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts
+
+diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile
+index 32fb4d9..2a00759 100644
+--- a/arch/arm64/boot/dts/renesas/Makefile
++++ b/arch/arm64/boot/dts/renesas/Makefile
+@@ -4,5 +4,8 @@ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-salvator-x.dtb r8a7795-es1-h3ulcb.dtb
+ dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-x.dtb r8a7796-m3ulcb.dtb
+ dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-xs.dtb
+
++# ADAS boards
++dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-salvator-x-view.dtb
++
+ always := $(dtb-y)
+ clean-files := *.dtb
+diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts
+new file mode 100644
+index 0000000..3f3d66a
+--- /dev/null
++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts
+@@ -0,0 +1,552 @@
++/*
++ * Device Tree Source for the Salvator-X.View board on r8a7795 ES1.x
++ *
++ * Copyright (C) 2016-2017 Renesas Electronics Corp.
++ * Copyright (C) 2015-2017 Cogent Embedded, Inc
++ *
++ * This file is licensed under the terms of the GNU General Public License
++ * version 2. This program is licensed "as is" without any warranty of any
++ * kind, whether express or implied.
++ */
++
++#include "r8a7795-es1-salvator-x.dts"
++
++/ {
++ model = "Renesas Salvator-X.View board based on r8a7795";
++};
++
++&pfc {
++ can0_pins: can0 {
++ groups = "can0_data_a";
++ function = "can0";
++ };
++
++ can1_pins: can1 {
++ groups = "can1_data";
++ function = "can1";
++ };
++};
++
++&i2c4 {
++ /delete-node/hdmi-in@34;
++ /delete-node/composite-in@70;
++
++ ov106xx@0 {
++ compatible = "ovti,ov106xx";
++ reg = <0x60>;
++
++ port@0 {
++ ov106xx_in0: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin0ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des0ep0: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep0>;
++ };
++ };
++ };
++
++ ov106xx@1 {
++ compatible = "ovti,ov106xx";
++ reg = <0x61>;
++
++ port@0 {
++ ov106xx_in1: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin1ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des0ep1: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep1>;
++ };
++ };
++ };
++
++ ov106xx@2 {
++ compatible = "ovti,ov106xx";
++ reg = <0x62>;
++
++ port@0 {
++ ov106xx_in2: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin2ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des0ep2: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep2>;
++ };
++ };
++ };
++
++ ov106xx@3 {
++ compatible = "ovti,ov106xx";
++ reg = <0x63>;
++
++ port@0 {
++ ov106xx_in3: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin3ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_des0ep3: endpoint {
++ remote-endpoint = <&max9286_des0ep3>;
++ };
++ };
++ };
++
++ ov106xx@4 {
++ compatible = "ovti,ov106xx";
++ reg = <0x64>;
++
++ port@0 {
++ ov106xx_in4: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin4ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des1ep0: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep0>;
++ };
++ };
++ };
++
++ ov106xx@5 {
++ compatible = "ovti,ov106xx";
++ reg = <0x65>;
++
++ port@0 {
++ ov106xx_in5: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin5ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des1ep1: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep1>;
++ };
++ };
++ };
++
++ ov106xx@6 {
++ compatible = "ovti,ov106xx";
++ reg = <0x66>;
++
++ port@0 {
++ ov106xx_in6: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin6ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des1ep2: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep2>;
++ };
++ };
++ };
++
++ ov106xx@7 {
++ compatible = "ovti,ov106xx";
++ reg = <0x67>;
++
++ port@0 {
++ ov106xx_in7: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin7ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_des1ep3: endpoint {
++ remote-endpoint = <&max9286_des1ep3>;
++ };
++ };
++ };
++
++ max9286-max9271@0 {
++ compatible = "maxim,max9286-max9271";
++ reg = <0x4c>;
++ gpios = <&gpio6 30 GPIO_ACTIVE_LOW>;
++ maxim,sensor_delay = <0>;
++ maxim,links = <4>;
++ maxim,lanes = <4>;
++ maxim,resetb-gpio = <1>;
++ maxim,fsync-mode = "automatic";
++ maxim,timeout = <100>;
++ maxim,i2c-quirk = <0x6c>;
++
++ port@0 {
++ max9286_des0ep0: endpoint@0 {
++ max9271-addr = <0x50>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in0>;
++ };
++ max9286_des0ep1: endpoint@1 {
++ max9271-addr = <0x51>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in1>;
++ };
++ max9286_des0ep2: endpoint@2 {
++ max9271-addr = <0x52>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in2>;
++ };
++ max9286_des0ep3: endpoint@3 {
++ max9271-addr = <0x53>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in3>;
++ };
++ };
++ port@1 {
++ max9286_csi0ep0: endpoint {
++ csi-rate = <700>;
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ };
++
++ max9286-max9271@1 {
++ compatible = "maxim,max9286-max9271";
++ reg = <0x6c>;
++ maxim,sensor_delay = <0>;
++ maxim,links = <4>;
++ maxim,lanes = <4>;
++ maxim,resetb-gpio = <1>;
++ maxim,fsync-mode = "automatic";
++ maxim,timeout = <100>;
++
++ port@0 {
++ max9286_des1ep0: endpoint@0 {
++ max9271-addr = <0x54>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in4>;
++ };
++ max9286_des1ep1: endpoint@1 {
++ max9271-addr = <0x55>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in5>;
++ };
++ max9286_des1ep2: endpoint@2 {
++ max9271-addr = <0x56>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in6>;
++ };
++ max9286_des1ep3: endpoint@3 {
++ max9271-addr = <0x57>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in7>;
++ };
++ };
++ port@1 {
++ max9286_csi2ep0: endpoint {
++ csi-rate = <700>;
++ remote-endpoint = <&csi2_41_ep>;
++ };
++ };
++ };
++};
++
++&vin0 {
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin0ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in0>;
++ };
++ };
++ port@1 {
++ csi0ep0: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin0_max9286_des0ep0: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep0>;
++ };
++ };
++ };
++};
++
++&vin1 {
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin1ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <1>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in1>;
++ };
++ };
++ port@1 {
++ csi0ep1: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin1_max9286_des0ep1: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep1>;
++ };
++ };
++ };
++};
++
++&vin2 {
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin2ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <2>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in2>;
++ };
++ };
++ port@1 {
++ csi0ep2: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin2_max9286_des0ep2: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep2>;
++ };
++ };
++ };
++};
++
++&vin3 {
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin3ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <3>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in3>;
++ };
++ };
++ port@1 {
++ csi0ep3: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin3_max9286_des0ep3: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep3>;
++ };
++ };
++ };
++};
++
++&vin4 {
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin4ep0: endpoint {
++ csi,select = "csi41";
++ virtual,channel = <0>;
++ remote-endpoint = <&ov106xx_in4>;
++ data-lanes = <1 2 3 4>;
++ };
++ };
++ port@1 {
++ csi2ep0: endpoint {
++ remote-endpoint = <&csi2_41_ep>;
++ };
++ };
++ port@2 {
++ vin4_max9286_des1ep0: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep0>;
++ };
++ };
++ };
++};
++
++&vin5 {
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin5ep0: endpoint@0 {
++ csi,select = "csi41";
++ virtual,channel = <1>;
++ remote-endpoint = <&ov106xx_in5>;
++ data-lanes = <1 2 3 4>;
++ };
++ };
++ port@1 {
++ csi2ep1: endpoint {
++ remote-endpoint = <&csi2_41_ep>;
++ };
++ };
++ port@2 {
++ vin5_max9286_des1ep1: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep1>;
++ };
++ };
++ };
++};
++
++&vin6 {
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin6ep0: endpoint@0 {
++ csi,select = "csi41";
++ virtual,channel = <2>;
++ remote-endpoint = <&ov106xx_in6>;
++ data-lanes = <1 2 3 4>;
++ };
++ };
++ port@1 {
++ csi2ep2: endpoint {
++ remote-endpoint = <&csi2_41_ep>;
++ };
++ };
++ port@2 {
++ vin6_max9286_des1ep2: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep2>;
++ };
++ };
++ };
++};
++
++&vin7 {
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin7ep0: endpoint@0 {
++ csi,select = "csi41";
++ virtual,channel = <3>;
++ remote-endpoint = <&ov106xx_in7>;
++ data-lanes = <1 2 3 4>;
++ };
++ };
++ port@1 {
++ csi2ep3: endpoint {
++ remote-endpoint = <&csi2_41_ep>;
++ };
++ };
++ port@2 {
++ vin7_max9286_des1ep3: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep3>;
++ };
++ };
++ };
++};
++
++&csi2_20 {
++ status = "disabled";
++ /delete-node/ports;
++};
++
++&csi2_40 {
++ /delete-node/ports;
++
++ virtual,channel {
++ csi2_vc0 {
++ data,type = "ycbcr422";
++ receive,vc = <0>;
++ };
++ csi2_vc1 {
++ data,type = "ycbcr422";
++ receive,vc = <1>;
++ };
++ csi2_vc2 {
++ data,type = "ycbcr422";
++ receive,vc = <2>;
++ };
++ csi2_vc3 {
++ data,type = "ycbcr422";
++ receive,vc = <3>;
++ };
++ };
++
++ port {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ csi2_40_ep: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ csi-rate = <300>;
++ };
++ };
++};
++
++&csi2_41 {
++ status = "okay";
++
++ virtual,channel {
++ csi2_vc0 {
++ data,type = "ycbcr422";
++ receive,vc = <0>;
++ };
++ csi2_vc1 {
++ data,type = "ycbcr422";
++ receive,vc = <1>;
++ };
++ csi2_vc2 {
++ data,type = "ycbcr422";
++ receive,vc = <2>;
++ };
++ csi2_vc3 {
++ data,type = "ycbcr422";
++ receive,vc = <3>;
++ };
++ };
++
++ port {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ csi2_41_ep: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ csi-rate = <300>;
++ };
++ };
++};
++
++&can0 {
++ pinctrl-0 = <&can0_pins>;
++ pinctrl-names = "default";
++ status = "okay";
++};
++
++&can1 {
++ pinctrl-0 = <&can1_pins>;
++ pinctrl-names = "default";
++ status = "okay";
++};
+--
+1.9.1
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0032-arm64-dts-r8a7795-es1-h3ulcb-view-add-ADAS-board.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0032-arm64-dts-r8a7795-es1-h3ulcb-view-add-ADAS-board.patch
new file mode 100644
index 0000000..24af837
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0032-arm64-dts-r8a7795-es1-h3ulcb-view-add-ADAS-board.patch
@@ -0,0 +1,581 @@
+From 14d2ada2089db7db1a059af37f371f6e2df213f4 Mon Sep 17 00:00:00 2001
+From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+Date: Wed, 4 Jan 2017 10:37:23 +0300
+Subject: [PATCH] arm64: dts: r8a7795-es1-h3ulcb-view: add ADAS board
+
+H3ULCB.View board on R8A7795 ES1.x SoC
+
+Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+---
+ arch/arm64/boot/dts/renesas/Makefile | 1 +
+ .../boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts | 546 +++++++++++++++++++++
+ 2 files changed, 547 insertions(+)
+ create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts
+
+diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile
+index 2a00759..43aa35d 100644
+--- a/arch/arm64/boot/dts/renesas/Makefile
++++ b/arch/arm64/boot/dts/renesas/Makefile
+@@ -6,6 +6,7 @@ dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-xs.dtb
+
+ # ADAS boards
+ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-salvator-x-view.dtb
++dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-h3ulcb-view.dtb
+
+ always := $(dtb-y)
+ clean-files := *.dtb
+diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts
+new file mode 100644
+index 0000000..de56fa4
+--- /dev/null
++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts
+@@ -0,0 +1,546 @@
++/*
++ * Device Tree Source for the H3ULCB.View board on r8a7795 ES1.x
++ *
++ * Copyright (C) 2016-2017 Renesas Electronics Corp.
++ * Copyright (C) 2016-2017 Cogent Embedded, Inc.
++ *
++ * This file is licensed under the terms of the GNU General Public License
++ * version 2. This program is licensed "as is" without any warranty of any
++ * kind, whether express or implied.
++ */
++
++#include "r8a7795-es1-h3ulcb.dts"
++
++/ {
++ model = "Renesas H3ULCB.View board based on r8a7795";
++};
++
++&i2c4 {
++ ov106xx@0 {
++ compatible = "ovti,ov106xx";
++ reg = <0x60>;
++
++ port@0 {
++ ov106xx_in0: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin0ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des0ep0: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep0>;
++ };
++ };
++ };
++
++ ov106xx@1 {
++ compatible = "ovti,ov106xx";
++ reg = <0x61>;
++
++ port@0 {
++ ov106xx_in1: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin1ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des0ep1: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep1>;
++ };
++ };
++ };
++
++ ov106xx@2 {
++ compatible = "ovti,ov106xx";
++ reg = <0x62>;
++
++ port@0 {
++ ov106xx_in2: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin2ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des0ep2: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep2>;
++ };
++ };
++ };
++
++ ov106xx@3 {
++ compatible = "ovti,ov106xx";
++ reg = <0x63>;
++
++ port@0 {
++ ov106xx_in3: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin3ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_des0ep3: endpoint {
++ remote-endpoint = <&max9286_des0ep3>;
++ };
++ };
++ };
++
++ ov106xx@4 {
++ compatible = "ovti,ov106xx";
++ reg = <0x64>;
++
++ port@0 {
++ ov106xx_in4: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin4ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des1ep0: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep0>;
++ };
++ };
++ };
++
++ ov106xx@5 {
++ compatible = "ovti,ov106xx";
++ reg = <0x65>;
++
++ port@0 {
++ ov106xx_in5: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin5ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des1ep1: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep1>;
++ };
++ };
++ };
++
++ ov106xx@6 {
++ compatible = "ovti,ov106xx";
++ reg = <0x66>;
++
++ port@0 {
++ ov106xx_in6: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin6ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des1ep2: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep2>;
++ };
++ };
++ };
++
++ ov106xx@7 {
++ compatible = "ovti,ov106xx";
++ reg = <0x67>;
++
++ port@0 {
++ ov106xx_in7: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin7ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_des1ep3: endpoint {
++ remote-endpoint = <&max9286_des1ep3>;
++ };
++ };
++ };
++
++ max9286-max9271@0 {
++ compatible = "maxim,max9286-max9271";
++ reg = <0x4c>;
++ gpios = <&gpio2 6 GPIO_ACTIVE_HIGH>;
++ maxim,sensor_delay = <0>;
++ maxim,links = <4>;
++ maxim,lanes = <4>;
++ maxim,resetb-gpio = <1>;
++ maxim,fsync-mode = "automatic";
++ maxim,timeout = <100>;
++ maxim,i2c-quirk = <0x6c>;
++
++ port@0 {
++ max9286_des0ep0: endpoint@0 {
++ max9271-addr = <0x50>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in0>;
++ };
++ max9286_des0ep1: endpoint@1 {
++ max9271-addr = <0x51>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in1>;
++ };
++ max9286_des0ep2: endpoint@2 {
++ max9271-addr = <0x52>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in2>;
++ };
++ max9286_des0ep3: endpoint@3 {
++ max9271-addr = <0x53>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in3>;
++ };
++ };
++ port@1 {
++ max9286_csi0ep0: endpoint {
++ csi-rate = <700>;
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ };
++
++ max9286-max9271@1 {
++ compatible = "maxim,max9286-max9271";
++ reg = <0x6c>;
++ gpios = <&gpio5 25 GPIO_ACTIVE_HIGH>;
++ maxim,sensor_delay = <0>;
++ maxim,links = <4>;
++ maxim,lanes = <4>;
++ maxim,resetb-gpio = <1>;
++ maxim,fsync-mode = "automatic";
++ maxim,timeout = <100>;
++
++ port@0 {
++ max9286_des1ep0: endpoint@0 {
++ max9271-addr = <0x54>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in4>;
++ };
++ max9286_des1ep1: endpoint@1 {
++ max9271-addr = <0x55>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in5>;
++ };
++ max9286_des1ep2: endpoint@2 {
++ max9271-addr = <0x56>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in6>;
++ };
++ max9286_des1ep3: endpoint@3 {
++ max9271-addr = <0x57>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in7>;
++ };
++ };
++ port@1 {
++ max9286_csi2ep0: endpoint {
++ csi-rate = <700>;
++ remote-endpoint = <&csi2_41_ep>;
++ };
++ };
++ };
++};
++
++&pcie_bus_clk {
++ clock-frequency = <100000000>;
++ status = "okay";
++};
++
++&pciec1 {
++ status = "okay";
++};
++
++&vin0 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin0ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in0>;
++ };
++ };
++ port@1 {
++ csi0ep0: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin0_max9286_des0ep0: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep0>;
++ };
++ };
++ };
++};
++
++&vin1 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin1ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <1>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in1>;
++ };
++ };
++ port@1 {
++ csi0ep1: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin1_max9286_des0ep1: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep1>;
++ };
++ };
++ };
++};
++
++&vin2 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin2ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <2>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in2>;
++ };
++ };
++ port@1 {
++ csi0ep2: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin2_max9286_des0ep2: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep2>;
++ };
++ };
++ };
++};
++
++&vin3 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin3ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <3>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in3>;
++ };
++ };
++ port@1 {
++ csi0ep3: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin3_max9286_des0ep3: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep3>;
++ };
++ };
++ };
++};
++
++&vin4 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin4ep0: endpoint {
++ csi,select = "csi41";
++ virtual,channel = <0>;
++ remote-endpoint = <&ov106xx_in4>;
++ data-lanes = <1 2 3 4>;
++ };
++ };
++ port@1 {
++ csi2ep0: endpoint {
++ remote-endpoint = <&csi2_41_ep>;
++ };
++ };
++ port@2 {
++ vin4_max9286_des1ep0: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep0>;
++ };
++ };
++ };
++};
++
++&vin5 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin5ep0: endpoint@0 {
++ csi,select = "csi41";
++ virtual,channel = <1>;
++ remote-endpoint = <&ov106xx_in5>;
++ data-lanes = <1 2 3 4>;
++ };
++ };
++ port@1 {
++ csi2ep1: endpoint {
++ remote-endpoint = <&csi2_41_ep>;
++ };
++ };
++ port@2 {
++ vin5_max9286_des1ep1: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep1>;
++ };
++ };
++ };
++};
++
++&vin6 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin6ep0: endpoint@0 {
++ csi,select = "csi41";
++ virtual,channel = <2>;
++ remote-endpoint = <&ov106xx_in6>;
++ data-lanes = <1 2 3 4>;
++ };
++ };
++ port@1 {
++ csi2ep2: endpoint {
++ remote-endpoint = <&csi2_41_ep>;
++ };
++ };
++ port@2 {
++ vin6_max9286_des1ep2: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep2>;
++ };
++ };
++ };
++};
++
++&vin7 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin7ep0: endpoint@0 {
++ csi,select = "csi41";
++ virtual,channel = <3>;
++ remote-endpoint = <&ov106xx_in7>;
++ data-lanes = <1 2 3 4>;
++ };
++ };
++ port@1 {
++ csi2ep3: endpoint {
++ remote-endpoint = <&csi2_41_ep>;
++ };
++ };
++ port@2 {
++ vin7_max9286_des1ep3: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep3>;
++ };
++ };
++ };
++};
++
++&csi2_40 {
++ status = "okay";
++
++ virtual,channel {
++ csi2_vc0 {
++ data,type = "ycbcr422";
++ receive,vc = <0>;
++ };
++ csi2_vc1 {
++ data,type = "ycbcr422";
++ receive,vc = <1>;
++ };
++ csi2_vc2 {
++ data,type = "ycbcr422";
++ receive,vc = <2>;
++ };
++ csi2_vc3 {
++ data,type = "ycbcr422";
++ receive,vc = <3>;
++ };
++ };
++
++ port {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ csi2_40_ep: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ csi-rate = <300>;
++ };
++ };
++};
++
++&csi2_41 {
++ status = "okay";
++
++ virtual,channel {
++ csi2_vc0 {
++ data,type = "ycbcr422";
++ receive,vc = <0>;
++ };
++ csi2_vc1 {
++ data,type = "ycbcr422";
++ receive,vc = <1>;
++ };
++ csi2_vc2 {
++ data,type = "ycbcr422";
++ receive,vc = <2>;
++ };
++ csi2_vc3 {
++ data,type = "ycbcr422";
++ receive,vc = <3>;
++ };
++ };
++
++ port {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ csi2_41_ep: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ csi-rate = <300>;
++ };
++ };
++};
+--
+1.9.1
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0033-arm64-dts-r8a7795-es1-h3ulcb-had-add-ADAS-board.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0033-arm64-dts-r8a7795-es1-h3ulcb-had-add-ADAS-board.patch
new file mode 100644
index 0000000..f8fb983
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0033-arm64-dts-r8a7795-es1-h3ulcb-had-add-ADAS-board.patch
@@ -0,0 +1,320 @@
+From 40240b74fe0b5c851127996328504e86a9fc4407 Mon Sep 17 00:00:00 2001
+From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+Date: Wed, 4 Jan 2017 10:41:48 +0300
+Subject: [PATCH] arm64: dts: r8a7795-es1-h3ulcb-had: add ADAS board
+
+H3ULCB.HAD board on R8A7795 ES1.x SoC
+
+Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+---
+ arch/arm64/boot/dts/renesas/Makefile | 1 +
+ .../dts/renesas/r8a7795-es1-h3ulcb-had-alfa.dts | 22 ++
+ .../dts/renesas/r8a7795-es1-h3ulcb-had-beta.dts | 23 +++
+ .../boot/dts/renesas/r8a7795-es1-h3ulcb-had.dtsi | 224 +++++++++++++++++++++
+ 4 files changed, 270 insertions(+)
+ create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-had-alfa.dts
+ create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-had-beta.dts
+ create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-had.dtsi
+
+diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile
+index 43aa35d..51a4ac9 100644
+--- a/arch/arm64/boot/dts/renesas/Makefile
++++ b/arch/arm64/boot/dts/renesas/Makefile
+@@ -7,6 +7,7 @@ dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-xs.dtb
+ # ADAS boards
+ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-salvator-x-view.dtb
+ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-h3ulcb-view.dtb
++dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-h3ulcb-had-alfa.dtb r8a7795-es1-h3ulcb-had-beta.dtb
+
+ always := $(dtb-y)
+ clean-files := *.dtb
+diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-had-alfa.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-had-alfa.dts
+new file mode 100644
+index 0000000..6b13f07
+--- /dev/null
++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-had-alfa.dts
+@@ -0,0 +1,22 @@
++/*
++ * Device Tree Source for the H3ULCB.HAD board Alfa side on r8a7795 ES1.x
++ *
++ * Copyright (C) 2017 Renesas Electronics Corp.
++ * Copyright (C) 2017 Cogent Embedded, Inc.
++ *
++ * This file is licensed under the terms of the GNU General Public License
++ * version 2. This program is licensed "as is" without any warranty of any
++ * kind, whether express or implied.
++ */
++
++#include "r8a7795-es1-h3ulcb-had.dtsi"
++
++/ {
++ model = "Renesas H3ULCB.HAD board Alfa side based on r8a7795";
++};
++
++&pciec0 {
++ status = "okay";
++
++ /* Root complex */
++};
+diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-had-beta.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-had-beta.dts
+new file mode 100644
+index 0000000..2f8b274
+--- /dev/null
++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-had-beta.dts
+@@ -0,0 +1,23 @@
++/*
++ * Device Tree Source for the H3ULCB.HAD board Beta side on r8a7795 ES1.x
++ *
++ * Copyright (C) 2017 Renesas Electronics Corp.
++ * Copyright (C) 2017 Cogent Embedded, Inc.
++ *
++ * This file is licensed under the terms of the GNU General Public License
++ * version 2. This program is licensed "as is" without any warranty of any
++ * kind, whether express or implied.
++ */
++
++#include "r8a7795-es1-h3ulcb-had.dtsi"
++
++/ {
++ model = "Renesas H3ULCB.HAD board Beta side based on r8a7795";
++};
++
++&pciec0 {
++ status = "okay";
++
++ /* Endpoint */
++ endpoint;
++};
+diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-had.dtsi b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-had.dtsi
+new file mode 100644
+index 0000000..d18ff37
+--- /dev/null
++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-had.dtsi
+@@ -0,0 +1,224 @@
++/*
++ * Device Tree Source for the H3ULCB.HAD board on r8a7795 ES1.x
++ *
++ * Copyright (C) 2016-2017 Renesas Electronics Corp.
++ * Copyright (C) 2016-2017 Cogent Embedded, Inc.
++ *
++ * This file is licensed under the terms of the GNU General Public License
++ * version 2. This program is licensed "as is" without any warranty of any
++ * kind, whether express or implied.
++ */
++
++/*
++ * MSIOF0 - /dev/spidev1.0 connected to FPGA ethernet switch (both sides)
++ * MSIOF1 - /dev/spidev2.0 connected to RH850 (sideA to CSIH1, sideB to CSIH0)
++ */
++
++#include "r8a7795-es1-h3ulcb-view.dts"
++
++/ {
++ model = "Renesas H3ULCB.HAD board based on r8a7795";
++
++ aliases {
++ spi1 = &spi0_gpio;
++ spi2 = &spi1_gpio;
++ };
++
++ chosen {
++ stdout-path = "serial1:115200n8";
++ };
++
++ spi0_gpio: spi_gpio@0 {
++ compatible = "spi-gpio";
++ num-chipselects = <1>;
++ gpio-sck = <&gpio5 17 0>;
++ gpio-mosi = <&gpio5 20 0>;
++ gpio-miso = <&gpio5 22 0>;
++ cs-gpios = <&gpio5 19 0>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ spidev@0 {
++ compatible = "spi-gpio";
++ reg = <0>;
++ spi-max-frequency = <2000000>;
++ spi-cpha;
++ spi-cpol;
++ };
++ };
++
++ spi1_gpio: spi_gpio@1 {
++ compatible = "spi-gpio";
++ num-chipselects = <1>;
++ gpio-sck = <&gpio6 8 0>;
++ gpio-mosi = <&gpio6 7 0>;
++ gpio-miso = <&gpio6 10 0>;
++ cs-gpios = <&gpio6 5 0>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ spidev@0 {
++ compatible = "spi-gpio";
++ reg = <0>;
++ spi-max-frequency = <2000000>;
++ spi-cpha;
++ spi-cpol;
++ };
++ };
++
++ hdmi1-out {
++ compatible = "hdmi-connector";
++ type = "a";
++
++ port {
++ hdmi1_con: endpoint {
++ remote-endpoint = <&rcar_dw_hdmi1_out>;
++ };
++ };
++ };
++};
++
++&du {
++ ports {
++ port@1 {
++ endpoint {
++ remote-endpoint = <&rcar_dw_hdmi0_in>;
++ };
++ };
++ port@2 {
++ endpoint {
++ remote-endpoint = <&rcar_dw_hdmi1_in>;
++ };
++ };
++ };
++};
++
++&hdmi1 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ port@0 {
++ reg = <0>;
++ rcar_dw_hdmi1_in: endpoint {
++ remote-endpoint = <&du_out_hdmi1>;
++ };
++ };
++ port@1 {
++ reg = <1>;
++ rcar_dw_hdmi1_out: endpoint {
++ remote-endpoint = <&hdmi1_con>;
++ };
++ };
++ };
++};
++
++&pfc {
++ scif1_pins: scif1 {
++ groups = "scif1_data_a";
++ function = "scif1";
++ };
++
++ msiof0_pins: spi1 {
++ groups = "msiof0_clk", "msiof0_rxd", "msiof0_txd",
++ "msiof0_ss1";
++ function = "msiof0";
++ };
++
++ msiof1_pins: spi2 {
++ groups = "msiof1_clk_a", "msiof1_rxd_a", "msiof1_txd_a",
++ "msiof1_ss1_a";
++ function = "msiof1";
++ };
++
++ sound_clk_pins: sound-clk {
++ groups = "audio_clk_a_a", "audio_clk_b_a", "audio_clk_c_a",
++ "audio_clkout_a" /*, "audio_clkout3_a"*/;
++ function = "audio_clk";
++ };
++
++ usb31_pins: usb31 {
++ groups = "usb31";
++ function = "usb31";
++ };
++
++ can0_pins: can0 {
++ groups = "can0_data_a";
++ function = "can0";
++ };
++
++ canfd0_pins: canfd0 {
++ groups = "canfd0_data_a";
++ function = "canfd0";
++ };
++};
++
++&scif1 {
++ pinctrl-0 = <&scif1_pins>;
++ pinctrl-names = "default";
++ status = "okay";
++};
++
++&avb {
++ /delete-property/phy-handle;
++ /delete-property/phy-gpios;
++ /delete-node/ethernet-phy@0;
++
++ fixed-link {
++ speed = <1000>;
++ full-duplex;
++ };
++};
++
++&msiof0 {
++ pinctrl-0 = <&msiof0_pins>;
++ pinctrl-names = "default";
++ status = "disabled";
++ cs-gpios = <&gpio5 19 0>;
++
++ spidev@0 {
++ compatible = "renesas,sh-msiof";
++ reg = <0>;
++ spi-max-frequency = <66666666>;
++ spi-cpha;
++ spi-cpol;
++ };
++};
++
++&msiof1 {
++ status = "disabled";
++ cs-gpios = <&gpio6 5 0>;
++};
++
++&can0 {
++ pinctrl-0 = <&can0_pins>;
++ pinctrl-names = "default";
++ status = "disabled";
++
++ renesas,can-clock-select = <0x0>;
++ gpios = <&gpio2 6 GPIO_ACTIVE_HIGH /* enable - shared with camera board */
++ &gpio2 7 GPIO_ACTIVE_LOW /* standby */
++ >;
++};
++
++&canfd {
++ pinctrl-0 = <&canfd0_pins>;
++ pinctrl-names = "default";
++ status = "okay";
++
++ renesas,can-clock-select = <0x0>;
++ gpios = <&gpio2 6 GPIO_ACTIVE_HIGH /* enable - shared with camera board */
++ &gpio2 7 GPIO_ACTIVE_LOW /* standby */
++ >;
++
++ channel0 {
++ status = "okay";
++ };
++};
++
++&xhci1 {
++ status = "okay";
++ pinctrl-0 = <&usb31_pins>;
++ pinctrl-names = "default";
++};
+--
+1.9.1
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0034-arm64-dts-r8a7795-es1-h3ulcb-kf-add-ADAS-board.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0034-arm64-dts-r8a7795-es1-h3ulcb-kf-add-ADAS-board.patch
new file mode 100644
index 0000000..985863a
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0034-arm64-dts-r8a7795-es1-h3ulcb-kf-add-ADAS-board.patch
@@ -0,0 +1,1718 @@
+From f0f043eab3dd06552b3600af1caf50e535f766f1 Mon Sep 17 00:00:00 2001
+From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+Date: Wed, 4 Jan 2017 10:37:23 +0300
+Subject: [PATCH] arm64: dts: r8a7795-es1-h3ulcb-kf: add ADAS board
+
+H3ULCB.View board on R8A7795 ES1.x SoC
+
+Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+---
+ arch/arm64/boot/dts/renesas/Makefile | 1 +
+ .../boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts | 1683 ++++++++++++++++++++
+ 2 files changed, 1684 insertions(+)
+ create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts
+
+diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile
+index 06207e3..a5dd1d3 100644
+--- a/arch/arm64/boot/dts/renesas/Makefile
++++ b/arch/arm64/boot/dts/renesas/Makefile
+@@ -10,6 +10,7 @@ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-h3ulcb-view.dtb
+ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-salvator-x-view.dtb
+ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-h3ulcb-view.dtb
+ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-h3ulcb-had-alfa.dtb r8a7795-es1-h3ulcb-had-beta.dtb
++dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-h3ulcb-kf.dtb
+
+ always := $(dtb-y)
+ clean-files := *.dtb
+diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts
+new file mode 100644
+index 0000000..50a37e0
+--- /dev/null
++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts
+@@ -0,0 +1,1683 @@
++/*
++ * Device Tree Source for the H3ULCB Kingfisher board on r8a7795 ES1.x
++ *
++ * Copyright (C) 2017 Renesas Electronics Corp.
++ * Copyright (C) 2017 Cogent Embedded, Inc.
++ *
++ * This file is licensed under the terms of the GNU General Public License
++ * version 2. This program is licensed "as is" without any warranty of any
++ * kind, whether express or implied.
++ */
++
++#include "r8a7795-es1-h3ulcb.dts"
++
++/ {
++ model = "Renesas H3ULCB Kingfisher board based on r8a7795";
++
++ aliases {
++ serial1 = &hscif4;
++ };
++
++ snd_clk: snd_clk {
++ compatible = "fixed-clock";
++ #clock-cells = <0>;
++ clock-frequency = <24576000>;
++ clock-output-names = "scki";
++ };
++
++ wlan_en: regulator@4 {
++ compatible = "regulator-fixed";
++ regulator-name = "wlan-en-regulator";
++
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++
++ gpio = <&gpio_ext_20 4 GPIO_ACTIVE_HIGH>;
++ enable-active-high;
++ };
++
++ vccq_sdhi3: regulator@5 {
++ compatible = "regulator-fixed";
++
++ regulator-name = "SDHI3 VccQ";
++ /* external voltage translator to 1.8V */
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ };
++
++ codec_en_reg: regulator@6 {
++ compatible = "regulator-fixed";
++ regulator-name = "codec-en-regulator";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++
++ gpio = <&gpio_ext_20 15 0>;
++
++ /* delay - CHECK */
++ startup-delay-us = <70000>;
++ enable-active-high;
++ };
++
++ amp_en_reg: regulator@7 {
++ compatible = "regulator-fixed";
++ regulator-name = "amp-en-regulator";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++
++ gpio = <&gpio_ext_20 0 0>;
++
++ startup-delay-us = <0>;
++ enable-active-high;
++ };
++
++ lvds_switch: regulator@8 {
++ compatible = "regulator-fixed";
++ regulator-name = "lvds_on";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ gpio = <&gpio1 24 0>;
++ enable-active-high;
++ regulator-always-on;
++ };
++
++ sdio_switch: regulator@9 {
++ compatible = "regulator-fixed";
++ regulator-name = "wifi_on";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ gpio = <&gpio_ext_20 5 0>;
++ enable-active-low;
++ regulator-always-on;
++ };
++
++ sound_switch: regulator@10 {
++ compatible = "regulator-fixed";
++ regulator-name = "pcm3168a_on";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ gpio = <&gpio_ext_21 5 0>;
++ enable-active-low;
++ regulator-always-on;
++ };
++
++ radio_switch: regulator@11 {
++ compatible = "regulator-fixed";
++ regulator-name = "radio_on";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ gpio = <&gpio_ext_20 13 GPIO_ACTIVE_HIGH>;
++ enable-active-high;
++ regulator-always-on;
++ };
++
++ kim {
++ compatible = "kim";
++ nshutdown_gpio = <343>; /* pca9535@i2c2.0x20 pin 3 */
++ /* serial1 */
++ dev_name = "/dev/ttySC1";
++ flow_cntrl = <1>;
++ /* int div 8 hscif@26.6666656MHz */
++ baud_rate = <3333332>;
++ };
++
++ btwilink {
++ compatible = "btwilink";
++ };
++
++ sound_ext: sound@0 {
++ pinctrl-0 = <&sound_0_pins>;
++ pinctrl-names = "default";
++ compatible = "simple-audio-card";
++
++ simple-audio-card,format = "left_j";
++ simple-audio-card,name = "pcm3168a";
++
++ simple-audio-card,bitclock-master = <&sound_ext_master>;
++ simple-audio-card,frame-master = <&sound_ext_master>;
++ sound_ext_master: simple-audio-card,cpu@0 {
++ sound-dai = <&rcar_sound 0>;
++ dai-tdm-slot-num = <8>;
++ dai-tdm-slot-width = <32>;
++ };
++
++ simple-audio-card,codec@0 {
++ sound-dai = <&pcm3168a>;
++ dai-tdm-slot-num = <8>;
++ dai-tdm-slot-width = <32>;
++ system-clock-frequency = <24576000>;
++ };
++ };
++
++ /delete-node/sound;
++
++ rsnd_ak4613: sound@1 {
++ pinctrl-0 = <&sound_1_pins>;
++ pinctrl-names = "default";
++ compatible = "simple-audio-card";
++
++ simple-audio-card,format = "left_j";
++ simple-audio-card,name = "ak4613";
++
++ simple-audio-card,bitclock-master = <&sndcpu>;
++ simple-audio-card,frame-master = <&sndcpu>;
++
++ sndcpu: simple-audio-card,cpu@1 {
++ sound-dai = <&rcar_sound 1>;
++ };
++
++ sndcodec: simple-audio-card,codec@1 {
++ sound-dai = <&ak4613>;
++ };
++ };
++
++ sound_radio: sound@2 {
++ pinctrl-0 = <&sound_2_pins>;
++ pinctrl-names = "default";
++ compatible = "simple-audio-card";
++
++ simple-audio-card,format = "i2s";
++ simple-audio-card,name = "radio";
++
++ simple-audio-card,bitclock-master = <&sound_radio_master>;
++ simple-audio-card,frame-master = <&sound_radio_master>;
++ simple-audio-card,cpu@2 {
++ sound-dai = <&rcar_sound 2>;
++ };
++
++ sound_radio_master: simple-audio-card,codec@2 {
++ sound-dai = <&radio>;
++ system-clock-frequency = <12288000>;
++ };
++ };
++
++ sound_amp: sound@3 {
++ pinctrl-0 = <&sound_9_pins>;
++ pinctrl-names = "default";
++ compatible = "simple-audio-card";
++
++ simple-audio-card,name = "power_amp";
++
++ simple-audio-card,dai-link@0 {
++ format = "i2s";
++ cpu {
++ sound-dai = <&rcar_sound 3>;
++ };
++ codec {
++ sound-dai = <&max98371_L>;
++ };
++ };
++ simple-audio-card,dai-link@1 {
++ format = "i2s";
++ cpu {
++ sound-dai = <&rcar_sound 3>;
++ };
++ codec {
++ sound-dai = <&max98371_R>;
++ };
++ };
++ simple-audio-card,dai-link@2 {
++ format = "i2s";
++ cpu {
++ sound-dai = <&rcar_sound 3>;
++ };
++ codec {
++ sound-dai = <&max98371_RL>;
++ };
++ };
++ simple-audio-card,dai-link@3 {
++ format = "i2s";
++ cpu {
++ sound-dai = <&rcar_sound 3>;
++ };
++ codec {
++ sound-dai = <&max98371_RR>;
++ };
++ };
++ simple-audio-card,dai-link@4 {
++ format = "i2s";
++ cpu {
++ sound-dai = <&rcar_sound 3>;
++ };
++ codec {
++ sound-dai = <&max98371_C>;
++ };
++ };
++ simple-audio-card,dai-link@5 {
++ format = "i2s";
++ cpu {
++ sound-dai = <&rcar_sound 3>;
++ };
++ codec {
++ sound-dai = <&max98371_S>;
++ };
++ };
++ };
++
++ lvds-encoder {
++ compatible = "thine,thc63lvdm83d";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ port@0 {
++ reg = <0>;
++ lvds_enc_in: endpoint {
++ remote-endpoint = <&du_out_lvds0>;
++ };
++ };
++ port@1 {
++ reg = <1>;
++ lvds_enc_out: endpoint {
++ remote-endpoint = <&lvds_in>;
++ };
++ };
++ };
++ };
++
++ lvds {
++ compatible = "lvds-connector";
++
++ width-mm = <210>;
++ height-mm = <158>;
++
++ panel-timing {
++ /* 1280x800 @60Hz */
++ clock-frequency = <65000000>;
++ hactive = <1280>;
++ vactive = <800>;
++ hsync-len = <40>;
++ hfront-porch = <80>;
++ hback-porch = <40>;
++ vfront-porch = <14>;
++ vback-porch = <14>;
++ vsync-len = <4>;
++ };
++
++ port {
++ lvds_in: endpoint {
++ remote-endpoint = <&lvds_enc_out>;
++ };
++ };
++ };
++
++ radio: si468x@0 {
++ compatible = "si,si468x-pcm";
++ status = "okay";
++
++ #sound-dai-cells = <0>;
++ };
++};
++
++&pfc {
++ hscif4_pins: hscif4 {
++ groups = "hscif4_data_a", "hscif4_ctrl";
++ function = "hscif4";
++ };
++
++ sdhi3_pins_3v3: sd3_3v3 {
++ groups = "sdhi3_data4", "sdhi3_ctrl";
++ function = "sdhi3";
++ power-source = <3300>;
++ };
++
++ sound_0_pins: sound0 {
++ groups = "ssi78_ctrl", "ssi7_data", "ssi8_data";
++ function = "ssi";
++ };
++
++ sound_1_pins: sound1 {
++ groups = "ssi01239_ctrl", "ssi0_data", "ssi1_data_a";
++ function = "ssi";
++ };
++
++ sound_2_pins: sound2 {
++ groups = "ssi6_ctrl", "ssi6_data";
++ function = "ssi";
++ };
++
++ sound_9_pins: sound2 {
++ groups = "ssi9_ctrl_b", "ssi9_data_b";
++ function = "ssi";
++ };
++
++ usb0_pins: usb0 {
++ groups = "usb0";
++ function = "usb0";
++ };
++};
++
++&gpio0 {
++ video_a_irq {
++ gpio-hog;
++ gpios = <13 GPIO_ACTIVE_HIGH>;
++ input;
++ line-name = "Video-A irq";
++ };
++
++ video_b_irq {
++ gpio-hog;
++ gpios = <14 GPIO_ACTIVE_HIGH>;
++ input;
++ line-name = "Video-B irq";
++ };
++
++ gpioext_2_20_irq {
++ gpio-hog;
++ gpios = <15 GPIO_ACTIVE_HIGH>;
++ input;
++ line-name = "0x20@i2c2 irq";
++ };
++};
++
++&gpio1 {
++ gpioext_2_21_irq {
++ gpio-hog;
++ gpios = <15 GPIO_ACTIVE_HIGH>;
++ input;
++ line-name = "0x21@i2c2 irq";
++ };
++
++ wifi_irq {
++ gpio-hog;
++ gpios = <25 GPIO_ACTIVE_HIGH>;
++ input;
++ line-name = "wifi irq";
++ };
++};
++
++&gpio5 {
++ touch_irq {
++ gpio-hog;
++ gpios = <6 GPIO_ACTIVE_HIGH>;
++ input;
++ line-name = "touch irq";
++ };
++
++ /* From TI forum */
++ /* BT_AUD_OUT should be pulled low when WL_EN is activated. */
++ /* in case it isn't, wilink8 ends up in one of the test modes that introduces various issues */
++ bt_strap {
++ gpio-hog;
++ gpios = <14 GPIO_ACTIVE_HIGH>;
++ output-low;
++ line-name = "BT strap pin";
++ };
++};
++
++&gpio7 {
++ gpioext_2_21_irq {
++ gpio-hog;
++ gpios = <3 GPIO_ACTIVE_HIGH>;
++ input;
++ line-name = "0x21@i2c4 irq";
++ };
++};
++
++&hscif4 {
++ pinctrl-0 = <&hscif4_pins>;
++ pinctrl-names = "default";
++ ctsrts;
++
++ status = "okay";
++};
++
++&i2c2 {
++ clock-frequency = <400000>;
++
++ gpio_ext_20: pca9535@20 {
++ compatible = "nxp,pca9535";
++ reg = <0x20>;
++ gpio-controller;
++ #gpio-cells = <2>;
++ interrupt-controller;
++ interrupt-parent = <&gpio0>;
++ interrupts = <15 IRQ_TYPE_EDGE_FALLING>;
++ };
++
++ gpio_ext_21: pca9535@21 {
++ compatible = "nxp,pca9535";
++ reg = <0x21>;
++ gpio-controller;
++ #gpio-cells = <2>;
++ interrupt-controller;
++ interrupt-parent = <&gpio1>;
++ interrupts = <15 IRQ_TYPE_EDGE_FALLING>;
++ };
++
++ i2cswitch2@74 {
++ compatible = "nxp,pca9548";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <0x74>;
++ reset-gpios = <&gpio6 5 GPIO_ACTIVE_LOW>;
++
++ i2c@0 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <0>;
++ /* BCM node(s) */
++ };
++
++ i2c@1 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <1>;
++ /* USB3.0 HUB node(s) */
++ };
++
++ i2c@2 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <2>;
++ /* Power amp node(s) */
++
++ max98371_L: max98371@0x31 {
++ compatible = "maxim,max98371";
++ reg = <0x31>;
++ #sound-dai-cells = <0>;
++ };
++ max98371_R: max98371@0x32 {
++ compatible = "maxim,max98371";
++ reg = <0x32>;
++ #sound-dai-cells = <0>;
++ };
++ max98371_RL: max98371@0x33 {
++ compatible = "maxim,max98371";
++ reg = <0x33>;
++ #sound-dai-cells = <0>;
++ };
++ max98371_RR: max98371@0x34 {
++ compatible = "maxim,max98371";
++ reg = <0x34>;
++ #sound-dai-cells = <0>;
++ };
++ max98371_C: max98371@0x35 {
++ compatible = "maxim,max98371";
++ reg = <0x35>;
++ #sound-dai-cells = <0>;
++ };
++ max98371_S: max98371@0x36 {
++ compatible = "maxim,max98371";
++ reg = <0x36>;
++ #sound-dai-cells = <0>;
++ };
++ };
++
++ i2c@3 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <3>;
++ /* Radio node(s) */
++ };
++
++ i2c@4 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <4>;
++ /* A2B node(s) */
++ };
++
++ i2c@5 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <5>;
++ /* PCIe node(s) */
++ };
++
++ i2c@6 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <6>;
++ /* LVDS display node(s) */
++
++ polytouch: edt-ft5x06@38 {
++ compatible = "edt,edt-ft5x06";
++ reg = <0x38>;
++ interrupt-parent = <&gpio5>;
++ interrupts = <6 IRQ_TYPE_EDGE_FALLING>;
++ };
++ };
++
++ i2c@7 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <7>;
++ /* Audio, GPS and Gyro node(s) */
++
++ pcm3168a: audio-codec@44 {
++ #sound-dai-cells = <0>;
++ compatible = "ti,pcm3168a";
++ reg = <0x44>;
++ clocks = <&snd_clk>;
++ clock-names = "scki";
++ tdm;
++ VDD1-supply = <&codec_en_reg>;
++ VDD2-supply = <&codec_en_reg>;
++ VCCAD1-supply = <&codec_en_reg>;
++ VCCAD2-supply = <&codec_en_reg>;
++ VCCDA1-supply = <&amp_en_reg>;
++ VCCDA2-supply = <&amp_en_reg>;
++ };
++
++ lsm9ds0_acc_mag@1d {
++ compatible = "st,lsm9ds0_acc_mag";
++ reg = <0x1d>;
++ };
++
++ lsm9ds0_gyr@6b {
++ compatible = "st,lsm9ds0-gyro";
++ reg = <0x6b>;
++ };
++
++ /* GPS@ 0x42 */
++ };
++ };
++};
++
++&i2c4 {
++ gpio_ext_22: pca9535@21 {
++ compatible = "nxp,pca9535";
++ reg = <0x22>;
++ gpio-controller;
++ #gpio-cells = <2>;
++ interrupt-controller;
++ interrupt-parent = <&gpio7>;
++ interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
++ };
++
++ i2cswitch4@74 {
++ compatible = "nxp,pca9548";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <0x74>;
++ reset-gpios= <&gpio6 21 GPIO_ACTIVE_LOW>;
++
++ i2c@0 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <0>;
++ /* SAM node(s) */
++ };
++
++ i2c@1 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <1>;
++ /* Video input "A" acc node(s) */
++
++ ov106xx@0 {
++ compatible = "ovti,ov106xx";
++ reg = <0x60>;
++
++ port@0 {
++ ov106xx_in0: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin0ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des0ep0: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep0>;
++ };
++ ov106xx_ti964_des0ep0: endpoint@1 {
++ remote-endpoint = <&ti964_des0ep0>;
++ };
++ ov106xx_ti954_des0ep0: endpoint@2 {
++ remote-endpoint = <&ti954_des0ep0>;
++ };
++ };
++ };
++
++ ov106xx@1 {
++ compatible = "ovti,ov106xx";
++ reg = <0x61>;
++
++ port@0 {
++ ov106xx_in1: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin1ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des0ep1: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep1>;
++ };
++ ov106xx_ti964_des0ep1: endpoint@1 {
++ remote-endpoint = <&ti964_des0ep1>;
++ };
++ ov106xx_ti954_des0ep1: endpoint@2 {
++ remote-endpoint = <&ti954_des0ep1>;
++ };
++ };
++ };
++
++ ov106xx@2 {
++ compatible = "ovti,ov106xx";
++ reg = <0x62>;
++
++ port@0 {
++ ov106xx_in2: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin2ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des0ep2: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep2>;
++ };
++ ov106xx_ti964_des0ep2: endpoint@1 {
++ remote-endpoint = <&ti964_des0ep2>;
++ };
++ };
++ };
++
++ ov106xx@3 {
++ compatible = "ovti,ov106xx";
++ reg = <0x63>;
++
++ port@0 {
++ ov106xx_in3: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin3ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des0ep3: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep3>;
++ };
++ ov106xx_ti964_des0ep3: endpoint@1 {
++ remote-endpoint = <&ti964_des0ep3>;
++ };
++ };
++ };
++
++ /* DS90UB964 @ 0x3a */
++ ti964-ti9x3@0 {
++ compatible = "ti,ti964-ti9x3";
++ reg = <0x3a>;
++ ti,sensor_delay = <350>;
++ ti,links = <4>;
++ ti,lanes = <4>;
++ ti,forwarding-mode = "round-robin";
++ ti,cable-mode = "coax";
++
++ port@0 {
++ ti964_des0ep0: endpoint@0 {
++ ti9x3-addr = <0x0c>;
++ dvp-order = <0>;
++ remote-endpoint = <&ov106xx_in0>;
++ };
++ ti964_des0ep1: endpoint@1 {
++ ti9x3-addr = <0x0d>;
++ dvp-order = <0>;
++ remote-endpoint = <&ov106xx_in1>;
++ };
++ ti964_des0ep2: endpoint@2 {
++ ti9x3-addr = <0x0e>;
++ dvp-order = <0>;
++ remote-endpoint = <&ov106xx_in2>;
++ };
++ ti964_des0ep3: endpoint@3 {
++ ti9x3-addr = <0x0f>;
++ dvp-order = <0>;
++ remote-endpoint = <&ov106xx_in3>;
++ };
++ };
++ port@1 {
++ ti964_csi0ep0: endpoint {
++ csi-rate = <1450>;
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ };
++
++ /* DS90UB954 @ 0x38 */
++ ti954-ti9x3@0 {
++ compatible = "ti,ti954-ti9x3";
++ reg = <0x38>;
++ gpios = <&video_a_ext1 10 GPIO_ACTIVE_HIGH>;
++ ti,sensor_delay = <350>;
++ ti,links = <2>;
++ ti,lanes = <4>;
++ ti,forwarding-mode = "round-robin";
++ ti,cable-mode = "coax";
++
++ port@0 {
++ ti954_des0ep0: endpoint@0 {
++ ti9x3-addr = <0x0c>;
++ dvp-order = <0>;
++ remote-endpoint = <&ov106xx_in0>;
++ };
++ ti954_des0ep1: endpoint@1 {
++ ti9x3-addr = <0x0d>;
++ dvp-order = <0>;
++ remote-endpoint = <&ov106xx_in1>;
++ };
++ };
++ port@1 {
++ ti954_csi0ep0: endpoint {
++ csi-rate = <1450>;
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ };
++
++ /* MAX9286 @ 0x2a */
++ max9286-max9271@0 {
++ compatible = "maxim,max9286-max9271";
++ reg = <0x2a>;
++ maxim,sensor_delay = <350>;
++ maxim,links = <4>;
++ maxim,lanes = <4>;
++ maxim,resetb-gpio = <1>;
++ maxim,fsync-mode = "automatic";
++ maxim,timeout = <100>;
++
++ port@0 {
++ max9286_des0ep0: endpoint@0 {
++ max9271-addr = <0x50>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in0>;
++ };
++ max9286_des0ep1: endpoint@1 {
++ max9271-addr = <0x51>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in1>;
++ };
++ max9286_des0ep2: endpoint@2 {
++ max9271-addr = <0x52>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in2>;
++ };
++ max9286_des0ep3: endpoint@3 {
++ max9271-addr = <0x53>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in3>;
++ };
++ };
++ port@1 {
++ max9286_csi0ep0: endpoint {
++ csi-rate = <700>;
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ };
++ };
++
++ i2c@2 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <2>;
++ /* Video input "B" acc node(s) */
++
++ ov106xx@4 {
++ compatible = "ovti,ov106xx";
++ reg = <0x64>;
++
++ port@0 {
++ ov106xx_in4: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin4ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des1ep0: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep0>;
++ };
++ ov106xx_ti964_des1ep0: endpoint@1 {
++ remote-endpoint = <&ti964_des1ep0>;
++ };
++ ov106xx_ti954_des1ep0: endpoint@2 {
++ remote-endpoint = <&ti954_des1ep0>;
++ };
++ };
++ };
++
++ ov106xx@5 {
++ compatible = "ovti,ov106xx";
++ reg = <0x65>;
++
++ port@0 {
++ ov106xx_in5: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin5ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des1ep1: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep1>;
++ };
++ ov106xx_ti964_des1ep1: endpoint@1 {
++ remote-endpoint = <&ti964_des1ep1>;
++ };
++ ov106xx_ti954_des1ep1: endpoint@2 {
++ remote-endpoint = <&ti954_des1ep1>;
++ };
++ };
++ };
++
++ ov106xx@6 {
++ compatible = "ovti,ov106xx";
++ reg = <0x66>;
++
++ port@0 {
++ ov106xx_in6: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin6ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des1ep2: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep2>;
++ };
++ ov106xx_ti964_des1ep2: endpoint@1 {
++ remote-endpoint = <&ti964_des1ep2>;
++ };
++ };
++ };
++
++ ov106xx@7 {
++ compatible = "ovti,ov106xx";
++ reg = <0x67>;
++
++ port@0 {
++ ov106xx_in7: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin7ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des1ep3: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep3>;
++ };
++ ov106xx_ti964_des1ep3: endpoint@1 {
++ remote-endpoint = <&ti964_des1ep3>;
++ };
++ };
++ };
++
++ /* DS90UB964 @ 0x3a */
++ ti964-ti9x3@1 {
++ compatible = "ti,ti964-ti9x3";
++ reg = <0x3a>;
++ ti,sensor_delay = <350>;
++ ti,links = <4>;
++ ti,lanes = <4>;
++ ti,forwarding-mode = "round-robin";
++ ti,cable-mode = "coax";
++
++ port@0 {
++ ti964_des1ep0: endpoint@0 {
++ ti9x3-addr = <0x0c>;
++ dvp-order = <0>;
++ remote-endpoint = <&ov106xx_in4>;
++ };
++ ti964_des1ep1: endpoint@1 {
++ ti9x3-addr = <0x0d>;
++ dvp-order = <0>;
++ remote-endpoint = <&ov106xx_in5>;
++ };
++ ti964_des1ep2: endpoint@2 {
++ ti9x3-addr = <0x0e>;
++ dvp-order = <0>;
++ remote-endpoint = <&ov106xx_in6>;
++ };
++ ti964_des1ep3: endpoint@3 {
++ ti9x3-addr = <0x0f>;
++ dvp-order = <0>;
++ remote-endpoint = <&ov106xx_in7>;
++ };
++ };
++ port@1 {
++ ti964_csi2ep0: endpoint {
++ csi-rate = <1450>;
++ remote-endpoint = <&csi2_41_ep>;
++ };
++ };
++ };
++
++ /* DS90UB954 @ 0x38 */
++ ti954-ti9x3@1 {
++ compatible = "ti,ti954-ti9x3";
++ reg = <0x38>;
++ gpios = <&video_b_ext1 10 GPIO_ACTIVE_HIGH>;
++ ti,sensor_delay = <350>;
++ ti,links = <2>;
++ ti,lanes = <4>;
++ ti,forwarding-mode = "round-robin";
++ ti,cable-mode = "coax";
++
++ port@0 {
++ ti954_des1ep0: endpoint@0 {
++ ti9x3-addr = <0x0c>;
++ dvp-order = <0>;
++ remote-endpoint = <&ov106xx_in4>;
++ };
++ ti954_des1ep1: endpoint@1 {
++ ti9x3-addr = <0x0d>;
++ dvp-order = <0>;
++ remote-endpoint = <&ov106xx_in5>;
++ };
++ };
++ port@1 {
++ ti954_csi2ep0: endpoint {
++ csi-rate = <1450>;
++ remote-endpoint = <&csi2_41_ep>;
++ };
++ };
++ };
++
++ /* MAX9286 @ 0x2a */
++ max9286-max9271@1 {
++ compatible = "maxim,max9286-max9271";
++ reg = <0x2a>;
++ maxim,sensor_delay = <350>;
++ maxim,links = <4>;
++ maxim,lanes = <4>;
++ maxim,resetb-gpio = <1>;
++ maxim,fsync-mode = "automatic";
++ maxim,timeout = <100>;
++
++ port@0 {
++ max9286_des1ep0: endpoint@0 {
++ max9271-addr = <0x50>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in4>;
++ };
++ max9286_des1ep1: endpoint@1 {
++ max9271-addr = <0x51>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in5>;
++ };
++ max9286_des1ep2: endpoint@2 {
++ max9271-addr = <0x52>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in6>;
++ };
++ max9286_des1ep3: endpoint@3 {
++ max9271-addr = <0x53>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in7>;
++ };
++ };
++ port@1 {
++ max9286_csi2ep0: endpoint {
++ csi-rate = <700>;
++ remote-endpoint = <&csi2_41_ep>;
++ };
++ };
++ };
++ };
++
++ i2c@3 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <3>;
++ /* MOST node(s) */
++ };
++
++ i2c@4 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <4>;
++ /* CSI camera node(s) */
++ };
++
++ i2c@5 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <5>;
++ /* CMOS camera node(s) */
++ };
++
++ i2c@6 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <6>;
++ /* Video input "B" main node(s) */
++
++ video_b_ext0: pca9535@27 {
++ compatible = "nxp,pca9535";
++ reg = <0x27>;
++ gpio-controller;
++ #gpio-cells = <2>;
++
++ video_b_des_cfg1 {
++ gpio-hog;
++ gpios = <5 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-B cfg1";
++ };
++ video_b_des_cfg0 {
++ gpio-hog;
++ gpios = <6 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-B cfg0";
++ };
++ video_b_pwr_shdn {
++ gpio-hog;
++ gpios = <3 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-B PWR_SHDN";
++ };
++ video_b_cam_pwr0 {
++ gpio-hog;
++ gpios = <12 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-B PWR0";
++ };
++ video_b_cam_pwr1 {
++ gpio-hog;
++ gpios = <13 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-B PWR1";
++ };
++ video_b_cam_pwr2 {
++ gpio-hog;
++ gpios = <14 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-B PWR2";
++ };
++ video_b_cam_pwr3 {
++ gpio-hog;
++ gpios = <15 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-B PWR3";
++ };
++ video_b_des_shdn {
++ gpio-hog;
++ gpios = <4 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-B DES_SHDN";
++ };
++ video_b_des_led {
++ gpio-hog;
++ gpios = <7 GPIO_ACTIVE_HIGH>;
++ output-low;
++ line-name = "Video-B led";
++ };
++ };
++
++ video_b_ext1: max7325@5c {
++ compatible = "maxim,max7325";
++ reg = <0x5c>;
++ gpio-controller;
++ #gpio-cells = <2>;
++
++ video_b_des_cfg2 {
++ gpio-hog;
++ gpios = <4 GPIO_ACTIVE_HIGH>;
++ output-low;
++ line-name = "Video-B cfg2";
++ };
++ video_b_des_cfg1 {
++ gpio-hog;
++ gpios = <6 GPIO_ACTIVE_HIGH>;
++ output-low;
++ line-name = "Video-B cfg1";
++ };
++ video_b_des_cfg0 {
++ gpio-hog;
++ gpios = <7 GPIO_ACTIVE_HIGH>;
++ output-low;
++ line-name = "Video-B cfg0";
++ };
++ video_b_pwr_shdn {
++ gpio-hog;
++ gpios = <14 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-B PWR_SHDN";
++ };
++ video_b_cam_pwr0 {
++ gpio-hog;
++ gpios = <8 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-B PWR0";
++ };
++ video_b_cam_pwr1 {
++ gpio-hog;
++ gpios = <9 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-B PWR1";
++ };
++ };
++ };
++
++ i2c@7 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <7>;
++ /* Video input "A" main node(s) */
++
++ video_a_ext0: pca9535@26 {
++ compatible = "nxp,pca9535";
++ reg = <0x26>;
++ gpio-controller;
++ #gpio-cells = <2>;
++
++ video_a_des_cfg1 {
++ gpio-hog;
++ gpios = <5 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-A cfg1";
++ };
++ video_a_des_cfg0 {
++ gpio-hog;
++ gpios = <6 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-A cfg0";
++ };
++ video_a_pwr_shdn {
++ gpio-hog;
++ gpios = <3 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-A PWR_SHDN";
++ };
++ video_a_cam_pwr0 {
++ gpio-hog;
++ gpios = <12 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-A PWR0";
++ };
++ video_a_cam_pwr1 {
++ gpio-hog;
++ gpios = <13 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-A PWR1";
++ };
++ video_a_cam_pwr2 {
++ gpio-hog;
++ gpios = <14 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-A PWR2";
++ };
++ video_a_cam_pwr3 {
++ gpio-hog;
++ gpios = <15 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-A PWR3";
++ };
++ video_a_des_shdn {
++ gpio-hog;
++ gpios = <4 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-A DES_SHDN";
++ };
++ video_a_des_led {
++ gpio-hog;
++ gpios = <7 GPIO_ACTIVE_HIGH>;
++ output-low;
++ line-name = "Video-A led";
++ };
++ };
++
++ video_a_ext1: max7325@5c {
++ compatible = "maxim,max7325";
++ reg = <0x5c>;
++ gpio-controller;
++ #gpio-cells = <2>;
++
++ video_a_des_cfg2 {
++ gpio-hog;
++ gpios = <4 GPIO_ACTIVE_HIGH>;
++ output-low;
++ line-name = "Video-A cfg2";
++ };
++ video_a_des_cfg1 {
++ gpio-hog;
++ gpios = <6 GPIO_ACTIVE_HIGH>;
++ output-low;
++ line-name = "Video-A cfg1";
++ };
++ video_a_des_cfg0 {
++ gpio-hog;
++ gpios = <7 GPIO_ACTIVE_HIGH>;
++ output-low;
++ line-name = "Video-A cfg0";
++ };
++ video_a_pwr_shdn {
++ gpio-hog;
++ gpios = <14 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-A PWR_SHDN";
++ };
++ video_a_cam_pwr0 {
++ gpio-hog;
++ gpios = <8 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-A PWR0";
++ };
++ video_a_cam_pwr1 {
++ gpio-hog;
++ gpios = <9 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-A PWR1";
++ };
++ };
++ };
++ };
++};
++
++&pcie_bus_clk {
++ clock-frequency = <100000000>;
++ status = "okay";
++};
++
++&pciec0 {
++ status = "okay";
++};
++
++&pciec1 {
++ status = "okay";
++};
++
++&vin0 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin0ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in0>;
++ };
++ };
++ port@1 {
++ csi0ep0: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin0_max9286_des0ep0: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep0>;
++ };
++ vin0_ti964_des0ep0: endpoint@1 {
++ remote-endpoint = <&ti964_des0ep0>;
++ };
++ vin0_ti954_des0ep0: endpoint@2 {
++ remote-endpoint = <&ti954_des0ep0>;
++ };
++ };
++ };
++};
++
++&vin1 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin1ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <1>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in1>;
++ };
++ };
++ port@1 {
++ csi0ep1: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin1_max9286_des0ep1: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep1>;
++ };
++ vin1_ti964_des0ep1: endpoint@1 {
++ remote-endpoint = <&ti964_des0ep1>;
++ };
++ vin1_ti954_des0ep1: endpoint@2 {
++ remote-endpoint = <&ti954_des0ep1>;
++ };
++ };
++ };
++};
++
++&vin2 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin2ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <2>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in2>;
++ };
++ };
++ port@1 {
++ csi0ep2: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin2_max9286_des0ep2: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep2>;
++ };
++ vin2_ti964_des0ep2: endpoint@1 {
++ remote-endpoint = <&ti964_des0ep2>;
++ };
++ };
++ };
++};
++
++&vin3 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin3ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <3>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in3>;
++ };
++ };
++ port@1 {
++ csi0ep3: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin3_max9286_des0ep3: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep3>;
++ };
++ vin3_ti964_des0ep3: endpoint@1 {
++ remote-endpoint = <&ti964_des0ep3>;
++ };
++ };
++ };
++};
++
++&vin4 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin4ep0: endpoint {
++ csi,select = "csi41";
++ virtual,channel = <0>;
++ remote-endpoint = <&ov106xx_in4>;
++ data-lanes = <1 2 3 4>;
++ };
++ };
++ port@1 {
++ csi2ep0: endpoint {
++ remote-endpoint = <&csi2_41_ep>;
++ };
++ };
++ port@2 {
++ vin4_max9286_des1ep0: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep0>;
++ };
++ vin4_ti964_des1ep0: endpoint@1 {
++ remote-endpoint = <&ti964_des1ep0>;
++ };
++ vin4_ti954_des1ep0: endpoint@2 {
++ remote-endpoint = <&ti954_des1ep0>;
++ };
++ };
++ };
++};
++
++&vin5 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin5ep0: endpoint@0 {
++ csi,select = "csi41";
++ virtual,channel = <1>;
++ remote-endpoint = <&ov106xx_in5>;
++ data-lanes = <1 2 3 4>;
++ };
++ };
++ port@1 {
++ csi2ep1: endpoint {
++ remote-endpoint = <&csi2_41_ep>;
++ };
++ };
++ port@2 {
++ vin5_max9286_des1ep1: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep1>;
++ };
++ vin5_ti964_des1ep1: endpoint@1 {
++ remote-endpoint = <&ti964_des1ep1>;
++ };
++ vin5_ti954_des1ep1: endpoint@2 {
++ remote-endpoint = <&ti954_des1ep1>;
++ };
++ };
++ };
++};
++
++&vin6 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin6ep0: endpoint@0 {
++ csi,select = "csi41";
++ virtual,channel = <2>;
++ remote-endpoint = <&ov106xx_in6>;
++ data-lanes = <1 2 3 4>;
++ };
++ };
++ port@1 {
++ csi2ep2: endpoint {
++ remote-endpoint = <&csi2_41_ep>;
++ };
++ };
++ port@2 {
++ vin6_max9286_des1ep2: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep2>;
++ };
++ vin6_ti964_des1ep2: endpoint@1 {
++ remote-endpoint = <&ti964_des1ep2>;
++ };
++ };
++ };
++};
++
++&vin7 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin7ep0: endpoint@0 {
++ csi,select = "csi41";
++ virtual,channel = <3>;
++ remote-endpoint = <&ov106xx_in7>;
++ data-lanes = <1 2 3 4>;
++ };
++ };
++ port@1 {
++ csi2ep3: endpoint {
++ remote-endpoint = <&csi2_41_ep>;
++ };
++ };
++ port@2 {
++ vin7_max9286_des1ep3: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep3>;
++ };
++ vin7_ti964_des1ep3: endpoint@1 {
++ remote-endpoint = <&ti964_des1ep3>;
++ };
++ };
++ };
++};
++
++&csi2_40 {
++ status = "okay";
++
++ virtual,channel {
++ csi2_vc0 {
++ data,type = "ycbcr422";
++ receive,vc = <0>;
++ };
++ csi2_vc1 {
++ data,type = "ycbcr422";
++ receive,vc = <1>;
++ };
++ csi2_vc2 {
++ data,type = "ycbcr422";
++ receive,vc = <2>;
++ };
++ csi2_vc3 {
++ data,type = "ycbcr422";
++ receive,vc = <3>;
++ };
++ };
++
++ port {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ csi2_40_ep: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ csi-rate = <300>;
++ };
++ };
++};
++
++&csi2_41 {
++ status = "okay";
++
++ virtual,channel {
++ csi2_vc0 {
++ data,type = "ycbcr422";
++ receive,vc = <0>;
++ };
++ csi2_vc1 {
++ data,type = "ycbcr422";
++ receive,vc = <1>;
++ };
++ csi2_vc2 {
++ data,type = "ycbcr422";
++ receive,vc = <2>;
++ };
++ csi2_vc3 {
++ data,type = "ycbcr422";
++ receive,vc = <3>;
++ };
++ };
++
++ port {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ csi2_41_ep: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ csi-rate = <300>;
++ };
++ };
++};
++
++&rcar_sound {
++ pinctrl-0 = <&sound_clk_pins>;
++
++ /* Multi DAI */
++ #sound-dai-cells = <1>;
++
++ rcar_sound,dai {
++ dai0 {
++ playback = <&ssi7>;
++ capture = <&ssi8>;
++ };
++
++ dai1 {
++ playback = <&ssi0 &src0 &dvc0>;
++ capture = <&ssi1 &src1 &dvc1>;
++ };
++
++ dai2 {
++ capture = <&ssi6>;
++ };
++
++ dai3 {
++ playback = <&ssi9>;
++ };
++ };
++};
++
++&sdhi3 {
++ pinctrl-0 = <&sdhi3_pins_3v3>;
++ pinctrl-names = "default";
++
++ vmmc-supply = <&wlan_en>;
++ vqmmc-supply = <&vccq_sdhi3>;
++ keep-power-in-suspend;
++ enable-sdio-wakeup;
++ bus-width = <4>;
++ no-1-8-v;
++ non-removable;
++ cap-power-off-card;
++ max-frequency = <26000000>;
++ status = "okay";
++
++ #address-cells = <1>;
++ #size-cells = <0>;
++ wlcore: wlcore@2 {
++ compatible = "ti,wl1837";
++ reg = <2>;
++ interrupt-parent = <&gpio1>;
++ interrupts = <25 IRQ_TYPE_EDGE_RISING>;
++ };
++};
++
++&xhci0 {
++ status = "okay";
++};
++
++&usb2_phy0 {
++ pinctrl-0 = <&usb0_pins>;
++ pinctrl-names = "default";
++
++ status = "okay";
++};
++
++&hsusb {
++ status = "okay";
++};
++
++&ehci0 {
++ status = "okay";
++};
++
++&ohci0 {
++ status = "okay";
++};
+--
+1.9.1
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0035-arm64-dts-r8a7796-salvator-x-view-add-ADAS-board.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0035-arm64-dts-r8a7796-salvator-x-view-add-ADAS-board.patch
new file mode 100644
index 0000000..9ca64c6
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0035-arm64-dts-r8a7796-salvator-x-view-add-ADAS-board.patch
@@ -0,0 +1,353 @@
+From 782e569e0b0e252b03fdaecae2e6f7c3267a4bcd Mon Sep 17 00:00:00 2001
+From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+Date: Mon, 17 Apr 2017 19:12:29 +0300
+Subject: [PATCH] arm64: dts: r8a7796-salvator-x-view: add ADAS board
+
+Salvator-X.View board on R8A7796 SoC
+
+Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+---
+ arch/arm64/boot/dts/renesas/Makefile | 1 +
+ .../boot/dts/renesas/r8a7796-salvator-x-view.dts | 318 +++++++++++++++++++++
+ 2 files changed, 319 insertions(+)
+ create mode 100644 arch/arm64/boot/dts/renesas/r8a7796-salvator-x-view.dts
+
+diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile
+index 49ddbd1..52bbef2 100644
+--- a/arch/arm64/boot/dts/renesas/Makefile
++++ b/arch/arm64/boot/dts/renesas/Makefile
+@@ -8,6 +8,7 @@ dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-xs.dtb
+ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-h3ulcb-view.dtb
+ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-h3ulcb-had-alfa.dtb r8a7795-es1-h3ulcb-had-beta.dtb
+ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-h3ulcb-kf.dtb
++dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-x-view.dtb
+
+ always := $(dtb-y)
+ clean-files := *.dtb
+diff --git a/arch/arm64/boot/dts/renesas/r8a7796-salvator-x-view.dts b/arch/arm64/boot/dts/renesas/r8a7796-salvator-x-view.dts
+new file mode 100644
+index 0000000..cc6866c
+--- /dev/null
++++ b/arch/arm64/boot/dts/renesas/r8a7796-salvator-x-view.dts
+@@ -0,0 +1,318 @@
++/*
++ * Device Tree Source for the Salvator-X.View board
++ *
++ * Copyright (C) 2016-2017 Renesas Electronics Corp.
++ * Copyright (C) 2016-2017 Cogent Embedded, Inc
++ *
++ * This file is licensed under the terms of the GNU General Public License
++ * version 2. This program is licensed "as is" without any warranty of any
++ * kind, whether express or implied.
++ */
++
++#include "r8a7796-salvator-x.dts"
++
++/ {
++ model = "Renesas Salvator-X.View board based on r8a7796";
++};
++
++&pfc {
++ can0_pins: can0 {
++ groups = "can0_data_a";
++ function = "can0";
++ };
++
++ can1_pins: can1 {
++ groups = "can1_data";
++ function = "can1";
++ };
++};
++
++&i2c4 {
++ /delete-node/hdmi-in@34;
++ /delete-node/composite-in@70;
++
++ ov106xx@0 {
++ compatible = "ovti,ov106xx";
++ reg = <0x60>;
++
++ port@0 {
++ ov106xx_in0: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin0ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des0ep0: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep0>;
++ };
++ };
++ };
++
++ ov106xx@1 {
++ compatible = "ovti,ov106xx";
++ reg = <0x61>;
++
++ port@0 {
++ ov106xx_in1: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin1ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des0ep1: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep1>;
++ };
++ };
++ };
++
++ ov106xx@2 {
++ compatible = "ovti,ov106xx";
++ reg = <0x62>;
++
++ port@0 {
++ ov106xx_in2: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin2ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des0ep2: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep2>;
++ };
++ };
++ };
++
++ ov106xx@3 {
++ compatible = "ovti,ov106xx";
++ reg = <0x63>;
++
++ port@0 {
++ ov106xx_in3: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin3ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_des0ep3: endpoint {
++ remote-endpoint = <&max9286_des0ep3>;
++ };
++ };
++ };
++
++ max9286-max9271@0 {
++ compatible = "maxim,max9286-max9271";
++ reg = <0x4c>;
++ gpios = <&gpio6 30 GPIO_ACTIVE_LOW>;
++ maxim,sensor_delay = <0>;
++ maxim,links = <4>;
++ maxim,lanes = <4>;
++ maxim,resetb-gpio = <1>;
++ maxim,fsync-mode = "automatic";
++ maxim,timeout = <100>;
++ maxim,i2c-quirk = <0x6c>;
++
++ port@0 {
++ max9286_des0ep0: endpoint@0 {
++ max9271-addr = <0x50>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in0>;
++ };
++ max9286_des0ep1: endpoint@1 {
++ max9271-addr = <0x51>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in1>;
++ };
++ max9286_des0ep2: endpoint@2 {
++ max9271-addr = <0x52>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in2>;
++ };
++ max9286_des0ep3: endpoint@3 {
++ max9271-addr = <0x53>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in3>;
++ };
++ };
++ port@1 {
++ max9286_csi0ep0: endpoint {
++ csi-rate = <700>;
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ };
++};
++
++&vin0 {
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin0ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in0>;
++ };
++ };
++ port@1 {
++ csi0ep0: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin0_max9286_des0ep0: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep0>;
++ };
++ };
++ };
++};
++
++&vin1 {
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin1ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <1>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in1>;
++ };
++ };
++ port@1 {
++ csi0ep1: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin1_max9286_des0ep1: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep1>;
++ };
++ };
++ };
++};
++
++&vin2 {
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin2ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <2>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in2>;
++ };
++ };
++ port@1 {
++ csi0ep2: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin2_max9286_des0ep2: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep2>;
++ };
++ };
++ };
++};
++
++&vin3 {
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin3ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <3>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in3>;
++ };
++ };
++ port@1 {
++ csi0ep3: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin3_max9286_des0ep3: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep3>;
++ };
++ };
++ };
++};
++
++&vin4 {
++ status = "disabled";
++};
++
++&vin5 {
++ status = "disabled";
++};
++
++&vin6 {
++ status = "disabled";
++};
++
++&vin7 {
++ status = "disabled";
++};
++
++&csi2_20 {
++ status = "disabled";
++ /delete-node/ports;
++};
++
++&csi2_40 {
++ /delete-node/ports;
++
++ virtual,channel {
++ csi2_vc0 {
++ data,type = "ycbcr422";
++ receive,vc = <0>;
++ };
++ csi2_vc1 {
++ data,type = "ycbcr422";
++ receive,vc = <1>;
++ };
++ csi2_vc2 {
++ data,type = "ycbcr422";
++ receive,vc = <2>;
++ };
++ csi2_vc3 {
++ data,type = "ycbcr422";
++ receive,vc = <3>;
++ };
++ };
++
++ port {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ csi2_40_ep: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ csi-rate = <300>;
++ };
++ };
++};
++
++&can0 {
++ pinctrl-0 = <&can0_pins>;
++ pinctrl-names = "default";
++ status = "okay";
++};
++
++&can1 {
++ pinctrl-0 = <&can1_pins>;
++ pinctrl-names = "default";
++ status = "okay";
++};
+--
+1.9.1
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0036-arm64-dts-r8a7796-m3ulcb-view-add-ADAS-board.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0036-arm64-dts-r8a7796-m3ulcb-view-add-ADAS-board.patch
new file mode 100644
index 0000000..9fb6a37
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0036-arm64-dts-r8a7796-m3ulcb-view-add-ADAS-board.patch
@@ -0,0 +1,322 @@
+From 51c5d0d6f36c1d049afc542130ac8186c12e3a46 Mon Sep 17 00:00:00 2001
+From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+Date: Wed, 4 Jan 2017 10:37:23 +0300
+Subject: [PATCH] arm64: dts: r8a7796-m3ulcb-view: add ADAS board
+
+M3ULCB.View board on R8A7796 SoC
+
+Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+---
+ arch/arm64/boot/dts/renesas/Makefile | 1 +
+ .../arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts | 287 +++++++++++++++++++++
+ 2 files changed, 288 insertions(+)
+ create mode 100644 arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts
+
+diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile
+index 52bbef2..06207e3 100644
+--- a/arch/arm64/boot/dts/renesas/Makefile
++++ b/arch/arm64/boot/dts/renesas/Makefile
+@@ -9,6 +9,7 @@ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-salvator-x-view.dtb
+ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-h3ulcb-had-alfa.dtb r8a7795-es1-h3ulcb-had-beta.dtb
+ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-h3ulcb-kf.dtb
+ dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-x-view.dtb
++dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-m3ulcb-view.dtb
+
+ always := $(dtb-y)
+ clean-files := *.dtb
+diff --git a/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts
+new file mode 100644
+index 0000000..1ac0041
+--- /dev/null
++++ b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts
+@@ -0,0 +1,287 @@
++/*
++ * Device Tree Source for the M3ULCB.View board on r8a7796
++ *
++ * Copyright (C) 2016-2017 Renesas Electronics Corp.
++ * Copyright (C) 2016-2017 Cogent Embedded, Inc.
++ *
++ * This file is licensed under the terms of the GNU General Public License
++ * version 2. This program is licensed "as is" without any warranty of any
++ * kind, whether express or implied.
++ */
++
++#include "r8a7796-m3ulcb.dts"
++
++/ {
++ model = "Renesas M3ULCB.View board based on r8a7796";
++};
++
++&i2c4 {
++ ov106xx@0 {
++ compatible = "ovti,ov106xx";
++ reg = <0x60>;
++
++ port@0 {
++ ov106xx_in0: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin0ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des0ep0: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep0>;
++ };
++ };
++ };
++
++ ov106xx@1 {
++ compatible = "ovti,ov106xx";
++ reg = <0x61>;
++
++ port@0 {
++ ov106xx_in1: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin1ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des0ep1: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep1>;
++ };
++ };
++ };
++
++ ov106xx@2 {
++ compatible = "ovti,ov106xx";
++ reg = <0x62>;
++
++ port@0 {
++ ov106xx_in2: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin2ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des0ep2: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep2>;
++ };
++ };
++ };
++
++ ov106xx@3 {
++ compatible = "ovti,ov106xx";
++ reg = <0x63>;
++
++ port@0 {
++ ov106xx_in3: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin3ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_des0ep3: endpoint {
++ remote-endpoint = <&max9286_des0ep3>;
++ };
++ };
++ };
++
++ max9286-max9271@0 {
++ compatible = "maxim,max9286-max9271";
++ reg = <0x4c>;
++ gpios = <&gpio2 6 GPIO_ACTIVE_HIGH>;
++ maxim,sensor_delay = <0>;
++ maxim,links = <4>;
++ maxim,lanes = <4>;
++ maxim,resetb-gpio = <1>;
++ maxim,fsync-mode = "automatic";
++ maxim,timeout = <100>;
++ maxim,i2c-quirk = <0x6c>;
++
++ port@0 {
++ max9286_des0ep0: endpoint@0 {
++ max9271-addr = <0x50>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in0>;
++ };
++ max9286_des0ep1: endpoint@1 {
++ max9271-addr = <0x51>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in1>;
++ };
++ max9286_des0ep2: endpoint@2 {
++ max9271-addr = <0x52>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in2>;
++ };
++ max9286_des0ep3: endpoint@3 {
++ max9271-addr = <0x53>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in3>;
++ };
++ };
++ port@1 {
++ max9286_csi0ep0: endpoint {
++ csi-rate = <700>;
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ };
++};
++
++&pcie_bus_clk {
++ clock-frequency = <100000000>;
++ status = "okay";
++};
++
++&pciec1 {
++ status = "okay";
++};
++
++&vin0 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin0ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in0>;
++ };
++ };
++ port@1 {
++ csi0ep0: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin0_max9286_des0ep0: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep0>;
++ };
++ };
++ };
++};
++
++&vin1 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin1ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <1>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in1>;
++ };
++ };
++ port@1 {
++ csi0ep1: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin1_max9286_des0ep1: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep1>;
++ };
++ };
++ };
++};
++
++&vin2 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin2ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <2>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in2>;
++ };
++ };
++ port@1 {
++ csi0ep2: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin2_max9286_des0ep2: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep2>;
++ };
++ };
++ };
++};
++
++&vin3 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin3ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <3>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in3>;
++ };
++ };
++ port@1 {
++ csi0ep3: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin3_max9286_des0ep3: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep3>;
++ };
++ };
++ };
++};
++
++&csi2_40 {
++ status = "okay";
++
++ virtual,channel {
++ csi2_vc0 {
++ data,type = "ycbcr422";
++ receive,vc = <0>;
++ };
++ csi2_vc1 {
++ data,type = "ycbcr422";
++ receive,vc = <1>;
++ };
++ csi2_vc2 {
++ data,type = "ycbcr422";
++ receive,vc = <2>;
++ };
++ csi2_vc3 {
++ data,type = "ycbcr422";
++ receive,vc = <3>;
++ };
++ };
++
++ port {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ csi2_40_ep: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ csi-rate = <300>;
++ };
++ };
++};
+--
+1.9.1
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0037-arm64-dts-r8a7796-m3ulcb-kf-add-ADAS-board.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0037-arm64-dts-r8a7796-m3ulcb-kf-add-ADAS-board.patch
new file mode 100644
index 0000000..92d3bf5
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0037-arm64-dts-r8a7796-m3ulcb-kf-add-ADAS-board.patch
@@ -0,0 +1,1232 @@
+From dffbc2287b4fd0c54b49fd4bb41d7f06c23e20b6 Mon Sep 17 00:00:00 2001
+From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+Date: Wed, 4 Jan 2017 10:37:23 +0300
+Subject: [PATCH] arm64: dts: r8a7796-m3ulcb-kf: add ADAS board
+
+M3ULCB.View board on R8A7796
+
+Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+---
+ arch/arm64/boot/dts/renesas/Makefile | 1 +
+ arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts | 1197 +++++++++++++++++++++
+ 2 files changed, 1198 insertions(+)
+ create mode 100644 arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts
+
+diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile
+index a5dd1d3..5cb7eb1 100644
+--- a/arch/arm64/boot/dts/renesas/Makefile
++++ b/arch/arm64/boot/dts/renesas/Makefile
+@@ -11,6 +11,7 @@ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-h3ulcb-had.dtb
+ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-h3ulcb-kf.dtb
+ dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-x-view.dtb
+ dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-m3ulcb-view.dtb
++dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-m3ulcb-kf.dtb
+
+ always := $(dtb-y)
+ clean-files := *.dtb
+diff --git a/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts
+new file mode 100644
+index 0000000..ffaef74
+--- /dev/null
++++ b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts
+@@ -0,0 +1,1197 @@
++/*
++ * Device Tree Source for the M3ULCB Kingfisher board on r8a7796
++ *
++ * Copyright (C) 2017 Renesas Electronics Corp.
++ * Copyright (C) 2017 Cogent Embedded, Inc.
++ *
++ * This file is licensed under the terms of the GNU General Public License
++ * version 2. This program is licensed "as is" without any warranty of any
++ * kind, whether express or implied.
++ */
++
++#include "r8a7796-m3ulcb.dts"
++
++/ {
++ model = "Renesas M3ULCB Kingfisher board based on r8a7796";
++
++ aliases {
++ serial1 = &hscif4;
++ };
++
++ snd_clk: snd_clk {
++ compatible = "fixed-clock";
++ #clock-cells = <0>;
++ clock-frequency = <24576000>;
++ clock-output-names = "scki";
++ };
++
++ wlan_en: regulator@4 {
++ compatible = "regulator-fixed";
++ regulator-name = "wlan-en-regulator";
++
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++
++ gpio = <&gpio_ext_20 4 GPIO_ACTIVE_HIGH>;
++ enable-active-high;
++ };
++
++ vccq_sdhi3: regulator@5 {
++ compatible = "regulator-fixed";
++
++ regulator-name = "SDHI3 VccQ";
++ /* external voltage translator to 1.8V */
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ };
++
++ codec_en_reg: regulator@6 {
++ compatible = "regulator-fixed";
++ regulator-name = "codec-en-regulator";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++
++ gpio = <&gpio_ext_20 15 0>;
++
++ /* delay - CHECK */
++ startup-delay-us = <70000>;
++ enable-active-high;
++ };
++
++ amp_en_reg: regulator@7 {
++ compatible = "regulator-fixed";
++ regulator-name = "amp-en-regulator";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++
++ gpio = <&gpio_ext_20 0 0>;
++
++ startup-delay-us = <0>;
++ enable-active-high;
++ };
++
++ lvds_switch: regulator@8 {
++ compatible = "regulator-fixed";
++ regulator-name = "lvds_on";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ gpio = <&gpio1 24 0>;
++ enable-active-high;
++ regulator-always-on;
++ };
++
++ sdio_switch: regulator@9 {
++ compatible = "regulator-fixed";
++ regulator-name = "wifi_on";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ gpio = <&gpio_ext_20 5 0>;
++ enable-active-low;
++ regulator-always-on;
++ };
++
++ sound_switch: regulator@10 {
++ compatible = "regulator-fixed";
++ regulator-name = "pcm3168a_on";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ gpio = <&gpio_ext_21 5 0>;
++ enable-active-low;
++ regulator-always-on;
++ };
++
++ radio_switch: regulator@11 {
++ compatible = "regulator-fixed";
++ regulator-name = "radio_on";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ gpio = <&gpio_ext_20 13 GPIO_ACTIVE_HIGH>;
++ enable-active-high;
++ regulator-always-on;
++ };
++
++ kim {
++ compatible = "kim";
++ nshutdown_gpio = <343>; /* pca9535@i2c2.0x20 pin 3 */
++ /* serial1 */
++ dev_name = "/dev/ttySC1";
++ flow_cntrl = <1>;
++ /* int div 8 hscif@26.6666656MHz */
++ baud_rate = <3333332>;
++ };
++
++ btwilink {
++ compatible = "btwilink";
++ };
++
++ sound_ext: sound@0 {
++ pinctrl-0 = <&sound_0_pins>;
++ pinctrl-names = "default";
++ compatible = "simple-audio-card";
++
++ simple-audio-card,format = "left_j";
++ simple-audio-card,name = "pcm3168a";
++
++ simple-audio-card,bitclock-master = <&sound_ext_master>;
++ simple-audio-card,frame-master = <&sound_ext_master>;
++ sound_ext_master: simple-audio-card,cpu@0 {
++ sound-dai = <&rcar_sound 0>;
++ dai-tdm-slot-num = <8>;
++ dai-tdm-slot-width = <32>;
++ };
++
++ simple-audio-card,codec@0 {
++ sound-dai = <&pcm3168a>;
++ dai-tdm-slot-num = <8>;
++ dai-tdm-slot-width = <32>;
++ system-clock-frequency = <24576000>;
++ };
++ };
++
++ /delete-node/sound;
++
++ rsnd_ak4613: sound@1 {
++ pinctrl-0 = <&sound_1_pins>;
++ pinctrl-names = "default";
++ compatible = "simple-audio-card";
++
++ simple-audio-card,format = "left_j";
++ simple-audio-card,name = "ak4613";
++
++ simple-audio-card,bitclock-master = <&sndcpu>;
++ simple-audio-card,frame-master = <&sndcpu>;
++
++ sndcpu: simple-audio-card,cpu@1 {
++ sound-dai = <&rcar_sound 1>;
++ };
++
++ sndcodec: simple-audio-card,codec@1 {
++ sound-dai = <&ak4613>;
++ };
++ };
++
++ sound_radio: sound@2 {
++ pinctrl-0 = <&sound_2_pins>;
++ pinctrl-names = "default";
++ compatible = "simple-audio-card";
++
++ simple-audio-card,format = "i2s";
++ simple-audio-card,name = "radio";
++
++ simple-audio-card,bitclock-master = <&sound_radio_master>;
++ simple-audio-card,frame-master = <&sound_radio_master>;
++ simple-audio-card,cpu@2 {
++ sound-dai = <&rcar_sound 2>;
++ };
++
++ sound_radio_master: simple-audio-card,codec@2 {
++ sound-dai = <&radio>;
++ system-clock-frequency = <12288000>;
++ };
++ };
++
++ sound_amp: sound@3 {
++ pinctrl-0 = <&sound_9_pins>;
++ pinctrl-names = "default";
++ compatible = "simple-audio-card";
++
++ simple-audio-card,name = "power_amp";
++
++ simple-audio-card,dai-link@0 {
++ format = "i2s";
++ cpu {
++ sound-dai = <&rcar_sound 3>;
++ };
++ codec {
++ sound-dai = <&max98371_L>;
++ };
++ };
++ simple-audio-card,dai-link@1 {
++ format = "i2s";
++ cpu {
++ sound-dai = <&rcar_sound 3>;
++ };
++ codec {
++ sound-dai = <&max98371_R>;
++ };
++ };
++ simple-audio-card,dai-link@2 {
++ format = "i2s";
++ cpu {
++ sound-dai = <&rcar_sound 3>;
++ };
++ codec {
++ sound-dai = <&max98371_RL>;
++ };
++ };
++ simple-audio-card,dai-link@3 {
++ format = "i2s";
++ cpu {
++ sound-dai = <&rcar_sound 3>;
++ };
++ codec {
++ sound-dai = <&max98371_RR>;
++ };
++ };
++ simple-audio-card,dai-link@4 {
++ format = "i2s";
++ cpu {
++ sound-dai = <&rcar_sound 3>;
++ };
++ codec {
++ sound-dai = <&max98371_C>;
++ };
++ };
++ simple-audio-card,dai-link@5 {
++ format = "i2s";
++ cpu {
++ sound-dai = <&rcar_sound 3>;
++ };
++ codec {
++ sound-dai = <&max98371_S>;
++ };
++ };
++ };
++
++ lvds-encoder {
++ compatible = "thine,thc63lvdm83d";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ port@0 {
++ reg = <0>;
++ lvds_enc_in: endpoint {
++ remote-endpoint = <&du_out_lvds0>;
++ };
++ };
++ port@1 {
++ reg = <1>;
++ lvds_enc_out: endpoint {
++ remote-endpoint = <&lvds_in>;
++ };
++ };
++ };
++ };
++
++ lvds {
++ compatible = "lvds-connector";
++
++ width-mm = <210>;
++ height-mm = <158>;
++
++ panel-timing {
++ /* 1280x800 @60Hz */
++ clock-frequency = <65000000>;
++ hactive = <1280>;
++ vactive = <800>;
++ hsync-len = <40>;
++ hfront-porch = <80>;
++ hback-porch = <40>;
++ vfront-porch = <14>;
++ vback-porch = <14>;
++ vsync-len = <4>;
++ };
++
++ port {
++ lvds_in: endpoint {
++ remote-endpoint = <&lvds_enc_out>;
++ };
++ };
++ };
++
++ radio: si468x@0 {
++ compatible = "si,si468x-pcm";
++ status = "okay";
++
++ #sound-dai-cells = <0>;
++ };
++};
++
++&pfc {
++ hscif4_pins: hscif4 {
++ groups = "hscif4_data_a", "hscif4_ctrl";
++ function = "hscif4";
++ };
++
++ sdhi3_pins_3v3: sd3_3v3 {
++ groups = "sdhi3_data4", "sdhi3_ctrl";
++ function = "sdhi3";
++ power-source = <3300>;
++ };
++
++ sound_0_pins: sound0 {
++ groups = "ssi78_ctrl", "ssi7_data", "ssi8_data";
++ function = "ssi";
++ };
++
++ sound_1_pins: sound1 {
++ groups = "ssi01239_ctrl", "ssi0_data", "ssi1_data_a";
++ function = "ssi";
++ };
++
++ sound_2_pins: sound2 {
++ groups = "ssi6_ctrl", "ssi6_data";
++ function = "ssi";
++ };
++
++ sound_9_pins: sound2 {
++ groups = "ssi9_ctrl_b", "ssi9_data_b";
++ function = "ssi";
++ };
++
++ usb0_pins: usb0 {
++ groups = "usb0";
++ function = "usb0";
++ };
++};
++
++&gpio0 {
++ video_a_irq {
++ gpio-hog;
++ gpios = <13 GPIO_ACTIVE_HIGH>;
++ input;
++ line-name = "Video-A irq";
++ };
++
++ video_b_irq {
++ gpio-hog;
++ gpios = <14 GPIO_ACTIVE_HIGH>;
++ input;
++ line-name = "Video-B irq";
++ };
++
++ gpioext_2_20_irq {
++ gpio-hog;
++ gpios = <15 GPIO_ACTIVE_HIGH>;
++ input;
++ line-name = "0x20@i2c2 irq";
++ };
++};
++
++&gpio1 {
++ gpioext_2_21_irq {
++ gpio-hog;
++ gpios = <15 GPIO_ACTIVE_HIGH>;
++ input;
++ line-name = "0x21@i2c2 irq";
++ };
++
++ wifi_irq {
++ gpio-hog;
++ gpios = <25 GPIO_ACTIVE_HIGH>;
++ input;
++ line-name = "wifi irq";
++ };
++};
++
++&gpio5 {
++ touch_irq {
++ gpio-hog;
++ gpios = <6 GPIO_ACTIVE_HIGH>;
++ input;
++ line-name = "touch irq";
++ };
++
++ /* From TI forum */
++ /* BT_AUD_OUT should be pulled low when WL_EN is activated. */
++ /* in case it isn't, wilink8 ends up in one of the test modes that introduces various issues */
++ bt_strap {
++ gpio-hog;
++ gpios = <14 GPIO_ACTIVE_HIGH>;
++ output-low;
++ line-name = "BT strap pin";
++ };
++};
++
++&gpio7 {
++ gpioext_2_21_irq {
++ gpio-hog;
++ gpios = <3 GPIO_ACTIVE_HIGH>;
++ input;
++ line-name = "0x21@i2c4 irq";
++ };
++};
++
++&hscif4 {
++ pinctrl-0 = <&hscif4_pins>;
++ pinctrl-names = "default";
++ ctsrts;
++
++ status = "okay";
++};
++
++&i2c2 {
++ clock-frequency = <400000>;
++
++ gpio_ext_20: pca9535@20 {
++ compatible = "nxp,pca9535";
++ reg = <0x20>;
++ gpio-controller;
++ #gpio-cells = <2>;
++ interrupt-controller;
++ interrupt-parent = <&gpio0>;
++ interrupts = <15 IRQ_TYPE_EDGE_FALLING>;
++ };
++
++ gpio_ext_21: pca9535@21 {
++ compatible = "nxp,pca9535";
++ reg = <0x21>;
++ gpio-controller;
++ #gpio-cells = <2>;
++ interrupt-controller;
++ interrupt-parent = <&gpio1>;
++ interrupts = <15 IRQ_TYPE_EDGE_FALLING>;
++ };
++
++ i2cswitch2@74 {
++ compatible = "nxp,pca9548";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <0x74>;
++ reset-gpios = <&gpio6 5 GPIO_ACTIVE_LOW>;
++
++ i2c@0 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <0>;
++ /* BCM node(s) */
++ };
++
++ i2c@1 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <1>;
++ /* USB3.0 HUB node(s) */
++ };
++
++ i2c@2 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <2>;
++ /* Power amp node(s) */
++
++ max98371_L: max98371@0x31 {
++ compatible = "maxim,max98371";
++ reg = <0x31>;
++ #sound-dai-cells = <0>;
++ };
++ max98371_R: max98371@0x32 {
++ compatible = "maxim,max98371";
++ reg = <0x32>;
++ #sound-dai-cells = <0>;
++ };
++ max98371_RL: max98371@0x33 {
++ compatible = "maxim,max98371";
++ reg = <0x33>;
++ #sound-dai-cells = <0>;
++ };
++ max98371_RR: max98371@0x34 {
++ compatible = "maxim,max98371";
++ reg = <0x34>;
++ #sound-dai-cells = <0>;
++ };
++ max98371_C: max98371@0x35 {
++ compatible = "maxim,max98371";
++ reg = <0x35>;
++ #sound-dai-cells = <0>;
++ };
++ max98371_S: max98371@0x36 {
++ compatible = "maxim,max98371";
++ reg = <0x36>;
++ #sound-dai-cells = <0>;
++ };
++ };
++
++ i2c@3 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <3>;
++ /* Radio node(s) */
++ };
++
++ i2c@4 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <4>;
++ /* A2B node(s) */
++ };
++
++ i2c@5 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <5>;
++ /* PCIe node(s) */
++ };
++
++ i2c@6 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <6>;
++ /* LVDS display node(s) */
++
++ polytouch: edt-ft5x06@38 {
++ compatible = "edt,edt-ft5x06";
++ reg = <0x38>;
++ interrupt-parent = <&gpio5>;
++ interrupts = <6 IRQ_TYPE_EDGE_FALLING>;
++ };
++ };
++
++ i2c@7 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <7>;
++ /* Audio, GPS and Gyro node(s) */
++
++ pcm3168a: audio-codec@44 {
++ #sound-dai-cells = <0>;
++ compatible = "ti,pcm3168a";
++ reg = <0x44>;
++ clocks = <&snd_clk>;
++ clock-names = "scki";
++ tdm;
++ VDD1-supply = <&codec_en_reg>;
++ VDD2-supply = <&codec_en_reg>;
++ VCCAD1-supply = <&codec_en_reg>;
++ VCCAD2-supply = <&codec_en_reg>;
++ VCCDA1-supply = <&amp_en_reg>;
++ VCCDA2-supply = <&amp_en_reg>;
++ };
++
++ lsm9ds0_acc_mag@1d {
++ compatible = "st,lsm9ds0_acc_mag";
++ reg = <0x1d>;
++ };
++
++ lsm9ds0_gyr@6b {
++ compatible = "st,lsm9ds0-gyro";
++ reg = <0x6b>;
++ };
++
++ /* GPS@ 0x42 */
++ };
++ };
++};
++
++&i2c4 {
++ gpio_ext_22: pca9535@21 {
++ compatible = "nxp,pca9535";
++ reg = <0x22>;
++ gpio-controller;
++ #gpio-cells = <2>;
++ interrupt-controller;
++ interrupt-parent = <&gpio7>;
++ interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
++ };
++
++ i2cswitch4@74 {
++ compatible = "nxp,pca9548";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <0x74>;
++ reset-gpios= <&gpio6 21 GPIO_ACTIVE_LOW>;
++
++ i2c@0 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <0>;
++ /* SAM node(s) */
++ };
++
++ i2c@1 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <1>;
++ /* Video input "A" acc node(s) */
++
++ ov106xx@0 {
++ compatible = "ovti,ov106xx";
++ reg = <0x60>;
++
++ port@0 {
++ ov106xx_in0: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin0ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des0ep0: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep0>;
++ };
++ ov106xx_ti964_des0ep0: endpoint@1 {
++ remote-endpoint = <&ti964_des0ep0>;
++ };
++ ov106xx_ti954_des0ep0: endpoint@2 {
++ remote-endpoint = <&ti954_des0ep0>;
++ };
++ };
++ };
++
++ ov106xx@1 {
++ compatible = "ovti,ov106xx";
++ reg = <0x61>;
++
++ port@0 {
++ ov106xx_in1: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin1ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des0ep1: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep1>;
++ };
++ ov106xx_ti964_des0ep1: endpoint@1 {
++ remote-endpoint = <&ti964_des0ep1>;
++ };
++ ov106xx_ti954_des0ep1: endpoint@2 {
++ remote-endpoint = <&ti954_des0ep1>;
++ };
++ };
++ };
++
++ ov106xx@2 {
++ compatible = "ovti,ov106xx";
++ reg = <0x62>;
++
++ port@0 {
++ ov106xx_in2: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin2ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des0ep2: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep2>;
++ };
++ ov106xx_ti964_des0ep2: endpoint@1 {
++ remote-endpoint = <&ti964_des0ep2>;
++ };
++ };
++ };
++
++ ov106xx@3 {
++ compatible = "ovti,ov106xx";
++ reg = <0x63>;
++
++ port@0 {
++ ov106xx_in3: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin3ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des0ep3: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep3>;
++ };
++ ov106xx_ti964_des0ep3: endpoint@1 {
++ remote-endpoint = <&ti964_des0ep3>;
++ };
++ };
++ };
++
++ /* DS90UB964 @ 0x3a */
++ ti964-ti9x3@0 {
++ compatible = "ti,ti964-ti9x3";
++ reg = <0x3a>;
++ ti,sensor_delay = <350>;
++ ti,links = <4>;
++ ti,lanes = <4>;
++ ti,forwarding-mode = "round-robin";
++ ti,cable-mode = "coax";
++
++ port@0 {
++ ti964_des0ep0: endpoint@0 {
++ ti9x3-addr = <0x0c>;
++ dvp-order = <0>;
++ remote-endpoint = <&ov106xx_in0>;
++ };
++ ti964_des0ep1: endpoint@1 {
++ ti9x3-addr = <0x0d>;
++ dvp-order = <0>;
++ remote-endpoint = <&ov106xx_in1>;
++ };
++ ti964_des0ep2: endpoint@2 {
++ ti9x3-addr = <0x0e>;
++ dvp-order = <0>;
++ remote-endpoint = <&ov106xx_in2>;
++ };
++ ti964_des0ep3: endpoint@3 {
++ ti9x3-addr = <0x0f>;
++ dvp-order = <0>;
++ remote-endpoint = <&ov106xx_in3>;
++ };
++ };
++ port@1 {
++ ti964_csi0ep0: endpoint {
++ csi-rate = <1450>;
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ };
++
++ /* DS90UB954 @ 0x38 */
++ ti954-ti9x3@0 {
++ compatible = "ti,ti954-ti9x3";
++ reg = <0x38>;
++ gpios = <&video_a_ext1 10 GPIO_ACTIVE_HIGH>;
++ ti,sensor_delay = <350>;
++ ti,links = <2>;
++ ti,lanes = <4>;
++ ti,forwarding-mode = "round-robin";
++ ti,cable-mode = "coax";
++
++ port@0 {
++ ti954_des0ep0: endpoint@0 {
++ ti9x3-addr = <0x0c>;
++ dvp-order = <0>;
++ remote-endpoint = <&ov106xx_in0>;
++ };
++ ti954_des0ep1: endpoint@1 {
++ ti9x3-addr = <0x0d>;
++ dvp-order = <0>;
++ remote-endpoint = <&ov106xx_in1>;
++ };
++ };
++ port@1 {
++ ti954_csi0ep0: endpoint {
++ csi-rate = <1450>;
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ };
++
++ /* MAX9286 @ 0x2a */
++ max9286-max9271@0 {
++ compatible = "maxim,max9286-max9271";
++ reg = <0x2a>;
++ maxim,sensor_delay = <350>;
++ maxim,links = <4>;
++ maxim,lanes = <4>;
++ maxim,resetb-gpio = <1>;
++ maxim,fsync-mode = "automatic";
++ maxim,timeout = <100>;
++
++ port@0 {
++ max9286_des0ep0: endpoint@0 {
++ max9271-addr = <0x50>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in0>;
++ };
++ max9286_des0ep1: endpoint@1 {
++ max9271-addr = <0x51>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in1>;
++ };
++ max9286_des0ep2: endpoint@2 {
++ max9271-addr = <0x52>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in2>;
++ };
++ max9286_des0ep3: endpoint@3 {
++ max9271-addr = <0x53>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in3>;
++ };
++ };
++ port@1 {
++ max9286_csi0ep0: endpoint {
++ csi-rate = <700>;
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ };
++ };
++
++ i2c@3 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <3>;
++ /* MOST node(s) */
++ };
++
++ i2c@4 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <4>;
++ /* CSI camera node(s) */
++ };
++
++ i2c@5 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <5>;
++ /* CMOS camera node(s) */
++ };
++
++ i2c@7 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <7>;
++ /* Video input "A" main node(s) */
++
++ video_a_ext0: pca9535@26 {
++ compatible = "nxp,pca9535";
++ reg = <0x26>;
++ gpio-controller;
++ #gpio-cells = <2>;
++
++ video_a_des_cfg1 {
++ gpio-hog;
++ gpios = <5 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-A cfg1";
++ };
++ video_a_des_cfg0 {
++ gpio-hog;
++ gpios = <6 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-A cfg0";
++ };
++ video_a_pwr_shdn {
++ gpio-hog;
++ gpios = <3 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-A PWR_SHDN";
++ };
++ video_a_cam_pwr0 {
++ gpio-hog;
++ gpios = <12 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-A PWR0";
++ };
++ video_a_cam_pwr1 {
++ gpio-hog;
++ gpios = <13 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-A PWR1";
++ };
++ video_a_cam_pwr2 {
++ gpio-hog;
++ gpios = <14 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-A PWR2";
++ };
++ video_a_cam_pwr3 {
++ gpio-hog;
++ gpios = <15 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-A PWR3";
++ };
++ video_a_des_shdn {
++ gpio-hog;
++ gpios = <4 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-A DES_SHDN";
++ };
++ video_a_des_led {
++ gpio-hog;
++ gpios = <7 GPIO_ACTIVE_HIGH>;
++ output-low;
++ line-name = "Video-A led";
++ };
++ };
++
++ video_a_ext1: max7325@5c {
++ compatible = "maxim,max7325";
++ reg = <0x5c>;
++ gpio-controller;
++ #gpio-cells = <2>;
++
++ video_a_des_cfg2 {
++ gpio-hog;
++ gpios = <4 GPIO_ACTIVE_HIGH>;
++ output-low;
++ line-name = "Video-A cfg2";
++ };
++ video_a_des_cfg1 {
++ gpio-hog;
++ gpios = <6 GPIO_ACTIVE_HIGH>;
++ output-low;
++ line-name = "Video-A cfg1";
++ };
++ video_a_des_cfg0 {
++ gpio-hog;
++ gpios = <7 GPIO_ACTIVE_HIGH>;
++ output-low;
++ line-name = "Video-A cfg0";
++ };
++ video_a_pwr_shdn {
++ gpio-hog;
++ gpios = <14 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-A PWR_SHDN";
++ };
++ video_a_cam_pwr0 {
++ gpio-hog;
++ gpios = <8 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-A PWR0";
++ };
++ video_a_cam_pwr1 {
++ gpio-hog;
++ gpios = <9 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-A PWR1";
++ };
++ };
++ };
++ };
++};
++
++&pcie_bus_clk {
++ clock-frequency = <100000000>;
++ status = "okay";
++};
++
++&pciec0 {
++ status = "okay";
++};
++
++&pciec1 {
++ status = "okay";
++};
++
++&vin0 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin0ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in0>;
++ };
++ };
++ port@1 {
++ csi0ep0: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin0_max9286_des0ep0: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep0>;
++ };
++ vin0_ti964_des0ep0: endpoint@1 {
++ remote-endpoint = <&ti964_des0ep0>;
++ };
++ vin0_ti954_des0ep0: endpoint@2 {
++ remote-endpoint = <&ti954_des0ep0>;
++ };
++ };
++ };
++};
++
++&vin1 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin1ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <1>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in1>;
++ };
++ };
++ port@1 {
++ csi0ep1: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin1_max9286_des0ep1: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep1>;
++ };
++ vin1_ti964_des0ep1: endpoint@1 {
++ remote-endpoint = <&ti964_des0ep1>;
++ };
++ vin1_ti954_des0ep1: endpoint@2 {
++ remote-endpoint = <&ti954_des0ep1>;
++ };
++ };
++ };
++};
++
++&vin2 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin2ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <2>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in2>;
++ };
++ };
++ port@1 {
++ csi0ep2: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin2_max9286_des0ep2: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep2>;
++ };
++ vin2_ti964_des0ep2: endpoint@1 {
++ remote-endpoint = <&ti964_des0ep2>;
++ };
++ };
++ };
++};
++
++&vin3 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin3ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <3>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in3>;
++ };
++ };
++ port@1 {
++ csi0ep3: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin3_max9286_des0ep3: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep3>;
++ };
++ vin3_ti964_des0ep3: endpoint@1 {
++ remote-endpoint = <&ti964_des0ep3>;
++ };
++ };
++ };
++};
++
++&csi2_40 {
++ status = "okay";
++
++ virtual,channel {
++ csi2_vc0 {
++ data,type = "ycbcr422";
++ receive,vc = <0>;
++ };
++ csi2_vc1 {
++ data,type = "ycbcr422";
++ receive,vc = <1>;
++ };
++ csi2_vc2 {
++ data,type = "ycbcr422";
++ receive,vc = <2>;
++ };
++ csi2_vc3 {
++ data,type = "ycbcr422";
++ receive,vc = <3>;
++ };
++ };
++
++ port {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ csi2_40_ep: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ csi-rate = <300>;
++ };
++ };
++};
++
++&rcar_sound {
++ pinctrl-0 = <&sound_clk_pins>;
++
++ /* Multi DAI */
++ #sound-dai-cells = <1>;
++
++ rcar_sound,dai {
++ dai0 {
++ playback = <&ssi7>;
++ capture = <&ssi8>;
++ };
++
++ dai1 {
++ playback = <&ssi0 &src0 &dvc0>;
++ capture = <&ssi1 &src1 &dvc1>;
++ };
++
++ dai2 {
++ capture = <&ssi6>;
++ };
++
++ dai3 {
++ playback = <&ssi9>;
++ };
++ };
++};
++
++&sdhi3 {
++ pinctrl-0 = <&sdhi3_pins_3v3>;
++ pinctrl-names = "default";
++
++ vmmc-supply = <&wlan_en>;
++ vqmmc-supply = <&vccq_sdhi3>;
++ keep-power-in-suspend;
++ enable-sdio-wakeup;
++ bus-width = <4>;
++ no-1-8-v;
++ non-removable;
++ cap-power-off-card;
++ max-frequency = <26000000>;
++ status = "okay";
++
++ #address-cells = <1>;
++ #size-cells = <0>;
++ wlcore: wlcore@2 {
++ compatible = "ti,wl1837";
++ reg = <2>;
++ interrupt-parent = <&gpio1>;
++ interrupts = <25 IRQ_TYPE_EDGE_RISING>;
++ };
++};
++
++&xhci0 {
++ status = "okay";
++};
++
++&usb2_phy0 {
++ pinctrl-0 = <&usb0_pins>;
++ pinctrl-names = "default";
++
++ status = "okay";
++};
++
++&hsusb {
++ status = "okay";
++};
++
++&ehci0 {
++ status = "okay";
++};
++
++&ohci0 {
++ status = "okay";
++};
+--
+1.9.1
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0038-arm64-dts-r8a7795-salvator-x-view-add-ADAS-board.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0038-arm64-dts-r8a7795-salvator-x-view-add-ADAS-board.patch
new file mode 100644
index 0000000..3609bb1
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0038-arm64-dts-r8a7795-salvator-x-view-add-ADAS-board.patch
@@ -0,0 +1,587 @@
+From c5d2ada2089db7db1a059af37f371f6e2df213f4 Mon Sep 17 00:00:00 2001
+From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+Date: Wed, 4 Jan 2017 10:37:23 +0300
+Subject: [PATCH] arm64: dts: r8a7795-salvator-x-view: add ADAS board
+
+Salvator-X.View board on R8A7795 SoC
+
+Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+---
+ arch/arm64/boot/dts/renesas/Makefile | 3 +
+ .../dts/renesas/r8a7795-salvator-x-view.dts | 552 +++++++++++++++++++++
+ 2 files changed, 555 insertions(+)
+ create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts
+
+diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile
+index 32fb4d9..2a00759 100644
+--- a/arch/arm64/boot/dts/renesas/Makefile
++++ b/arch/arm64/boot/dts/renesas/Makefile
+@@ -4,6 +4,7 @@ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-salvator-x.dtb r8a7795-es1-h3ulcb.dtb
+ dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-x-view.dtb
+ dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-m3ulcb-view.dtb
+ dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-m3ulcb-kf.dtb
++dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-salvator-x-view.dtb
+
+ always := $(dtb-y)
+ clean-files := *.dtb
+diff --git a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts
+new file mode 100644
+index 0000000..3f3d66a
+--- /dev/null
++++ b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts
+@@ -0,0 +1,552 @@
++/*
++ * Device Tree Source for the Salvator-X.View board
++ *
++ * Copyright (C) 2016-2017 Renesas Electronics Corp.
++ * Copyright (C) 2015-2017 Cogent Embedded, Inc
++ *
++ * This file is licensed under the terms of the GNU General Public License
++ * version 2. This program is licensed "as is" without any warranty of any
++ * kind, whether express or implied.
++ */
++
++#include "r8a7795-salvator-x.dts"
++
++/ {
++ model = "Renesas Salvator-X.View board based on r8a7795";
++};
++
++&pfc {
++ can0_pins: can0 {
++ groups = "can0_data_a";
++ function = "can0";
++ };
++
++ can1_pins: can1 {
++ groups = "can1_data";
++ function = "can1";
++ };
++};
++
++&i2c4 {
++ /delete-node/hdmi-in@34;
++ /delete-node/composite-in@70;
++
++ ov106xx@0 {
++ compatible = "ovti,ov106xx";
++ reg = <0x60>;
++
++ port@0 {
++ ov106xx_in0: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin0ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des0ep0: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep0>;
++ };
++ };
++ };
++
++ ov106xx@1 {
++ compatible = "ovti,ov106xx";
++ reg = <0x61>;
++
++ port@0 {
++ ov106xx_in1: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin1ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des0ep1: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep1>;
++ };
++ };
++ };
++
++ ov106xx@2 {
++ compatible = "ovti,ov106xx";
++ reg = <0x62>;
++
++ port@0 {
++ ov106xx_in2: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin2ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des0ep2: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep2>;
++ };
++ };
++ };
++
++ ov106xx@3 {
++ compatible = "ovti,ov106xx";
++ reg = <0x63>;
++
++ port@0 {
++ ov106xx_in3: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin3ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_des0ep3: endpoint {
++ remote-endpoint = <&max9286_des0ep3>;
++ };
++ };
++ };
++
++ ov106xx@4 {
++ compatible = "ovti,ov106xx";
++ reg = <0x64>;
++
++ port@0 {
++ ov106xx_in4: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin4ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des1ep0: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep0>;
++ };
++ };
++ };
++
++ ov106xx@5 {
++ compatible = "ovti,ov106xx";
++ reg = <0x65>;
++
++ port@0 {
++ ov106xx_in5: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin5ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des1ep1: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep1>;
++ };
++ };
++ };
++
++ ov106xx@6 {
++ compatible = "ovti,ov106xx";
++ reg = <0x66>;
++
++ port@0 {
++ ov106xx_in6: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin6ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des1ep2: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep2>;
++ };
++ };
++ };
++
++ ov106xx@7 {
++ compatible = "ovti,ov106xx";
++ reg = <0x67>;
++
++ port@0 {
++ ov106xx_in7: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin7ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_des1ep3: endpoint {
++ remote-endpoint = <&max9286_des1ep3>;
++ };
++ };
++ };
++
++ max9286-max9271@0 {
++ compatible = "maxim,max9286-max9271";
++ reg = <0x4c>;
++ gpios = <&gpio6 30 GPIO_ACTIVE_LOW>;
++ maxim,sensor_delay = <0>;
++ maxim,links = <4>;
++ maxim,lanes = <4>;
++ maxim,resetb-gpio = <1>;
++ maxim,fsync-mode = "automatic";
++ maxim,timeout = <100>;
++ maxim,i2c-quirk = <0x6c>;
++
++ port@0 {
++ max9286_des0ep0: endpoint@0 {
++ max9271-addr = <0x50>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in0>;
++ };
++ max9286_des0ep1: endpoint@1 {
++ max9271-addr = <0x51>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in1>;
++ };
++ max9286_des0ep2: endpoint@2 {
++ max9271-addr = <0x52>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in2>;
++ };
++ max9286_des0ep3: endpoint@3 {
++ max9271-addr = <0x53>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in3>;
++ };
++ };
++ port@1 {
++ max9286_csi0ep0: endpoint {
++ csi-rate = <700>;
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ };
++
++ max9286-max9271@1 {
++ compatible = "maxim,max9286-max9271";
++ reg = <0x6c>;
++ maxim,sensor_delay = <0>;
++ maxim,links = <4>;
++ maxim,lanes = <4>;
++ maxim,resetb-gpio = <1>;
++ maxim,fsync-mode = "automatic";
++ maxim,timeout = <100>;
++
++ port@0 {
++ max9286_des1ep0: endpoint@0 {
++ max9271-addr = <0x54>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in4>;
++ };
++ max9286_des1ep1: endpoint@1 {
++ max9271-addr = <0x55>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in5>;
++ };
++ max9286_des1ep2: endpoint@2 {
++ max9271-addr = <0x56>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in6>;
++ };
++ max9286_des1ep3: endpoint@3 {
++ max9271-addr = <0x57>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in7>;
++ };
++ };
++ port@1 {
++ max9286_csi2ep0: endpoint {
++ csi-rate = <700>;
++ remote-endpoint = <&csi2_41_ep>;
++ };
++ };
++ };
++};
++
++&vin0 {
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin0ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in0>;
++ };
++ };
++ port@1 {
++ csi0ep0: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin0_max9286_des0ep0: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep0>;
++ };
++ };
++ };
++};
++
++&vin1 {
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin1ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <1>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in1>;
++ };
++ };
++ port@1 {
++ csi0ep1: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin1_max9286_des0ep1: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep1>;
++ };
++ };
++ };
++};
++
++&vin2 {
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin2ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <2>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in2>;
++ };
++ };
++ port@1 {
++ csi0ep2: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin2_max9286_des0ep2: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep2>;
++ };
++ };
++ };
++};
++
++&vin3 {
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin3ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <3>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in3>;
++ };
++ };
++ port@1 {
++ csi0ep3: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin3_max9286_des0ep3: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep3>;
++ };
++ };
++ };
++};
++
++&vin4 {
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin4ep0: endpoint {
++ csi,select = "csi41";
++ virtual,channel = <0>;
++ remote-endpoint = <&ov106xx_in4>;
++ data-lanes = <1 2 3 4>;
++ };
++ };
++ port@1 {
++ csi2ep0: endpoint {
++ remote-endpoint = <&csi2_41_ep>;
++ };
++ };
++ port@2 {
++ vin4_max9286_des1ep0: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep0>;
++ };
++ };
++ };
++};
++
++&vin5 {
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin5ep0: endpoint@0 {
++ csi,select = "csi41";
++ virtual,channel = <1>;
++ remote-endpoint = <&ov106xx_in5>;
++ data-lanes = <1 2 3 4>;
++ };
++ };
++ port@1 {
++ csi2ep1: endpoint {
++ remote-endpoint = <&csi2_41_ep>;
++ };
++ };
++ port@2 {
++ vin5_max9286_des1ep1: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep1>;
++ };
++ };
++ };
++};
++
++&vin6 {
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin6ep0: endpoint@0 {
++ csi,select = "csi41";
++ virtual,channel = <2>;
++ remote-endpoint = <&ov106xx_in6>;
++ data-lanes = <1 2 3 4>;
++ };
++ };
++ port@1 {
++ csi2ep2: endpoint {
++ remote-endpoint = <&csi2_41_ep>;
++ };
++ };
++ port@2 {
++ vin6_max9286_des1ep2: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep2>;
++ };
++ };
++ };
++};
++
++&vin7 {
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin7ep0: endpoint@0 {
++ csi,select = "csi41";
++ virtual,channel = <3>;
++ remote-endpoint = <&ov106xx_in7>;
++ data-lanes = <1 2 3 4>;
++ };
++ };
++ port@1 {
++ csi2ep3: endpoint {
++ remote-endpoint = <&csi2_41_ep>;
++ };
++ };
++ port@2 {
++ vin7_max9286_des1ep3: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep3>;
++ };
++ };
++ };
++};
++
++&csi2_20 {
++ status = "disabled";
++ /delete-node/ports;
++};
++
++&csi2_40 {
++ /delete-node/ports;
++
++ virtual,channel {
++ csi2_vc0 {
++ data,type = "ycbcr422";
++ receive,vc = <0>;
++ };
++ csi2_vc1 {
++ data,type = "ycbcr422";
++ receive,vc = <1>;
++ };
++ csi2_vc2 {
++ data,type = "ycbcr422";
++ receive,vc = <2>;
++ };
++ csi2_vc3 {
++ data,type = "ycbcr422";
++ receive,vc = <3>;
++ };
++ };
++
++ port {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ csi2_40_ep: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ csi-rate = <300>;
++ };
++ };
++};
++
++&csi2_41 {
++ status = "okay";
++
++ virtual,channel {
++ csi2_vc0 {
++ data,type = "ycbcr422";
++ receive,vc = <0>;
++ };
++ csi2_vc1 {
++ data,type = "ycbcr422";
++ receive,vc = <1>;
++ };
++ csi2_vc2 {
++ data,type = "ycbcr422";
++ receive,vc = <2>;
++ };
++ csi2_vc3 {
++ data,type = "ycbcr422";
++ receive,vc = <3>;
++ };
++ };
++
++ port {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ csi2_41_ep: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ csi-rate = <300>;
++ };
++ };
++};
++
++&can0 {
++ pinctrl-0 = <&can0_pins>;
++ pinctrl-names = "default";
++ status = "okay";
++};
++
++&can1 {
++ pinctrl-0 = <&can1_pins>;
++ pinctrl-names = "default";
++ status = "okay";
++};
+--
+1.9.1
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0039-arm64-dts-r8a7795-h3ulcb-view-add-ADAS-board.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0039-arm64-dts-r8a7795-h3ulcb-view-add-ADAS-board.patch
new file mode 100644
index 0000000..f8304df
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0039-arm64-dts-r8a7795-h3ulcb-view-add-ADAS-board.patch
@@ -0,0 +1,581 @@
+From 24d2ada2089db7db1a059af37f371f6e2df213f4 Mon Sep 17 00:00:00 2001
+From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+Date: Wed, 4 Jan 2017 10:37:23 +0300
+Subject: [PATCH] arm64: dts: r8a7795-h3ulcb-view: add ADAS board
+
+H3ULCB.View board on R8A7795 SoC
+
+Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+---
+ arch/arm64/boot/dts/renesas/Makefile | 1 +
+ .../boot/dts/renesas/r8a7795-h3ulcb-view.dts | 546 +++++++++++++++++++++
+ 2 files changed, 547 insertions(+)
+ create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts
+
+diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile
+index 2a00759..43aa35d 100644
+--- a/arch/arm64/boot/dts/renesas/Makefile
++++ b/arch/arm64/boot/dts/renesas/Makefile
+@@ -6,6 +6,7 @@ dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-xs.dtb
+ dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-m3ulcb-view.dtb
+ dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-m3ulcb-kf.dtb
+ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-salvator-x-view.dtb
++dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-view.dtb
+
+ always := $(dtb-y)
+ clean-files := *.dtb
+diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts
+new file mode 100644
+index 0000000..de56fa4
+--- /dev/null
++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts
+@@ -0,0 +1,546 @@
++/*
++ * Device Tree Source for the H3ULCB.View board
++ *
++ * Copyright (C) 2016-2017 Renesas Electronics Corp.
++ * Copyright (C) 2016-2017 Cogent Embedded, Inc.
++ *
++ * This file is licensed under the terms of the GNU General Public License
++ * version 2. This program is licensed "as is" without any warranty of any
++ * kind, whether express or implied.
++ */
++
++#include "r8a7795-h3ulcb.dts"
++
++/ {
++ model = "Renesas H3ULCB.View board based on r8a7795";
++};
++
++&i2c4 {
++ ov106xx@0 {
++ compatible = "ovti,ov106xx";
++ reg = <0x60>;
++
++ port@0 {
++ ov106xx_in0: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin0ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des0ep0: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep0>;
++ };
++ };
++ };
++
++ ov106xx@1 {
++ compatible = "ovti,ov106xx";
++ reg = <0x61>;
++
++ port@0 {
++ ov106xx_in1: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin1ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des0ep1: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep1>;
++ };
++ };
++ };
++
++ ov106xx@2 {
++ compatible = "ovti,ov106xx";
++ reg = <0x62>;
++
++ port@0 {
++ ov106xx_in2: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin2ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des0ep2: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep2>;
++ };
++ };
++ };
++
++ ov106xx@3 {
++ compatible = "ovti,ov106xx";
++ reg = <0x63>;
++
++ port@0 {
++ ov106xx_in3: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin3ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_des0ep3: endpoint {
++ remote-endpoint = <&max9286_des0ep3>;
++ };
++ };
++ };
++
++ ov106xx@4 {
++ compatible = "ovti,ov106xx";
++ reg = <0x64>;
++
++ port@0 {
++ ov106xx_in4: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin4ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des1ep0: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep0>;
++ };
++ };
++ };
++
++ ov106xx@5 {
++ compatible = "ovti,ov106xx";
++ reg = <0x65>;
++
++ port@0 {
++ ov106xx_in5: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin5ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des1ep1: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep1>;
++ };
++ };
++ };
++
++ ov106xx@6 {
++ compatible = "ovti,ov106xx";
++ reg = <0x66>;
++
++ port@0 {
++ ov106xx_in6: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin6ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des1ep2: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep2>;
++ };
++ };
++ };
++
++ ov106xx@7 {
++ compatible = "ovti,ov106xx";
++ reg = <0x67>;
++
++ port@0 {
++ ov106xx_in7: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin7ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_des1ep3: endpoint {
++ remote-endpoint = <&max9286_des1ep3>;
++ };
++ };
++ };
++
++ max9286-max9271@0 {
++ compatible = "maxim,max9286-max9271";
++ reg = <0x4c>;
++ gpios = <&gpio2 6 GPIO_ACTIVE_HIGH>;
++ maxim,sensor_delay = <0>;
++ maxim,links = <4>;
++ maxim,lanes = <4>;
++ maxim,resetb-gpio = <1>;
++ maxim,fsync-mode = "automatic";
++ maxim,timeout = <100>;
++ maxim,i2c-quirk = <0x6c>;
++
++ port@0 {
++ max9286_des0ep0: endpoint@0 {
++ max9271-addr = <0x50>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in0>;
++ };
++ max9286_des0ep1: endpoint@1 {
++ max9271-addr = <0x51>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in1>;
++ };
++ max9286_des0ep2: endpoint@2 {
++ max9271-addr = <0x52>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in2>;
++ };
++ max9286_des0ep3: endpoint@3 {
++ max9271-addr = <0x53>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in3>;
++ };
++ };
++ port@1 {
++ max9286_csi0ep0: endpoint {
++ csi-rate = <700>;
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ };
++
++ max9286-max9271@1 {
++ compatible = "maxim,max9286-max9271";
++ reg = <0x6c>;
++ gpios = <&gpio5 25 GPIO_ACTIVE_HIGH>;
++ maxim,sensor_delay = <0>;
++ maxim,links = <4>;
++ maxim,lanes = <4>;
++ maxim,resetb-gpio = <1>;
++ maxim,fsync-mode = "automatic";
++ maxim,timeout = <100>;
++
++ port@0 {
++ max9286_des1ep0: endpoint@0 {
++ max9271-addr = <0x54>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in4>;
++ };
++ max9286_des1ep1: endpoint@1 {
++ max9271-addr = <0x55>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in5>;
++ };
++ max9286_des1ep2: endpoint@2 {
++ max9271-addr = <0x56>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in6>;
++ };
++ max9286_des1ep3: endpoint@3 {
++ max9271-addr = <0x57>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in7>;
++ };
++ };
++ port@1 {
++ max9286_csi2ep0: endpoint {
++ csi-rate = <700>;
++ remote-endpoint = <&csi2_41_ep>;
++ };
++ };
++ };
++};
++
++&pcie_bus_clk {
++ clock-frequency = <100000000>;
++ status = "okay";
++};
++
++&pciec1 {
++ status = "okay";
++};
++
++&vin0 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin0ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in0>;
++ };
++ };
++ port@1 {
++ csi0ep0: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin0_max9286_des0ep0: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep0>;
++ };
++ };
++ };
++};
++
++&vin1 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin1ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <1>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in1>;
++ };
++ };
++ port@1 {
++ csi0ep1: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin1_max9286_des0ep1: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep1>;
++ };
++ };
++ };
++};
++
++&vin2 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin2ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <2>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in2>;
++ };
++ };
++ port@1 {
++ csi0ep2: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin2_max9286_des0ep2: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep2>;
++ };
++ };
++ };
++};
++
++&vin3 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin3ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <3>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in3>;
++ };
++ };
++ port@1 {
++ csi0ep3: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin3_max9286_des0ep3: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep3>;
++ };
++ };
++ };
++};
++
++&vin4 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin4ep0: endpoint {
++ csi,select = "csi41";
++ virtual,channel = <0>;
++ remote-endpoint = <&ov106xx_in4>;
++ data-lanes = <1 2 3 4>;
++ };
++ };
++ port@1 {
++ csi2ep0: endpoint {
++ remote-endpoint = <&csi2_41_ep>;
++ };
++ };
++ port@2 {
++ vin4_max9286_des1ep0: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep0>;
++ };
++ };
++ };
++};
++
++&vin5 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin5ep0: endpoint@0 {
++ csi,select = "csi41";
++ virtual,channel = <1>;
++ remote-endpoint = <&ov106xx_in5>;
++ data-lanes = <1 2 3 4>;
++ };
++ };
++ port@1 {
++ csi2ep1: endpoint {
++ remote-endpoint = <&csi2_41_ep>;
++ };
++ };
++ port@2 {
++ vin5_max9286_des1ep1: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep1>;
++ };
++ };
++ };
++};
++
++&vin6 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin6ep0: endpoint@0 {
++ csi,select = "csi41";
++ virtual,channel = <2>;
++ remote-endpoint = <&ov106xx_in6>;
++ data-lanes = <1 2 3 4>;
++ };
++ };
++ port@1 {
++ csi2ep2: endpoint {
++ remote-endpoint = <&csi2_41_ep>;
++ };
++ };
++ port@2 {
++ vin6_max9286_des1ep2: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep2>;
++ };
++ };
++ };
++};
++
++&vin7 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin7ep0: endpoint@0 {
++ csi,select = "csi41";
++ virtual,channel = <3>;
++ remote-endpoint = <&ov106xx_in7>;
++ data-lanes = <1 2 3 4>;
++ };
++ };
++ port@1 {
++ csi2ep3: endpoint {
++ remote-endpoint = <&csi2_41_ep>;
++ };
++ };
++ port@2 {
++ vin7_max9286_des1ep3: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep3>;
++ };
++ };
++ };
++};
++
++&csi2_40 {
++ status = "okay";
++
++ virtual,channel {
++ csi2_vc0 {
++ data,type = "ycbcr422";
++ receive,vc = <0>;
++ };
++ csi2_vc1 {
++ data,type = "ycbcr422";
++ receive,vc = <1>;
++ };
++ csi2_vc2 {
++ data,type = "ycbcr422";
++ receive,vc = <2>;
++ };
++ csi2_vc3 {
++ data,type = "ycbcr422";
++ receive,vc = <3>;
++ };
++ };
++
++ port {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ csi2_40_ep: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ csi-rate = <300>;
++ };
++ };
++};
++
++&csi2_41 {
++ status = "okay";
++
++ virtual,channel {
++ csi2_vc0 {
++ data,type = "ycbcr422";
++ receive,vc = <0>;
++ };
++ csi2_vc1 {
++ data,type = "ycbcr422";
++ receive,vc = <1>;
++ };
++ csi2_vc2 {
++ data,type = "ycbcr422";
++ receive,vc = <2>;
++ };
++ csi2_vc3 {
++ data,type = "ycbcr422";
++ receive,vc = <3>;
++ };
++ };
++
++ port {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ csi2_41_ep: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ csi-rate = <300>;
++ };
++ };
++};
+--
+1.9.1
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-r8a7795-h3ulcb-had-add-ADAS-board.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-r8a7795-h3ulcb-had-add-ADAS-board.patch
new file mode 100644
index 0000000..b669d26
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-r8a7795-h3ulcb-had-add-ADAS-board.patch
@@ -0,0 +1,314 @@
+From 30240b74fe0b5c851127996328504e86a9fc4407 Mon Sep 17 00:00:00 2001
+From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+Date: Wed, 4 Jan 2017 10:41:48 +0300
+Subject: [PATCH] arm64: dts: r8a7795-h3ulcb-had: add ADAS board
+
+H3ULCB.HAD board on R8A7795 SoC
+
+Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+---
+ arch/arm64/boot/dts/renesas/Makefile | 1 +
+ .../boot/dts/renesas/r8a7795-h3ulcb-had-alfa.dts | 22 +++
+ .../boot/dts/renesas/r8a7795-h3ulcb-had-beta.dts | 23 +++
+ .../arm64/boot/dts/renesas/r8a7795-h3ulcb-had.dtsi | 218 +++++++++++++++++++++
+ 4 files changed, 264 insertions(+)
+ create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-had-alfa.dts
+ create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-had-beta.dts
+ create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-had.dtsi
+
+diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile
+index 387652e..9dad6dc 100644
+--- a/arch/arm64/boot/dts/renesas/Makefile
++++ b/arch/arm64/boot/dts/renesas/Makefile
+@@ -14,6 +14,7 @@ dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-m3ulcb-view.dtb
+ dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-m3ulcb-kf.dtb
+ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-salvator-x-view.dtb
+ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-view.dtb
++dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-had-alfa.dtb r8a7795-h3ulcb-had-beta.dtb
+
+ always := $(dtb-y)
+ clean-files := *.dtb
+diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-had-alfa.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-had-alfa.dts
+new file mode 100644
+index 0000000..ae115bd
+--- /dev/null
++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-had-alfa.dts
+@@ -0,0 +1,22 @@
++/*
++ * Device Tree Source for the H3ULCB.HAD board Alfa side
++ *
++ * Copyright (C) 2017 Renesas Electronics Corp.
++ * Copyright (C) 2017 Cogent Embedded, Inc.
++ *
++ * This file is licensed under the terms of the GNU General Public License
++ * version 2. This program is licensed "as is" without any warranty of any
++ * kind, whether express or implied.
++ */
++
++#include "r8a7795-h3ulcb-had.dtsi"
++
++/ {
++ model = "Renesas H3ULCB.HAD board Alfa side based on r8a7795";
++};
++
++&pciec0 {
++ status = "okay";
++
++ /* Root complex */
++};
+diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-had-beta.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-had-beta.dts
+new file mode 100644
+index 0000000..805067e
+--- /dev/null
++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-had-beta.dts
+@@ -0,0 +1,23 @@
++/*
++ * Device Tree Source for the H3ULCB.HAD board Beta side
++ *
++ * Copyright (C) 2017 Renesas Electronics Corp.
++ * Copyright (C) 2017 Cogent Embedded, Inc.
++ *
++ * This file is licensed under the terms of the GNU General Public License
++ * version 2. This program is licensed "as is" without any warranty of any
++ * kind, whether express or implied.
++ */
++
++#include "r8a7795-h3ulcb-had.dtsi"
++
++/ {
++ model = "Renesas H3ULCB.HAD board Beta side based on r8a7795";
++};
++
++&pciec0 {
++ status = "okay";
++
++ /* Endpoint */
++ endpoint;
++};
+diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-had.dtsi b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-had.dtsi
+new file mode 100644
+index 0000000..d146938
+--- /dev/null
++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-had.dtsi
+@@ -0,0 +1,218 @@
++/*
++ * Device Tree Source for the H3ULCB.HAD board on r8a7795
++ *
++ * Copyright (C) 2016-2017 Renesas Electronics Corp.
++ * Copyright (C) 2016-2017 Cogent Embedded, Inc.
++ *
++ * This file is licensed under the terms of the GNU General Public License
++ * version 2. This program is licensed "as is" without any warranty of any
++ * kind, whether express or implied.
++ */
++
++/*
++ * MSIOF0 - /dev/spidev1.0 connected to FPGA ethernet switch (both sides)
++ * MSIOF1 - /dev/spidev2.0 connected to RH850 (sideA to CSIH1, sideB to CSIH0)
++ */
++
++#include "r8a7795-h3ulcb-view.dts"
++
++/ {
++ model = "Renesas H3ULCB.HAD board based on r8a7795";
++
++ aliases {
++ spi1 = &spi0_gpio;
++ spi2 = &spi1_gpio;
++ };
++
++ chosen {
++ stdout-path = "serial1:115200n8";
++ };
++
++ spi0_gpio: spi_gpio@0 {
++ compatible = "spi-gpio";
++ num-chipselects = <1>;
++ gpio-sck = <&gpio5 17 0>;
++ gpio-mosi = <&gpio5 20 0>;
++ gpio-miso = <&gpio5 22 0>;
++ cs-gpios = <&gpio5 19 0>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ spidev@0 {
++ compatible = "spi-gpio";
++ reg = <0>;
++ spi-max-frequency = <2000000>;
++ spi-cpha;
++ spi-cpol;
++ };
++ };
++
++ spi1_gpio: spi_gpio@1 {
++ compatible = "spi-gpio";
++ num-chipselects = <1>;
++ gpio-sck = <&gpio6 8 0>;
++ gpio-mosi = <&gpio6 7 0>;
++ gpio-miso = <&gpio6 10 0>;
++ cs-gpios = <&gpio6 5 0>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ spidev@0 {
++ compatible = "spi-gpio";
++ reg = <0>;
++ spi-max-frequency = <2000000>;
++ spi-cpha;
++ spi-cpol;
++ };
++ };
++
++ hdmi1-out {
++ compatible = "hdmi-connector";
++ type = "a";
++
++ port {
++ hdmi1_con: endpoint {
++ remote-endpoint = <&rcar_dw_hdmi1_out>;
++ };
++ };
++ };
++};
++
++&du {
++ ports {
++ port@1 {
++ endpoint {
++ remote-endpoint = <&rcar_dw_hdmi0_in>;
++ };
++ };
++ port@2 {
++ endpoint {
++ remote-endpoint = <&rcar_dw_hdmi1_in>;
++ };
++ };
++ };
++};
++
++&hdmi1 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ port@0 {
++ reg = <0>;
++ rcar_dw_hdmi1_in: endpoint {
++ remote-endpoint = <&du_out_hdmi1>;
++ };
++ };
++ port@1 {
++ reg = <1>;
++ rcar_dw_hdmi1_out: endpoint {
++ remote-endpoint = <&hdmi1_con>;
++ };
++ };
++ };
++};
++
++&pfc {
++ scif1_pins: scif1 {
++ groups = "scif1_data_a";
++ function = "scif1";
++ };
++
++ msiof0_pins: spi1 {
++ groups = "msiof0_clk", "msiof0_rxd", "msiof0_txd",
++ "msiof0_ss1";
++ function = "msiof0";
++ };
++
++ msiof1_pins: spi2 {
++ groups = "msiof1_clk_a", "msiof1_rxd_a", "msiof1_txd_a",
++ "msiof1_ss1_a";
++ function = "msiof1";
++ };
++
++ sound_clk_pins: sound-clk {
++ groups = "audio_clk_a_a", "audio_clk_b_a", "audio_clk_c_a",
++ "audio_clkout_a" /*, "audio_clkout3_a"*/;
++ function = "audio_clk";
++ };
++
++ usb31_pins: usb31 {
++ groups = "usb31";
++ function = "usb31";
++ };
++
++ can0_pins: can0 {
++ groups = "can0_data_a";
++ function = "can0";
++ };
++
++ canfd0_pins: canfd0 {
++ groups = "canfd0_data_a";
++ function = "canfd0";
++ };
++};
++
++&scif1 {
++ pinctrl-0 = <&scif1_pins>;
++ pinctrl-names = "default";
++ status = "okay";
++};
++
++&avb {
++ /delete-property/phy-handle;
++ /delete-property/phy-gpios;
++ /delete-node/ethernet-phy@0;
++
++ fixed-link {
++ speed = <1000>;
++ full-duplex;
++ };
++};
++
++&msiof0 {
++ pinctrl-0 = <&msiof0_pins>;
++ pinctrl-names = "default";
++ status = "disabled";
++ cs-gpios = <&gpio5 19 0>;
++
++ spidev@0 {
++ compatible = "renesas,sh-msiof";
++ reg = <0>;
++ spi-max-frequency = <66666666>;
++ spi-cpha;
++ spi-cpol;
++ };
++};
++
++&msiof1 {
++ status = "disabled";
++ cs-gpios = <&gpio6 5 0>;
++};
++
++&can0 {
++ pinctrl-0 = <&can0_pins>;
++ pinctrl-names = "default";
++ status = "disabled";
++
++ renesas,can-clock-select = <0x0>;
++ gpios = <&gpio2 6 GPIO_ACTIVE_HIGH /* enable - shared with camera board */
++ &gpio2 7 GPIO_ACTIVE_LOW /* standby */
++ >;
++};
++
++&canfd {
++ pinctrl-0 = <&canfd0_pins>;
++ pinctrl-names = "default";
++ status = "okay";
++
++ renesas,can-clock-select = <0x0>;
++ gpios = <&gpio2 6 GPIO_ACTIVE_HIGH /* enable - shared with camera board */
++ &gpio2 7 GPIO_ACTIVE_LOW /* standby */
++ >;
++
++ channel0 {
++ status = "okay";
++ };
++};
+--
+1.9.1
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0041-arm64-dts-r8a7795-h3ulcb-kf-add-ADAS-board.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0041-arm64-dts-r8a7795-h3ulcb-kf-add-ADAS-board.patch
new file mode 100644
index 0000000..6898c49
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0041-arm64-dts-r8a7795-h3ulcb-kf-add-ADAS-board.patch
@@ -0,0 +1,1714 @@
+From f1f043eab3dd06552b3600af1caf50e535f766f1 Mon Sep 17 00:00:00 2001
+From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+Date: Wed, 4 Jan 2017 10:37:23 +0300
+Subject: [PATCH] arm64: dts: r8a7795-h3ulcb-kf: add ADAS board
+
+H3ULCB.View board on R8A7795 SoC
+
+Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+---
+ arch/arm64/boot/dts/renesas/Makefile | 1 +
+ .../boot/dts/renesas/r8a7795-h3ulcb-kf.dts | 1683 ++++++++++++++++++++
+ 2 files changed, 1684 insertions(+)
+ create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts
+
+diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile
+index 06207e3..a5dd1d3 100644
+--- a/arch/arm64/boot/dts/renesas/Makefile
++++ b/arch/arm64/boot/dts/renesas/Makefile
+@@ -10,6 +10,7 @@ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-h3ulcb-view.dtb
+ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-salvator-x-view.dtb
+ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-view.dtb
+ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-had-alfa.dtb r8a7795-h3ulcb-had-beta.dtb
++dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-kf.dtb
+
+ always := $(dtb-y)
+ clean-files := *.dtb
+diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts
+new file mode 100644
+index 0000000..50a37e0
+--- /dev/null
++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts
+@@ -0,0 +1,1679 @@
++/*
++ * Device Tree Source for the H3ULCB Kingfisher board on r8a7795
++ *
++ * Copyright (C) 2017 Renesas Electronics Corp.
++ * Copyright (C) 2017 Cogent Embedded, Inc.
++ *
++ * This file is licensed under the terms of the GNU General Public License
++ * version 2. This program is licensed "as is" without any warranty of any
++ * kind, whether express or implied.
++ */
++
++#include "r8a7795-h3ulcb.dts"
++
++/ {
++ model = "Renesas H3ULCB Kingfisher board based on r8a7795";
++
++ aliases {
++ serial1 = &hscif4;
++ };
++
++ snd_clk: snd_clk {
++ compatible = "fixed-clock";
++ #clock-cells = <0>;
++ clock-frequency = <24576000>;
++ clock-output-names = "scki";
++ };
++
++ wlan_en: regulator@4 {
++ compatible = "regulator-fixed";
++ regulator-name = "wlan-en-regulator";
++
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++
++ gpio = <&gpio_ext_20 4 GPIO_ACTIVE_HIGH>;
++ enable-active-high;
++ };
++
++ vccq_sdhi3: regulator@5 {
++ compatible = "regulator-fixed";
++
++ regulator-name = "SDHI3 VccQ";
++ /* external voltage translator to 1.8V */
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ };
++
++ codec_en_reg: regulator@6 {
++ compatible = "regulator-fixed";
++ regulator-name = "codec-en-regulator";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++
++ gpio = <&gpio_ext_20 15 0>;
++
++ /* delay - CHECK */
++ startup-delay-us = <70000>;
++ enable-active-high;
++ };
++
++ amp_en_reg: regulator@7 {
++ compatible = "regulator-fixed";
++ regulator-name = "amp-en-regulator";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++
++ gpio = <&gpio_ext_20 0 0>;
++
++ startup-delay-us = <0>;
++ enable-active-high;
++ };
++
++ lvds_switch: regulator@8 {
++ compatible = "regulator-fixed";
++ regulator-name = "lvds_on";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ gpio = <&gpio1 24 0>;
++ enable-active-high;
++ regulator-always-on;
++ };
++
++ sdio_switch: regulator@9 {
++ compatible = "regulator-fixed";
++ regulator-name = "wifi_on";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ gpio = <&gpio_ext_20 5 0>;
++ enable-active-low;
++ regulator-always-on;
++ };
++
++ sound_switch: regulator@10 {
++ compatible = "regulator-fixed";
++ regulator-name = "pcm3168a_on";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ gpio = <&gpio_ext_21 5 0>;
++ enable-active-low;
++ regulator-always-on;
++ };
++
++ radio_switch: regulator@11 {
++ compatible = "regulator-fixed";
++ regulator-name = "radio_on";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ gpio = <&gpio_ext_20 13 GPIO_ACTIVE_HIGH>;
++ enable-active-high;
++ regulator-always-on;
++ };
++
++ kim {
++ compatible = "kim";
++ nshutdown_gpio = <343>; /* pca9535@i2c2.0x20 pin 3 */
++ /* serial1 */
++ dev_name = "/dev/ttySC1";
++ flow_cntrl = <1>;
++ /* int div 8 hscif@26.6666656MHz */
++ baud_rate = <3333332>;
++ };
++
++ btwilink {
++ compatible = "btwilink";
++ };
++
++ sound_ext: sound@0 {
++ pinctrl-0 = <&sound_0_pins>;
++ pinctrl-names = "default";
++ compatible = "simple-audio-card";
++
++ simple-audio-card,format = "left_j";
++ simple-audio-card,name = "pcm3168a";
++
++ simple-audio-card,bitclock-master = <&sound_ext_master>;
++ simple-audio-card,frame-master = <&sound_ext_master>;
++ sound_ext_master: simple-audio-card,cpu@0 {
++ sound-dai = <&rcar_sound 0>;
++ dai-tdm-slot-num = <8>;
++ dai-tdm-slot-width = <32>;
++ };
++
++ simple-audio-card,codec@0 {
++ sound-dai = <&pcm3168a>;
++ dai-tdm-slot-num = <8>;
++ dai-tdm-slot-width = <32>;
++ system-clock-frequency = <24576000>;
++ };
++ };
++
++ /delete-node/sound;
++
++ rsnd_ak4613: sound@1 {
++ pinctrl-0 = <&sound_1_pins>;
++ pinctrl-names = "default";
++ compatible = "simple-audio-card";
++
++ simple-audio-card,format = "left_j";
++ simple-audio-card,name = "ak4613";
++
++ simple-audio-card,bitclock-master = <&sndcpu>;
++ simple-audio-card,frame-master = <&sndcpu>;
++
++ sndcpu: simple-audio-card,cpu@1 {
++ sound-dai = <&rcar_sound 1>;
++ };
++
++ sndcodec: simple-audio-card,codec@1 {
++ sound-dai = <&ak4613>;
++ };
++ };
++
++ sound_radio: sound@2 {
++ pinctrl-0 = <&sound_2_pins>;
++ pinctrl-names = "default";
++ compatible = "simple-audio-card";
++
++ simple-audio-card,format = "i2s";
++ simple-audio-card,name = "radio";
++
++ simple-audio-card,bitclock-master = <&sound_radio_master>;
++ simple-audio-card,frame-master = <&sound_radio_master>;
++ simple-audio-card,cpu@2 {
++ sound-dai = <&rcar_sound 2>;
++ };
++
++ sound_radio_master: simple-audio-card,codec@2 {
++ sound-dai = <&radio>;
++ system-clock-frequency = <12288000>;
++ };
++ };
++
++ sound_amp: sound@3 {
++ pinctrl-0 = <&sound_9_pins>;
++ pinctrl-names = "default";
++ compatible = "simple-audio-card";
++
++ simple-audio-card,name = "power_amp";
++
++ simple-audio-card,dai-link@0 {
++ format = "i2s";
++ cpu {
++ sound-dai = <&rcar_sound 3>;
++ };
++ codec {
++ sound-dai = <&max98371_L>;
++ };
++ };
++ simple-audio-card,dai-link@1 {
++ format = "i2s";
++ cpu {
++ sound-dai = <&rcar_sound 3>;
++ };
++ codec {
++ sound-dai = <&max98371_R>;
++ };
++ };
++ simple-audio-card,dai-link@2 {
++ format = "i2s";
++ cpu {
++ sound-dai = <&rcar_sound 3>;
++ };
++ codec {
++ sound-dai = <&max98371_RL>;
++ };
++ };
++ simple-audio-card,dai-link@3 {
++ format = "i2s";
++ cpu {
++ sound-dai = <&rcar_sound 3>;
++ };
++ codec {
++ sound-dai = <&max98371_RR>;
++ };
++ };
++ simple-audio-card,dai-link@4 {
++ format = "i2s";
++ cpu {
++ sound-dai = <&rcar_sound 3>;
++ };
++ codec {
++ sound-dai = <&max98371_C>;
++ };
++ };
++ simple-audio-card,dai-link@5 {
++ format = "i2s";
++ cpu {
++ sound-dai = <&rcar_sound 3>;
++ };
++ codec {
++ sound-dai = <&max98371_S>;
++ };
++ };
++ };
++
++ lvds-encoder {
++ compatible = "thine,thc63lvdm83d";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ port@0 {
++ reg = <0>;
++ lvds_enc_in: endpoint {
++ remote-endpoint = <&du_out_lvds0>;
++ };
++ };
++ port@1 {
++ reg = <1>;
++ lvds_enc_out: endpoint {
++ remote-endpoint = <&lvds_in>;
++ };
++ };
++ };
++ };
++
++ lvds {
++ compatible = "lvds-connector";
++
++ width-mm = <210>;
++ height-mm = <158>;
++
++ panel-timing {
++ /* 1280x800 @60Hz */
++ clock-frequency = <65000000>;
++ hactive = <1280>;
++ vactive = <800>;
++ hsync-len = <40>;
++ hfront-porch = <80>;
++ hback-porch = <40>;
++ vfront-porch = <14>;
++ vback-porch = <14>;
++ vsync-len = <4>;
++ };
++
++ port {
++ lvds_in: endpoint {
++ remote-endpoint = <&lvds_enc_out>;
++ };
++ };
++ };
++
++ radio: si468x@0 {
++ compatible = "si,si468x-pcm";
++ status = "okay";
++
++ #sound-dai-cells = <0>;
++ };
++};
++
++&pfc {
++ hscif4_pins: hscif4 {
++ groups = "hscif4_data_a", "hscif4_ctrl";
++ function = "hscif4";
++ };
++
++ sdhi3_pins_3v3: sd3_3v3 {
++ groups = "sdhi3_data4", "sdhi3_ctrl";
++ function = "sdhi3";
++ power-source = <3300>;
++ };
++
++ sound_0_pins: sound0 {
++ groups = "ssi78_ctrl", "ssi7_data", "ssi8_data";
++ function = "ssi";
++ };
++
++ sound_1_pins: sound1 {
++ groups = "ssi01239_ctrl", "ssi0_data", "ssi1_data_a";
++ function = "ssi";
++ };
++
++ sound_2_pins: sound2 {
++ groups = "ssi6_ctrl", "ssi6_data";
++ function = "ssi";
++ };
++
++ sound_9_pins: sound2 {
++ groups = "ssi9_ctrl_b", "ssi9_data_b";
++ function = "ssi";
++ };
++
++ usb0_pins: usb0 {
++ groups = "usb0";
++ function = "usb0";
++ };
++};
++
++&gpio0 {
++ video_a_irq {
++ gpio-hog;
++ gpios = <13 GPIO_ACTIVE_HIGH>;
++ input;
++ line-name = "Video-A irq";
++ };
++
++ video_b_irq {
++ gpio-hog;
++ gpios = <14 GPIO_ACTIVE_HIGH>;
++ input;
++ line-name = "Video-B irq";
++ };
++
++ gpioext_2_20_irq {
++ gpio-hog;
++ gpios = <15 GPIO_ACTIVE_HIGH>;
++ input;
++ line-name = "0x20@i2c2 irq";
++ };
++};
++
++&gpio1 {
++ gpioext_2_21_irq {
++ gpio-hog;
++ gpios = <15 GPIO_ACTIVE_HIGH>;
++ input;
++ line-name = "0x21@i2c2 irq";
++ };
++
++ wifi_irq {
++ gpio-hog;
++ gpios = <25 GPIO_ACTIVE_HIGH>;
++ input;
++ line-name = "wifi irq";
++ };
++};
++
++&gpio5 {
++ touch_irq {
++ gpio-hog;
++ gpios = <6 GPIO_ACTIVE_HIGH>;
++ input;
++ line-name = "touch irq";
++ };
++
++ /* From TI forum */
++ /* BT_AUD_OUT should be pulled low when WL_EN is activated. */
++ /* in case it isn't, wilink8 ends up in one of the test modes that introduces various issues */
++ bt_strap {
++ gpio-hog;
++ gpios = <14 GPIO_ACTIVE_HIGH>;
++ output-low;
++ line-name = "BT strap pin";
++ };
++};
++
++&gpio7 {
++ gpioext_2_21_irq {
++ gpio-hog;
++ gpios = <3 GPIO_ACTIVE_HIGH>;
++ input;
++ line-name = "0x21@i2c4 irq";
++ };
++};
++
++&hscif4 {
++ pinctrl-0 = <&hscif4_pins>;
++ pinctrl-names = "default";
++ ctsrts;
++
++ status = "okay";
++};
++
++&i2c2 {
++ clock-frequency = <400000>;
++
++ gpio_ext_20: pca9535@20 {
++ compatible = "nxp,pca9535";
++ reg = <0x20>;
++ gpio-controller;
++ #gpio-cells = <2>;
++ interrupt-controller;
++ interrupt-parent = <&gpio0>;
++ interrupts = <15 IRQ_TYPE_EDGE_FALLING>;
++ };
++
++ gpio_ext_21: pca9535@21 {
++ compatible = "nxp,pca9535";
++ reg = <0x21>;
++ gpio-controller;
++ #gpio-cells = <2>;
++ interrupt-controller;
++ interrupt-parent = <&gpio1>;
++ interrupts = <15 IRQ_TYPE_EDGE_FALLING>;
++ };
++
++ i2cswitch2@74 {
++ compatible = "nxp,pca9548";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <0x74>;
++ reset-gpios = <&gpio6 5 GPIO_ACTIVE_LOW>;
++
++ i2c@0 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <0>;
++ /* BCM node(s) */
++ };
++
++ i2c@1 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <1>;
++ /* USB3.0 HUB node(s) */
++ };
++
++ i2c@2 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <2>;
++ /* Power amp node(s) */
++
++ max98371_L: max98371@0x31 {
++ compatible = "maxim,max98371";
++ reg = <0x31>;
++ #sound-dai-cells = <0>;
++ };
++ max98371_R: max98371@0x32 {
++ compatible = "maxim,max98371";
++ reg = <0x32>;
++ #sound-dai-cells = <0>;
++ };
++ max98371_RL: max98371@0x33 {
++ compatible = "maxim,max98371";
++ reg = <0x33>;
++ #sound-dai-cells = <0>;
++ };
++ max98371_RR: max98371@0x34 {
++ compatible = "maxim,max98371";
++ reg = <0x34>;
++ #sound-dai-cells = <0>;
++ };
++ max98371_C: max98371@0x35 {
++ compatible = "maxim,max98371";
++ reg = <0x35>;
++ #sound-dai-cells = <0>;
++ };
++ max98371_S: max98371@0x36 {
++ compatible = "maxim,max98371";
++ reg = <0x36>;
++ #sound-dai-cells = <0>;
++ };
++ };
++
++ i2c@3 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <3>;
++ /* Radio node(s) */
++ };
++
++ i2c@4 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <4>;
++ /* A2B node(s) */
++ };
++
++ i2c@5 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <5>;
++ /* PCIe node(s) */
++ };
++
++ i2c@6 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <6>;
++ /* LVDS display node(s) */
++
++ polytouch: edt-ft5x06@38 {
++ compatible = "edt,edt-ft5x06";
++ reg = <0x38>;
++ interrupt-parent = <&gpio5>;
++ interrupts = <6 IRQ_TYPE_EDGE_FALLING>;
++ };
++ };
++
++ i2c@7 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <7>;
++ /* Audio, GPS and Gyro node(s) */
++
++ pcm3168a: audio-codec@44 {
++ #sound-dai-cells = <0>;
++ compatible = "ti,pcm3168a";
++ reg = <0x44>;
++ clocks = <&snd_clk>;
++ clock-names = "scki";
++ tdm;
++ VDD1-supply = <&codec_en_reg>;
++ VDD2-supply = <&codec_en_reg>;
++ VCCAD1-supply = <&codec_en_reg>;
++ VCCAD2-supply = <&codec_en_reg>;
++ VCCDA1-supply = <&amp_en_reg>;
++ VCCDA2-supply = <&amp_en_reg>;
++ };
++
++ lsm9ds0_acc_mag@1d {
++ compatible = "st,lsm9ds0_acc_mag";
++ reg = <0x1d>;
++ };
++
++ lsm9ds0_gyr@6b {
++ compatible = "st,lsm9ds0-gyro";
++ reg = <0x6b>;
++ };
++
++ /* GPS@ 0x42 */
++ };
++ };
++};
++
++&i2c4 {
++ gpio_ext_22: pca9535@21 {
++ compatible = "nxp,pca9535";
++ reg = <0x22>;
++ gpio-controller;
++ #gpio-cells = <2>;
++ interrupt-controller;
++ interrupt-parent = <&gpio7>;
++ interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
++ };
++
++ i2cswitch4@74 {
++ compatible = "nxp,pca9548";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <0x74>;
++ reset-gpios= <&gpio6 21 GPIO_ACTIVE_LOW>;
++
++ i2c@0 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <0>;
++ /* SAM node(s) */
++ };
++
++ i2c@1 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <1>;
++ /* Video input "A" acc node(s) */
++
++ ov106xx@0 {
++ compatible = "ovti,ov106xx";
++ reg = <0x60>;
++
++ port@0 {
++ ov106xx_in0: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin0ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des0ep0: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep0>;
++ };
++ ov106xx_ti964_des0ep0: endpoint@1 {
++ remote-endpoint = <&ti964_des0ep0>;
++ };
++ ov106xx_ti954_des0ep0: endpoint@2 {
++ remote-endpoint = <&ti954_des0ep0>;
++ };
++ };
++ };
++
++ ov106xx@1 {
++ compatible = "ovti,ov106xx";
++ reg = <0x61>;
++
++ port@0 {
++ ov106xx_in1: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin1ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des0ep1: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep1>;
++ };
++ ov106xx_ti964_des0ep1: endpoint@1 {
++ remote-endpoint = <&ti964_des0ep1>;
++ };
++ ov106xx_ti954_des0ep1: endpoint@2 {
++ remote-endpoint = <&ti954_des0ep1>;
++ };
++ };
++ };
++
++ ov106xx@2 {
++ compatible = "ovti,ov106xx";
++ reg = <0x62>;
++
++ port@0 {
++ ov106xx_in2: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin2ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des0ep2: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep2>;
++ };
++ ov106xx_ti964_des0ep2: endpoint@1 {
++ remote-endpoint = <&ti964_des0ep2>;
++ };
++ };
++ };
++
++ ov106xx@3 {
++ compatible = "ovti,ov106xx";
++ reg = <0x63>;
++
++ port@0 {
++ ov106xx_in3: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin3ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des0ep3: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep3>;
++ };
++ ov106xx_ti964_des0ep3: endpoint@1 {
++ remote-endpoint = <&ti964_des0ep3>;
++ };
++ };
++ };
++
++ /* DS90UB964 @ 0x3a */
++ ti964-ti9x3@0 {
++ compatible = "ti,ti964-ti9x3";
++ reg = <0x3a>;
++ ti,sensor_delay = <350>;
++ ti,links = <4>;
++ ti,lanes = <4>;
++ ti,forwarding-mode = "round-robin";
++ ti,cable-mode = "coax";
++
++ port@0 {
++ ti964_des0ep0: endpoint@0 {
++ ti9x3-addr = <0x0c>;
++ dvp-order = <0>;
++ remote-endpoint = <&ov106xx_in0>;
++ };
++ ti964_des0ep1: endpoint@1 {
++ ti9x3-addr = <0x0d>;
++ dvp-order = <0>;
++ remote-endpoint = <&ov106xx_in1>;
++ };
++ ti964_des0ep2: endpoint@2 {
++ ti9x3-addr = <0x0e>;
++ dvp-order = <0>;
++ remote-endpoint = <&ov106xx_in2>;
++ };
++ ti964_des0ep3: endpoint@3 {
++ ti9x3-addr = <0x0f>;
++ dvp-order = <0>;
++ remote-endpoint = <&ov106xx_in3>;
++ };
++ };
++ port@1 {
++ ti964_csi0ep0: endpoint {
++ csi-rate = <1450>;
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ };
++
++ /* DS90UB954 @ 0x38 */
++ ti954-ti9x3@0 {
++ compatible = "ti,ti954-ti9x3";
++ reg = <0x38>;
++ gpios = <&video_a_ext1 10 GPIO_ACTIVE_HIGH>;
++ ti,sensor_delay = <350>;
++ ti,links = <2>;
++ ti,lanes = <4>;
++ ti,forwarding-mode = "round-robin";
++ ti,cable-mode = "coax";
++
++ port@0 {
++ ti954_des0ep0: endpoint@0 {
++ ti9x3-addr = <0x0c>;
++ dvp-order = <0>;
++ remote-endpoint = <&ov106xx_in0>;
++ };
++ ti954_des0ep1: endpoint@1 {
++ ti9x3-addr = <0x0d>;
++ dvp-order = <0>;
++ remote-endpoint = <&ov106xx_in1>;
++ };
++ };
++ port@1 {
++ ti954_csi0ep0: endpoint {
++ csi-rate = <1450>;
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ };
++
++ /* MAX9286 @ 0x2a */
++ max9286-max9271@0 {
++ compatible = "maxim,max9286-max9271";
++ reg = <0x2a>;
++ maxim,sensor_delay = <350>;
++ maxim,links = <4>;
++ maxim,lanes = <4>;
++ maxim,resetb-gpio = <1>;
++ maxim,fsync-mode = "automatic";
++ maxim,timeout = <100>;
++
++ port@0 {
++ max9286_des0ep0: endpoint@0 {
++ max9271-addr = <0x50>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in0>;
++ };
++ max9286_des0ep1: endpoint@1 {
++ max9271-addr = <0x51>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in1>;
++ };
++ max9286_des0ep2: endpoint@2 {
++ max9271-addr = <0x52>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in2>;
++ };
++ max9286_des0ep3: endpoint@3 {
++ max9271-addr = <0x53>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in3>;
++ };
++ };
++ port@1 {
++ max9286_csi0ep0: endpoint {
++ csi-rate = <700>;
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ };
++ };
++
++ i2c@2 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <2>;
++ /* Video input "B" acc node(s) */
++
++ ov106xx@4 {
++ compatible = "ovti,ov106xx";
++ reg = <0x64>;
++
++ port@0 {
++ ov106xx_in4: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin4ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des1ep0: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep0>;
++ };
++ ov106xx_ti964_des1ep0: endpoint@1 {
++ remote-endpoint = <&ti964_des1ep0>;
++ };
++ ov106xx_ti954_des1ep0: endpoint@2 {
++ remote-endpoint = <&ti954_des1ep0>;
++ };
++ };
++ };
++
++ ov106xx@5 {
++ compatible = "ovti,ov106xx";
++ reg = <0x65>;
++
++ port@0 {
++ ov106xx_in5: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin5ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des1ep1: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep1>;
++ };
++ ov106xx_ti964_des1ep1: endpoint@1 {
++ remote-endpoint = <&ti964_des1ep1>;
++ };
++ ov106xx_ti954_des1ep1: endpoint@2 {
++ remote-endpoint = <&ti954_des1ep1>;
++ };
++ };
++ };
++
++ ov106xx@6 {
++ compatible = "ovti,ov106xx";
++ reg = <0x66>;
++
++ port@0 {
++ ov106xx_in6: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin6ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des1ep2: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep2>;
++ };
++ ov106xx_ti964_des1ep2: endpoint@1 {
++ remote-endpoint = <&ti964_des1ep2>;
++ };
++ };
++ };
++
++ ov106xx@7 {
++ compatible = "ovti,ov106xx";
++ reg = <0x67>;
++
++ port@0 {
++ ov106xx_in7: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin7ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des1ep3: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep3>;
++ };
++ ov106xx_ti964_des1ep3: endpoint@1 {
++ remote-endpoint = <&ti964_des1ep3>;
++ };
++ };
++ };
++
++ /* DS90UB964 @ 0x3a */
++ ti964-ti9x3@1 {
++ compatible = "ti,ti964-ti9x3";
++ reg = <0x3a>;
++ ti,sensor_delay = <350>;
++ ti,links = <4>;
++ ti,lanes = <4>;
++ ti,forwarding-mode = "round-robin";
++ ti,cable-mode = "coax";
++
++ port@0 {
++ ti964_des1ep0: endpoint@0 {
++ ti9x3-addr = <0x0c>;
++ dvp-order = <0>;
++ remote-endpoint = <&ov106xx_in4>;
++ };
++ ti964_des1ep1: endpoint@1 {
++ ti9x3-addr = <0x0d>;
++ dvp-order = <0>;
++ remote-endpoint = <&ov106xx_in5>;
++ };
++ ti964_des1ep2: endpoint@2 {
++ ti9x3-addr = <0x0e>;
++ dvp-order = <0>;
++ remote-endpoint = <&ov106xx_in6>;
++ };
++ ti964_des1ep3: endpoint@3 {
++ ti9x3-addr = <0x0f>;
++ dvp-order = <0>;
++ remote-endpoint = <&ov106xx_in7>;
++ };
++ };
++ port@1 {
++ ti964_csi2ep0: endpoint {
++ csi-rate = <1450>;
++ remote-endpoint = <&csi2_41_ep>;
++ };
++ };
++ };
++
++ /* DS90UB954 @ 0x38 */
++ ti954-ti9x3@1 {
++ compatible = "ti,ti954-ti9x3";
++ reg = <0x38>;
++ gpios = <&video_b_ext1 10 GPIO_ACTIVE_HIGH>;
++ ti,sensor_delay = <350>;
++ ti,links = <2>;
++ ti,lanes = <4>;
++ ti,forwarding-mode = "round-robin";
++ ti,cable-mode = "coax";
++
++ port@0 {
++ ti954_des1ep0: endpoint@0 {
++ ti9x3-addr = <0x0c>;
++ dvp-order = <0>;
++ remote-endpoint = <&ov106xx_in4>;
++ };
++ ti954_des1ep1: endpoint@1 {
++ ti9x3-addr = <0x0d>;
++ dvp-order = <0>;
++ remote-endpoint = <&ov106xx_in5>;
++ };
++ };
++ port@1 {
++ ti954_csi2ep0: endpoint {
++ csi-rate = <1450>;
++ remote-endpoint = <&csi2_41_ep>;
++ };
++ };
++ };
++
++ /* MAX9286 @ 0x2a */
++ max9286-max9271@1 {
++ compatible = "maxim,max9286-max9271";
++ reg = <0x2a>;
++ maxim,sensor_delay = <350>;
++ maxim,links = <4>;
++ maxim,lanes = <4>;
++ maxim,resetb-gpio = <1>;
++ maxim,fsync-mode = "automatic";
++ maxim,timeout = <100>;
++
++ port@0 {
++ max9286_des1ep0: endpoint@0 {
++ max9271-addr = <0x50>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in4>;
++ };
++ max9286_des1ep1: endpoint@1 {
++ max9271-addr = <0x51>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in5>;
++ };
++ max9286_des1ep2: endpoint@2 {
++ max9271-addr = <0x52>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in6>;
++ };
++ max9286_des1ep3: endpoint@3 {
++ max9271-addr = <0x53>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in7>;
++ };
++ };
++ port@1 {
++ max9286_csi2ep0: endpoint {
++ csi-rate = <700>;
++ remote-endpoint = <&csi2_41_ep>;
++ };
++ };
++ };
++ };
++
++ i2c@3 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <3>;
++ /* MOST node(s) */
++ };
++
++ i2c@4 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <4>;
++ /* CSI camera node(s) */
++ };
++
++ i2c@5 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <5>;
++ /* CMOS camera node(s) */
++ };
++
++ i2c@6 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <6>;
++ /* Video input "B" main node(s) */
++
++ video_b_ext0: pca9535@27 {
++ compatible = "nxp,pca9535";
++ reg = <0x27>;
++ gpio-controller;
++ #gpio-cells = <2>;
++
++ video_b_des_cfg1 {
++ gpio-hog;
++ gpios = <5 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-B cfg1";
++ };
++ video_b_des_cfg0 {
++ gpio-hog;
++ gpios = <6 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-B cfg0";
++ };
++ video_b_pwr_shdn {
++ gpio-hog;
++ gpios = <3 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-B PWR_SHDN";
++ };
++ video_b_cam_pwr0 {
++ gpio-hog;
++ gpios = <12 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-B PWR0";
++ };
++ video_b_cam_pwr1 {
++ gpio-hog;
++ gpios = <13 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-B PWR1";
++ };
++ video_b_cam_pwr2 {
++ gpio-hog;
++ gpios = <14 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-B PWR2";
++ };
++ video_b_cam_pwr3 {
++ gpio-hog;
++ gpios = <15 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-B PWR3";
++ };
++ video_b_des_shdn {
++ gpio-hog;
++ gpios = <4 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-B DES_SHDN";
++ };
++ video_b_des_led {
++ gpio-hog;
++ gpios = <7 GPIO_ACTIVE_HIGH>;
++ output-low;
++ line-name = "Video-B led";
++ };
++ };
++
++ video_b_ext1: max7325@5c {
++ compatible = "maxim,max7325";
++ reg = <0x5c>;
++ gpio-controller;
++ #gpio-cells = <2>;
++
++ video_b_des_cfg2 {
++ gpio-hog;
++ gpios = <4 GPIO_ACTIVE_HIGH>;
++ output-low;
++ line-name = "Video-B cfg2";
++ };
++ video_b_des_cfg1 {
++ gpio-hog;
++ gpios = <6 GPIO_ACTIVE_HIGH>;
++ output-low;
++ line-name = "Video-B cfg1";
++ };
++ video_b_des_cfg0 {
++ gpio-hog;
++ gpios = <7 GPIO_ACTIVE_HIGH>;
++ output-low;
++ line-name = "Video-B cfg0";
++ };
++ video_b_pwr_shdn {
++ gpio-hog;
++ gpios = <14 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-B PWR_SHDN";
++ };
++ video_b_cam_pwr0 {
++ gpio-hog;
++ gpios = <8 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-B PWR0";
++ };
++ video_b_cam_pwr1 {
++ gpio-hog;
++ gpios = <9 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-B PWR1";
++ };
++ };
++ };
++
++ i2c@7 {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ reg = <7>;
++ /* Video input "A" main node(s) */
++
++ video_a_ext0: pca9535@26 {
++ compatible = "nxp,pca9535";
++ reg = <0x26>;
++ gpio-controller;
++ #gpio-cells = <2>;
++
++ video_a_des_cfg1 {
++ gpio-hog;
++ gpios = <5 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-A cfg1";
++ };
++ video_a_des_cfg0 {
++ gpio-hog;
++ gpios = <6 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-A cfg0";
++ };
++ video_a_pwr_shdn {
++ gpio-hog;
++ gpios = <3 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-A PWR_SHDN";
++ };
++ video_a_cam_pwr0 {
++ gpio-hog;
++ gpios = <12 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-A PWR0";
++ };
++ video_a_cam_pwr1 {
++ gpio-hog;
++ gpios = <13 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-A PWR1";
++ };
++ video_a_cam_pwr2 {
++ gpio-hog;
++ gpios = <14 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-A PWR2";
++ };
++ video_a_cam_pwr3 {
++ gpio-hog;
++ gpios = <15 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-A PWR3";
++ };
++ video_a_des_shdn {
++ gpio-hog;
++ gpios = <4 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-A DES_SHDN";
++ };
++ video_a_des_led {
++ gpio-hog;
++ gpios = <7 GPIO_ACTIVE_HIGH>;
++ output-low;
++ line-name = "Video-A led";
++ };
++ };
++
++ video_a_ext1: max7325@5c {
++ compatible = "maxim,max7325";
++ reg = <0x5c>;
++ gpio-controller;
++ #gpio-cells = <2>;
++
++ video_a_des_cfg2 {
++ gpio-hog;
++ gpios = <4 GPIO_ACTIVE_HIGH>;
++ output-low;
++ line-name = "Video-A cfg2";
++ };
++ video_a_des_cfg1 {
++ gpio-hog;
++ gpios = <6 GPIO_ACTIVE_HIGH>;
++ output-low;
++ line-name = "Video-A cfg1";
++ };
++ video_a_des_cfg0 {
++ gpio-hog;
++ gpios = <7 GPIO_ACTIVE_HIGH>;
++ output-low;
++ line-name = "Video-A cfg0";
++ };
++ video_a_pwr_shdn {
++ gpio-hog;
++ gpios = <14 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-A PWR_SHDN";
++ };
++ video_a_cam_pwr0 {
++ gpio-hog;
++ gpios = <8 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-A PWR0";
++ };
++ video_a_cam_pwr1 {
++ gpio-hog;
++ gpios = <9 GPIO_ACTIVE_HIGH>;
++ output-high;
++ line-name = "Video-A PWR1";
++ };
++ };
++ };
++ };
++};
++
++&pcie_bus_clk {
++ clock-frequency = <100000000>;
++ status = "okay";
++};
++
++&pciec0 {
++ status = "okay";
++};
++
++&pciec1 {
++ status = "okay";
++};
++
++&vin0 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin0ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in0>;
++ };
++ };
++ port@1 {
++ csi0ep0: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin0_max9286_des0ep0: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep0>;
++ };
++ vin0_ti964_des0ep0: endpoint@1 {
++ remote-endpoint = <&ti964_des0ep0>;
++ };
++ vin0_ti954_des0ep0: endpoint@2 {
++ remote-endpoint = <&ti954_des0ep0>;
++ };
++ };
++ };
++};
++
++&vin1 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin1ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <1>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in1>;
++ };
++ };
++ port@1 {
++ csi0ep1: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin1_max9286_des0ep1: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep1>;
++ };
++ vin1_ti964_des0ep1: endpoint@1 {
++ remote-endpoint = <&ti964_des0ep1>;
++ };
++ vin1_ti954_des0ep1: endpoint@2 {
++ remote-endpoint = <&ti954_des0ep1>;
++ };
++ };
++ };
++};
++
++&vin2 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin2ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <2>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in2>;
++ };
++ };
++ port@1 {
++ csi0ep2: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin2_max9286_des0ep2: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep2>;
++ };
++ vin2_ti964_des0ep2: endpoint@1 {
++ remote-endpoint = <&ti964_des0ep2>;
++ };
++ };
++ };
++};
++
++&vin3 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin3ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <3>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in3>;
++ };
++ };
++ port@1 {
++ csi0ep3: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin3_max9286_des0ep3: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep3>;
++ };
++ vin3_ti964_des0ep3: endpoint@1 {
++ remote-endpoint = <&ti964_des0ep3>;
++ };
++ };
++ };
++};
++
++&vin4 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin4ep0: endpoint {
++ csi,select = "csi41";
++ virtual,channel = <0>;
++ remote-endpoint = <&ov106xx_in4>;
++ data-lanes = <1 2 3 4>;
++ };
++ };
++ port@1 {
++ csi2ep0: endpoint {
++ remote-endpoint = <&csi2_41_ep>;
++ };
++ };
++ port@2 {
++ vin4_max9286_des1ep0: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep0>;
++ };
++ vin4_ti964_des1ep0: endpoint@1 {
++ remote-endpoint = <&ti964_des1ep0>;
++ };
++ vin4_ti954_des1ep0: endpoint@2 {
++ remote-endpoint = <&ti954_des1ep0>;
++ };
++ };
++ };
++};
++
++&vin5 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin5ep0: endpoint@0 {
++ csi,select = "csi41";
++ virtual,channel = <1>;
++ remote-endpoint = <&ov106xx_in5>;
++ data-lanes = <1 2 3 4>;
++ };
++ };
++ port@1 {
++ csi2ep1: endpoint {
++ remote-endpoint = <&csi2_41_ep>;
++ };
++ };
++ port@2 {
++ vin5_max9286_des1ep1: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep1>;
++ };
++ vin5_ti964_des1ep1: endpoint@1 {
++ remote-endpoint = <&ti964_des1ep1>;
++ };
++ vin5_ti954_des1ep1: endpoint@2 {
++ remote-endpoint = <&ti954_des1ep1>;
++ };
++ };
++ };
++};
++
++&vin6 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin6ep0: endpoint@0 {
++ csi,select = "csi41";
++ virtual,channel = <2>;
++ remote-endpoint = <&ov106xx_in6>;
++ data-lanes = <1 2 3 4>;
++ };
++ };
++ port@1 {
++ csi2ep2: endpoint {
++ remote-endpoint = <&csi2_41_ep>;
++ };
++ };
++ port@2 {
++ vin6_max9286_des1ep2: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep2>;
++ };
++ vin6_ti964_des1ep2: endpoint@1 {
++ remote-endpoint = <&ti964_des1ep2>;
++ };
++ };
++ };
++};
++
++&vin7 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin7ep0: endpoint@0 {
++ csi,select = "csi41";
++ virtual,channel = <3>;
++ remote-endpoint = <&ov106xx_in7>;
++ data-lanes = <1 2 3 4>;
++ };
++ };
++ port@1 {
++ csi2ep3: endpoint {
++ remote-endpoint = <&csi2_41_ep>;
++ };
++ };
++ port@2 {
++ vin7_max9286_des1ep3: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep3>;
++ };
++ vin7_ti964_des1ep3: endpoint@1 {
++ remote-endpoint = <&ti964_des1ep3>;
++ };
++ };
++ };
++};
++
++&csi2_40 {
++ status = "okay";
++
++ virtual,channel {
++ csi2_vc0 {
++ data,type = "ycbcr422";
++ receive,vc = <0>;
++ };
++ csi2_vc1 {
++ data,type = "ycbcr422";
++ receive,vc = <1>;
++ };
++ csi2_vc2 {
++ data,type = "ycbcr422";
++ receive,vc = <2>;
++ };
++ csi2_vc3 {
++ data,type = "ycbcr422";
++ receive,vc = <3>;
++ };
++ };
++
++ port {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ csi2_40_ep: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ csi-rate = <300>;
++ };
++ };
++};
++
++&csi2_41 {
++ status = "okay";
++
++ virtual,channel {
++ csi2_vc0 {
++ data,type = "ycbcr422";
++ receive,vc = <0>;
++ };
++ csi2_vc1 {
++ data,type = "ycbcr422";
++ receive,vc = <1>;
++ };
++ csi2_vc2 {
++ data,type = "ycbcr422";
++ receive,vc = <2>;
++ };
++ csi2_vc3 {
++ data,type = "ycbcr422";
++ receive,vc = <3>;
++ };
++ };
++
++ port {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ csi2_41_ep: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ csi-rate = <300>;
++ };
++ };
++};
++
++&rcar_sound {
++ pinctrl-0 = <&sound_clk_pins>;
++
++ /* Multi DAI */
++ #sound-dai-cells = <1>;
++
++ rcar_sound,dai {
++ dai0 {
++ playback = <&ssi7>;
++ capture = <&ssi8>;
++ };
++
++ dai1 {
++ playback = <&ssi0 &src0 &dvc0>;
++ capture = <&ssi1 &src1 &dvc1>;
++ };
++
++ dai2 {
++ capture = <&ssi6>;
++ };
++
++ dai3 {
++ playback = <&ssi9>;
++ };
++ };
++};
++
++&sdhi3 {
++ pinctrl-0 = <&sdhi3_pins_3v3>;
++ pinctrl-names = "default";
++
++ vmmc-supply = <&wlan_en>;
++ vqmmc-supply = <&vccq_sdhi3>;
++ keep-power-in-suspend;
++ enable-sdio-wakeup;
++ bus-width = <4>;
++ no-1-8-v;
++ non-removable;
++ cap-power-off-card;
++ max-frequency = <26000000>;
++ status = "okay";
++
++ #address-cells = <1>;
++ #size-cells = <0>;
++ wlcore: wlcore@2 {
++ compatible = "ti,wl1837";
++ reg = <2>;
++ interrupt-parent = <&gpio1>;
++ interrupts = <25 IRQ_TYPE_EDGE_RISING>;
++ };
++};
++
++&xhci0 {
++ status = "okay";
++};
++
++&usb2_phy0 {
++ pinctrl-0 = <&usb0_pins>;
++ pinctrl-names = "default";
++
++ status = "okay";
++};
++
++&ehci0 {
++ status = "okay";
++};
++
++&ohci0 {
++ status = "okay";
++};
+--
+1.9.1
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0044-arm64-renesas-TTA-R-Drive-board-support.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0044-arm64-renesas-TTA-R-Drive-board-support.patch
new file mode 100644
index 0000000..6d669c2
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0044-arm64-renesas-TTA-R-Drive-board-support.patch
@@ -0,0 +1,1314 @@
+From 408420d2ceedc1b8c92dd132fd2617bc001120b8 Mon Sep 17 00:00:00 2001
+From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+Date: Thu, 16 Feb 2017 05:42:47 +0300
+Subject: [PATCH] arm64: renesas: TTA-R-Drive board support
+
+Add support for TTA-R-Drive board
+
+Signed-off-by: Stefan Hepp <stefan.hepp@tttech-automotive.com>
+Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+---
+ arch/arm64/boot/dts/renesas/Makefile | 3 +-
+ .../boot/dts/renesas/r8a7795-ttardrive-alfa.dts | 225 +++++
+ .../boot/dts/renesas/r8a7795-ttardrive-beta.dts | 129 +++
+ arch/arm64/boot/dts/renesas/r8a7795-ttardrive.dtsi | 909 +++++++++++++++++++++
+ 4 files changed, 1265 insertions(+), 1 deletion(-)
+ create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-ttardrive-alfa.dts
+ create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-ttardrive-beta.dts
+ create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-ttardrive.dtsi
+
+diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile
+index e42396e..fc4438b 100644
+--- a/arch/arm64/boot/dts/renesas/Makefile
++++ b/arch/arm64/boot/dts/renesas/Makefile
+@@ -1,7 +1,8 @@
+ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-salvator-x.dtb r8a7795-h3ulcb.dtb \
+ r8a7795-salvator-x-view.dtb r8a7795-h3ulcb-had.dtb \
+ r8a7795-h3ulcb-view.dtb \
+- r8a7795-h3ulcb-kf.dtb
++ r8a7795-h3ulcb-kf.dtb \
++ r8a7795-ttardrive-alfa.dtb r8a7795-ttardrive-beta.dtb
+ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-salvator-x.dtb
+ dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-x.dtb r8a7796-m3ulcb.dtb \
+ r8a7796-salvator-x-view.dtb r8a7796-m3ulcb-view.dtb \
+diff --git a/arch/arm64/boot/dts/renesas/r8a7795-ttardrive-alfa.dts b/arch/arm64/boot/dts/renesas/r8a7795-ttardrive-alfa.dts
+new file mode 100644
+index 0000000..2a1ae85
+--- /dev/null
++++ b/arch/arm64/boot/dts/renesas/r8a7795-ttardrive-alfa.dts
+@@ -0,0 +1,224 @@
++/*
++ * Base Device Tree Source for the TTA-R-Drive board Alfa CPU
++ *
++ * Copyright (C) 2016 TTTech Automotive GmbH
++ *
++ * This file is licensed under the terms of the GNU General Public License
++ * version 2. This program is licensed "as is" without any warranty of any
++ * kind, whether express or implied.
++ */
++
++/dts-v1/;
++#include "r8a7795-ttardrive.dtsi"
++#include <dt-bindings/gpio/gpio.h>
++#include <dt-bindings/input/input.h>
++
++/ {
++ model = "TTTech TTA-R-Drive board Alfa CPU based on r8a7795";
++
++ aliases {
++ /* Using GPIO SPI instead of MSIOF; remove to use HW MSIOF */
++ /* On Alfa:
++ * MSIOF0 is interconnect master
++ * MSIOF1_C is Switch 1 master
++ * MSIOF2_B is FPDLink master
++ * MSIOF2_D is RH850 slave (not used)
++ * MSIOF3_A is Switch 2 master
++ */
++ spi1 = &spi0_gpio;
++ spi2 = &spi1_gpio;
++ spi3 = &spi2_gpio;
++ spi4 = &spi3_gpio;
++ };
++
++ /* Software SPI driver */
++ spi0_gpio: spi_gpio@0 {
++ compatible = "spi-gpio";
++ num-chipselects = <1>;
++ gpio-sck = <&gpio5 17 0>;
++ gpio-mosi = <&gpio5 20 0>;
++ gpio-miso = <&gpio5 22 0>;
++ cs-gpios = <&gpio5 18 0>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ spidev@0 {
++ compatible = "spi-gpio";
++ reg = <0>;
++ spi-max-frequency = <2000000>;
++ spi-cpha;
++ spi-cpol;
++ };
++ };
++
++ spi1_gpio: spi_gpio@1 {
++ compatible = "spi-gpio";
++ num-chipselects = <1>;
++ gpio-sck = <&gpio6 17 0>;
++ gpio-mosi = <&gpio6 20 0>;
++ gpio-miso = <&gpio6 19 0>;
++ cs-gpios = <&gpio6 18 0>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ spidev@0 {
++ compatible = "spi-gpio";
++ reg = <0>;
++ spi-max-frequency = <2000000>;
++ spi-cpha;
++ spi-cpol;
++ };
++ };
++
++ spi2_gpio: spi_gpio@2 {
++ compatible = "spi-gpio";
++ num-chipselects = <1>;
++ gpio-sck = <&gpio0 4 0>;
++ gpio-mosi = <&gpio0 7 0>;
++ gpio-miso = <&gpio0 6 0>;
++ cs-gpios = <&gpio0 5 0>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ spidev@0 {
++ compatible = "spi-gpio";
++ reg = <0>;
++ spi-max-frequency = <2000000>;
++ spi-cpha;
++ spi-cpol;
++ };
++ };
++
++ spi3_gpio: spi_gpio@3 {
++ compatible = "spi-gpio";
++ num-chipselects = <1>;
++ gpio-sck = <&gpio0 0 0>;
++ gpio-mosi = <&gpio0 3 0>;
++ gpio-miso = <&gpio0 2 0>;
++ cs-gpios = <&gpio0 1 0>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ spidev@0 {
++ compatible = "spi-gpio";
++ reg = <0>;
++ spi-max-frequency = <2000000>;
++ spi-cpha;
++ spi-cpol;
++ };
++ };
++
++};
++
++&pcie_bus_clk {
++ clock-frequency = <100000000>;
++};
++
++&pfc {
++ msiof0_pins: spi1 {
++ groups = "msiof0_clk", "msiof0_sync",
++ "msiof0_rxd", "msiof0_txd";
++ function = "msiof0";
++ };
++
++ msiof1_pins: spi2 {
++ groups = "msiof1_clk_c", "msiof1_sync_c",
++ "msiof1_rxd_c", "msiof1_txd_c";
++ function = "msiof1";
++ };
++
++ msiof2_pins: spi3 {
++ groups = "msiof2_clk_b", "msiof2_sync_b",
++ "msiof2_rxd_b", "msiof2_txd_b";
++ function = "msiof2";
++ };
++
++ msiof3_pins: spi4 {
++ groups = "msiof3_clk_a", "msiof3_sync_a",
++ "msiof3_rxd_a", "msiof3_txd_a";
++ function = "msiof3";
++ };
++};
++
++&msiof0 {
++ pinctrl-0 = <&msiof0_pins>;
++ pinctrl-names = "default";
++ status = "disabled";
++ cs-gpios = <&gpio5 18 0>;
++
++ spidev@0 {
++ compatible = "renesas,sh-msiof";
++ reg = <0>;
++ spi-max-frequency = <66666666>;
++ spi-cpha;
++ spi-cpol;
++ };
++};
++
++&msiof1 {
++ pinctrl-0 = <&msiof1_pins>;
++ pinctrl-names = "default";
++ status = "disabled";
++ cs-gpios = <&gpio6 18 0>;
++
++ spidev@0 {
++ compatible = "renesas,sh-msiof";
++ reg = <0>;
++ spi-max-frequency = <33333333>;
++ spi-cpha;
++ spi-cpol;
++ };
++};
++
++&msiof2 {
++ pinctrl-0 = <&msiof2_pins>;
++ pinctrl-names = "default";
++ status = "disabled";
++ cs-gpios = <&gpio0 5 0>;
++
++ spidev@0 {
++ compatible = "renesas,sh-msiof";
++ reg = <0>;
++ spi-max-frequency = <66666666>;
++ spi-cpha;
++ spi-cpol;
++ };
++};
++
++&msiof3 {
++ pinctrl-0 = <&msiof3_pins>;
++ pinctrl-names = "default";
++ status = "disabled";
++ cs-gpios = <&gpio0 1 0>;
++
++ spidev@0 {
++ compatible = "renesas,sh-msiof";
++ reg = <0>;
++ spi-max-frequency = <66666666>;
++ spi-cpha;
++ spi-cpol;
++ };
++};
++
++
++&i2c4 {
++ status = "okay";
++ clock-frequency = <100000>;
++
++ /* TODO support for 5P49V5901B device, is it compatible??
++ clk_5p49v5901b: programmable_clk@6a {
++ compatible = "idt,5p49v5923a";
++ reg = <0x6a>;
++
++ programable_clk0: 5p49v5901b_clk1@6a {
++ #clock-cells = <0>;
++ clocks = <&dclkin_p0>;
++ };
++
++ programable_clk1: 5p49v5901b_clk2@6a {
++ #clock-cells = <0>;
++ clocks = <&dclkin_p3>;
++ };
++ };
++ */
++};
+diff --git a/arch/arm64/boot/dts/renesas/r8a7795-ttardrive-beta.dts b/arch/arm64/boot/dts/renesas/r8a7795-ttardrive-beta.dts
+new file mode 100644
+index 0000000..234bb68
+--- /dev/null
++++ b/arch/arm64/boot/dts/renesas/r8a7795-ttardrive-beta.dts
+@@ -0,0 +1,128 @@
++/*
++ * Base Device Tree Source for the TTA-R-Drive board Beta CPU
++ *
++ * Copyright (C) 2016 TTTech Automotive GmbH
++ *
++ * This file is licensed under the terms of the GNU General Public License
++ * version 2. This program is licensed "as is" without any warranty of any
++ * kind, whether express or implied.
++ */
++
++/dts-v1/;
++#include "r8a7795-ttardrive.dtsi"
++#include <dt-bindings/gpio/gpio.h>
++#include <dt-bindings/input/input.h>
++
++/ {
++ model = "TTTech TTA-R-Drive board Beta CPU based on r8a7795";
++
++ aliases {
++ /* Using GPIO SPI instead of MSIOF; remove to use HW MSIOF */
++ /* On Beta:
++ * MSIOF0 is interconnect slave (not used)
++ * MSIOF1_C is RH850 slave (not used)
++ * MSIOF3_B is FPDLink master
++ */
++ spi4 = &spi3_gpio;
++ };
++
++ /* Software SPI driver */
++ spi3_gpio: spi_gpio@3 {
++ compatible = "spi-gpio";
++ num-chipselects = <1>;
++ gpio-sck = <&gpio1 2 0>;
++ gpio-mosi = <&gpio1 1 0>;
++ gpio-miso = <&gpio1 3 0>;
++ cs-gpios = <&gpio1 0 0>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ spidev@0 {
++ compatible = "spi-gpio";
++ reg = <0>;
++ spi-max-frequency = <2000000>;
++ spi-cpha;
++ spi-cpol;
++ };
++ };
++
++};
++
++&pcie_bus_clk {
++ clock-frequency = <100000000>;
++};
++
++&pfc {
++ msiof3_pins: spi4 {
++ groups = "msiof3_clk_b", "msiof3_sync_b",
++ "msiof3_rxd_b", "msiof3_txd_b";
++ function = "msiof3";
++ };
++
++ can0_pins: can0 {
++ groups = "can0_data_b";
++ function = "can0";
++ };
++
++ can1_pins: can1 {
++ groups = "can1_data";
++ function = "can1";
++ };
++
++ canfd0_pins: canfd0 {
++ groups = "canfd0_data_b";
++ function = "canfd0";
++ };
++
++ canfd1_pins: canfd1 {
++ groups = "canfd1_data";
++ function = "canfd1";
++ };
++};
++
++&msiof3 {
++ pinctrl-0 = <&msiof3_pins>;
++ pinctrl-names = "default";
++ status = "disabled";
++ cs-gpios = <&gpio1 0 0>;
++
++ spidev@0 {
++ compatible = "renesas,sh-msiof";
++ reg = <0>;
++ spi-max-frequency = <66666666>;
++ spi-cpha;
++ spi-cpol;
++ };
++};
++
++&can0 {
++ pinctrl-0 = <&can0_pins>;
++ pinctrl-names = "default";
++ status = "okay";
++
++ renesas,can-clock-select = <0x0>;
++};
++
++&can1 {
++ pinctrl-0 = <&can1_pins>;
++ pinctrl-names = "default";
++ status = "okay";
++
++ renesas,can-clock-select = <0x0>;
++};
++
++
++&canfd {
++ pinctrl-0 = <&canfd0_pins &canfd1_pins>;
++ pinctrl-names = "default";
++ status = "disabled";
++
++ renesas,can-clock-select = <0x0>;
++
++ channel0 {
++ status = "okay";
++ };
++ channel1 {
++ status = "okay";
++ };
++};
+diff --git a/arch/arm64/boot/dts/renesas/r8a7795-ttardrive.dtsi b/arch/arm64/boot/dts/renesas/r8a7795-ttardrive.dtsi
+new file mode 100644
+index 0000000..e74a2c1
+--- /dev/null
++++ b/arch/arm64/boot/dts/renesas/r8a7795-ttardrive.dtsi
+@@ -0,0 +1,908 @@
++/*
++ * Base Device Tree Source for the TTA-R-Drive board
++ *
++ * Copyright (C) 2016 Renesas Electronics Corp.
++ * Copyright (C) 2016 Cogent Embedded, Inc.
++ * Copyright (C) 2016 TTTech Automotive GmbH
++ *
++ * This file is licensed under the terms of the GNU General Public License
++ * version 2. This program is licensed "as is" without any warranty of any
++ * kind, whether express or implied.
++ */
++
++#include "r8a7795.dtsi"
++#include <dt-bindings/gpio/gpio.h>
++#include <dt-bindings/input/input.h>
++
++/ {
++ compatible = "tttech,ttardrive", "renesas,r8a7795";
++
++ aliases {
++ serial0 = &scif2;
++ serial1 = &scif1;
++ serial2 = &scif0;
++ serial3 = &hscif0;
++ ethernet0 = &avb;
++ };
++
++ chosen {
++ bootargs = "ignore_loglevel rw root=/dev/nfs ip=dhcp";
++ stdout-path = "serial0:115200n8";
++ };
++
++ memory@48000000 {
++ device_type = "memory";
++ /* first 128MB is reserved for secure area. */
++ reg = <0x0 0x48000000 0x0 0x78000000>;
++ };
++
++ memory@500000000 {
++ device_type = "memory";
++ reg = <0x5 0x00000000 0x0 0x80000000>;
++ };
++
++ memory@600000000 {
++ device_type = "memory";
++ reg = <0x6 0x00000000 0x0 0x80000000>;
++ };
++
++ memory@700000000 {
++ device_type = "memory";
++ reg = <0x7 0x00000000 0x0 0x80000000>;
++ };
++
++ reserved-memory {
++ #address-cells = <2>;
++ #size-cells = <2>;
++ ranges;
++
++ /* device specific region for Lossy Decompression */
++ lossy_decompress: linux,lossy_decompress {
++ no-map;
++ reg = <0x00000000 0x54000000 0x0 0x03000000>;
++ };
++
++ /* For Audio DSP */
++ adsp_reserved: linux,adsp {
++ compatible = "shared-dma-pool";
++ reusable;
++ reg = <0x00000000 0x57000000 0x0 0x01000000>;
++ };
++
++ /* global autoconfigured region for contiguous allocations */
++ linux,cma {
++ compatible = "shared-dma-pool";
++ reusable;
++ reg = <0x00000000 0x58000000 0x0 0x18000000>;
++ linux,cma-default;
++ };
++
++ /* device specific region for contiguous allocations */
++ linux,multimedia {
++ compatible = "shared-dma-pool";
++ reusable;
++ reg = <0x00000000 0x70000000 0x0 0x10000000>;
++ };
++ };
++
++ mmngr {
++ compatible = "renesas,mmngr";
++ memory-region = <&lossy_decompress>;
++ };
++
++ mmngrbuf {
++ compatible = "renesas,mmngrbuf";
++ };
++
++ leds {
++ compatible = "gpio-leds";
++
++ pwr {
++ gpios = <&gpio6 4 GPIO_ACTIVE_HIGH>;
++ default-state = "on";
++ };
++ load {
++ gpios = <&gpio6 5 GPIO_ACTIVE_HIGH>;
++ default-state = "off";
++ linux,default-trigger = "heartbeat";
++ };
++
++ /* Workaround to avoid clearing the USB clock enable during boot.
++ * Should be moved to the clock driver */
++ clken {
++ gpios = <&gpio6 7 GPIO_ACTIVE_LOW>;
++ default-state = "keep";
++ };
++ };
++
++ fixedregulator3v3: regulator@0 {
++ compatible = "regulator-fixed";
++ regulator-name = "fixed-3.3V";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ regulator-boot-on;
++ regulator-always-on;
++ };
++
++ fixedregulator1v8: regulator@1 {
++ compatible = "regulator-fixed";
++ regulator-name = "fixed-1.8V";
++ regulator-min-microvolt = <1800000>;
++ regulator-max-microvolt = <1800000>;
++ regulator-boot-on;
++ regulator-always-on;
++ };
++
++ vspm_if {
++ compatible = "renesas,vspm_if";
++ };
++
++ hdmi0-encoder {
++ compatible = "rockchip,rcar-dw-hdmi";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ port@0 {
++ reg = <0>;
++ rcar_dw_hdmi0_in: endpoint {
++ remote-endpoint = <&du_out_hdmi0>;
++ };
++ };
++ port@1 {
++ reg = <1>;
++ rcar_dw_hdmi0_out: endpoint {
++ remote-endpoint = <&hdmi0_con>;
++ };
++ };
++ };
++ };
++
++ hdmi0-out {
++ compatible = "hdmi-connector";
++ type = "a";
++
++ port {
++ hdmi0_con: endpoint {
++ remote-endpoint = <&rcar_dw_hdmi0_out>;
++ };
++ };
++ };
++
++ hdmi1-encoder {
++ compatible = "rockchip,rcar-dw-hdmi";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++ port@0 {
++ reg = <0>;
++ rcar_dw_hdmi1_in: endpoint {
++ remote-endpoint = <&du_out_hdmi1>;
++ };
++ };
++ port@1 {
++ reg = <1>;
++ rcar_dw_hdmi1_out: endpoint {
++ remote-endpoint = <&hdmi1_con>;
++ };
++ };
++ };
++ };
++
++ hdmi1-out {
++ compatible = "hdmi-connector";
++ type = "a";
++
++ port {
++ hdmi1_con: endpoint {
++ remote-endpoint = <&rcar_dw_hdmi1_out>;
++ };
++ };
++ };
++
++ /* TODO check clcoks */
++ programable_clk0: 5p49v5923a_clk0 {
++ compatible = "fixed-clock";
++ #clock-cells = <0>;
++ clock-frequency = <148500000>;
++ };
++
++ x21_clk: 5p49v5923a_clk2 {
++ compatible = "fixed-clock";
++ #clock-cells = <0>;
++ clock-frequency = <33000000>;
++ };
++
++ x22_clk: 5p49v5923a_clk3 {
++ compatible = "fixed-clock";
++ #clock-cells = <0>;
++ clock-frequency = <33000000>;
++ };
++
++ programable_clk1: 5p49v5923a_clk1 {
++ compatible = "fixed-clock";
++ #clock-cells = <0>;
++ clock-frequency = <108000000>;
++ };
++
++ /* Module clock for all MSIOFs baud rate generators, provided by CPG */
++ msiof_ref_clk: msiof-ref-clock {
++ compatible = "fixed-clock";
++ #clock-cells = <0>;
++ clock-frequency = <66666666>;
++ };
++};
++
++&du {
++ status = "okay";
++
++ ports {
++ port@1 {
++ endpoint {
++ remote-endpoint = <&rcar_dw_hdmi0_in>;
++ };
++ };
++ port@2 {
++ endpoint {
++ remote-endpoint = <&rcar_dw_hdmi1_in>;
++ };
++ };
++ };
++};
++
++&extal_clk {
++ clock-frequency = <20000000>;
++};
++
++&extalr_clk {
++ clock-frequency = <32768>;
++};
++
++&pfc {
++ pwm1_pins: pwm1 {
++ groups = "pwm1_b";
++ function = "pwm1";
++ };
++
++ pwm2_pins: pwm2 {
++ groups = "pwm2_b";
++ function = "pwm2";
++ };
++
++ scif0_pins: scif0 {
++ groups = "scif0_data";
++ function = "scif0";
++ };
++ scif1_pins: scif1 {
++ groups = "scif1_data_a";
++ function = "scif1";
++ };
++ scif2_pins: scif2 {
++ groups = "scif2_data_a";
++ function = "scif2";
++ };
++
++ hscif0_pins: hscif0 {
++ groups = "hscif0_data";
++ function = "hscif0";
++ };
++
++ i2c1_pins: i2c1 {
++ groups = "i2c1_b";
++ function = "i2c1";
++ };
++
++ avb_pins: avb {
++ groups = "avb_mdc";
++ function = "avb";
++ };
++
++ mmc1_pins_3v3: mmc1_3v3 {
++ groups = "sdhi3_data8", "sdhi3_ctrl";
++ function = "sdhi3";
++ power-source = <3300>;
++ };
++
++ usb2_pins: usb2 {
++ groups = "usb2";
++ function = "usb2";
++ };
++};
++
++/* PWMs */
++&pwm1 {
++ pinctrl-0 = <&pwm1_pins>;
++ pinctrl-names = "default";
++ status = "okay";
++};
++
++&pwm2 {
++ pinctrl-0 = <&pwm2_pins>;
++ pinctrl-names = "default";
++ status = "okay";
++};
++
++/* UARTs */
++
++&scif0 {
++ pinctrl-0 = <&scif0_pins>;
++ pinctrl-names = "default";
++
++ status = "okay";
++};
++
++&scif1 {
++ pinctrl-0 = <&scif1_pins>;
++ pinctrl-names = "default";
++
++ status = "okay";
++};
++
++&scif2 {
++ pinctrl-0 = <&scif2_pins>;
++ pinctrl-names = "default";
++
++ status = "okay";
++};
++
++&hscif0 {
++ pinctrl-0 = <&hscif0_pins>;
++ pinctrl-names = "default";
++
++ status = "okay";
++};
++
++/* eMMC */
++&mmc1 {
++ pinctrl-0 = <&mmc1_pins_3v3>;
++ pinctrl-1 = <&mmc1_pins_3v3>;
++ pinctrl-names = "default", "state_uhs";
++
++ /delete-property/mmc-hs200-1_8v;
++
++ vmmc-supply = <&fixedregulator3v3>;
++ vqmmc-supply = <&fixedregulator3v3>;
++ bus-width = <8>;
++ status = "okay";
++};
++
++/* I2C busses */
++&i2c0 {
++ status = "okay";
++ clock-frequency = <400000>;
++
++ ov106xx@0 {
++ compatible = "ovti,ov106xx";
++ reg = <0x60>;
++
++ port@0 {
++ ov106xx_in0: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin0ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des0ep0: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep0>;
++ };
++ };
++ };
++
++ ov106xx@1 {
++ compatible = "ovti,ov106xx";
++ reg = <0x61>;
++
++ port@0 {
++ ov106xx_in1: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin1ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des0ep1: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep1>;
++ };
++ };
++ };
++
++ ov106xx@2 {
++ compatible = "ovti,ov106xx";
++ reg = <0x62>;
++
++ port@0 {
++ ov106xx_in2: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin2ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des0ep2: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep2>;
++ };
++ };
++ };
++
++ ov106xx@3 {
++ compatible = "ovti,ov106xx";
++ reg = <0x63>;
++
++ port@0 {
++ ov106xx_in3: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&vin3ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_des0ep3: endpoint {
++ remote-endpoint = <&max9286_des0ep3>;
++ };
++ };
++ };
++
++ max9286-max9271@0 {
++ compatible = "maxim,max9286-max9271";
++ reg = <0x48>;
++ gpios = <&gpio3 7 GPIO_ACTIVE_HIGH>;
++ maxim,sensor_delay = <0>;
++ maxim,links = <4>;
++ maxim,lanes = <4>;
++ maxim,resetb-gpio = <1>;
++ maxim,fsync-mode = "automatic";
++ maxim,timeout = <100>;
++
++ port@0 {
++ max9286_des0ep0: endpoint@0 {
++ max9271-addr = <0x50>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in0>;
++ };
++ max9286_des0ep1: endpoint@1 {
++ max9271-addr = <0x51>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in1>;
++ };
++ max9286_des0ep2: endpoint@2 {
++ max9271-addr = <0x52>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in2>;
++ };
++ max9286_des0ep3: endpoint@3 {
++ max9271-addr = <0x53>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in3>;
++ };
++ };
++ port@1 {
++ max9286_csi0ep0: endpoint {
++ csi-rate = <700>;
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ };
++};
++
++&i2c1 {
++ pinctrl-0 = <&i2c1_pins>;
++ pinctrl-names = "default";
++
++ status = "okay";
++ clock-frequency = <100000>;
++
++ /* TODO FPDLink support */
++};
++
++&i2c3 {
++ status = "okay";
++ clock-frequency = <400000>;
++
++ ov106xx@4 {
++ compatible = "ovti,ov106xx";
++ reg = <0x64>;
++
++ port@0 {
++ ov106xx_in4: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2>;
++ remote-endpoint = <&vin4ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des1ep0: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep0>;
++ };
++ };
++ };
++
++ ov106xx@5 {
++ compatible = "ovti,ov106xx";
++ reg = <0x65>;
++
++ port@0 {
++ ov106xx_in5: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2>;
++ remote-endpoint = <&vin5ep0>;
++ };
++ };
++ port@1 {
++ ov106xx_max9286_des1ep1: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep1>;
++ };
++ };
++ };
++
++ max9286-max9271@1 {
++ compatible = "maxim,max9286-max9271";
++ reg = <0x48>;
++ gpios = <&gpio4 4 GPIO_ACTIVE_HIGH>;
++ maxim,sensor_delay = <0>;
++ maxim,links = <2>;
++ maxim,lanes = <2>;
++ maxim,resetb-gpio = <1>;
++ maxim,fsync-mode = "automatic";
++ maxim,timeout = <100>;
++
++ port@0 {
++ max9286_des1ep0: endpoint@0 {
++ max9271-addr = <0x54>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in4>;
++ };
++ max9286_des1ep1: endpoint@1 {
++ max9271-addr = <0x55>;
++ dvp-order = <1>;
++ remote-endpoint = <&ov106xx_in5>;
++ };
++ };
++ port@1 {
++ max9286_csi2ep0: endpoint {
++ csi-rate = <700>;
++ remote-endpoint = <&csi2_20_ep>;
++ };
++ };
++ };
++};
++
++&i2c5 {
++ status = "okay";
++ clock-frequency = <100000>;
++
++ /* TODO support for 5P49V5901B device, is it compatible??
++ clk_5p49v5923a: programmable_clk@6a {
++ compatible = "idt,5p49v5923a";
++ reg = <0x6a>;
++
++ programable_clk0: 5p49v5923a_clk1@6a {
++ #clock-cells = <0>;
++ clocks = <&dclkin_p0>;
++ };
++
++ programable_clk1: 5p49v5923a_clk2@6a {
++ #clock-cells = <0>;
++ clocks = <&dclkin_p3>;
++ };
++ };
++ */
++};
++
++&i2c_dvfs {
++ status = "okay";
++
++ vdd_dvfs: regulator@30 {
++ compatible = "rohm,bd9571mwv";
++ reg = <0x30>;
++
++ regulator-min-microvolt = <750000>;
++ regulator-max-microvolt = <1030000>;
++ regulator-boot-on;
++ regulator-always-on;
++ };
++};
++
++/* Ethernet */
++&avb {
++ pinctrl-0 = <&avb_pins>;
++ pinctrl-names = "default";
++ renesas,no-ether-link;
++ status = "okay";
++
++ fixed-link {
++ speed = <1000>;
++ full-duplex;
++ reg = <0>;
++ };
++};
++
++/* USB */
++&usb2_phy2 {
++ pinctrl-0 = <&usb2_pins>;
++ pinctrl-names = "default";
++
++ status = "okay";
++};
++
++&ehci2 {
++ status = "okay";
++};
++
++&ohci2 {
++ status = "okay";
++};
++
++/* PCIe and SATA */
++&pcie_bus_clk {
++ clock-frequency = <100000000>;
++ status = "okay";
++};
++
++&pciec0 {
++ status = "disabled";
++};
++
++&pciec1 {
++ status = "disabled";
++};
++
++&sata {
++ status = "okay";
++};
++
++/* Watchdog timer */
++&wdt0 {
++ status = "okay";
++};
++
++
++/* Video Codec interfaces. */
++&vin0 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin0ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <0>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in0>;
++ };
++ };
++ port@1 {
++ csi0ep0: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin0_max9286_des0ep0: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep0>;
++ };
++ };
++ };
++};
++
++&vin1 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin1ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <1>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in1>;
++ };
++ };
++ port@1 {
++ csi0ep1: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin1_max9286_des0ep1: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep1>;
++ };
++ };
++ };
++};
++
++&vin2 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin2ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <2>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in2>;
++ };
++ };
++ port@1 {
++ csi0ep2: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin2_max9286_des0ep2: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep2>;
++ };
++ };
++ };
++};
++
++&vin3 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin3ep0: endpoint {
++ csi,select = "csi40";
++ virtual,channel = <3>;
++ data-lanes = <1 2 3 4>;
++ remote-endpoint = <&ov106xx_in3>;
++ };
++ };
++ port@1 {
++ csi0ep3: endpoint {
++ remote-endpoint = <&csi2_40_ep>;
++ };
++ };
++ port@2 {
++ vin3_max9286_des0ep3: endpoint@0 {
++ remote-endpoint = <&max9286_des0ep3>;
++ };
++ };
++ };
++};
++
++&vin4 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin4ep0: endpoint {
++ csi,select = "csi20";
++ virtual,channel = <0>;
++ remote-endpoint = <&ov106xx_in4>;
++ data-lanes = <1 2>;
++ };
++ };
++ port@1 {
++ csi1ep0: endpoint {
++ remote-endpoint = <&csi2_20_ep>;
++ };
++ };
++ port@2 {
++ vin4_max9286_des1ep0: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep0>;
++ };
++ };
++ };
++};
++
++&vin5 {
++ status = "okay";
++
++ ports {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ port@0 {
++ vin5ep0: endpoint@0 {
++ csi,select = "csi20";
++ virtual,channel = <1>;
++ remote-endpoint = <&ov106xx_in5>;
++ data-lanes = <1 2>;
++ };
++ };
++ port@1 {
++ csi1ep1: endpoint {
++ remote-endpoint = <&csi2_20_ep>;
++ };
++ };
++ port@2 {
++ vin5_max9286_des1ep1: endpoint@0 {
++ remote-endpoint = <&max9286_des1ep1>;
++ };
++ };
++ };
++};
++
++&csi2_40 {
++ status = "okay";
++
++ virtual,channel {
++ csi2_vc0 {
++ data,type = "ycbcr422";
++ receive,vc = <0>;
++ };
++ csi2_vc1 {
++ data,type = "ycbcr422";
++ receive,vc = <1>;
++ };
++ csi2_vc2 {
++ data,type = "ycbcr422";
++ receive,vc = <2>;
++ };
++ csi2_vc3 {
++ data,type = "ycbcr422";
++ receive,vc = <3>;
++ };
++ };
++
++ port {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ csi2_40_ep: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2 3 4>;
++ csi-rate = <700>;
++ };
++ };
++};
++
++&csi2_20 {
++ status = "okay";
++
++ virtual,channel {
++ csi2_vc0 {
++ data,type = "ycbcr422";
++ receive,vc = <0>;
++ };
++ csi2_vc1 {
++ data,type = "ycbcr422";
++ receive,vc = <1>;
++ };
++ };
++
++ port {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ csi2_20_ep: endpoint {
++ clock-lanes = <0>;
++ data-lanes = <1 2>;
++ csi-rate = <350>;
++ };
++ };
++};
++
++&vspbc {
++ status = "okay";
++};
++
++&vspbd {
++ status = "okay";
++};
++
++&vspi0 {
++ status = "okay";
++};
++
++&vspi1 {
++ status = "okay";
++};
++
++&vspi2 {
++ status = "okay";
++};
+--
+1.9.1
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0050-arm64-dts-Gen3-view-boards-TYPE1-first-4-cameras.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0050-arm64-dts-Gen3-view-boards-TYPE1-first-4-cameras.patch
new file mode 100644
index 0000000..d368b6a
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0050-arm64-dts-Gen3-view-boards-TYPE1-first-4-cameras.patch
@@ -0,0 +1,302 @@
+From 67d29f4fe320f555366ea45f5439ac52641472ec Mon Sep 17 00:00:00 2001
+From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+Date: Mon, 15 May 2017 19:16:23 +0300
+Subject: [PATCH] arm64: dts: Gen3 view boards: TYPE1 first 4 cameras
+
+This set 4 cameras to TYPE1 in DT
+
+Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+---
+ arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts | 8 ++++----
+ arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts | 8 ++++----
+ arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts | 8 ++++----
+ arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts | 8 ++++----
+ arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts | 8 ++++----
+ arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts | 8 ++++----
+ arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts | 8 ++++----
+ arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts | 8 ++++----
+ arch/arm64/boot/dts/renesas/r8a7796-salvator-x-view.dts | 8 ++++----
+ 9 files changed, 36 insertions(+), 36 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts
+index 50a37e0..8da87dd 100644
+--- a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts
++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts
+@@ -780,22 +780,22 @@
+ port@0 {
+ max9286_des0ep0: endpoint@0 {
+ max9271-addr = <0x50>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in0>;
+ };
+ max9286_des0ep1: endpoint@1 {
+ max9271-addr = <0x51>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in1>;
+ };
+ max9286_des0ep2: endpoint@2 {
+ max9271-addr = <0x52>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in2>;
+ };
+ max9286_des0ep3: endpoint@3 {
+ max9271-addr = <0x53>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in3>;
+ };
+ };
+diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts
+index de56fa4..b36b9d8 100644
+--- a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts
++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts
+@@ -175,22 +175,22 @@
+ port@0 {
+ max9286_des0ep0: endpoint@0 {
+ max9271-addr = <0x50>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in0>;
+ };
+ max9286_des0ep1: endpoint@1 {
+ max9271-addr = <0x51>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in1>;
+ };
+ max9286_des0ep2: endpoint@2 {
+ max9271-addr = <0x52>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in2>;
+ };
+ max9286_des0ep3: endpoint@3 {
+ max9271-addr = <0x53>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in3>;
+ };
+ };
+diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts
+index 3f3d66a..c063899 100644
+--- a/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts
++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts
+@@ -190,22 +190,22 @@
+ port@0 {
+ max9286_des0ep0: endpoint@0 {
+ max9271-addr = <0x50>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in0>;
+ };
+ max9286_des0ep1: endpoint@1 {
+ max9271-addr = <0x51>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in1>;
+ };
+ max9286_des0ep2: endpoint@2 {
+ max9271-addr = <0x52>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in2>;
+ };
+ max9286_des0ep3: endpoint@3 {
+ max9271-addr = <0x53>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in3>;
+ };
+ };
+diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts
+index 94c86f6..b26d8e2 100644
+--- a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts
++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts
+@@ -780,22 +780,22 @@
+ port@0 {
+ max9286_des0ep0: endpoint@0 {
+ max9271-addr = <0x50>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in0>;
+ };
+ max9286_des0ep1: endpoint@1 {
+ max9271-addr = <0x51>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in1>;
+ };
+ max9286_des0ep2: endpoint@2 {
+ max9271-addr = <0x52>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in2>;
+ };
+ max9286_des0ep3: endpoint@3 {
+ max9271-addr = <0x53>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in3>;
+ };
+ };
+diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts
+index 2c24b85..a8b9eea 100644
+--- a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts
++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts
+@@ -175,22 +175,22 @@
+ port@0 {
+ max9286_des0ep0: endpoint@0 {
+ max9271-addr = <0x50>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in0>;
+ };
+ max9286_des0ep1: endpoint@1 {
+ max9271-addr = <0x51>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in1>;
+ };
+ max9286_des0ep2: endpoint@2 {
+ max9271-addr = <0x52>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in2>;
+ };
+ max9286_des0ep3: endpoint@3 {
+ max9271-addr = <0x53>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in3>;
+ };
+ };
+diff --git a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts
+index fb12a39f3..eb09ef0 100644
+--- a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts
++++ b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts
+@@ -190,22 +190,22 @@
+ port@0 {
+ max9286_des0ep0: endpoint@0 {
+ max9271-addr = <0x50>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in0>;
+ };
+ max9286_des0ep1: endpoint@1 {
+ max9271-addr = <0x51>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in1>;
+ };
+ max9286_des0ep2: endpoint@2 {
+ max9271-addr = <0x52>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in2>;
+ };
+ max9286_des0ep3: endpoint@3 {
+ max9271-addr = <0x53>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in3>;
+ };
+ };
+diff --git a/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts
+index ffaef74..83c6355 100644
+--- a/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts
++++ b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts
+@@ -780,22 +780,22 @@
+ port@0 {
+ max9286_des0ep0: endpoint@0 {
+ max9271-addr = <0x50>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in0>;
+ };
+ max9286_des0ep1: endpoint@1 {
+ max9271-addr = <0x51>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in1>;
+ };
+ max9286_des0ep2: endpoint@2 {
+ max9271-addr = <0x52>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in2>;
+ };
+ max9286_des0ep3: endpoint@3 {
+ max9271-addr = <0x53>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in3>;
+ };
+ };
+diff --git a/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts
+index 1ac0041..096fb5f 100644
+--- a/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts
++++ b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts
+@@ -103,22 +103,22 @@
+ port@0 {
+ max9286_des0ep0: endpoint@0 {
+ max9271-addr = <0x50>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in0>;
+ };
+ max9286_des0ep1: endpoint@1 {
+ max9271-addr = <0x51>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in1>;
+ };
+ max9286_des0ep2: endpoint@2 {
+ max9271-addr = <0x52>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in2>;
+ };
+ max9286_des0ep3: endpoint@3 {
+ max9271-addr = <0x53>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in3>;
+ };
+ };
+diff --git a/arch/arm64/boot/dts/renesas/r8a7796-salvator-x-view.dts b/arch/arm64/boot/dts/renesas/r8a7796-salvator-x-view.dts
+index cc6866c..7a592d1 100644
+--- a/arch/arm64/boot/dts/renesas/r8a7796-salvator-x-view.dts
++++ b/arch/arm64/boot/dts/renesas/r8a7796-salvator-x-view.dts
+@@ -118,22 +118,22 @@
+ port@0 {
+ max9286_des0ep0: endpoint@0 {
+ max9271-addr = <0x50>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in0>;
+ };
+ max9286_des0ep1: endpoint@1 {
+ max9271-addr = <0x51>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in1>;
+ };
+ max9286_des0ep2: endpoint@2 {
+ max9271-addr = <0x52>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in2>;
+ };
+ max9286_des0ep3: endpoint@3 {
+ max9271-addr = <0x53>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in3>;
+ };
+ };
+--
+1.9.1
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-dts-Gen3-view-boards-TYPE1-second-4-cameras.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-dts-Gen3-view-boards-TYPE1-second-4-cameras.patch
new file mode 100644
index 0000000..a09c485
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-dts-Gen3-view-boards-TYPE1-second-4-cameras.patch
@@ -0,0 +1,206 @@
+From d9ec2149ffc47fd2ea4ab5e9a503a3be7c6f09f5 Mon Sep 17 00:00:00 2001
+From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+Date: Mon, 15 May 2017 19:18:06 +0300
+Subject: [PATCH] arm64: dts: Gen3 view boards: TYPE1 second 4 cameras
+
+This set 4 cameras to TYPE1 in DT
+
+Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+---
+ arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts | 8 ++++----
+ arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts | 8 ++++----
+ arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts | 8 ++++----
+ arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts | 8 ++++----
+ arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts | 8 ++++----
+ arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts | 8 ++++----
+ 6 files changed, 24 insertions(+), 24 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts
+index 8da87dd..d2e6f66 100644
+--- a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts
++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts
+@@ -989,22 +989,22 @@
+ port@0 {
+ max9286_des1ep0: endpoint@0 {
+ max9271-addr = <0x50>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in4>;
+ };
+ max9286_des1ep1: endpoint@1 {
+ max9271-addr = <0x51>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in5>;
+ };
+ max9286_des1ep2: endpoint@2 {
+ max9271-addr = <0x52>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in6>;
+ };
+ max9286_des1ep3: endpoint@3 {
+ max9271-addr = <0x53>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in7>;
+ };
+ };
+diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts
+index b36b9d8..e3a9414 100644
+--- a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts
++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts
+@@ -216,22 +216,22 @@
+ port@0 {
+ max9286_des1ep0: endpoint@0 {
+ max9271-addr = <0x54>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in4>;
+ };
+ max9286_des1ep1: endpoint@1 {
+ max9271-addr = <0x55>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in5>;
+ };
+ max9286_des1ep2: endpoint@2 {
+ max9271-addr = <0x56>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in6>;
+ };
+ max9286_des1ep3: endpoint@3 {
+ max9271-addr = <0x57>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in7>;
+ };
+ };
+diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts
+index c063899..2785fd7 100644
+--- a/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts
++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts
+@@ -230,22 +230,22 @@
+ port@0 {
+ max9286_des1ep0: endpoint@0 {
+ max9271-addr = <0x54>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in4>;
+ };
+ max9286_des1ep1: endpoint@1 {
+ max9271-addr = <0x55>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in5>;
+ };
+ max9286_des1ep2: endpoint@2 {
+ max9271-addr = <0x56>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in6>;
+ };
+ max9286_des1ep3: endpoint@3 {
+ max9271-addr = <0x57>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in7>;
+ };
+ };
+diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts
+index b26d8e2..b8f8819 100644
+--- a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts
++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts
+@@ -989,22 +989,22 @@
+ port@0 {
+ max9286_des1ep0: endpoint@0 {
+ max9271-addr = <0x50>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in4>;
+ };
+ max9286_des1ep1: endpoint@1 {
+ max9271-addr = <0x51>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in5>;
+ };
+ max9286_des1ep2: endpoint@2 {
+ max9271-addr = <0x52>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in6>;
+ };
+ max9286_des1ep3: endpoint@3 {
+ max9271-addr = <0x53>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in7>;
+ };
+ };
+diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts
+index a8b9eea..86ed4a8 100644
+--- a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts
++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts
+@@ -216,22 +216,22 @@
+ port@0 {
+ max9286_des1ep0: endpoint@0 {
+ max9271-addr = <0x54>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in4>;
+ };
+ max9286_des1ep1: endpoint@1 {
+ max9271-addr = <0x55>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in5>;
+ };
+ max9286_des1ep2: endpoint@2 {
+ max9271-addr = <0x56>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in6>;
+ };
+ max9286_des1ep3: endpoint@3 {
+ max9271-addr = <0x57>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in7>;
+ };
+ };
+diff --git a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts
+index eb09ef0..37eabc0 100644
+--- a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts
++++ b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts
+@@ -230,22 +230,22 @@
+ port@0 {
+ max9286_des1ep0: endpoint@0 {
+ max9271-addr = <0x54>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in4>;
+ };
+ max9286_des1ep1: endpoint@1 {
+ max9271-addr = <0x55>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in5>;
+ };
+ max9286_des1ep2: endpoint@2 {
+ max9271-addr = <0x56>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in6>;
+ };
+ max9286_des1ep3: endpoint@3 {
+ max9271-addr = <0x57>;
+- dvp-order = <1>;
++ dvp-order = <2>;
+ remote-endpoint = <&ov106xx_in7>;
+ };
+ };
+--
+1.9.1
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0052-arm64-dts-Gen3-view-boards-TYPE2-first-4-cameras.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0052-arm64-dts-Gen3-view-boards-TYPE2-first-4-cameras.patch
new file mode 100644
index 0000000..2c4d9f3
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0052-arm64-dts-Gen3-view-boards-TYPE2-first-4-cameras.patch
@@ -0,0 +1,527 @@
+From fa7c75c71d40c8ce44b0fbaea79031daaede2ba7 Mon Sep 17 00:00:00 2001
+From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+Date: Mon, 15 May 2017 19:24:29 +0300
+Subject: [PATCH] arm64: dts: Gen3 view boards: TYPE2 first 4 cameras
+
+This set 4 cameras to TYPE2 in DT
+
+Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+---
+ arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts | 17 +++++++++++++++--
+ arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts | 17 +++++++++++++++--
+ .../boot/dts/renesas/r8a7795-es1-salvator-x-view.dts | 17 +++++++++++++++--
+ arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts | 17 +++++++++++++++--
+ arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts | 17 +++++++++++++++--
+ arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts | 17 +++++++++++++++--
+ arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts | 17 +++++++++++++++--
+ arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts | 17 +++++++++++++++--
+ arch/arm64/boot/dts/renesas/r8a7796-salvator-x-view.dts | 17 +++++++++++++++--
+ 9 files changed, 135 insertions(+), 18 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts
+index 50a37e0..8808e80 100644
+--- a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts
++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts
+@@ -609,6 +609,9 @@
+ compatible = "ovti,ov106xx";
+ reg = <0x60>;
+
++ maxim,fixed-sensor = "ov490";
++ maxim,width = <1280>;
++ maxim,height = <966>;
+ port@0 {
+ ov106xx_in0: endpoint {
+ clock-lanes = <0>;
+@@ -633,6 +636,9 @@
+ compatible = "ovti,ov106xx";
+ reg = <0x61>;
+
++ maxim,fixed-sensor = "ov490";
++ maxim,width = <1280>;
++ maxim,height = <966>;
+ port@0 {
+ ov106xx_in1: endpoint {
+ clock-lanes = <0>;
+@@ -657,6 +663,9 @@
+ compatible = "ovti,ov106xx";
+ reg = <0x62>;
+
++ maxim,fixed-sensor = "ov490";
++ maxim,width = <1280>;
++ maxim,height = <966>;
+ port@0 {
+ ov106xx_in2: endpoint {
+ clock-lanes = <0>;
+@@ -678,6 +687,9 @@
+ compatible = "ovti,ov106xx";
+ reg = <0x63>;
+
++ maxim,fixed-sensor = "ov490";
++ maxim,width = <1280>;
++ maxim,height = <966>;
+ port@0 {
+ ov106xx_in3: endpoint {
+ clock-lanes = <0>;
+@@ -773,8 +785,9 @@
+ maxim,sensor_delay = <350>;
+ maxim,links = <4>;
+ maxim,lanes = <4>;
+- maxim,resetb-gpio = <1>;
+- maxim,fsync-mode = "automatic";
++ maxim,resetb-gpio = <4>;
++ maxim,resetb-active-high;
++ maxim,fsync-mode = "manual";
+ maxim,timeout = <100>;
+
+ port@0 {
+diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts
+index de56fa4..007aa7a 100644
+--- a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts
++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts
+@@ -20,6 +20,9 @@
+ compatible = "ovti,ov106xx";
+ reg = <0x60>;
+
++ maxim,fixed-sensor = "ov490";
++ maxim,width = <1280>;
++ maxim,height = <966>;
+ port@0 {
+ ov106xx_in0: endpoint {
+ clock-lanes = <0>;
+@@ -38,6 +41,9 @@
+ compatible = "ovti,ov106xx";
+ reg = <0x61>;
+
++ maxim,fixed-sensor = "ov490";
++ maxim,width = <1280>;
++ maxim,height = <966>;
+ port@0 {
+ ov106xx_in1: endpoint {
+ clock-lanes = <0>;
+@@ -56,6 +62,9 @@
+ compatible = "ovti,ov106xx";
+ reg = <0x62>;
+
++ maxim,fixed-sensor = "ov490";
++ maxim,width = <1280>;
++ maxim,height = <966>;
+ port@0 {
+ ov106xx_in2: endpoint {
+ clock-lanes = <0>;
+@@ -74,6 +83,9 @@
+ compatible = "ovti,ov106xx";
+ reg = <0x63>;
+
++ maxim,fixed-sensor = "ov490";
++ maxim,width = <1280>;
++ maxim,height = <966>;
+ port@0 {
+ ov106xx_in3: endpoint {
+ clock-lanes = <0>;
+@@ -167,8 +179,9 @@
+ maxim,sensor_delay = <0>;
+ maxim,links = <4>;
+ maxim,lanes = <4>;
+- maxim,resetb-gpio = <1>;
+- maxim,fsync-mode = "automatic";
++ maxim,resetb-gpio = <4>;
++ maxim,resetb-active-high;
++ maxim,fsync-mode = "manual";
+ maxim,timeout = <100>;
+ maxim,i2c-quirk = <0x6c>;
+
+diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts
+index 3f3d66a..4b3513a 100644
+--- a/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts
++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts
+@@ -35,6 +35,9 @@
+ compatible = "ovti,ov106xx";
+ reg = <0x60>;
+
++ maxim,fixed-sensor = "ov490";
++ maxim,width = <1280>;
++ maxim,height = <966>;
+ port@0 {
+ ov106xx_in0: endpoint {
+ clock-lanes = <0>;
+@@ -53,6 +56,9 @@
+ compatible = "ovti,ov106xx";
+ reg = <0x61>;
+
++ maxim,fixed-sensor = "ov490";
++ maxim,width = <1280>;
++ maxim,height = <966>;
+ port@0 {
+ ov106xx_in1: endpoint {
+ clock-lanes = <0>;
+@@ -71,6 +77,9 @@
+ compatible = "ovti,ov106xx";
+ reg = <0x62>;
+
++ maxim,fixed-sensor = "ov490";
++ maxim,width = <1280>;
++ maxim,height = <966>;
+ port@0 {
+ ov106xx_in2: endpoint {
+ clock-lanes = <0>;
+@@ -89,6 +98,9 @@
+ compatible = "ovti,ov106xx";
+ reg = <0x63>;
+
++ maxim,fixed-sensor = "ov490";
++ maxim,width = <1280>;
++ maxim,height = <966>;
+ port@0 {
+ ov106xx_in3: endpoint {
+ clock-lanes = <0>;
+@@ -182,8 +194,9 @@
+ maxim,sensor_delay = <0>;
+ maxim,links = <4>;
+ maxim,lanes = <4>;
+- maxim,resetb-gpio = <1>;
+- maxim,fsync-mode = "automatic";
++ maxim,resetb-gpio = <4>;
++ maxim,resetb-active-high;
++ maxim,fsync-mode = "manual";
+ maxim,timeout = <100>;
+ maxim,i2c-quirk = <0x6c>;
+
+diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts
+index 94c86f6..e650c5b 100644
+--- a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts
++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts
+@@ -609,6 +609,9 @@
+ compatible = "ovti,ov106xx";
+ reg = <0x60>;
+
++ maxim,fixed-sensor = "ov490";
++ maxim,width = <1280>;
++ maxim,height = <966>;
+ port@0 {
+ ov106xx_in0: endpoint {
+ clock-lanes = <0>;
+@@ -633,6 +636,9 @@
+ compatible = "ovti,ov106xx";
+ reg = <0x61>;
+
++ maxim,fixed-sensor = "ov490";
++ maxim,width = <1280>;
++ maxim,height = <966>;
+ port@0 {
+ ov106xx_in1: endpoint {
+ clock-lanes = <0>;
+@@ -657,6 +663,9 @@
+ compatible = "ovti,ov106xx";
+ reg = <0x62>;
+
++ maxim,fixed-sensor = "ov490";
++ maxim,width = <1280>;
++ maxim,height = <966>;
+ port@0 {
+ ov106xx_in2: endpoint {
+ clock-lanes = <0>;
+@@ -678,6 +687,9 @@
+ compatible = "ovti,ov106xx";
+ reg = <0x63>;
+
++ maxim,fixed-sensor = "ov490";
++ maxim,width = <1280>;
++ maxim,height = <966>;
+ port@0 {
+ ov106xx_in3: endpoint {
+ clock-lanes = <0>;
+@@ -773,8 +785,9 @@
+ maxim,sensor_delay = <350>;
+ maxim,links = <4>;
+ maxim,lanes = <4>;
+- maxim,resetb-gpio = <1>;
+- maxim,fsync-mode = "automatic";
++ maxim,resetb-gpio = <4>;
++ maxim,resetb-active-high;
++ maxim,fsync-mode = "manual";
+ maxim,timeout = <100>;
+
+ port@0 {
+diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts
+index 2c24b85..ac0723d 100644
+--- a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts
++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts
+@@ -20,6 +20,9 @@
+ compatible = "ovti,ov106xx";
+ reg = <0x60>;
+
++ maxim,fixed-sensor = "ov490";
++ maxim,width = <1280>;
++ maxim,height = <966>;
+ port@0 {
+ ov106xx_in0: endpoint {
+ clock-lanes = <0>;
+@@ -38,6 +41,9 @@
+ compatible = "ovti,ov106xx";
+ reg = <0x61>;
+
++ maxim,fixed-sensor = "ov490";
++ maxim,width = <1280>;
++ maxim,height = <966>;
+ port@0 {
+ ov106xx_in1: endpoint {
+ clock-lanes = <0>;
+@@ -56,6 +62,9 @@
+ compatible = "ovti,ov106xx";
+ reg = <0x62>;
+
++ maxim,fixed-sensor = "ov490";
++ maxim,width = <1280>;
++ maxim,height = <966>;
+ port@0 {
+ ov106xx_in2: endpoint {
+ clock-lanes = <0>;
+@@ -74,6 +83,9 @@
+ compatible = "ovti,ov106xx";
+ reg = <0x63>;
+
++ maxim,fixed-sensor = "ov490";
++ maxim,width = <1280>;
++ maxim,height = <966>;
+ port@0 {
+ ov106xx_in3: endpoint {
+ clock-lanes = <0>;
+@@ -167,8 +179,9 @@
+ maxim,sensor_delay = <0>;
+ maxim,links = <4>;
+ maxim,lanes = <4>;
+- maxim,resetb-gpio = <1>;
+- maxim,fsync-mode = "automatic";
++ maxim,resetb-gpio = <4>;
++ maxim,resetb-active-high;
++ maxim,fsync-mode = "manual";
+ maxim,timeout = <100>;
+ maxim,i2c-quirk = <0x6c>;
+
+diff --git a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts
+index fb12a39f3..ef0895e 100644
+--- a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts
++++ b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts
+@@ -35,6 +35,9 @@
+ compatible = "ovti,ov106xx";
+ reg = <0x60>;
+
++ maxim,fixed-sensor = "ov490";
++ maxim,width = <1280>;
++ maxim,height = <966>;
+ port@0 {
+ ov106xx_in0: endpoint {
+ clock-lanes = <0>;
+@@ -53,6 +56,9 @@
+ compatible = "ovti,ov106xx";
+ reg = <0x61>;
+
++ maxim,fixed-sensor = "ov490";
++ maxim,width = <1280>;
++ maxim,height = <966>;
+ port@0 {
+ ov106xx_in1: endpoint {
+ clock-lanes = <0>;
+@@ -71,6 +77,9 @@
+ compatible = "ovti,ov106xx";
+ reg = <0x62>;
+
++ maxim,fixed-sensor = "ov490";
++ maxim,width = <1280>;
++ maxim,height = <966>;
+ port@0 {
+ ov106xx_in2: endpoint {
+ clock-lanes = <0>;
+@@ -89,6 +98,9 @@
+ compatible = "ovti,ov106xx";
+ reg = <0x63>;
+
++ maxim,fixed-sensor = "ov490";
++ maxim,width = <1280>;
++ maxim,height = <966>;
+ port@0 {
+ ov106xx_in3: endpoint {
+ clock-lanes = <0>;
+@@ -182,8 +194,9 @@
+ maxim,sensor_delay = <0>;
+ maxim,links = <4>;
+ maxim,lanes = <4>;
+- maxim,resetb-gpio = <1>;
+- maxim,fsync-mode = "automatic";
++ maxim,resetb-gpio = <4>;
++ maxim,resetb-active-high;
++ maxim,fsync-mode = "manual";
+ maxim,timeout = <100>;
+ maxim,i2c-quirk = <0x6c>;
+
+diff --git a/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts
+index ffaef74..5670f3a 100644
+--- a/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts
++++ b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts
+@@ -609,6 +609,9 @@
+ compatible = "ovti,ov106xx";
+ reg = <0x60>;
+
++ maxim,fixed-sensor = "ov490";
++ maxim,width = <1280>;
++ maxim,height = <966>;
+ port@0 {
+ ov106xx_in0: endpoint {
+ clock-lanes = <0>;
+@@ -633,6 +636,9 @@
+ compatible = "ovti,ov106xx";
+ reg = <0x61>;
+
++ maxim,fixed-sensor = "ov490";
++ maxim,width = <1280>;
++ maxim,height = <966>;
+ port@0 {
+ ov106xx_in1: endpoint {
+ clock-lanes = <0>;
+@@ -657,6 +663,9 @@
+ compatible = "ovti,ov106xx";
+ reg = <0x62>;
+
++ maxim,fixed-sensor = "ov490";
++ maxim,width = <1280>;
++ maxim,height = <966>;
+ port@0 {
+ ov106xx_in2: endpoint {
+ clock-lanes = <0>;
+@@ -678,6 +687,9 @@
+ compatible = "ovti,ov106xx";
+ reg = <0x63>;
+
++ maxim,fixed-sensor = "ov490";
++ maxim,width = <1280>;
++ maxim,height = <966>;
+ port@0 {
+ ov106xx_in3: endpoint {
+ clock-lanes = <0>;
+@@ -773,8 +785,9 @@
+ maxim,sensor_delay = <350>;
+ maxim,links = <4>;
+ maxim,lanes = <4>;
+- maxim,resetb-gpio = <1>;
+- maxim,fsync-mode = "automatic";
++ maxim,resetb-gpio = <4>;
++ maxim,resetb-active-high;
++ maxim,fsync-mode = "manual";
+ maxim,timeout = <100>;
+
+ port@0 {
+diff --git a/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts
+index 1ac0041..8a67c5f 100644
+--- a/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts
++++ b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts
+@@ -20,6 +20,9 @@
+ compatible = "ovti,ov106xx";
+ reg = <0x60>;
+
++ maxim,fixed-sensor = "ov490";
++ maxim,width = <1280>;
++ maxim,height = <966>;
+ port@0 {
+ ov106xx_in0: endpoint {
+ clock-lanes = <0>;
+@@ -38,6 +41,9 @@
+ compatible = "ovti,ov106xx";
+ reg = <0x61>;
+
++ maxim,fixed-sensor = "ov490";
++ maxim,width = <1280>;
++ maxim,height = <966>;
+ port@0 {
+ ov106xx_in1: endpoint {
+ clock-lanes = <0>;
+@@ -56,6 +62,9 @@
+ compatible = "ovti,ov106xx";
+ reg = <0x62>;
+
++ maxim,fixed-sensor = "ov490";
++ maxim,width = <1280>;
++ maxim,height = <966>;
+ port@0 {
+ ov106xx_in2: endpoint {
+ clock-lanes = <0>;
+@@ -74,6 +83,9 @@
+ compatible = "ovti,ov106xx";
+ reg = <0x63>;
+
++ maxim,fixed-sensor = "ov490";
++ maxim,width = <1280>;
++ maxim,height = <966>;
+ port@0 {
+ ov106xx_in3: endpoint {
+ clock-lanes = <0>;
+@@ -95,8 +107,9 @@
+ maxim,sensor_delay = <0>;
+ maxim,links = <4>;
+ maxim,lanes = <4>;
+- maxim,resetb-gpio = <1>;
+- maxim,fsync-mode = "automatic";
++ maxim,resetb-gpio = <4>;
++ maxim,resetb-active-high;
++ maxim,fsync-mode = "manual";
+ maxim,timeout = <100>;
+ maxim,i2c-quirk = <0x6c>;
+
+diff --git a/arch/arm64/boot/dts/renesas/r8a7796-salvator-x-view.dts b/arch/arm64/boot/dts/renesas/r8a7796-salvator-x-view.dts
+index cc6866c..ab6e28a 100644
+--- a/arch/arm64/boot/dts/renesas/r8a7796-salvator-x-view.dts
++++ b/arch/arm64/boot/dts/renesas/r8a7796-salvator-x-view.dts
+@@ -35,6 +35,9 @@
+ compatible = "ovti,ov106xx";
+ reg = <0x60>;
+
++ maxim,fixed-sensor = "ov490";
++ maxim,width = <1280>;
++ maxim,height = <966>;
+ port@0 {
+ ov106xx_in0: endpoint {
+ clock-lanes = <0>;
+@@ -53,6 +56,9 @@
+ compatible = "ovti,ov106xx";
+ reg = <0x61>;
+
++ maxim,fixed-sensor = "ov490";
++ maxim,width = <1280>;
++ maxim,height = <966>;
+ port@0 {
+ ov106xx_in1: endpoint {
+ clock-lanes = <0>;
+@@ -71,6 +77,9 @@
+ compatible = "ovti,ov106xx";
+ reg = <0x62>;
+
++ maxim,fixed-sensor = "ov490";
++ maxim,width = <1280>;
++ maxim,height = <966>;
+ port@0 {
+ ov106xx_in2: endpoint {
+ clock-lanes = <0>;
+@@ -89,6 +98,9 @@
+ compatible = "ovti,ov106xx";
+ reg = <0x63>;
+
++ maxim,fixed-sensor = "ov490";
++ maxim,width = <1280>;
++ maxim,height = <966>;
+ port@0 {
+ ov106xx_in3: endpoint {
+ clock-lanes = <0>;
+@@ -110,8 +122,9 @@
+ maxim,sensor_delay = <0>;
+ maxim,links = <4>;
+ maxim,lanes = <4>;
+- maxim,resetb-gpio = <1>;
+- maxim,fsync-mode = "automatic";
++ maxim,resetb-gpio = <4>;
++ maxim,resetb-active-high;
++ maxim,fsync-mode = "manual";
+ maxim,timeout = <100>;
+ maxim,i2c-quirk = <0x6c>;
+
+--
+1.9.1
+
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/eagle.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/eagle.cfg
new file mode 100644
index 0000000..2b6c4ea
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/eagle.cfg
@@ -0,0 +1,26 @@
+CONFIG_ARCH_R8A7797=y
+CONFIG_CAN=y
+CONFIG_CAN_PEAK_USB=y
+CONFIG_CAN_BCM=y
+CONFIG_CAN_RAW=y
+CONFIG_CAN_DEV=y
+CONFIG_CAN_CALC_BITTIMING=y
+CONFIG_CAN_RCAR=y
+CONFIG_CANFD_RCAR=y
+CONFIG_DRM_I2C_ADV7511=y
+CONFIG_GPIO_PCA953X=y
+CONFIG_GPIO_PCA953X_IRQ=y
+CONFIG_VIDEO_ADV_DEBUG=y
+CONFIG_VIDEO_RCAR_VIN_LEGACY=y
+CONFIG_VIDEO_RCAR_CSI2_LEGACY=y
+# CONFIG_VIDEO_RCAR_VIN is not set
+# CONFIG_VIDEO_RCAR_CSI2 is not set
+CONFIG_SOC_CAMERA=y
+CONFIG_SOC_CAMERA_SCALE_CROP=y
+CONFIG_SOC_CAMERA_PLATFORM=y
+CONFIG_SOC_CAMERA_MAX9286_MAX9271=y
+CONFIG_SOC_CAMERA_OV106XX=y
+CONFIG_VIDEO_RENESAS_IMR=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_PROPERTIES=y
+CONFIG_HID_MULTITOUCH=y
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/h3ulcb.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/h3ulcb.cfg
new file mode 100644
index 0000000..0e0ade7
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/h3ulcb.cfg
@@ -0,0 +1,50 @@
+CONFIG_CAN=y
+CONFIG_CAN_PEAK_USB=y
+CONFIG_CAN_BCM=y
+CONFIG_CAN_RAW=y
+CONFIG_CAN_DEV=y
+CONFIG_CAN_CALC_BITTIMING=y
+CONFIG_CAN_RCAR=y
+CONFIG_CANFD_RCAR=y
+CONFIG_EXTRA_FIRMWARE="r8a779x_usb3_v2.dlmem"
+CONFIG_EXTRA_FIRMWARE_DIR="firmware"
+CONFIG_BLK_DEV_NVME=m
+CONFIG_SATA_ACARD_AHCI=y
+CONFIG_FIXED_PHY=y
+CONFIG_SPI_BITBANG=y
+CONFIG_SPI_GPIO=y
+CONFIG_GPIO_MAX732X=y
+CONFIG_GPIO_PCA953X=y
+CONFIG_GPIO_PCA953X_IRQ=y
+CONFIG_VIDEO_ADV_DEBUG=y
+CONFIG_VIDEO_RCAR_VIN_LEGACY=y
+CONFIG_VIDEO_RCAR_CSI2_LEGACY=y
+# CONFIG_VIDEO_RCAR_VIN is not set
+# CONFIG_VIDEO_RCAR_CSI2 is not set
+CONFIG_SOC_CAMERA=y
+CONFIG_SOC_CAMERA_SCALE_CROP=y
+CONFIG_SOC_CAMERA_PLATFORM=y
+CONFIG_SOC_CAMERA_MAX9286_MAX9271=y
+CONFIG_SOC_CAMERA_TI964_TI9X3=y
+CONFIG_SOC_CAMERA_TI954_TI9X3=y
+CONFIG_SOC_CAMERA_OV106XX=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_PLATFORM=y
+CONFIG_USB_XHCI_RCAR=y
+CONFIG_VIDEO_RENESAS_IMR=y
+CONFIG_VIRTIO_RCAR_PCIE=y
+CONFIG_BT=y
+CONFIG_TI_ST=m
+CONFIG_BT_WILINK=m
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_CFG80211_WEXT=y
+CONFIG_MAC80211=y
+CONFIG_WLAN=y
+CONFIG_WL18XX=m
+CONFIG_WLCORE=m
+CONFIG_WLCORE_SDIO=m
+CONFIG_SND_SOC_SI468X=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_PROPERTIES=y
+CONFIG_HID_MULTITOUCH=y
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/hyperflash.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/hyperflash.cfg
new file mode 100644
index 0000000..df45d5e
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/hyperflash.cfg
@@ -0,0 +1,2 @@
+CONFIG_MTD=y
+CONFIG_MTD_RPC_HYPERFLASH=y
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/m3ulcb.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/m3ulcb.cfg
new file mode 100644
index 0000000..0e0ade7
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/m3ulcb.cfg
@@ -0,0 +1,50 @@
+CONFIG_CAN=y
+CONFIG_CAN_PEAK_USB=y
+CONFIG_CAN_BCM=y
+CONFIG_CAN_RAW=y
+CONFIG_CAN_DEV=y
+CONFIG_CAN_CALC_BITTIMING=y
+CONFIG_CAN_RCAR=y
+CONFIG_CANFD_RCAR=y
+CONFIG_EXTRA_FIRMWARE="r8a779x_usb3_v2.dlmem"
+CONFIG_EXTRA_FIRMWARE_DIR="firmware"
+CONFIG_BLK_DEV_NVME=m
+CONFIG_SATA_ACARD_AHCI=y
+CONFIG_FIXED_PHY=y
+CONFIG_SPI_BITBANG=y
+CONFIG_SPI_GPIO=y
+CONFIG_GPIO_MAX732X=y
+CONFIG_GPIO_PCA953X=y
+CONFIG_GPIO_PCA953X_IRQ=y
+CONFIG_VIDEO_ADV_DEBUG=y
+CONFIG_VIDEO_RCAR_VIN_LEGACY=y
+CONFIG_VIDEO_RCAR_CSI2_LEGACY=y
+# CONFIG_VIDEO_RCAR_VIN is not set
+# CONFIG_VIDEO_RCAR_CSI2 is not set
+CONFIG_SOC_CAMERA=y
+CONFIG_SOC_CAMERA_SCALE_CROP=y
+CONFIG_SOC_CAMERA_PLATFORM=y
+CONFIG_SOC_CAMERA_MAX9286_MAX9271=y
+CONFIG_SOC_CAMERA_TI964_TI9X3=y
+CONFIG_SOC_CAMERA_TI954_TI9X3=y
+CONFIG_SOC_CAMERA_OV106XX=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_PLATFORM=y
+CONFIG_USB_XHCI_RCAR=y
+CONFIG_VIDEO_RENESAS_IMR=y
+CONFIG_VIRTIO_RCAR_PCIE=y
+CONFIG_BT=y
+CONFIG_TI_ST=m
+CONFIG_BT_WILINK=m
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_CFG80211_WEXT=y
+CONFIG_MAC80211=y
+CONFIG_WLAN=y
+CONFIG_WL18XX=m
+CONFIG_WLCORE=m
+CONFIG_WLCORE_SDIO=m
+CONFIG_SND_SOC_SI468X=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_PROPERTIES=y
+CONFIG_HID_MULTITOUCH=y
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/salvator-x.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/salvator-x.cfg
new file mode 100644
index 0000000..c5fd6fd
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/salvator-x.cfg
@@ -0,0 +1,29 @@
+CONFIG_CAN=y
+CONFIG_CAN_PEAK_USB=y
+CONFIG_CAN_BCM=y
+CONFIG_CAN_RAW=y
+CONFIG_CAN_DEV=y
+CONFIG_CAN_CALC_BITTIMING=y
+CONFIG_CAN_RCAR=y
+CONFIG_CANFD_RCAR=y
+CONFIG_EXTRA_FIRMWARE="r8a779x_usb3_v2.dlmem"
+CONFIG_EXTRA_FIRMWARE_DIR="firmware"
+CONFIG_VIDEO_ADV_DEBUG=y
+CONFIG_VIDEO_RCAR_VIN_LEGACY=y
+CONFIG_VIDEO_RCAR_CSI2_LEGACY=y
+# CONFIG_VIDEO_RCAR_VIN is not set
+# CONFIG_VIDEO_RCAR_CSI2 is not set
+CONFIG_SOC_CAMERA=y
+CONFIG_SOC_CAMERA_SCALE_CROP=y
+CONFIG_SOC_CAMERA_PLATFORM=y
+CONFIG_SOC_CAMERA_MAX9286_MAX9271=y
+CONFIG_SOC_CAMERA_OV106XX=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_PLATFORM=y
+CONFIG_USB_XHCI_RCAR=y
+CONFIG_MMC_SDHI_PRE_REQ=y
+CONFIG_MMC_SDHI_SEQ=y
+CONFIG_VIDEO_RENESAS_IMR=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_PROPERTIES=y
+CONFIG_HID_MULTITOUCH=y
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/sdhi_seq.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/sdhi_seq.cfg
new file mode 100644
index 0000000..9c43599
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/sdhi_seq.cfg
@@ -0,0 +1,2 @@
+CONFIG_MMC_SDHI_PRE_REQ=y
+CONFIG_MMC_SDHI_SEQ=y
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas_4.9.bbappend b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas_4.9.bbappend
new file mode 100644
index 0000000..bf3c6fc
--- /dev/null
+++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas_4.9.bbappend
@@ -0,0 +1,75 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRC_URI_append = " \
+ ${@base_conditional("SDHI_SEQ", "1", " file://sdhi_seq.cfg", "", d)} \
+ file://0001-spi-sh-msiof-fixes.patch \
+ file://0002-spi-spidev-add-spi-gpio-into-spidev.patch \
+ file://0003-spi-spi-gpio-fix-CPOL-mode.patch \
+ file://0004-xhci-rcar-add-firmware-for-R-Car-H2-M2-USB-3.0-host-.patch \
+ file://0005-usb-host-xhci-plat-add-support-for-the-R-Car-H3-xHCI.patch \
+ file://0006-spi-spi-gpio-fix-set-CPOL-default-inverted.patch \
+ file://0007-mmc-sh_mobile_sdhi-Add-R-CarGen3-SDHI-SEQUENCER-supp.patch \
+ file://0008-arm64-do-not-set-dma-masks-that-device-connection-ca.patch \
+ file://0009-swiotlb-ensure-that-page-sized-mappings-are-page-ali.patch \
+ file://0010-can-rcar_can-add-enable-and-standby-control-pins.patch \
+ file://0011-can-rcar_canfd-add-enable-and-standby-control-pins.patch \
+ file://0012-mtd-Add-RPC-HyperFlash-driver.patch \
+ file://0013-IMR-driver-interim-patch.patch \
+ file://0014-lib-swiotlb-reduce-verbosity.patch \
+ file://0015-gpio-max732x-fix-gpio-set.patch \
+ file://0016-gpio-gpiolib-suppress-gpiod-warning.patch \
+ file://0017-media-soc_camera-add-legacy-VIN-CSI2.patch \
+ file://0018-arm64-renesas-r8a7797-Add-Renesas-R8A7797-SoC-suppor.patch \
+ file://0019-Revert-media-v4l2-async-remove-unneeded-.registered_.patch \
+ file://0020-ti-st-add-device-tree-support.patch \
+ file://0021-btwilink-add-minimal-device-tree-support.patch \
+ file://0022-ASoC-Modify-check-condition-of-multiple-bindings-of-.patch \
+ file://0023-ASoC-add-dummy-Si468x-driver.patch \
+ file://0030-Gen3-LVDS-cameras.patch \
+ file://0031-arm64-dts-r8a7795-es1-salvator-x-view-add-ADAS-board.patch \
+ file://0032-arm64-dts-r8a7795-es1-h3ulcb-view-add-ADAS-board.patch \
+ file://0033-arm64-dts-r8a7795-es1-h3ulcb-had-add-ADAS-board.patch \
+ file://0034-arm64-dts-r8a7795-es1-h3ulcb-kf-add-ADAS-board.patch \
+ file://0035-arm64-dts-r8a7796-salvator-x-view-add-ADAS-board.patch \
+ file://0036-arm64-dts-r8a7796-m3ulcb-view-add-ADAS-board.patch \
+ file://0037-arm64-dts-r8a7796-m3ulcb-kf-add-ADAS-board.patch \
+ file://0038-arm64-dts-r8a7795-salvator-x-view-add-ADAS-board.patch \
+ file://0039-arm64-dts-r8a7795-h3ulcb-view-add-ADAS-board.patch \
+ file://0040-arm64-dts-r8a7795-h3ulcb-had-add-ADAS-board.patch \
+ file://0041-arm64-dts-r8a7795-h3ulcb-kf-add-ADAS-board.patch \
+ ${@base_conditional("LVDSCAMERA_FIRST4_TYPE1", "1", " file://0050-arm64-dts-Gen3-view-boards-TYPE1-first-4-cameras.patch", "", d)} \
+ ${@base_conditional("LVDSCAMERA_SECOND4_TYPE1", "1", " file://0051-arm64-dts-Gen3-view-boards-TYPE1-second-4-cameras.patch", "", d)} \
+ ${@base_conditional("LVDSCAMERA_FIRST4_TYPE2", "1", " file://0052-arm64-dts-Gen3-view-boards-TYPE2-first-4-cameras.patch", "", d)} \
+"
+
+SRC_URI_append_h3ulcb = " file://h3ulcb.cfg"
+SRC_URI_append_m3ulcb = " file://m3ulcb.cfg"
+SRC_URI_append_salvator-x = " file://salvator-x.cfg"
+SRC_URI_append_eagle = " file://eagle.cfg"
+
+KERNEL_DEVICETREE_append_h3ulcb = " \
+ renesas/r8a7795-es1-h3ulcb-view.dtb \
+ renesas/r8a7795-es1-h3ulcb-had-alfa.dtb \
+ renesas/r8a7795-es1-h3ulcb-had-beta.dtb \
+ renesas/r8a7795-es1-h3ulcb-kf.dtb \
+ renesas/r8a7795-h3ulcb-view.dtb \
+ renesas/r8a7795-h3ulcb-had-alfa.dtb \
+ renesas/r8a7795-h3ulcb-had-beta.dtb \
+ renesas/r8a7795-h3ulcb-kf.dtb \
+"
+
+KERNEL_DEVICETREE_append_m3ulcb = " \
+ renesas/r8a7796-m3ulcb-view.dtb \
+ renesas/r8a7796-m3ulcb-had-alfa.dtb \
+ renesas/r8a7796-m3ulcb-had-beta.dtb \
+ renesas/r8a7796-m3ulcb-kf.dtb \
+"
+
+KERNEL_DEVICETREE_append_salvator-x = " \
+ renesas/r8a7795-es1-salvator-x-view.dtb \
+ renesas/r8a7795-salvator-x-view.dtb \
+"
+
+KERNEL_DEVICETREE_append_eagle = " \
+ renesas/r8a7797-eagle.dtb \
+"