diff options
Diffstat (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas')
78 files changed, 50791 insertions, 0 deletions
diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0001-arm64-dts-renesas-preserve-drm-HDMI-connector-naming.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0001-arm64-dts-renesas-preserve-drm-HDMI-connector-naming.patch new file mode 100644 index 0000000..4f87f30 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0001-arm64-dts-renesas-preserve-drm-HDMI-connector-naming.patch @@ -0,0 +1,54 @@ +From df5348a8ec6f611fe3fc51d7c12898b8830d89d3 Mon Sep 17 00:00:00 2001 +From: Matt Porter <mporter@konsulko.com> +Date: Wed, 13 Dec 2017 12:49:20 -0500 +Subject: [PATCH] arm64: dts: renesas: preserve drm HDMI connector naming on KF + +Kingfisher adds encoders on ports 0 and 2 of the R-Car +display unit. The bare ULCB SK has only an HDMI encoder +in use on port 1. When the system is booted with an SK +dtb, port 1's HDMI encoder is assigned as HDMI-A-1 because +it is the first (and only) encoder present. When booting +a KF dtb, port 0's HDMI encoder preceeds port1 in the dtb due +to incremental ordering of the endpoint port nodes. This causes +the KF HDMI to be assigned HDMI-A-1 and the SK HDMI to be assigned +as HDMI-A-2. In order to preserve the SK's HDMI output naming as +connector HDMI-A-1, reorder the endpoint port nodes so that port1 +is first. + +Change-Id: Ibbb1975c2383a526a54c257fb7d68d32a042d468 +Signed-off-by: Matt Porter <mporter@konsulko.com> +--- + arch/arm64/boot/dts/renesas/r8a7796.dtsi | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/r8a7796.dtsi b/arch/arm64/boot/dts/renesas/r8a7796.dtsi +index bf37b8aa0e2f..e3a5c25bc3da 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7796.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a7796.dtsi +@@ -2391,11 +2391,6 @@ + #address-cells = <1>; + #size-cells = <0>; + +- port@0 { +- reg = <0>; +- du_out_rgb: endpoint { +- }; +- }; + port@1 { + reg = <1>; + du_out_hdmi0: endpoint { +@@ -2406,6 +2401,11 @@ + du_out_lvds0: endpoint { + }; + }; ++ port@0 { ++ reg = <0>; ++ du_out_rgb: endpoint { ++ }; ++ }; + }; + }; + +-- +2.11.0 + 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/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..60834a9 --- /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,119 @@ +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,26 @@ static int rcar_canfd_probe(struct platform_device *pdev) + goto fail_channel; + } + ++ 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..30cf006 --- /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_S3D4), + DEF_MOD("gpio6", 906, R8A7795_CLK_S3D4), + DEF_MOD("gpio5", 907, R8A7795_CLK_S3D4), +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..c08c0ed --- /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 not binary 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..d6726a3 --- /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,5132 @@ +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 | 1002 ++++++++++ + drivers/clk/renesas/Kconfig | 1 + + drivers/clk/renesas/Makefile | 1 + + drivers/clk/renesas/r8a7797-cpg-mssr.c | 222 +++ + drivers/clk/renesas/rcar-gen3-cpg.c | 41 +- + drivers/clk/renesas/rcar-gen3-cpg.h | 6 + + drivers/clk/renesas/renesas-cpg-mssr.c | 6 + + drivers/clk/renesas/renesas-cpg-mssr.h | 1 + + drivers/cpufreq/cpufreq-dt-platdev.c | 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/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 | 26 +- + drivers/media/platform/soc_camera/rcar_vin.c | 86 +- + drivers/media/platform/vsp1/vsp1_drv.c | 9 + + drivers/media/platform/vsp1/vsp1_lif.c | 12 +- + 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 | 2586 +++++++++++++++++++++++++ + drivers/pinctrl/sh-pfc/sh_pfc.h | 12 + + drivers/soc/renesas/Makefile | 4 + + drivers/soc/renesas/r8a7797-sysc.c | 39 + + drivers/soc/renesas/rcar-rst.c | 1 + + 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 + + 40 files changed, 4281 insertions(+), 29 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 ebe0a37..d3b6771 100644 +--- a/arch/arm64/Kconfig.platforms ++++ b/arch/arm64/Kconfig.platforms +@@ -166,6 +166,12 @@ config ARCH_R8A77965 + help + This enables support for the Renesas R-Car M3N 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..6eaa5ba +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7797.dtsi +@@ -0,0 +1,1002 @@ ++/* ++ * 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 28>; ++ #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,r8a7797-csi2"; ++ 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"; ++ }; ++ ++ prr: chipid@fff00044 { ++ compatible = "renesas,prr"; ++ reg = <0 0xfff00044 0 4>; ++ }; ++ ++ rst: reset-controller@e6160000 { ++ compatible = "renesas,r8a7797-rst"; ++ reg = <0 0xe6160000 0 0x0200>; ++ }; ++ ++ 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>; ++ }; ++ ++ 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>; ++ clocks = <&cpg CPG_MOD 914>, ++ <&cpg CPG_CORE R8A7797_CLK_CANFD>, ++ <&can_clk>; ++ clock-names = "fck", "canfd", "can_clk"; ++ assigned-clocks = <&cpg CPG_CORE R8A7797_CLK_CANFD>; ++ assigned-clock-rates = <40000000>; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ 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>; ++ clocks = <&cpg CPG_MOD 314>; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ renesas,clk-rate = <200000000>; ++ 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>; ++ clocks = <&cpg CPG_MOD 213>; ++ clock-names = "mfis"; ++ interrupts = <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>; ++ interrupt-names = "eicr0"; ++ status = "okay"; ++ }; ++ ++ mfis_lock: mfis-lock@e62600c0 { ++ compatible = "renesas,mfis-lock-r8a7797", ++ "renesas,mfis-lock"; ++ reg = <0 0xe62600c0 0 0x0020>; ++ status = "okay"; ++ }; ++ ++ 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 R8A7797_PD_ALWAYS_ON>; ++ }; ++ ++ 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 R8A7797_PD_ALWAYS_ON>; ++ }; ++ ++ 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 R8A7797_PD_ALWAYS_ON>; ++ }; ++ ++ 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 R8A7797_PD_ALWAYS_ON>; ++ }; ++ }; ++}; +diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig +index bbd9701..b52e907 100644 +--- a/drivers/clk/renesas/Kconfig ++++ b/drivers/clk/renesas/Kconfig +@@ -5,6 +5,7 @@ config CLK_RENESAS_CPG_MSSR + default y if ARCH_R8A7795 + default y if ARCH_R8A7796 + default y if ARCH_R8A77965 ++ default y if ARCH_R8A7797 + + config CLK_RENESAS_CPG_MSTP + bool +diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile +index 2c224e9..c2ef11e 100644 +--- a/drivers/clk/renesas/Makefile ++++ b/drivers/clk/renesas/Makefile +@@ -14,6 +14,7 @@ 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_R8A77965) += r8a77965-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..29dfe4a +--- /dev/null ++++ b/drivers/clk/renesas/r8a7797-cpg-mssr.c +@@ -0,0 +1,222 @@ ++/* ++ * 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_PLL1_DIV4), ++ 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_SD0H("sd0h", R8A7797_CLK_SD0H, CLK_PLL1_DIV4, 0x0074), ++ DEF_GEN3_SD0("sd0", R8A7797_CLK_SD0, CLK_PLL1_DIV4, 0x0074), ++ ++ DEF_FIXED("cl", R8A7797_CLK_CL, CLK_PLL1_DIV2, 48, 1), ++ DEF_FIXED("cp", R8A7797_CLK_CP, CLK_EXTAL, 2, 1), ++ ++ DEF_DIV6P1("mso", R8A7797_CLK_MSO, CLK_PLL1_DIV4, 0x014), ++ DEF_DIV6P1("canfd", R8A7797_CLK_CANFD, CLK_PLL1_DIV4, 0x244), ++ DEF_DIV6P1("csi0", R8A7797_CLK_CSI0, CLK_PLL1_DIV4, 0x00c), ++ ++ DEF_FIXED("osc", R8A7797_CLK_OSC, CLK_PLL1_DIV2, (12*1024), 1), ++ DEF_BASE("r_int", CLK_RINT, CLK_TYPE_GEN3_RINT, CLK_EXTAL), ++ ++ 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("imr3", 820, R8A7797_CLK_S2D1), ++ DEF_MOD("imr2", 821, R8A7797_CLK_S2D1), ++ DEF_MOD("imr1", 822, R8A7797_CLK_S2D1), ++ DEF_MOD("imr0", 823, R8A7797_CLK_S2D1), ++ 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/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c +index 1cd2c05..b145f14 100644 +--- a/drivers/clk/renesas/rcar-gen3-cpg.c ++++ b/drivers/clk/renesas/rcar-gen3-cpg.c +@@ -26,6 +26,13 @@ + #include "renesas-cpg-mssr.h" + #include "rcar-gen3-cpg.h" + ++static spinlock_t cpg_lock; ++ ++static const struct soc_device_attribute r8a7797[] = { ++ { .soc_id = "r8a7797" }, ++ { /* sentinel */ } ++}; ++ + #define CPG_PLL0CR 0x00d8 + #define CPG_PLL2CR 0x002c + #define CPG_PLL4CR 0x01f4 +@@ -228,7 +235,10 @@ static unsigned long cpg_z2_clk_recalc_rate(struct clk_hw *hw, + unsigned int val; + unsigned long rate; + +- val = (clk_readl(zclk->reg) & CPG_FRQCRC_Z2FC_MASK); ++ if (!soc_device_match(r8a7797)) ++ val = (clk_readl(zclk->reg) & CPG_FRQCRC_Z2FC_MASK); ++ else ++ val = 0; + mult = 32 - val; + + rate = div_u64((u64)parent_rate * mult + 16, 32); +@@ -372,6 +382,11 @@ static int cpg_z2_clk_set_rate(struct clk_hw *hw, unsigned long rate, + u32 val, kick; + unsigned int i; + ++ if (soc_device_match(r8a7797)){ ++ pr_info("Do not support V3M's Z2 clock changing\n"); ++ return 0; ++ } ++ + mult = div_u64((u64)rate * 32 + parent_rate/2, parent_rate); + mult = clamp(mult, 1U, 32U); + +@@ -566,6 +581,19 @@ static struct clk * __init cpg_zg_clk_register(const char *name, + /* + * SDn Clock + */ ++/* SDHI divisors */ ++static const struct clk_div_table cpg_sdh_div_table[] = { ++ { 0, 2 }, { 1, 3 }, { 2, 4 }, { 3, 6 }, ++ { 4, 8 }, { 5, 12 }, { 6, 16 }, { 7, 18 }, ++ { 8, 24 }, { 10, 36 }, { 11, 48 }, { 0, 0 }, ++}; ++ ++static const struct clk_div_table cpg_sd01_div_table[] = { ++ { 4, 8 }, ++ { 5, 12 }, { 6, 16 }, { 7, 18 }, { 8, 24 }, ++ { 10, 36 }, { 11, 48 }, { 12, 10 }, { 0, 0 }, ++}; ++ + #define CPG_SD_STP_HCK BIT(9) + #define CPG_SD_STP_CK BIT(8) + +@@ -864,6 +892,14 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, + case CLK_TYPE_GEN3_SD: + return cpg_sd_clk_register(core, base, __clk_get_name(parent)); + ++ case CLK_TYPE_GEN3_SD0: ++ return clk_register_divider_table(NULL, core->name, __clk_get_name(parent), 0, base + 0x0074, ++ 4, 4,0, cpg_sd01_div_table, &cpg_lock); ++ ++ case CLK_TYPE_GEN3_SD0H: ++ return clk_register_divider_table(NULL, core->name, __clk_get_name(parent), 0, base + 0x0074, ++ 8, 4,0, cpg_sdh_div_table, &cpg_lock); ++ + case CLK_TYPE_GEN3_RINT: + div = cpg_pll_config->rint; + break; +@@ -917,5 +953,8 @@ int __init rcar_gen3_cpg_init(const struct rcar_gen3_cpg_pll_config *config, + if (attr) + cpg_quirks = (uintptr_t)attr->data; + pr_debug("%s: mode = 0x%x quirks = 0x%x\n", __func__, mode, cpg_quirks); ++ ++ spin_lock_init(&cpg_lock); ++ + return 0; + } +diff --git a/drivers/clk/renesas/rcar-gen3-cpg.h b/drivers/clk/renesas/rcar-gen3-cpg.h +index 51ae7b8..694bedc 100644 +--- a/drivers/clk/renesas/rcar-gen3-cpg.h ++++ b/drivers/clk/renesas/rcar-gen3-cpg.h +@@ -19,6 +19,8 @@ enum rcar_gen3_clk_types { + CLK_TYPE_GEN3_PLL3, + CLK_TYPE_GEN3_PLL4, + CLK_TYPE_GEN3_SD, ++ CLK_TYPE_GEN3_SD0, ++ CLK_TYPE_GEN3_SD0H, + CLK_TYPE_GEN3_R, + CLK_TYPE_GEN3_Z, + CLK_TYPE_GEN3_Z2, +@@ -29,6 +31,10 @@ enum rcar_gen3_clk_types { + + #define DEF_GEN3_SD(_name, _id, _parent, _offset) \ + DEF_BASE(_name, _id, CLK_TYPE_GEN3_SD, _parent, .offset = _offset) ++#define DEF_GEN3_SD0(_name, _id, _parent, _offset) \ ++ DEF_BASE(_name, _id, CLK_TYPE_GEN3_SD0, _parent, .offset = _offset) ++#define DEF_GEN3_SD0H(_name, _id, _parent, _offset) \ ++ DEF_BASE(_name, _id, CLK_TYPE_GEN3_SD0H, _parent, .offset = _offset) + + struct rcar_gen3_cpg_pll_config { + unsigned int extal_div; +diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c +index 8c261e1..bd901a6 100644 +--- a/drivers/clk/renesas/renesas-cpg-mssr.c ++++ b/drivers/clk/renesas/renesas-cpg-mssr.c +@@ -594,6 +594,12 @@ static int __init cpg_mssr_add_clk_domain(struct device *dev, + .data = &r8a77965_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 145b738..ce3546a 100644 +--- a/drivers/clk/renesas/renesas-cpg-mssr.h ++++ b/drivers/clk/renesas/renesas-cpg-mssr.h +@@ -135,6 +135,7 @@ struct 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 r8a77965_cpg_mssr_info; ++extern const struct cpg_mssr_info r8a7797_cpg_mssr_info; + + + /* +diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c +index 515d0e7..5a2ec23 100644 +--- a/drivers/cpufreq/cpufreq-dt-platdev.c ++++ b/drivers/cpufreq/cpufreq-dt-platdev.c +@@ -60,6 +60,7 @@ + { .compatible = "renesas,r8a7795", }, + { .compatible = "renesas,r8a7796", }, + { .compatible = "renesas,r8a77965", }, ++ { .compatible = "renesas,r8a7797", }, + { .compatible = "renesas,sh73a0", }, + + { .compatible = "rockchip,rk2928", }, +diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c +index 6917932..fd15649 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 +@@ -367,6 +367,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 b234918..f74f264 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c ++++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c +@@ -312,6 +312,30 @@ + .skip_ch = BIT(2), + }; + ++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 = BIT(1), ++}; ++ + static const struct soc_device_attribute ths_quirks_match[] = { + { .soc_id = "r8a7795", .revision = "ES1.*", + .data = (void *)(RCAR_DU_DPLL_DUTY_RATE_WA +@@ -335,6 +359,7 @@ + { .compatible = "renesas,du-r8a7795", .data = &rcar_du_r8a7795_info }, + { .compatible = "renesas,du-r8a7796", .data = &rcar_du_r8a7796_info }, + { .compatible = "renesas,du-r8a77965", .data = &rcar_du_r8a77965_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 1af5eb7..3916b63 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); +@@ -155,8 +161,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..d5fa06c 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_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_38M; ++ else if (freq < 61000) ++ pllcr = LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_60M; ++ else if (freq < 121000) ++ pllcr = LVDPLLCR_CEEN | LVDPLLCR_COSEL | 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/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c +index 74c17d8..149c107 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-r8a7795", .data = (void *)I2C_RCAR_GEN3 }, + { .compatible = "renesas,i2c-r8a7796", .data = (void *)I2C_RCAR_GEN3 }, + { .compatible = "renesas,i2c-r8a77965", .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 e2baed1..1ae9174 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 +@@ -1277,6 +1277,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 */ + }, + }; +@@ -1648,6 +1651,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 05f623468..4d95da6 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, 0x78 /* 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 +510,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 +519,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 cdaa097..6daeab4 100644 +--- a/drivers/media/platform/vsp1/vsp1_drv.c ++++ b/drivers/media/platform/vsp1/vsp1_drv.c +@@ -893,6 +893,15 @@ 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, ++ .model = "VSP2-D", ++ .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..e79f9e6 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 + */ +@@ -145,7 +151,7 @@ static void lif_configure(struct vsp1_entity *entity, + format = vsp1_entity_get_pad_format(&lif->entity, lif->entity.config, + LIF_PAD_SOURCE); + +- if (vsp1_gen3_vspdl_check(vsp1)) ++ if (vsp1_gen3_vspdl_check(vsp1) || soc_device_match(r8a7797)) + obth = 1500; + else + obth = 3000; +@@ -158,6 +164,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 9134dbd..6c971f7 100644 +--- a/drivers/media/platform/vsp1/vsp1_regs.h ++++ b/drivers/media/platform/vsp1/vsp1_regs.h +@@ -789,6 +789,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 + */ +@@ -812,6 +818,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_GEN3 (0x19 << 8) + + #define VI6_IP_VERSION_SOC_MASK (0xff << 0) +diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c +index a7fb054..040f474 100644 +--- a/drivers/mmc/host/sh_mobile_sdhi.c ++++ b/drivers/mmc/host/sh_mobile_sdhi.c +@@ -140,6 +140,7 @@ struct sh_mobile_sdhi_of_data { + { .compatible = "renesas,sdhi-r8a7796", .data = &of_rcar_gen3_compatible, }, + { .compatible = "renesas,sdhi-r8a77965", + .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 5ad4d13..73fa286 100644 +--- a/drivers/net/ethernet/renesas/ravb_main.c ++++ b/drivers/net/ethernet/renesas/ravb_main.c +@@ -1920,6 +1920,7 @@ static int ravb_mdio_release(struct ravb_private *priv) + { .compatible = "renesas,etheravb-r8a7795", .data = (void *)RCAR_GEN3 }, + { .compatible = "renesas,etheravb-r8a7796", .data = (void *)RCAR_GEN3 }, + { .compatible = "renesas,etheravb-r8a77965", .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 6d2cdf8..4aaf0be 100644 +--- a/drivers/pinctrl/sh-pfc/Kconfig ++++ b/drivers/pinctrl/sh-pfc/Kconfig +@@ -84,6 +84,11 @@ config PINCTRL_PFC_R8A77965 + depends on ARCH_R8A77965 + 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 f12017b..e263c14 100644 +--- a/drivers/pinctrl/sh-pfc/Makefile ++++ b/drivers/pinctrl/sh-pfc/Makefile +@@ -14,6 +14,7 @@ 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_R8A77965) += pfc-r8a77965.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 a6a8f65..9aba933 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 +@@ -545,6 +546,12 @@ static int sh_pfc_init_ranges(struct sh_pfc *pfc) + .data = &r8a77965_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..9b6127f +--- /dev/null ++++ b/drivers/pinctrl/sh-pfc/pfc-r8a7797.c +@@ -0,0 +1,2586 @@ ++/* ++ * 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 <linux/sys_soc.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 | \ ++ SH_PFC_PIN_CFG_IO_VOLTAGE), \ ++ 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_i2c3 SDA3_A VI0_DATA2 SDA3_B VI1_DATA10 ++ SCL3_A VI0_DATA3 SCL3_B VI1_DATA9 ++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_11 FM(SEL_I2C3_0) FM(SEL_I2C3_1) ++#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_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 ++ ++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[] = { ++ /* PWM1 */ ++ 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, ++}; ++ ++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, ++}; ++ ++/* - 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[] = { ++ /* FIELD */ ++ RCAR_GP_PIN(3, 16), ++}; ++static const unsigned int vin1_field_mux[] = { ++ VI1_FIELD_MARK, ++}; ++static const unsigned int vin1_clkenb_pins[] = { ++ /* CLKENB */ ++ RCAR_GP_PIN(3, 1), ++}; ++static const unsigned int vin1_clkenb_mux[] = { ++ VI1_CLKENB_MARK, ++}; ++static const unsigned int vin1_clk_pins[] = { ++ /* CLK */ ++ RCAR_GP_PIN(3, 0), ++}; ++static const unsigned int vin1_clk_mux[] = { ++ 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", ++ "canfd_clk_a", ++ "canfd0_data_b", ++ "canfd_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_ctrl", ++}; ++ ++static const char * const scif1_groups[] = { ++ "scif1_data_a", ++ "scif1_clk", ++ "scif1_ctrl", ++ "scif1_data_b", ++}; ++ ++static const char * const scif3_groups[] = { ++ "scif3_data", ++ "scif3_clk", ++ "scif3_ctrl", ++}; ++ ++static const char * const scif4_groups[] = { ++ "scif4_data", ++ "scif4_clk", ++ "scif4_ctrl", ++}; ++ ++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 < 17)) ? _bit + 7 : -1; \ ++}) ++ ++ ++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("MOD_SEL0", 0xe6060500, 32, 1) { ++ /* RESERVED 31..12 */ ++ 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, ++ MOD_SEL0_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 int r8a7797_pin_to_pocctrl(struct sh_pfc *pfc, unsigned int pin, u32 *pocctrl) ++{ ++ int bit = -EINVAL; ++ ++ *pocctrl = 0xe6060384; ++ ++ if (pin >= RCAR_GP_PIN(3, 0) && pin <= RCAR_GP_PIN(3, 16)) ++ bit = (pin & 0x1f) + 7; ++ ++ return bit; ++} ++ ++static const struct sh_pfc_soc_operations pinmux_ops = { ++ .pin_to_pocctrl = r8a7797_pin_to_pocctrl, ++}; ++ ++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 5a0da3c..062af89 100644 +--- a/drivers/pinctrl/sh-pfc/sh_pfc.h ++++ b/drivers/pinctrl/sh-pfc/sh_pfc.h +@@ -288,6 +288,7 @@ struct sh_pfc_soc_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 r8a77965_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; +@@ -393,6 +394,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), \ +@@ -439,6 +445,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 29b8a4d..2ba6a76 100644 +--- a/drivers/soc/renesas/Makefile ++++ b/drivers/soc/renesas/Makefile +@@ -5,6 +5,7 @@ obj-$(CONFIG_ARCH_RCAR_GEN2) += rcar-rst.o + obj-$(CONFIG_ARCH_R8A7795) += rcar-rst.o + obj-$(CONFIG_ARCH_R8A7796) += rcar-rst.o + obj-$(CONFIG_ARCH_R8A77965) += rcar-rst.o ++obj-$(CONFIG_ARCH_R8A7797) += rcar-rst.o + + obj-$(CONFIG_ARCH_R8A7743) += rcar-sysc.o r8a7743-sysc.o + obj-$(CONFIG_ARCH_R8A7745) += rcar-sysc.o r8a7745-sysc.o +@@ -18,13 +19,16 @@ 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_R8A77965) += rcar-sysc.o r8a77965-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_R8A77965) += 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_R8A77965) += 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-rst.c b/drivers/soc/renesas/rcar-rst.c +index 61c2f2c..bc3632b 100644 +--- a/drivers/soc/renesas/rcar-rst.c ++++ b/drivers/soc/renesas/rcar-rst.c +@@ -42,6 +42,7 @@ struct rst_config { + { .compatible = "renesas,r8a7795-rst", .data = &rcar_rst_gen2 }, + { .compatible = "renesas,r8a7796-rst", .data = &rcar_rst_gen2 }, + { .compatible = "renesas,r8a77965-rst", .data = &rcar_rst_gen2 }, ++ { .compatible = "renesas,r8a7797-rst", .data = &rcar_rst_gen2 }, + { /* sentinel */ } + }; + +diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c +index b25c5cf..1d5d440 100644 +--- a/drivers/soc/renesas/rcar-sysc.c ++++ b/drivers/soc/renesas/rcar-sysc.c +@@ -324,6 +324,9 @@ static void __init rcar_sysc_pd_setup(struct rcar_sysc_pd *pd) + #ifdef CONFIG_ARCH_R8A77965 + { .compatible = "renesas,r8a77965-sysc", .data = &r8a77965_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 04b5d01..1eb4e6d 100644 +--- a/drivers/soc/renesas/rcar-sysc.h ++++ b/drivers/soc/renesas/rcar-sysc.h +@@ -61,4 +61,5 @@ struct rcar_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 r8a77965_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 1b33c50..63f943d 100644 +--- a/drivers/soc/renesas/renesas-soc.c ++++ b/drivers/soc/renesas/renesas-soc.c +@@ -139,6 +139,11 @@ struct renesas_soc { + .id = 0x55, + }; + ++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, +@@ -191,6 +196,9 @@ struct renesas_soc { + #ifdef CONFIG_ARCH_R8A77965 + { .compatible = "renesas,r8a77965", .data = &soc_rcar_m3_n }, + #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 36e70db..a2606fe 100644 +--- a/drivers/spi/spi-sh-msiof.c ++++ b/drivers/spi/spi-sh-msiof.c +@@ -216,7 +216,8 @@ static int msiof_rcar_is_gen3(struct device *dev) + + return of_device_is_compatible(node, "renesas,msiof-r8a7795") || + of_device_is_compatible(node, "renesas,msiof-r8a7796") || +- of_device_is_compatible(node, "renesas,msiof-r8a77965"); ++ of_device_is_compatible(node, "renesas,msiof-r8a77965") || ++ of_device_is_compatible(node, "renesas,msiof-r8a7797"); + } + + static u32 sh_msiof_read(struct sh_msiof_spi_priv *p, int reg_offs) +@@ -1190,6 +1191,7 @@ static int sh_msiof_transfer_one(struct spi_master *master, + { .compatible = "renesas,msiof-r8a7795", .data = &r8a779x_data }, + { .compatible = "renesas,msiof-r8a7796", .data = &r8a779x_data }, + { .compatible = "renesas,msiof-r8a77965", .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 6eb7395..a23dd44 100644 +--- a/drivers/thermal/rcar_gen3_thermal.c ++++ b/drivers/thermal/rcar_gen3_thermal.c +@@ -391,6 +391,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 + */ +@@ -472,10 +496,15 @@ 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-r8a77965", .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(¬ifier->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..d979a41 --- /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,48 @@ +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] 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. + +KF has 4 sound cards (pcm3168a, ak4613, radio, wl18xx) and just one +compinent ec500000.sound that can not be bound to all 4 cards. +This is a lack of current implementation of sound/soc/sh/rcar/* ASoC stack +The ec500000.sound resources (PCM/DMA, dais) needs to be shared between +all 4 sound cards if we want all cards work runtime. +Or we have to enable only one of them in dts file as it is designed. + +Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +--- + sound/soc/soc-core.c | 6 ++++-- + 1 files changed, 6 insertions(+), 0 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/0024-wl18xx-do-not-invert-IRQ-on-WLxxxx-side.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0024-wl18xx-do-not-invert-IRQ-on-WLxxxx-side.patch new file mode 100644 index 0000000..f956c58 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0024-wl18xx-do-not-invert-IRQ-on-WLxxxx-side.patch @@ -0,0 +1,48 @@ +From 60d86113a92ac35421865f9b8db504530962c829 Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +Date: Mon, 22 May 2017 17:22:38 +0300 +Subject: [PATCH] wl18xx: do not invert IRQ on WLxxxx side + + +Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +--- + drivers/net/wireless/ti/wl18xx/main.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c +index ae47c79..cdde6e0 100644 +--- a/drivers/net/wireless/ti/wl18xx/main.c ++++ b/drivers/net/wireless/ti/wl18xx/main.c +@@ -876,7 +876,9 @@ static int wl18xx_pre_upload(struct wl1271 *wl) + { + u32 tmp; + int ret; ++#if 0 + u16 irq_invert; ++#endif + + BUILD_BUG_ON(sizeof(struct wl18xx_mac_and_phy_params) > + WL18XX_PHY_INIT_MEM_SIZE); +@@ -929,6 +931,11 @@ static int wl18xx_pre_upload(struct wl1271 *wl) + if (ret < 0) + goto out; + ++#if 0 ++ /* We have level translator with inversion on IRQ line so we ++ * set IRQ_TYPE_EDGE_FALLING in DTS, but we do not need to ++ * invert IRQ logic on WLxxxx side! ++ */ + ret = irq_get_trigger_type(wl->irq); + if ((ret == IRQ_TYPE_LEVEL_LOW) || (ret == IRQ_TYPE_EDGE_FALLING)) { + wl1271_info("using inverted interrupt logic: %d", ret); +@@ -948,6 +955,7 @@ static int wl18xx_pre_upload(struct wl1271 *wl) + + ret = wlcore_set_partition(wl, &wl->ptable[PART_PHY_INIT]); + } ++#endif + + out: + return ret; +-- +1.7.10.4 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0025-drm-adv7511-Enable-HPD-interrupts-to-support-hotplug.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0025-drm-adv7511-Enable-HPD-interrupts-to-support-hotplug.patch new file mode 100644 index 0000000..dc29695 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0025-drm-adv7511-Enable-HPD-interrupts-to-support-hotplug.patch @@ -0,0 +1,46 @@ +From 0ec0f782c0d19b1e1293e8e281c335186ce3f3cc Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Tue, 30 May 2017 17:41:21 +0300 +Subject: [PATCH] drm: adv7511: Enable HPD interrupts to support hotplug + +This patch enables HPD (hot plug detect) interrupt support + +Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +--- + drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +index a104b43..e20f475 100644 +--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c ++++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +@@ -55,7 +55,7 @@ static const struct reg_sequence adv7511_fixed_registers[] = { + { 0x98, 0x03 }, + { 0x9a, 0xe0 }, + { 0x9c, 0x30 }, +- { 0x9d, 0x61 }, ++ { 0x9d, 0x01 }, + { 0xa2, 0xa4 }, + { 0xa3, 0xa4 }, + { 0xe0, 0xd0 }, +@@ -369,7 +369,7 @@ static void adv7511_power_on(struct adv7511 *adv7511) + * Still, let's be safe and stick to the documentation. + */ + regmap_write(adv7511->regmap, ADV7511_REG_INT_ENABLE(0), +- ADV7511_INT0_EDID_READY); ++ ADV7511_INT0_EDID_READY | ADV7511_INT0_HPD); + regmap_write(adv7511->regmap, ADV7511_REG_INT_ENABLE(1), + ADV7511_INT1_DDC_ERROR); + } +@@ -575,7 +575,7 @@ static int adv7511_get_modes(struct adv7511 *adv7511, + ADV7511_POWER_POWER_DOWN, 0); + if (adv7511->i2c_main->irq) { + regmap_write(adv7511->regmap, ADV7511_REG_INT_ENABLE(0), +- ADV7511_INT0_EDID_READY); ++ ADV7511_INT0_EDID_READY | ADV7511_INT0_HPD); + regmap_write(adv7511->regmap, ADV7511_REG_INT_ENABLE(1), + ADV7511_INT1_DDC_ERROR); + } +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0026-drm-adv7511-add-polling-mode-when-no-irq-available.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0026-drm-adv7511-add-polling-mode-when-no-irq-available.patch new file mode 100644 index 0000000..3adfa21 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0026-drm-adv7511-add-polling-mode-when-no-irq-available.patch @@ -0,0 +1,30 @@ +From 06473f51a6aa077cd56745bd14d114ff3269fe19 Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +Date: Tue, 30 May 2017 18:42:09 +0300 +Subject: [PATCH] drm: adv7511: add polling mode (when no irq available) + +Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +--- + drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +index a104b43b56a0..8be1baca05d0 100644 +--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c ++++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +@@ -838,7 +838,11 @@ static int adv7511_bridge_attach(struct drm_bridge *bridge) + return -ENODEV; + } + +- adv->connector.polled = DRM_CONNECTOR_POLL_HPD; ++ if (adv->i2c_main->irq) ++ adv->connector.polled = DRM_CONNECTOR_POLL_HPD; ++ else ++ adv->connector.polled = DRM_CONNECTOR_POLL_CONNECT | ++ DRM_CONNECTOR_POLL_DISCONNECT; + + ret = drm_connector_init(bridge->dev, &adv->connector, + &adv7511_connector_funcs, +-- +2.13.0 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0027-usb-host-xhci-plat-add-firmware-for-the-R-Car-M3-W-x.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0027-usb-host-xhci-plat-add-firmware-for-the-R-Car-M3-W-x.patch new file mode 100644 index 0000000..dc79798 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0027-usb-host-xhci-plat-add-firmware-for-the-R-Car-M3-W-x.patch @@ -0,0 +1,179 @@ +From b0668886def608d352cd0263a7ef04e64e25574a Mon Sep 17 00:00:00 2001 +From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> +Date: Tue, 12 Apr 2016 16:28:44 +0900 +Subject: [PATCH] usb: host: xhci-plat: add firmware for the R-Car M3-W xHCI + controllers + +This patch adds a firmware for the USB 3.0 host controllers of Renesas +R-Car M3-W SoC. + + - This firmware is possible to be used on R-Car H2 and M2. However, + this version causes performance degradation on such SoCs. + - This firmware is impossible to be used on R-Car H3 because data + transfer might not work correctly. + +So, we would like to keep the v1 and v2 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_v3.dlmem | Bin 0 -> 9472 bytes + 2 files changed, 2 insertions(+), 1 deletion(-) + create mode 100644 r8a779x_usb3_v3.dlmem + +diff --git a/firmware/WHENCE b/firmware/WHENCE +index c2d83f4..02b46c7 100644 +--- a/firmware/WHENCE ++++ b/firmware/WHENCE +@@ -2922,10 +2922,11 @@ Licence: + + -------------------------------------------------------------------------- + +-Driver: xhci-rcar -- Renesas R-Car H2/M2/H3 USB 3.0 host controller driver ++Driver: xhci-rcar -- Renesas R-Car Gen2/3 USB 3.0 host controller driver + + File: r8a779x_usb3_v1.dlmem + File: r8a779x_usb3_v2.dlmem ++File: r8a779x_usb3_v3.dlmem + + Licence: Redistributable. See LICENCE.r8a779x_usb3 for details. + +diff --git a/firmware/r8a779x_usb3_v3.dlmem b/firmware/r8a779x_usb3_v3.dlmem +new file mode 100644 +index 0000000000000000000000000000000000000000..eac36a96bee1a8614eef9caa88e5a9de136af30c +GIT binary patch +literal 9472 +zcmai44O~=J+J9z-JD0DE%!QeY<mgB<W~{cz`bjBB=$cutpn@Ny@*$Ox*>2nRwwB{K +zD4Ci1rfYs>HkeYmO5m31jV34~)&K>O6o(P~7+pbD-BR(s|8ob#ecSi9{C@v?&b{~C +z=R9BMInQ~9;u*j3Mp7NIzY7#;Wi4;XjLuOsWLNsr{b*C7mr~CYucqgTozEhh{^R~y +z;vS+T2HOp?$LiOfB6?v)tUmHIQGg^i{2qOuk!V3ieSzE5L0Y{>@tLiXt@SPOBxf;E +zcrN-@$=L9oxZiARx2;Ij7m}7V@vjlZ%gTD4C)LZbUMqSBIZC^3^pDz$QG`+K+il|K +zoUE)CDx}B;>vpN(*eD`dshO-vOVTf;lBi+&&3%Xx^|@h0OUc1_f4i^UdWA?Am#Du6 +zN-vUarO`e}U&H23NYn>vw6vJa9UQ0O#=ag%y4R9SWH%TEW028$gSvva0iw=m`=i-@ +z|0oUh7jq>;W}<!^zFI`dn3L&8e?eA4h1W7P#JG_8V8Lp#NU?g_s_0f3a`}OhR)1M} +zL$KbkNSYBk&LKV}a>k{QXrMIFP-14!wKIal-C~6yJ8`HKY|@a<Xw7&~@}_>l<?=QO +zdIY^I_*2JZ43+#duTbaq;Qg%3;F-(B{etJ>dci7j(9}uJ-_~}8Ol5ox(>FZatD9fi +zHHEJcG-8TWD>&P0g)CnS=N58&wL+&*X0$643HCADmA#SI1-oL>RN|VTE#vIUe4Sl6 +z5LwA-U^}hkOso~U#&n*J(UYOLSUZM2Z8Tl4XB@COWn~lWTcwV^g1dx%va;gtlT+}< +z(E)a4XTX5?FO@@gWM$#qcjeHR(BKd+8fE2ZGHla8MoYSKb+SQYWRfyJvu@Wk99u~k +z`FTUG)Db8vv3I|>li#0iYyDm)D`9uv<zn83fI<3Js}?+6FndxvG0PQg52q>J-;UP# +zebKXWzJ^Kmicyo6l2If0rE7^}d{Et6;vR6sc&$}!P$0f9ShrKdF^PF=aEe{=QvLI? +z5<ST(T|D6wYr99U!<>WqTP01yCir>9m)ZtKZwustPX^?o?;pR1)71GTUI$yVc}{Yk +z+JjgbP5o`{`yGk;X7I^Y412d{gs0Xwf@x%#__NI^{Ugw0IB3)OZ18h!a|P8K&2cNh +z*RDobScrv}KYU(;H53z|r6sU>6<4wHvxXvJypMUAHf@=R`O|zCPqZ;_`8lxS?a&5K +zZ4+jnZLuqEU6NjjQ@u-F;|oEBt#MiT9i(eE_V|GdewHO3G&-eOtsX<CAS<28w)W@k +ziTcg>0=#eU({OA6Q3_wH`g4JJk*j#1q`|JNr}_!D_Rk?@g*wuc>c-stql(62J+(p? +z0*fNe5w`ZPFy?|fhWU2UQ1-r1jUZEFSY&!b?N3qrtJHpjRaSmdW!A(WR-U}WzE}o| +zer}uKUw*DC-U|gMgVgojD{DIE_YPUfhOCQBOjb1pwfBWwFX62&?zL`Da@-xe+9WHb +zCKg?6?PexF-Y|VxC4YQrfgKqa%b<rbtxoYPthu#R*{y>k>S(_XRz+<XYiqBE)ShnY +zwsynvMEzxTj7$0_vpl|@gcVk*b>co-blCjQtIV>JKOxv7E8~XQ+FL*)M$h=LwO>X5 +zA+;|nuf}^?I-%|42`om-%C#Y|_B}Gr#JFA=^Ki#(50CaCHgOd^`QW1_wsvP4lhVT} +z*f0y4ik5n%-_$+pCk2UmS9hOjucVu@tUP(o=x@{!J#lz|2+El}B6kSlH~L+i5pnbe +zUF3{BYa2MD-slk52?G$vxdyfi`u}Y08q5*N`z2=k!(~KxE%t}O-OmQ%{cyGK_uzqa +zSgF2cG1c(a8=v*DN7~aBW!ZGc^yQHjQ$Moahzi^n5s<cjnocZ<_%uQ@yL3+3v}Ku= +z^dsb$ZkfAQvpmx>H<z551=CjqtPHTE-=so3AEJ39a~0Z1dJ|*Ib*rayX`82QnWoR) +zniI5e+jHCJyf<yfwD)s@XYZV2nHx?Y%+bzv%_*9*E8@e5-4T1{6wmo6;^T-<BKA)E +z%bX;Aq8f1_w<pDD*{F1+85}0kO@PM3qS#upwLbyx2oCi7+wQ1;^;avNGh4b4F|x!} +z*vq+wt>Sk^#G*h|dt#6Fh{lUgiyOQABldGC{67$R18wk1cvYsY*SasObFpzr>7<)% +zaD$gY(YWt&h%Mdgd|lTDq4$g3>KDwyy(>xX=1f**4)Ub3$kRMXR-zv0{i^xyS9X3N +z)>7Dmp41YIJ09Dk6<hl-WFYz=CcEF4bL0J%ZCOlpEV9iAR3qfkIGwh6xXvn-`Lq|R +ze4Bl4QzCgUx<{Ng4IuBxP^uWFmrCCmG;-fNjp9}@OT22X<8l!3-NqvG7&VgSW0oa| +zv;MgHs(M$fR}{CPsVfp5J|9Gh`nBp)wx5op@xIgPiIkFYz*k?Hgj@g?^y!SVjrY#K +z>Tp)wP0rRn1{SPVrNByD%wmzgBX_1QqH*@t*^T16;z4LtV~4imCL8K(tY0N=7PV8| +zX%(rl8F-UN_9>|jbBMk}sl{$~DFgfLyb-OBV=vH-_L@Qw0iGzRFnE9aU7wWrME&Ss +zrm=2K(Ia|_DK56&aMAn=P94h`9LO2g2_-^3BKqd!dSnU1sR-AX={od(F1eD^B04vP +zITMShYfK&2Zw$LX5ayKj5Tes*7EhQIuJ$5g^wt}5RH{XwXL^)fD;{N(!cr<Z9ll%} +z=29s+1Y{h)VHrmNp5}%1aOiCRkX+|KBy+e{|97S3iDZf(6ZNHjG=O5rMuX{B^bifB +z;WUa8Xe=esqx2X}gwJ$7S~M2)Q?8FdcA8Q-!mezh4Y(eswxM<<Qd5TOZcPEM9!<T? +zuH4ZU;ku8zjx6aoR|(Hge|7_|u?yRfKLzMn7S&&00FU35&$QE-&!pM@Jd-AGQ6<Ot +zb_>qL51|)TniM8YAf9d#TzGnW%z7r{4EEGAG8`P*k#{IqpC8h*;z#CW3Z_uHkHRP% +zSCJxdH6a^)B}L|AC&>Ip-~bRaQRb6@?Gw3pnV%{w?WXX(O2G^o;h<qsDVQk=6as!L +z^Uc7N$7KH1Nisifvdpgs9JpWdxE@r3yQygP=at$C$<Xga%x;E`2h#n}@&oiB^gNV) +z4Nd=sM&Ruz8bc35-xDbj7>`*BAD8*ODKa1V1ZDx6fOnph`RM<W`RP+-{thraRpyTZ +z(P=V2c$&;FoG$Z?fHqy`M*=&5Mqv0%nRm_N!P(-_9{Ju><?9Ri!oXiRAOew?dE#uD +zuK+UV$h;ef&6N3+r=WR0zWeJe?7j|Tj(C-;6LLi_2b=Ljp0e|>0zZ6S5Jm=K<O;rJ +zv2&Cm&}woz^cO09?u%^4CNI@ln_c{JWH7E#pYpOI=eI48l{<UPl7>!-+r(UPvvB&K +zdh&AH&hw<HYxKV7{X!Cm(X##UH>~hdK}*fzd!lyqf0G8g+{d&vVw=uW>#%uRngp|C +zM2whz>9n|A{91Hh9UyA3?-dz)Mw&B1s49H`jZgDQ<up&+7Gb?n%4;|sSMlfRVHJI* +zhdrDqPz66dOozDlA@OmW;=fPWlJHFea^XPh$dAclN+MkcsB$)G+j8r;>0!Z1A(J@x +z@^NmW8g~Y&UX+EswbPg@uCsL-^TcIludo5DApsdc->yn=gP1J3O*%@EBBcVXhIkEI +z2bOs(KJ3!4bwF8_TrfQTV6Z<<BlnrNpSNCd@m9pCknl}v<f=~f7<LL;{Tbyd7YiLC +zy4jPFkA%cmKE)zka;kTRd!#}k;opn4^JeE3=q*v-8OEY;N=A6#Dhhr^&})=~92Z|U +zp>m-RUSWul-gUT5JY|WUV{=5`h~V%7(VeHGDnxnBZ122s%6+=8<jxLN$3EuEooALF +zH?R}#UCCb7-IbF`dBw1~tK!+Acj=bEe~N{QtRd24zT{bToL<#+rO`4nf(|G4!Fo15 +zS1<U_C_DQ2Gbd(27da!AN3fO7@<8ic7mth-=ZZ0{%h7%`3SaX13!Rc7uoCCT9yxNv +zPL6%MT&EG85k-jneI;v#Sz_nM7{)<r59c`RaJ_b^7n~VJiSh3<+~ht2UyMJj$c0O( +z5PPZh>HWUC?9JJsCPm2-KZQ)|jn9gm!gFGs@Vr<8tF$W)L2LRu-hR!^!hX2r31<e@ +z#9XH%IJ{E)-jJ1D!ewV46#P3-fqhNdNu2g`cnx+4YsT}Jax$>vWxRMv*P)vMYu?Ar +z;5lJhRl1H=rQ7MPX<>6>Fyi~U9;#Y2fP`6V<{VFZH|_0dp~%3p(#~?vrn$LbaN*+| +z@ak{J^`Uysnz-Lrov<}Q7l-^dfKxR;3HcF=o&Roam(G>>>UoF+^Fy$<hXnS-kpDl* +zj+>9DnkDmlfule|w#?548nZ(|!N>b4WZ^_uB4mqht{xF2DHkzkfq?f__q_LV+1(Ll +z(gK;+=gIt{yfBQ}#oPIoaCYLa^i^DZjeo=O8vhos4%h&^3v2`4cj!GUiEqRn`J7oQ +zaNIY#Uz|V6RAGf>=9l5RCLjJ34tk6E#w`?Bvzda9=sjDhA851a<-TZ+qXf%D3%oL3 +z-!JaI(a}kLCt-ie?-$3SmjB*Qbrsvu7P0u%cT#i`n~lvA^FkZ0=`XO^GGD-K$W3~= +z@8PijV#eXvD^3TS!%xqLm=L{~(d(g=znIZFx|q?T7yX=P5z|BkxOH*vi-RSO_?d5# +zcB(e6CT&w%@Hh>vq_y!`vv&^7ne8^`&MqF&gh-nO&E|*>VS%_48A>3$A-dqYjkUK6 +z%G9=b#dR~gcdaZl`@bmR7Kluu`GrN0bYbCj;a{IWQ^>emQ^>e0E$pcRu^i@J4!>;= +zKwM>Xs@0LNzwufIr{+<s_!h-7@(?s#u{wB%tbDUNCxcZXWV8Wj524j#6|xZr&=2hH +zm!KbvXRT;M(VjvZhPDZ9c=wp&=p#)prh`;MRmKZnGkpcXx*hWypDxewTsvdYMnT%i +ztIZu*;lA@0?b!?+ot?*#PqJtiO#QLtQier)%HU2tJCCQ_@Jo1_-B@Kfn-N5L9-sQP +z`y@`^tJ$~ajvrg**PN9?C@L<e(R;$8MP1BK86(eT2%y}jn{v}hM)^mTvZ04^4Wk@E +zd5u1N8x`lSl@)O{o2BXG?a%jc{XV<3e-C%xKJ%3%8ejD;<yL*Q&4{X*c4|fH!Y>c& +zP(AzWY2EnZ4fIU$)q=^$uvzx6mjd7m%w{aAWhLyN;U1ckP&?LZ%uQ%|B1>%Hyh0AH +z4xw!Vsxz)iT=QKUaDB3<4H;nYuClTBjw%}=E9D<-z%|CzHWd1HmEpRvs9@;5qY7-Y +zlKVj$^1sFp%5ZhM3UEy-syE&{itT^a56W=e`#}M&ajtp}`#@0<DlGmTa3DFQulk@u +zf@uC(pJ(F=b@0`XtdgP2$xhS*0=v3*$_}=3;N*fF{gjdA=xR-{e3^LhJdyt-Q%+^( +zerm1f;5We+JQqt)`LQcIXzVBrjXA?=J|>fv{zO@bpr?P(Q3>iy8-(#*MhSFKz4ErK +zZ1e9>$ru@h(_u7fi%JJu+iG<P=X_L$x@$}2)Ye^Fn*2?$$J62!`eD8}dIa<N&q6Ce +zWeMgh`9*c<+cts*l<>^xL5Mf8dJVF*9Q3{y-xMbslF~)&Pd-5_PLxn{`8R*8nr*#d +z73?~T=@c!C(29<T<+@z{L7^~0Bfb&As*x?^Y;Os2oo@*;hd(WDu_aR=g&;dLAS;w8 +z8u_bTS%h<&UD0aU+E1yu4jZklsl=6PHy~>ntz~QfPAyyex9gmVEkRxWEIrSkrL*|i +zq;cVSclQ2A|MMg~cWazdOOVG<f-~R8ddLcnSQgb1#CC~JHBPZPhEN+uY$P_vslUm} +zzB*?HxR%Zac~k4)6^DXc5k;uF`A_@cui9^~t3&;kx(p5Zt1y4K6&$xltTj8OtW1_Y +zxx4(mX2pxj)*o&i`!!LUP{F6%>Ur+&>UmzVGUb+^UP4sQ39t|`&OcYn^H%Boa+Zfp +zHf+X;b08`OsC{m{zo8B_yxw;^pVF}!P5Ch6RO4hr$qYZmHK5qT;TlvJe#xH?`Odam +zZha`-yl&n2hg)@jA*y&gw_Kg!J;EBP#jbi2zaMB4C|NsMRxS_IVwZ0TvPxOy4)HtG +zBwB*XP-&;~*<)vp2v0t&9O|-~ZU?fg)?zA0z1?CW3um-RpDeSEJQT$8Ti$qB*?x19 +zTDkUH#$)huxyY;*U=P^<FL<e%+5ccQv&}fzCbG8IHYGSIu!`Yh<;QsF;1_lp`~$Op +zp4fz(?+Mh{*7s$4wY8_Bzg_M7&#<h1@l2glG6o}Z2&}fiVilYHcpaO4=P@?>lH)z` +z0#)DOU%{Ich0-23WMijG+89TjhV^KNq4j_3InKT<uV>#jpgPaI2iYCIr8M_k<j#7# +z;xlf-j=A5+d~unuQ+NUS9rOKw1~z+S1EXMVU=(5-7zLNq2RtrQ$6p1HFZi{@$27?N +zBw!Ix*uYjEi)w5pEoS*y@N!!H>&nG$sbrPzQI+lml`b30Mxx@#hn>*sm#V$E6FBpo +z=;8W5OYA$r_}$vb_$_T@{4)J(((*(`*W0-CU+yQJWPHNEuTZ5KJLLA0=8-|L#6Gmx +zQE@Ulf?i*>cMUz967Z}Py+LZvbJB0UUJ6Zk$AN;k`%MdeH(L_qKXa5o!>pb<^GCK; +z3dGu>sH_wg7rWYD3`yY^hh(WWl^ma2Sm3J@@_b%_MWTJDm^HMgnKfLenRGW#vkKBK +zawWbP(ly45>WXEg9hJ&-tn?Q{Jcd=>^%XYvBmZY^`;YLmOP<vA_^seB57mr^jL;N5 +zJ@nu6;PNsaZg?3F`_3{RQd$`gcfdnNXb%q*a9F9k?UXV?dwIx0^!<H^Is7?s%ZOy0 +z%KIR~8&Pk#kNTr(U`5R!78L_onR<GI&8}n;+e@2Hv%OT`%=XgE=6b~B+-4S;^P8DI +z=nUiKcV`$cyU#FQ<TK3L{XEXZ-$Ng2{p4ML1SZX4CFypLja=X)%g1~?$G2aogO>do +zzN1pKdKks|9!7DWhf$p0;_9XNMK?w5VdcuL9*WNPS)u<~wzX$_WotdlWJ_*kvh8kV +zvemRQ*?wwevW2!W+0L~wP9~jWoXkDPIO#a&Oq>NhtFoQ$<|Od2l6#jE7dT<E)j_rv +z0kNxFwz_kS;_Y*cV&DZvapna^arFgPFU2d}6vGcI;$4a?rmhg*6)YwT<)W{RXX~N$ +zimSaIo^tZ8r+j5BfhNBa{JNw|Y`#I4*nE30vH8TyY`(RZU5WKQ5-8pCSq>{ZZ@Q$D +z@Rug_w?m?4{9-#KoRBLLZ3p@ph-L%HsMJpfcA<X-*oEae6}Sex96@xXn&>w0yT1|b +z27-?gRRc$mB~|=D6jei%4NO8V@=z_t00DJGF99{c@MA=Gfb8S=?Hrg~kLN%<em{5> +z@B#@Zh)RJejo6m}(@COdfL35+6Hy5e@FVyIoPY~x1Y+<j`c#1Zn*I&IeofB?RscJJ +zgTPV13;YC#%|wHNaex!J1C*R0ItN61Knqv_90EGoeGAc6pau}V;NdKIMjM6J1;n-z +z1%3lwfG58tS_rHF8i2ebL~-8{%?H*1M}TJFHZZt~C?8l0>;zhY!tXI2dQJmgX@l;4 +z;0suI31hII)c`lzF?R=1Xtb7|1o~eknh3m%{w`o#C-eqv2i&+n@(<`7xPyM!eOg*| +zji^7``M~SfLFWee16Bb$ffC>p@G9Ql0Fr(tIsnYQ1Dz<)8EMGFY3K^_$rw}|vVm2= +zPe5j%hPDG2f-ojTL(WhQT>~6~hIRm9VH%nblmbzGG?WJ{0$v6V0LOub{_xL%m@9_p +z^8L^g5N9Lx?>O2i55SiAZK8BIQPl{dy(5Vp8U>67k3jes$OEhaZUfIG5N!gE0$~qh +z955eP2;5+F&>nmQzB`uaIA9+~G$;|a#xDYKNze;m8joL5fmUGfqqtAO8km6f0PF^C +z15+mwtp=KbwZBDw5-^$QW3>Cw-uo9dg~)?voscp2N%+qq@RpDERqz2E1e$=K0LPz* +z>VTvrkd?upr8_{rs3oTpYq$Wm0;+(yD~M*Ugx-Lig`o8Y(ezdDI{-&}It6qBQ&wZG +z0dwDie*yVxutwj;J#Y<}xEAvR{nnumtO51{H-XmmL_7WmHUO;efG$u7Q~{wIz$dT* +z_;@4q`)8uhz-P%8=mikBV*N&FsdyWaWjpu=N`dJ2h+YR8fZ!eQF^s838~#2~I<Ow_ +z0&8|cwhuttg|R?v5z&xcSnt4+5AmM?Kr3L`4cb8D9@q$oFNQvVpFV>9K7n3<eL&h? +z*a#^63z2poWCV)$6Lpl}{ileFr9_K?=rY(Bcm>!DR0B7FNe95wU!g<bozGy?NG-km +z1$aG#IB^)yfK4)JeTj7ibOQ6s5i5Y1Um;!rVP8X^h@*vQYbtPG3A#Wba0F<LK>Uk@ +zet=y-Gtdc4G$Kv{>_3L4m_Qd;15^PWKz|AL1U3OO&<Z3(!S8`;AfYd4BIf6zT?14> +Zzol-hJ3M=-8oCR|x&%(egRelM{{{cB@hkuU + +literal 0 +HcmV?d00001 + +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0028-usb-host-xhci-rcar-update-firmware-for-R-Car-H3-and-.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0028-usb-host-xhci-rcar-update-firmware-for-R-Car-H3-and-.patch new file mode 100644 index 0000000..2068abc --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0028-usb-host-xhci-rcar-update-firmware-for-R-Car-H3-and-.patch @@ -0,0 +1,206 @@ +From 7c3dfc0bb21bf717dc19a6b677a866aef8b70c35 Mon Sep 17 00:00:00 2001 +From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> +Date: Wed, 10 Aug 2016 19:56:39 +0900 +Subject: [PATCH] usb: host: xhci-rcar: update firmware for R-Car H3 and M3-W + +This patch updates the firmware files for R-Car H3 and M3-W to fix +the device detection issue. + +The md5sum of the files are: +645db7e9056029efa15f158e51cc8a11 r8a779x_usb3_v2.dlmem +687d5d42f38f9850f8d5a6071dca3109 r8a779x_usb3_v3.dlmem + +Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> +Signed-off-by: Kyle McMartin <kyle@kernel.org> +--- + firmware/r8a779x_usb3_v2.dlmem | Bin 9472 -> 9416 bytes + firmware/r8a779x_usb3_v3.dlmem | Bin 9472 -> 9416 bytes + 2 files changed, 0 insertions(+), 0 deletions(-) + +diff --git a/firmware/r8a779x_usb3_v2.dlmem b/firmware/r8a779x_usb3_v2.dlmem +index 7db71726f45943e7162d8e21ce7d80885bd79184..2b85222467e555a0f33002d1dad5ecf39da9d9b8 100644 +GIT binary patch +delta 2698 +zcmY*b4Nz3q6~6b$zQ-=?!aiA+U3U4~T_YkEsUnEF2x#y(qNq_(0hRFwm1eAyrdn14 +zmQw3zZZKr3Mu#6Q<Cu!B%}{ciSg_WTksz!}6&Dp`)Cn~Lb&{CZa~2zuo%zl^_ug~9 +zbKZI9-nXv#SLOvbEN>YKAsqyN1LU^taBu?Mb$E82Fymk61`;UU#Z1Cv<He9+txE}| +ztstihZk0>P8{<+q%NPDZ&zz4PGn>+@=ePOQP}LGYm(qNGtoV#hvmgKEw@dY<p@hyc +zT>qF5u83hRuQhrcgNxpEin6~z_QKkUur#rRluG%;F=%o*#ffaHzcZFNyxEtmT*-0R +zrcv0j!p?7e9(JS3leU74nXkWO;7SBL=5H<evu`K;Cp?#7ZA=12STfF=-L2w^XB=08 +zUwg&Z|AUuHipK0>z1fXm*ES(dbP|^@qsjZ7qE3yOdb68gFE<ghbxFO&q=U+t#^wHw +zP{LBwa~!+CY7gl$q&}p?DVF+X4Wgo4($bDPZR$fctX8ucbt>&-ch%cy8e5==i+eA< +z3raeL)PdYhh9N>vdaFuE<VuIG%vncXq;#k(DL6mNPHG%+x{Nw4SDG`>Qp{{sje(sC +zU9HcuR2w6bpEooJDSoiJjy=_6Xdh+N%>;|g;i+7yWU~XN&Re{t3hElOwa?&E{6sg% +z2(cV0dAz6#m>(4(|B>y;zivmX3YnU;WzJKOiH|=M`Tb$_5c^wzQT4VqO;p%yeRO1T +zCYNI7aOoi6EWkXMOVa^I=Bg68l*PgWZMN@V?s=U{ne({xRu-3%=5whM@D9v(EfB#@ +zVEKU=D_sk?v~D4n0vCZDpaXDVF_+{wxU_Hymqq{+v$=E`ATQ-o)G{s=<Z!7S@Xc~A +zO<KXFYCt<+;+tGLx=I4>&FtGiTllQiTxtg7tl?4<ASRbfGuFZrNfTI#Hay6_)+GfK +z@LR8jHNrM%<D`p4eVe#4!m6}!w3&Ub{T21HR9z%(V{3G?4Poo??bTDP+4H<sl?JNQ +z$j<4O(QlY4=wyIyTbI@`=zvZ-&CUh=jBaGTLHYD8mJ$3<n#8nvThN(xTxwYlx#R^v +zOgnSxZIMZNP``XG)dMaA5(~Jr6wqD}2sZcFKD{9zc_Tc>CN0b_v6Fg3P}(LgeGe!s +z)WO<u)~cTzE^f0L%S*$PEeW^eWAaA%DrA{c<OaE)>E*bL38Ez-JlULP%7QmtWJ$0Z +zDH)xQ+E-$4?6~t^k(jc~X~=^N=AC^Y7w<%#99ANmri2z_oS9#hl_KA$?<43Xxfp%_ +z@3*lS{Vo@y-}7SDCNF+NE+2OICvat`-0d4Z`-iPKKl)p@wHs2-mm5`^d}+T~Q3uHs +zR19l>x}H~or28w7^bFfF)>hKu(|7-F?@ATH16wKeDp5(zaLAhvXijj2AK0)`fZ0VD +z{b0NRqew<A&Vug$Qf~lV1N*mO41}>0MjebDFb2Q0X#-s*q=7V%Msn3K@b^b{77${f +z=`1?LNkdtFh>7~KUxTh;e+}7LBGk6d;mXF^Dv)#Q`rvp9_3oMZa<A&1b_2*#ts4&O +zCpA?d&9!~;5Uth?@?c$g{Ew~59dI4h^ub|nuW^IiQ(F!)xvtCbV=Fw=mKrz6`kHc( +z<Hg!8D3gwTY>1>o>>9`iY|s!*8<{@TNF!KmXe^!2mW9T{1MGv9gY3i5Q!_77Ed7l3 +zVW6mJZw2|hy$ZViImObCe2JwW>L_#es$ZnMhxbq+-V;$tQCKXt*J#u>(K2JN+N*Db +zk4F(ZX^ak7LC~x73$C1IUl=3p6>WCos@#3@)0d}Z$S4q+xEF4JJUc>|Kr{(#N!Vh# +zf_)UWOt2@ip|B`;27}2#JuKB^)t_m@Y`$(o-rc~vkZm!=#phka$c1t@@GdHKimOd{ +zpF0M#K`->_qjx%f15U8dO$IseI`VX1N1h9v_%&eN<_Ws6E?j=zh08h*i!x6dJHt~2 +zwOHuEja(0I6tH}=RlC~5B^RI`@EQBPIXZsCXCvM~o2VPeS!UE~1kt6ycSV|eLl8@R +z+U6Tv+QDv_<4R&~B5UVO^muY})T38Tmln$CVZK!Y46o)cnBzCg{uODp!twFkvL>nF +zi3VVV_MFZY(rryL`Lv0kMG^{YPhfYPPYdfFt-=os0g4P}DxffTvxDJgdWiigJU(vV +zHopDocksDy-@yzMd+-lIJ*jp6BH%^JJ@{TlCAr9_%0WggHq|Hp#;V3zCXc;+4?QQ{ +zN6&%#=(&e&w-^P@3%1{qlu>b~%HdLS33jyHgB?Aq2Rr)xo-Sy;qdnMwwLRE?$#;>c +z;Vu$+?;_F2T`W=#Q!GaMHZxkIO-Wv~$@QX5wHIv$yl7L+vaLp8+;?oNb<&zE_g{sy +zJiw6eJiw6N2N=@74?`yOVaUurq>JcBI#)l^9qC89@ej+Ks{&v4{GHLBC;p!*N7*w- +zLh}&4raVNiv;p)wG=N?$EIz^rr)*9{q+l6jg%J^^<i}{b?lGG7KStB}Ptf!VI|ioR +z%pI{_-);~{%QZs6+6gHDEIIFpTtl<BLJwC1Mh0Q)KZJCG9%>dy#8X1%0%n1}12F4r +zLN)`A11e#D<r)0t16&5(1E?G#q#wrd?8~S~ReCsFkZd^W1Nw;lA^LUe_waA&LMkCm +zGYH9=2~hy9S%i#p5@Kdgqd!nz)C)wE1+t4Bjya|O47A2S64C>Zk3zz1p3O!Nu<f?L +U&;jPKPot;VTKh+StJ4YjA4B_1P5=M^ + +delta 2932 +zcmY*b4Ny~87QXMndyfQOfCnK22n3Q~714moimn6^6}6)H|3fP%vR3hLckAvtx}*ro +zb{q%2i{0*4RwbZS$FT@@wQ{GE1y?)NA|;4aAVfg?sedhYw*qg^4OrUDeCM8b&-u<h +z_vhT3>+`Jh{mv|(<O)Phi2nLepz*MunK^fOW(B*c|C2s5!<@rfHcoRsuwS&wK}<c! +zX>1K=m9spo@+F+j{)g$lIM!n(!`Lrw@hoS!G*7EseKCOlj+wZ`zaR)Pv(-da1=o$K +zYB4=sxX;2Xy;!st5&3j*GM|qMgluGbs<m2pBc9=9QG1!38Fn3!GfjqHF<{YwWfwl| +z6_6htV$^Vh1yYv?ZA+1Kc(7C)^*Qa1n(~W?1o}M8bgWg;&WtvW$Q{u{4jwbg>iCIe +z6(Ye;HP)F?1%A!rl6ecVx^s)$Z{c|btAwPT8CSrVgJTt|O?e6y?LiLp^!p65@Vnh# +zXLwn*i%e66IQ_l?dQ0$G#dM|t-&bs5rsAc_n3%t(IA8@QqY99_P(MWLO{wSDcp|r{ +z3N00AFtLdXOQheI@W)D1Owg<fk;rwksHZBmp7Q`piOS~oED)o3H0jJ4HqjG$bMgO_ +zv&0v(DrSI3YX1}>AHnmyr%YP$PAM$sxXnFktL(|wfDGr0U`s0V91!_M9*tkNmB!EA +zR?pE$cKnIATKhNAW;ulh5|7YPmeW!634X9dR@~`riuhwH5ys6X!co8_K-3%}qyWn1 +zaPdS~j14{pgXdf#bO7F*M}*yJL`a%Xgd>0g_};UC2R|i#$7j~c;sr#=eUk`*3&9W2 +z2KZ|_5keLbVcB9L3;`x*5aA{uWC;=8SW1M=%ZShlU{??!0dO493Yff#2)5M%#NL5D +zL__GDHAJWbWUeKG9WXAF2&r#*fju726hnQ-zhxC*R>I_U3h48~Tf`WF<n?SM@(?~I +z#xT|RhWMw*J}+a!IiwFtMjp=?wFhU?9NTA1TBcGad#7=*md$vBYNlGhj_ztDL)Q{z +z*K<l(%PaV@YAN#qi@qnkgSI$C(^C^1r{nmt??fgKKk&_FcH;$pH<%=>_BZ%ezfFXO +zb&zG2H)Jy&&-FKKNXmkh%_hQmz)irk^+Z?$XkG6EJ`aU_WYe5N+0repN?b45IR{6C +z<Q$msMiJ~^{LJp+)=Mr9vJ=ua5`oVp!nRx$_*CLA{o_JaTXdSDg3zg9<~!0cDM$JO +zW|5g!1M(2oN-<(QA7&1n8j`F{qbDRo(j-=HYyW{q+O&{l%A)>J+j~H+*iKoQ+mm^D +zhgInE+mHCZ`iFH7c;^8mv=TWSpO7?RAv-AhH8XDqW!~IDnP?|&meLo66!n|D%tRh2 +zs&Tg+`}=kD+jgKv*9IwOOI6%PcbZwn6|f1Li~Gf2_HQbtK@Szvpw)P1fMIKcTmSQ4 +z_O9d*y?x#nx@3LARXEml2bIT(eC^<dl`MP_Xg#653N4R@JuZRnHKJF6t^|8Gv_8<@ +zg;oV^8?=5SKFyd39K+1VV*@Rr;Rhey*R#53-*ja)-qU!aVDpAn*KIvZWFNdQ(85Ug +z-+|lLDQ)$$iJWIE1({ya1BI-tteKH5b#X3n1IPlg2Fm*L@=}mdww_oR&sGESXhl)% +z&%KIFa7mT-K-ssJ*MKav6@g5~ht&ZA#_}2{`19pOAk8)htV|I8R2{(#;M*YY;vdwJ +z+AG(Tea;6}YMt3CA4fCb9!~6}ms}8z3mVI$;I%=q+WFU%PG^@(3<DoC`Zf3rUxfSd +ziJ(&^mZdwA+Sm`Hlr+|ZM7K(zIHt06M}}_E9T~t|H5yYJW3zNAMy{DZ3|}+Ju#$GB +zP}8Mw`d7hIa}Iy3iS#~-DC_Q*M81F>nuwf|2BT(m=6llf*x{mjtYHxozZV%b@4ix+ +z4@tLlg_`V4mhY79gTq>f?Ba}N@4otaB0@c4osjzKb-#V^b${J~)K|mtrUkPI2M4D! +zhwyKLm$HxJ@YP^Fa}~D-n<ke1m<FeZz8N-mmM$(wdI6`gKrDs1{=R|E@=62EHwp3$ +z#Bth~MQ?mXXOt_o!6mS;z``HV(s$7GGz0W9w@y#w@H@1rsZgU<!k&sv-0;rRxXn#8 +z?#Zud+&%cLcB0DJOnW|e(4H0t?$b^P@NA*3fi2WvY@vp6cx;GHjB0_p2W$fr<E0^y +zvBd3j)9usOLLa<Bji_XKs|>H4pt{ZS`EJd88}3+qA|xjN;cXiAqgEQVx^<Y*rC^ri +zN|fPh&4&o1-)VQ~bh450398pY;g;ReB`9EPFF-3HG>ypDLDRam??H<|4D?ll7VXxY +zcZL__rwGw<8yGnV;Tkb@Ay3U7g*`}s3$O}SiayV)@XpZKm<xC5sbkyeV%XYg+CR3_ +zzb%!>X4&aInCOCMR-a%+wekvlBh<iIzajD_{5&*nyv;?KFI|**;T~nCc2njMFjxA# +zW+Km8xoH5Whb63C++J$3%9)53Tw6OWIKG1xTxN#@iXf+hmO@@fKZHY_H1uyfY3S3P +zG&Jd?YZ>M&wEPZ|a=*174i^DpYN2F1!y@B{+$^J$va+0%b-_tlSzWeK)@LIuwpM=f +z3didvtSz}WnpXEcnpR3TP3v?wO{=k+ruE-$nwC!wO{=$u4v^MM2Y9=e4)CnE(6Sn4 +z>`tqFWB{*P_yhErE;6pEm$C+WDa)&mvR3s`*1<m8DC@}x%db|Juoxb}c0a)r!o%ax +zBT9~bM9JqLQL^-yl1m=jERNSh$|Gcbt$Y&i4PWPfUCpApuMi4uL})!A?c%rLYnhCb +zP(6)+mrud;3?ZKo7NrBipCdE}unY7`K++3@HUY{2cKE*j9sK1541ul+WzqZJBNPs8 +z7XDBl!R-d^C9c(fz_{@8$hpi*d@M2)ZtBaCA1KcIvuFsAhgV0P^8c5_qN;x&)B%t_ +gLTC;4HyD^gJjL)S<HX;>-_7ILWc;UR@mYla4-;9yJOBUy + +diff --git a/firmware/r8a779x_usb3_v3.dlmem b/firmware/r8a779x_usb3_v3.dlmem +index eac36a96bee1a8614eef9caa88e5a9de136af30c..1e09014d1876e1acd638db7b067f96397216af1b 100644 +GIT binary patch +delta 2698 +zcmY*b4Nz3q6~6buzQ-=?!aiA+U3U4~T_PeDsUnEFC}{kTC~8zxKxO<vr5Woasg{)h +zrPMl_8;qH%(cwqSIHsa&GnCvW7OZv1NDx+~ii-*|>Vz7BI!VmyIg5?S&V1*dd+#~l +zIq$r4?_1aWEAv7cmbVOrk`98u0dm`RC?tvQIyAFR=#M)$kVNS&W)dbEFNO|lT}l{j +z1vyo4t6WN+pG)B^U-&0Ib3Wd0CZ$);Z}YFAswMs|rTP3A@fn?BKmP0Qmg-Bxh~I3( +z^-l=liWuJVTBFA?xad8nC<h2+FRYyi&k##UsgzF~gC>_#9M2{PIOB=Kn|;a3l^lm{ +z3WXgj?EKc}VK=Hg87qk2eElT@S0dT50Bgx#d^@v##&a3g{E{%jk~nX6w~8yCIIe`e +z_KL6nM=zHYgW1J<vm3##ZCr-vBrab@6DypePK}v*vzuTqHyN{aNxj9SgUVUP<pGW` +z!qU{U9lOA459u<bKcvJdmilH5qM}^V(vCW9`a?CW9$_`=blS=8s<+V$wm_4R@cyhW +zDCs0p2XZ$Vh6p{gT2(?aS2}cM&N}iUtwUu=!}(cuQsYR_W!7oA(wvEwVpgll4|Xbb +zwLZ&IZLCOs+0Y=Q`NQfu_EeLpeUw=@9W1hjCv&BW%?zA8Z}FCDsB7%jK7&i~7u_Hu +z#d4_R@uDtZepH0~hqojDx*e@5WNOluIZr_*KK?A^4}jH!?C*g_)!W((QDHOnF;T@? +zT#B8|r2~Mo0P`F!O$8jDqe|w|Tow^zvwaV9&+A;un#ZNL=5i@zK9{Nh@4|f70uk&4 +zmLHV4(zSp~>lSh;Xc5=}Isp3@b4h-KOAD89X#_Ann@g7g@=`8EFXK`{4wu>i-!A9U +zgcV#m0%!+}f0Ii`S4qIVnSB>zi<q&ROU;0sHC$=}#O88o+FE!bX&g(_Mg-f}x}*>S +ze(Tk+M%V^zf^@N{ZxdHWShY5RHnT6Z?@%vG*G17bwnjJ85WXJYUOmN{J<n@ZX`nid +z?3`{H{g$bMPX_9?b!i=g4(O!Q>|F3K=tkBXoKN3knIZq8DNL)k1)o{RrIz)OOI{$v +zv@@sP7L}3*^~>i{J>W7RxqwSc0qq4rU~`Y{(;EU)H^Osl(!%@_JE=DWXKdoq4}ii# +z9jqN^t@?=(;x?<Xyfh-!l5|TxCU2ClLY6s2ZjcpBFDGP<6D>&*spbsRTzJz(mL#i@ +zlF|97eHHe`jywMqiD|Am19_0ayt5DF;+@Eo!%Ae+q_AR)GyUtbQsf);eFVKE7o+e0 +z{Wcb(-{oTTdtS`i<i&5u<-?AEB(4mVyM3dlV%UoFqrY=oyCLO#xly&rm-d^Lb&yO! +z<*@eW>v@$(T2YClXV{i8wvrZ~zWeukSE>je*ea=4iB4&TL*Be!bAl^;|Av(U%r3&{ +z590+GMKWq}7W9CZdIRVh*uM>95R9EL>R{}EG32F98|X424Wx-QlB<S+e>}3Yz)%C7 +z#bQF8G>qkkny5ef4d@#7x6qv>LT&48u57HW205p$500l$@1CA7_p0t`H-IeFy5X>X +zT2l?uT-%oj(Q4fw57d<>{?w}60oPGY9~|cP8aK#2wdEjF>$(g-wZcPfsd0m>uPFyP +zR;=xUGU?bShA2A3u7P~O1`RQ^k?F&XG?K-K#nbt0Sy&=Gz&=<xz&;8)HT@FB(obt2 +z28zn|R*=uztD)<kQ!M?+S6KR?jxuMj`bFCNcn=lgJrSJ}jm2VnjYe$~Ei?A2z4}J@ +zcoead#+bkr1id=H<jQIGr7_B0*=9Gc%H1bFeR*1ji~^y_d*SxSvm=BHM3cmpgfFHm +z*vH|^1bZ?Y3Xg_oFqj<F!_rMw{h2n*=9@O;-3`18*%nhmV%{~3Tqt(~@1jztxY~sG +zxnnRJ^g^FLdZ*(z-~{`^WRQcdBTx5r<hjs^Ujx={9;XZM!sX{(xUBQAX!C?I(>&Es +zi-jKC$o1ex0n0aAwW~c`aslcApR+%hV-iPvHsTGmiN1lHWk#(=5M2s<SEM;N1hK@Y +zZN9;!9qg7lp(OSuvUc7?k0&=rJ$lu2X`zfB=36De@M`XYIexS3Uz1iV93RguYl<44 +zXaGiND?-PRP7Pa6+f6rr&81a{+mT6p(p6@Fw0RAewy0fo7n9f&Z~gY3@{i3tO@ +z@$FB&gU@~Y4rZ9#gMSF>Nv-o&fiKeT!S^aU#YH|-4lru5sXqNTRyE!-am?*|=sDp& +zdJf!2&pm9r#VBZAunJ2`X62n~hfB#N*wJzicJz!M?C1}Ax}f!r_Fx0n_Fx01-bJE@ +zyGZ1{i$o)Lu}C>gu^8#w%xH}<rFhXM*NZksyl6AvMVlim+iDczzGqvl6V_b0|0<;A +z0fv0{0fzKGz>oob7&563LuU0MU1UGfx%!dra6i(GeOTsP74)*_?~L|53HVGo%AP?I +znuq8$=^=V$44~J+0rYBNiIGM)WwRrr1j`^RjEpp;K1S1ZkI}UMF`CYQf~Hs4F);0B +z?#T7}c7s4#t`QR6PDlY@$$3ZA8k)TodiV%nWDvIgLr5p+VP=6uJ|$!hU<T+r05iTJ +zWHaD6pbF+!p21%}z-7=qfT|%v`e7W)zKV`g&5D2vk_|_HNFT93#=LI*0sbvrNGGIe +z8X<G1Lll5(1|e}yLd@)G%!lfWdVz?tKz6Z1v8VK(gVy*bLV5u5QAn80v)Sl=w%ztu +UI=~$EDfBd3Yya5)+B<~&507_F0RR91 + +delta 2932 +zcmY*b4Ny~87QXMndoKyR2oFLMAP`7`RYU_SD|RJ_sHhdi{~uaGk+q6{yIXhH(IrJt +zw&OVHUF>$ZvMK?sbsUReS1WfqEV$aC7AYW7fg}RrPyK7LyA^nQZotxJ<~#Sid(L<6 +zxj*OLT$^W~?{{YTWOpEHLiE>%0?mj0tjyWNGt1dZ-6wrkhB=G%Y^?TNV83XWgP3}d +z)7fgyE@yh#<%>9r{SVW9VVu`YhN-=<#k-8*QoZeR)rA25J7&@n|NJ22HCsbuwXSY# +zWvk`M!hJSgrC`xsMC8-DBt8%23t7nWL~pn8W;{b-(<m&?^jZUvGc2ZGF<>!(WfwlI +z2*`^HHfy=Te90w3+gd0c9xM?@eNKC#CjTNLfj%!Q9cxvTGrgT7a%U8gbz?_aoj<Yc +zLIn7!$2rq0!LNCI5^qCxPj0dMZ9K1JRgknZ{W2J{ag1`cC0EI!J*Y+V`aK5O_}!kb +zGrTO<icC|v`1(C1^cLffm9H}m_?~hLGYv0QMMwWVxdm2m3MvP=3-v>^-sF0YjU#fq +zy1-VB1{0dN&;<H@5r3qzL<h|(7l~Xqi+ZY4>Nzj46ssK`&wMeGN0ZN-VH3QeHwXVu +zHA{Rxt9%A{r1VcE@)11GXX@k?Z<oMwj^Es)vCH0kHOMf&5VoWuw*?|U&!zE8x6=4I +z+v+(QsTP0YqtX9Obl6UzfrKM;l;w03W4s?MksWvWSi=99LWJ?NiEtEf5fC|t2+4rb +zIb0kO7GsmI$>cqk2%Ug8<`H3cDiIRr6X6ITAHMf2;K5IY-}argvS<Mja^4_9;6m^N +zv;+Q{Mugx+L|C?%2t$A==|s2z2wp;j*On4t^D-i|0oWBphzA@8v;n59B7$SJ0I_#q +zFVPe-XAKeR02ynEPzxBJL4=ey6=09UGsTcG6W+87Fe_ooIwkZe@D?#zAh|soi9Cdl +ziP20IzApYLqEBItKZ}e(NyzIdqw(S_+GG37iObZgB%f3c*0LFIP|wsD*U??AVCY(+ +zta?rbYk3)8QZHqmV{yz0pP(%*qUDJNj?-~`Y0M-h7vCR~#q7ol{H`;JSmSRRQ}q@R +z8rDIUnLd!s1U%Q@v>`DQRyK<W=KwbV)7KMW4WMnkFZetV@{mJ&3S~(*xk_=pRLiw+ +zL`cep8E+K9{>9JiZf?Eg<{&#Ebt4h@93pJXQG-tf{?b1-M7_nJEzA#@7HYjM9h0)9 +zFJKlKxz!*KVZ9VB#_^%nkZHk5`c!&C(j{#|#kP(gc%)AaPNFR8AGy5;<cjT-m9agE +zmv`6&m*0NG_tihByU#lhAfb)OVfcik4GrEw*{_(nJ1FzU4$4G3akG@RD7diSqOcNq +zps?E0cJA*t&~L|qYC}7um?c$m8$D@e7L~&$Y%b~-f7!pOhz31WM1xl0odKq;4Icf^ +zf7!c|L-h7}PjJb`_$zR%>kg`p6Zz`F4J%prBG7t6dj(n^4SQS!T`{6pg02F4H?+Rc +z-hoyPZ9BAnBR<WT2^`DJ$KwKRAz=p}+%vL<r{B0T8}Dj;kj}cH&3((r64@8;3$!s3 +z{&(Q^bt*^wY$E46N<gNS_dp@5DynB>NiNPUZUC7tRzq2TURDA!($NzG<2kB99xX47 +z`MFo21um(w9w_^^vTBe8jzW-0_^>7*z+6@h1%Ixr5Tw=70xJ`QKh=aY1NaumJNO4p +zg#PkXRiE>IrN&^j%g50SxQ7$E=p`3~V}r&q$#`v0jDG%AmDA~Ri=p6SMZX50;fruT +zJ`r@v!m@NnQX2bVl;XyEkmzO!6vs4{?#R$hx+4R4t5$1iXB;+{a^#x%!|*ke1S?s~ +z6lh&ar++0pHD~ch+6bSch_dc{N#ygmMH`-7++fzO&UjaP7BgH_kF+de;`So5_MMk1 +z>mli;p+K9J!SY>l?clK1DZ4py={qmKo`g`3SSO^seAQn&_^Q9|K+4PEc++((!a7|V +za|r)Nx0HPpi?8U6%oW_BvrH=eF%?b^eKQ=MEZtnT^c+rOzE}ct{e1(S<>dyNZzALy +zh-3B9i(dPR&L~G}hf82#zKuVkr|+QUNjm7I9-W@Z;df|LQ-M~af;|<RxZ$0rahscH +z+>>9^xO?!&`blbMGwu1jh4!?z;6DAt0Pj}n8rVt==2mJLkH-ZY#K=~td%!k85ndV` +z5kovaH#|Olt@Obw(26RSx6AO#3F=!cpXbr6x8RP&CxWB%9^9f)KWw8>tJ;PcE+w-h +zN1_aOTOLFh{Z742r;~-uk5Rn=3b*vOAzlevdmdT|q3J}v2AbZZeGghVVxX@Iv?!0} +zygj@iKShX=+rh{|2=|D|g}k+Ul(j(uT!59ZQuKLVg?EO;M4!JyPaWGq7sJs()Bdr8 +z{%xs14%<$j!2~xvv&MKks*zXV>mer2{tb~g;b$SS6C7^JeBq|d^LHsTrJFK`fVtB5 +z6%%>a$V~${Ei``Z;*JuFUCuzX;MzNA!SS86;4(T}pa`-%X({A(_Cq+-MMM9#i-tbk +zMMIM=x|X5N0^9E(DbHK`!Eg~ErUpv3D>Nc*$ip%_DJ#=SS?8UUmFaSfvOXJOu{HAJ +zmpINaac%M4(X_hn(zKGhX<DbdX<CilG_C)3)3khhXj;8Jbb!=eI>1}KbbzP51-8{N +zV^3NgBLgUE;1AGehKSgvUdkHir7T4sWv%L?tb=`yQP$%TmS2r5VKFS6?S70WhK0qV +zhm;)kkdn_mq-5z4B^N((*jio<DUXniHS$TkH*B5%H4TgEzCuXXh|qdK>V<E^)-vfQ +zp?VqtFP?zuDMG%%EJ_1}Jws>?U>E2WfW+qrZ32`6YT^6Zckq`NFa)|fghlUtk5Cx2 +znfL=^IJX<L7r4gwKI6vABjz$M@Ue&xxT!Biystdx&!QnfE?ymZ%Ku*yiz@$tP$xk8 +g5TP~L-(+G6@Kn>Mj1zwge>aa~i}|14jS7VR52nDsPyhe` + +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0029-i2c-mux-pca954x-fix-i2c-mux-selection-caching.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0029-i2c-mux-pca954x-fix-i2c-mux-selection-caching.patch new file mode 100644 index 0000000..1640b51 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0029-i2c-mux-pca954x-fix-i2c-mux-selection-caching.patch @@ -0,0 +1,51 @@ +From 7f638c1cb0a1112dbe0b682a42db30521646686b Mon Sep 17 00:00:00 2001 +From: Russell King <rmk+kernel@armlinux.org.uk> +Date: Sat, 17 Dec 2016 12:10:56 +0000 +Subject: [PATCH] i2c: mux: pca954x: fix i2c mux selection caching + +smbus functions return -ve on error, 0 on success. However, +__i2c_transfer() have a different return signature - -ve on error, or +number of buffers transferred (which may be zero or greater.) + +The upshot of this is that the sense of the test is reversed when using +the mux on a bus supporting the master_xfer method: we cache the value +and never retry if we fail to transfer any buffers, but if we succeed, +we clear the cached value. + +Fix this by making pca954x_reg_write() return a negative error code for +all failure cases. + +Fixes: 463e8f845cbf ("i2c: mux: pca954x: retry updating the mux selection on failure") +Acked-by: Peter Rosin <peda@axentia.se> +Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> +Signed-off-by: Wolfram Sang <wsa@the-dreams.de> +--- + drivers/i2c/muxes/i2c-mux-pca954x.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c +index 9a348ee..dd18b9c 100644 +--- a/drivers/i2c/muxes/i2c-mux-pca954x.c ++++ b/drivers/i2c/muxes/i2c-mux-pca954x.c +@@ -167,6 +167,9 @@ static int pca954x_reg_write(struct i2c_adapter *adap, + buf[0] = val; + msg.buf = buf; + ret = __i2c_transfer(adap, &msg, 1); ++ ++ if (ret >= 0 && ret != 1) ++ ret = -EREMOTEIO; + } else { + union i2c_smbus_data data; + ret = adap->algo->smbus_xfer(adap, client->addr, +@@ -195,7 +198,7 @@ static int pca954x_select_chan(struct i2c_mux_core *muxc, u32 chan) + /* Only select the channel if its different from the last channel */ + if (data->last_chan != regval) { + ret = pca954x_reg_write(muxc->parent, client, regval); +- data->last_chan = ret ? 0 : regval; ++ data->last_chan = ret < 0 ? 0 : regval; + } + + return ret; +-- +1.9.1 + 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..75b3fb9 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0030-Gen3-LVDS-cameras.patch @@ -0,0 +1,7768 @@ +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, TI954, TI960 +- cameras: ov10635, ov490+ov10640, ov495+OV2775, ar0132 + +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/ar0132.c | 581 +++++++++++ + drivers/media/i2c/soc_camera/ar0132.h | 213 ++++ + drivers/media/i2c/soc_camera/max9286_max9271.c | 607 ++++++++++++ + drivers/media/i2c/soc_camera/max9286_max9271.h | 244 +++++ + drivers/media/i2c/soc_camera/ov10635.c | 758 ++++++++++++++ + drivers/media/i2c/soc_camera/ov10635.h | 1139 ++++++++++++++++++++++ + drivers/media/i2c/soc_camera/ov10635_debug.h | 54 + + drivers/media/i2c/soc_camera/ov106xx.c | 106 ++ + drivers/media/i2c/soc_camera/ov490_ov10640.c | 1092 +++++++++++++++++++++ + drivers/media/i2c/soc_camera/ov490_ov10640.h | 93 ++ + drivers/media/i2c/soc_camera/ov495_ov2775.c | 658 +++++++++++++ + drivers/media/i2c/soc_camera/ov495_ov2775.h | 23 + + drivers/media/i2c/soc_camera/ti954_ti9x3.c | 431 ++++++++ + drivers/media/i2c/soc_camera/ti964_ti9x3.c | 399 ++++++++ + drivers/media/i2c/soc_camera/ti9x4_ti9x3.h | 153 +++ + drivers/media/platform/soc_camera/rcar_csi2.c | 297 ++++-- + drivers/media/platform/soc_camera/rcar_vin.c | 174 +++- + 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 + + 23 files changed, 7004 insertions(+), 109 deletions(-) + create mode 100644 drivers/media/i2c/soc_camera/ar0132.c + create mode 100644 drivers/media/i2c/soc_camera/ar0132.h + 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/ar0132.c b/drivers/media/i2c/soc_camera/ar0132.c +new file mode 100644 +index 0000000..decbf5f +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ar0132.c +@@ -0,0 +1,581 @@ ++/* ++ * Aptina AR0132 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 "ar0132.h" ++ ++#define AR0132_I2C_ADDR 0x18 ++//#define AR0132_I2C_ADDR 0x50 // eeprom ++ ++#define AR0132_PID 0x3000 ++#define AR0132_VERSION_REG 0x2400 ++ ++#define AR0132_MEDIA_BUS_FMT MEDIA_BUS_FMT_SBGGR12_1X12 ++ ++struct ar0132_priv { ++ struct v4l2_subdev sd; ++ struct v4l2_ctrl_handler hdl; ++ struct media_pad pad; ++ struct v4l2_rect rect; ++ 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 inline struct ar0132_priv *to_ar0132(const struct i2c_client *client) ++{ ++ return container_of(i2c_get_clientdata(client), struct ar0132_priv, sd); ++} ++ ++static void ar0132_s_port(struct i2c_client *client, int fwd_en) ++{ ++ struct ar0132_priv *priv = to_ar0132(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 ar0132_set_regs(struct i2c_client *client, ++ const struct ar0132_reg *regs, int nr_regs) ++{ ++ int i; ++ ++ for (i = 0; i < nr_regs; i++) { ++ if (regs[i].reg == AR0132_DELAY) { ++ mdelay(regs[i].val); ++ continue; ++ } ++ ++ reg16_write16(client, regs[i].reg, regs[i].val); ++ } ++ ++ return 0; ++} ++ ++static int ar0132_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ return 0; ++} ++ ++static int ar0132_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 ar0132_priv *priv = to_ar0132(client); ++ ++ if (format->pad) ++ return -EINVAL; ++ ++ mf->width = priv->rect.width; ++ mf->height = priv->rect.height; ++ mf->code = AR0132_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static int ar0132_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 = AR0132_MEDIA_BUS_FMT; ++ 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 ar0132_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 = AR0132_MEDIA_BUS_FMT; ++ ++ return 0; ++} ++ ++static int ar0132_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0132_priv *priv = to_ar0132(client); ++ ++ memcpy(edid->edid, priv->id, 6); ++ ++ edid->edid[6] = 0xff; ++ edid->edid[7] = client->addr; ++ edid->edid[8] = AR0132_VERSION_REG >> 8; ++ edid->edid[9] = AR0132_VERSION_REG & 0xff; ++ ++ return 0; ++} ++ ++static int ar0132_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 ar0132_priv *priv = to_ar0132(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 > AR0132_MAX_WIDTH) || ++ (rect->top + rect->height > AR0132_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 ar0132_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 ar0132_priv *priv = to_ar0132(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 = AR0132_MAX_WIDTH; ++ sel->r.height = AR0132_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = AR0132_MAX_WIDTH; ++ sel->r.height = AR0132_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP: ++ sel->r = priv->rect; ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int ar0132_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 ar0132_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ int ret; ++ u16 val = 0; ++ ++ ret = reg16_read16(client, (u16)reg->reg, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u16); ++ ++ return 0; ++} ++ ++static int ar0132_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ return reg16_write16(client, (u16)reg->reg, (u16)reg->val); ++} ++#endif ++ ++static struct v4l2_subdev_core_ops ar0132_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = ar0132_g_register, ++ .s_register = ar0132_s_register, ++#endif ++}; ++ ++static int ar0132_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct v4l2_subdev *sd = to_sd(ctrl); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0132_priv *priv = to_ar0132(client); ++ int ret = -EINVAL; ++ ++ if (!priv->init_complete) ++ return 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_BRIGHTNESS: ++ case V4L2_CID_CONTRAST: ++ case V4L2_CID_SATURATION: ++ case V4L2_CID_HUE: ++ case V4L2_CID_GAMMA: ++ case V4L2_CID_SHARPNESS: ++ case V4L2_CID_AUTOGAIN: ++ case V4L2_CID_GAIN: ++ case V4L2_CID_EXPOSURE: ++ case V4L2_CID_HFLIP: ++ case V4L2_CID_VFLIP: ++ break; ++ } ++ ++ return ret; ++} ++ ++static const struct v4l2_ctrl_ops ar0132_ctrl_ops = { ++ .s_ctrl = ar0132_s_ctrl, ++}; ++ ++static struct v4l2_subdev_video_ops ar0132_video_ops = { ++ .s_stream = ar0132_s_stream, ++ .g_mbus_config = ar0132_g_mbus_config, ++}; ++ ++static const struct v4l2_subdev_pad_ops ar0132_subdev_pad_ops = { ++ .get_edid = ar0132_get_edid, ++ .enum_mbus_code = ar0132_enum_mbus_code, ++ .get_selection = ar0132_get_selection, ++ .set_selection = ar0132_set_selection, ++ .get_fmt = ar0132_get_fmt, ++ .set_fmt = ar0132_set_fmt, ++}; ++ ++static struct v4l2_subdev_ops ar0132_subdev_ops = { ++ .core = &ar0132_core_ops, ++ .video = &ar0132_video_ops, ++ .pad = &ar0132_subdev_pad_ops, ++}; ++ ++static void ar0132_otp_id_read(struct i2c_client *client) ++{ ++} ++ ++static ssize_t ar0132_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 ar0132_priv *priv = to_ar0132(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_ar0132, S_IRUGO, ar0132_otp_id_show, NULL); ++ ++static int ar0132_initialize(struct i2c_client *client) ++{ ++ struct ar0132_priv *priv = to_ar0132(client); ++ u16 val = 0; ++ u16 pid = 0; ++ int ret = 0; ++ ++ ar0132_s_port(client, 1); ++ ++ /* check and show model ID */ ++ reg16_read16(client, AR0132_PID, &pid); ++ ++ if (pid != AR0132_VERSION_REG) { ++ dev_dbg(&client->dev, "Product ID error %x\n", pid); ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ /* Program wizard registers */ ++ ar0132_set_regs(client, ar0132_regs_wizard, ARRAY_SIZE(ar0132_regs_wizard)); ++ ++ /* Enable stream */ ++ reg16_read16(client, 0x301a, &val); // read inital reset_register value ++ val |= (1 << 2); // Set streamOn bit ++ reg16_write16(client, 0x301a, val); // Start Streaming ++ ++ /* Read OTP IDs */ ++ ar0132_otp_id_read(client); ++ ++ dev_info(&client->dev, "ar0132 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, AR0132_MAX_WIDTH, AR0132_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++err: ++ ar0132_s_port(client, 0); ++ ++ return ret; ++} ++ ++static int ar0132_parse_dt(struct device_node *np, struct ar0132_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 for AR0132\n"); ++ return -EINVAL; ++ } ++ ++ ar0132_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, AR0132_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, AR0132_I2C_ADDR << 1); /* Sensor native I2C address */ ++ ++ reg8_write(client, 0x6e, 0xa9); /* GPIO0 - reset, GPIO1 - fsin */ ++ } ++ 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, AR0132_I2C_ADDR << 1); /* Sensor native I2C address */ ++ ++ reg8_write(client, 0x6e, 0xa9); /* GPIO0 - reset, GPIO1 - fsin */ ++ } ++ client->addr = tmp_addr; ++ ++ mdelay(10); ++ ++ return 0; ++} ++ ++static int ar0132_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct ar0132_priv *priv; ++ int ret; ++ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ v4l2_i2c_subdev_init(&priv->sd, client, &ar0132_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, &ar0132_ctrl_ops, ++ V4L2_CID_BRIGHTNESS, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0132_ctrl_ops, ++ V4L2_CID_CONTRAST, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0132_ctrl_ops, ++ V4L2_CID_SATURATION, 0, 7, 1, 2); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0132_ctrl_ops, ++ V4L2_CID_HUE, 0, 23, 1, 12); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0132_ctrl_ops, ++ V4L2_CID_GAMMA, -128, 128, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0132_ctrl_ops, ++ V4L2_CID_SHARPNESS, 0, 10, 1, 3); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0132_ctrl_ops, ++ V4L2_CID_AUTOGAIN, 0, 1, 1, priv->autogain); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0132_ctrl_ops, ++ V4L2_CID_GAIN, 0, 0xffff, 1, priv->gain); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0132_ctrl_ops, ++ V4L2_CID_EXPOSURE, 0, 0xffff, 1, priv->exposure); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0132_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 1); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0132_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 = ar0132_parse_dt(client->dev.of_node, priv); ++ if (ret) ++ goto cleanup; ++ ++ ret = ar0132_initialize(client); ++ if (ret < 0) ++ goto cleanup; ++ ++ priv->rect.left = 0; ++ priv->rect.top = 0; ++ priv->rect.width = AR0132_MAX_WIDTH; ++ priv->rect.height = AR0132_MAX_HEIGHT; ++ ++ ret = v4l2_async_register_subdev(&priv->sd); ++ if (ret) ++ goto cleanup; ++ ++ if (device_create_file(&client->dev, &dev_attr_otp_id_ar0132) != 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_AR0132 ++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", ++ client->addr, client->adapter->name); ++#endif ++ return ret; ++} ++ ++static int ar0132_remove(struct i2c_client *client) ++{ ++ struct ar0132_priv *priv = i2c_get_clientdata(client); ++ ++ device_remove_file(&client->dev, &dev_attr_otp_id_ar0132); ++ 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_AR0132 ++static const struct i2c_device_id ar0132_id[] = { ++ { "ar0132", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, ar0132_id); ++ ++static const struct of_device_id ar0132_of_ids[] = { ++ { .compatible = "aptina,ar0132", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ar0132_of_ids); ++ ++static struct i2c_driver ar0132_i2c_driver = { ++ .driver = { ++ .name = "ar0132", ++ .of_match_table = ar0132_of_ids, ++ }, ++ .probe = ar0132_probe, ++ .remove = ar0132_remove, ++ .id_table = ar0132_id, ++}; ++ ++module_i2c_driver(ar0132_i2c_driver); ++ ++MODULE_DESCRIPTION("SoC Camera driver for AR0132"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); ++#endif +diff --git a/drivers/media/i2c/soc_camera/ar0132.h b/drivers/media/i2c/soc_camera/ar0132.h +new file mode 100644 +index 0000000..055841d +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ar0132.h +@@ -0,0 +1,213 @@ ++/* ++ * OmniVision ar0132 sensor camera wizard 1110x620@30/BGGR/BT601/12bit ++ * ++ * 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. ++ */ ++ ++//#define AR0132_DISPLAY_PATTERN_FIXED ++//#define AR0132_DISPLAY_PATTERN_COLOR_BAR ++ ++#define AR0132_EMBEDDED_LINE ++ ++#define AR0132_MAX_WIDTH 1665 // (1110*3/2) ++#define AR0132_MAX_HEIGHT 624 ++ ++#define AR0132_DELAY 0xffff ++ ++#define AR0132_MAX_ROI_DIM_X 1288 ++#define AR0132_MAX_ROI_DIM_Y 968 ++#define AR0132_InfoLines 4 ++ ++#define AR0132_ROI_DIM_X 1110 // 1104 ++#define AR0132_ROI_DIM_Y 620 // AR0132_MAX_HEIGHT ++ ++#define AR0132_ROI_Y_START 0x00AE ++#define AR0132_ROI_X_START 0x005C ++#define AR0132_ROI_Y_END AR0132_ROI_Y_START+AR0132_ROI_DIM_Y-1 ++#define AR0132_ROI_X_END AR0132_ROI_X_START+AR0132_ROI_DIM_X-1 ++ ++#define AR0132_FrameLength_Lines 0x029E ++#define AR0132_LineLength_Ticks 0x06B6 ++ ++#define AR0132_PLL_VT_Pix_Clk_Div 0x0008 ++#define AR0132_PLL_VT_Sys_Clk_Div 0x0001 ++#define AR0132_PLL_Pre_Clk_Div 0x0004 ++#define AR0132_PLL_Multiplier 0x003C ++ ++#define AR0132_DigitalTest 0x2002 ++ ++struct ar0132_reg { ++ u16 reg; ++ u16 val; ++}; ++ ++static const struct ar0132_reg ar0132_regs_wizard[] = { ++{0x301A, 0x0001}, // reset ++{AR0132_DELAY, 100}, ++{0x301A, 0x10D8}, // Stream off and setup parallel ++{0x3070, 0x0001}, ++{0x3070, 0x0000}, // 1: Solid color test pattern, ++ // 2: Full color bar test pattern, ++ // 3: Fade to grey color bar test pattern, ++ //256: Walking 1 test pattern (12 bit) ++#ifdef AR0132_DISPLAY_PATTERN_FIXED ++{0x3070, 0x0001}, ++{0x3072, 0x0123}, // R ++{0x3074, 0x0456}, // G(GR row) ++{0x3076, 0x0abc}, // B ++{0x3078, 0x0def}, // G(GB row) ++#endif ++#ifdef AR0132_DISPLAY_PATTERN_COLOR_BAR ++{0x3070, 0x0002}, ++#endif ++{AR0132_DELAY, 250}, ++// patch begin ++{0x3088, 0x8000}, ++{0x3086, 0x0025}, {0x3086, 0x5050}, {0x3086, 0x2D26}, {0x3086, 0x0828}, {0x3086, 0x0D17}, {0x3086, 0x0926}, {0x3086, 0x0028}, {0x3086, 0x0526}, ++{0x3086, 0xA728}, {0x3086, 0x0725}, {0x3086, 0x8080}, {0x3086, 0x2925}, {0x3086, 0x0040}, {0x3086, 0x2702}, {0x3086, 0x1616}, {0x3086, 0x2706}, ++{0x3086, 0x1736}, {0x3086, 0x26A6}, {0x3086, 0x1703}, {0x3086, 0x26A4}, {0x3086, 0x171F}, {0x3086, 0x2805}, {0x3086, 0x2620}, {0x3086, 0x2804}, ++{0x3086, 0x2520}, {0x3086, 0x2027}, {0x3086, 0x0017}, {0x3086, 0x1D25}, {0x3086, 0x0020}, {0x3086, 0x1F17}, {0x3086, 0x1028}, {0x3086, 0x0519}, ++{0x3086, 0x1703}, {0x3086, 0x2706}, {0x3086, 0x1703}, {0x3086, 0x1741}, {0x3086, 0x2660}, {0x3086, 0x17AE}, {0x3086, 0x2500}, {0x3086, 0x9027}, ++{0x3086, 0x0026}, {0x3086, 0x1828}, {0x3086, 0x002E}, {0x3086, 0x2A28}, {0x3086, 0x081C}, {0x3086, 0x1470}, {0x3086, 0x7003}, {0x3086, 0x1470}, ++{0x3086, 0x7004}, {0x3086, 0x1470}, {0x3086, 0x7005}, {0x3086, 0x1470}, {0x3086, 0x7009}, {0x3086, 0x170C}, {0x3086, 0x0014}, {0x3086, 0x0020}, ++{0x3086, 0x2300}, {0x3086, 0x1400}, {0x3086, 0x5003}, {0x3086, 0x1400}, {0x3086, 0x2003}, {0x3086, 0x1400}, {0x3086, 0x5022}, {0x3086, 0x0414}, ++{0x3086, 0x0020}, {0x3086, 0x0414}, {0x3086, 0x0050}, {0x3086, 0x0514}, {0x3086, 0x0020}, {0x3086, 0x2405}, {0x3086, 0x1400}, {0x3086, 0x5001}, ++{0x3086, 0x2550}, {0x3086, 0x502D}, {0x3086, 0x2608}, {0x3086, 0x280D}, {0x3086, 0x1709}, {0x3086, 0x2600}, {0x3086, 0x2805}, {0x3086, 0x26A7}, ++{0x3086, 0x2807}, {0x3086, 0x2580}, {0x3086, 0x8029}, {0x3086, 0x2500}, {0x3086, 0x4027}, {0x3086, 0x0216}, {0x3086, 0x1627}, {0x3086, 0x0617}, ++{0x3086, 0x3626}, {0x3086, 0xA617}, {0x3086, 0x0326}, {0x3086, 0xA417}, {0x3086, 0x1F28}, {0x3086, 0x0526}, {0x3086, 0x2028}, {0x3086, 0x0425}, ++{0x3086, 0x2020}, {0x3086, 0x2700}, {0x3086, 0x171D}, {0x3086, 0x2500}, {0x3086, 0x2020}, {0x3086, 0x1710}, {0x3086, 0x2805}, {0x3086, 0x1A17}, ++{0x3086, 0x0327}, {0x3086, 0x0617}, {0x3086, 0x0317}, {0x3086, 0x4126}, {0x3086, 0x6017}, {0x3086, 0xAE25}, {0x3086, 0x0090}, {0x3086, 0x2700}, ++{0x3086, 0x2618}, {0x3086, 0x2800}, {0x3086, 0x2E2A}, {0x3086, 0x2808}, {0x3086, 0x1D05}, {0x3086, 0x1470}, {0x3086, 0x7009}, {0x3086, 0x1720}, ++{0x3086, 0x1400}, {0x3086, 0x2024}, {0x3086, 0x1400}, {0x3086, 0x5002}, {0x3086, 0x2550}, {0x3086, 0x502D}, {0x3086, 0x2608}, {0x3086, 0x280D}, ++{0x3086, 0x1709}, {0x3086, 0x2600}, {0x3086, 0x2805}, {0x3086, 0x26A7}, {0x3086, 0x2807}, {0x3086, 0x2580}, {0x3086, 0x8029}, {0x3086, 0x2500}, ++{0x3086, 0x4027}, {0x3086, 0x0216}, {0x3086, 0x1627}, {0x3086, 0x0617}, {0x3086, 0x3626}, {0x3086, 0xA617}, {0x3086, 0x0326}, {0x3086, 0xA417}, ++{0x3086, 0x1F28}, {0x3086, 0x0526}, {0x3086, 0x2028}, {0x3086, 0x0425}, {0x3086, 0x2020}, {0x3086, 0x2700}, {0x3086, 0x171D}, {0x3086, 0x2500}, ++{0x3086, 0x2021}, {0x3086, 0x1710}, {0x3086, 0x2805}, {0x3086, 0x1B17}, {0x3086, 0x0327}, {0x3086, 0x0617}, {0x3086, 0x0317}, {0x3086, 0x4126}, ++{0x3086, 0x6017}, {0x3086, 0xAE25}, {0x3086, 0x0090}, {0x3086, 0x2700}, {0x3086, 0x2618}, {0x3086, 0x2800}, {0x3086, 0x2E2A}, {0x3086, 0x2808}, ++{0x3086, 0x1E17}, {0x3086, 0x0A05}, {0x3086, 0x1470}, {0x3086, 0x7009}, {0x3086, 0x1616}, {0x3086, 0x1616}, {0x3086, 0x1616}, {0x3086, 0x1616}, ++{0x3086, 0x1616}, {0x3086, 0x1616}, {0x3086, 0x1616}, {0x3086, 0x1616}, {0x3086, 0x1616}, {0x3086, 0x1616}, {0x3086, 0x1616}, {0x3086, 0x1616}, ++{0x3086, 0x1616}, {0x3086, 0x1616}, {0x3086, 0x1616}, {0x3086, 0x1616}, {0x3086, 0x1400}, {0x3086, 0x2024}, {0x3086, 0x1400}, {0x3086, 0x502B}, ++{0x3086, 0x302C}, {0x3086, 0x2C2C}, {0x3086, 0x2C00}, {0x3086, 0x0225}, {0x3086, 0x5050}, {0x3086, 0x2D26}, {0x3086, 0x0828}, {0x3086, 0x0D17}, ++{0x3086, 0x0926}, {0x3086, 0x0028}, {0x3086, 0x0526}, {0x3086, 0xA728}, {0x3086, 0x0725}, {0x3086, 0x8080}, {0x3086, 0x2917}, {0x3086, 0x0525}, ++{0x3086, 0x0040}, {0x3086, 0x2702}, {0x3086, 0x1616}, {0x3086, 0x2706}, {0x3086, 0x1736}, {0x3086, 0x26A6}, {0x3086, 0x1703}, {0x3086, 0x26A4}, ++{0x3086, 0x171F}, {0x3086, 0x2805}, {0x3086, 0x2620}, {0x3086, 0x2804}, {0x3086, 0x2520}, {0x3086, 0x2027}, {0x3086, 0x0017}, {0x3086, 0x1E25}, ++{0x3086, 0x0020}, {0x3086, 0x2117}, {0x3086, 0x1028}, {0x3086, 0x051B}, {0x3086, 0x1703}, {0x3086, 0x2706}, {0x3086, 0x1703}, {0x3086, 0x1747}, ++{0x3086, 0x2660}, {0x3086, 0x17AE}, {0x3086, 0x2500}, {0x3086, 0x9027}, {0x3086, 0x0026}, {0x3086, 0x1828}, {0x3086, 0x002E}, {0x3086, 0x2A28}, ++{0x3086, 0x081E}, {0x3086, 0x0831}, {0x3086, 0x1440}, {0x3086, 0x4014}, {0x3086, 0x2020}, {0x3086, 0x1410}, {0x3086, 0x1034}, {0x3086, 0x1400}, ++{0x3086, 0x1014}, {0x3086, 0x0020}, {0x3086, 0x1400}, {0x3086, 0x4013}, {0x3086, 0x1802}, {0x3086, 0x1470}, {0x3086, 0x7004}, {0x3086, 0x1470}, ++{0x3086, 0x7003}, {0x3086, 0x1470}, {0x3086, 0x7017}, {0x3086, 0x2002}, {0x3086, 0x1400}, {0x3086, 0x2002}, {0x3086, 0x1400}, {0x3086, 0x5004}, ++{0x3086, 0x1400}, {0x3086, 0x2004}, {0x3086, 0x1400}, {0x3086, 0x5022}, {0x3086, 0x0314}, {0x3086, 0x0020}, {0x3086, 0x0314}, {0x3086, 0x0050}, ++{0x3086, 0x2C2C}, {0x3086, 0x2C2C}, ++{0x309E, 0x0186}, ++{0x309E, 0x0186}, ++// patch end ++{AR0132_DELAY, 250}, ++{0x301A, 0x10D8}, // WR= RESET_REGISTER, 0x10D8 - stop streaming ++{0x3082, 0x0028}, // Set HiDy OPERATION_MODE_CTRL(A) Requested integration time ratio (T2 to T3): 8 & (T1 t0 T2): 16 ++{0x3084, 0x0028}, // Set HiDy OPERATION_MODE_CTRL(B) Requested integration time ratio (T2 to T3): 16 & (T1 t0 T2): 16 ++{0x301E, 0x00C8}, // set datapedestal to 200 to avoid clipping near saturation ++{0x3EDA, 0x0F03}, // Set vln_dac to 0x3 as recommended by Sergey ++{0x3EDE, 0xC007}, ++{0x3ED8, 0x01EF}, // Vrst_low = +1 ++{0x3EE2, 0xA46B}, ++{0x3EE0, 0x067D}, // enable anti eclipse and adjust setting for high conversion gain ++{0x3EDC, 0x0070}, // adjust anti eclipse setting for low conversion gain ++{0x3044, 0x0404}, // disable digital row noise correction and cancels TX during column correction ++{0x3EE6, 0x4303}, // Helps with column noise at low light ++{0x3EE4, 0xD208}, // enable analog row noise correction ++{0x3ED6, 0x00BD}, ++{0x3EE6, 0x8303}, // improves low light FPN ++{0x30E4, 0x6372}, // ADC settings to improve noise performance ++{0x30E2, 0x7253}, ++{0x30E0, 0x5470}, ++{0x30E6, 0xC4CC}, ++{0x30E8, 0x8050}, ++{AR0132_DELAY, 250}, ++{0x3058, 0x003F}, // WR= BLUE_GAIN, 0x003F ++{0x3014, 0}, // Fine_IT_Time(A) ++{0x3002, AR0132_ROI_Y_START}, // WR= Y_ADDR_START_(A) ++{0x3004, AR0132_ROI_X_START}, // WR= X_ADDR_START_(A) ++{0x3006, AR0132_ROI_Y_END}, // WR= Y_ADDR_END_(A) ++{0x3008, AR0132_ROI_X_END}, // WR= X_ADDR_END_(A) ++{0x300A, AR0132_FrameLength_Lines}, // WR= FRAME_LENGTH_LINES_(A) ++{0x3018, 0}, // Fine_IT_Time(B) ++{0x308C, AR0132_ROI_Y_START}, // Y_ADDR_START_(B) ++{0x308A, AR0132_ROI_X_START}, // X_ADDR_START_(B) ++{0x3090, AR0132_ROI_Y_END}, // Y_ADDR_END_(B) ++{0x308E, AR0132_ROI_X_END}, // X_ADDR_END_(B) ++{0x30AA, AR0132_FrameLength_Lines}, // FRAME_LENGTH_LINES_(B) ++{0x300C, AR0132_LineLength_Ticks}, // Line Length ++{0x301A, 0x10D8}, // Disable Streaming and setup parallel ++{0x31D0, 0x0001}, // Set to 12 bits ++{0x3028, 0x0010}, // ROW_SPEED = 16 ++{0x302A, AR0132_PLL_VT_Pix_Clk_Div}, ++{0x302C, AR0132_PLL_VT_Sys_Clk_Div}, ++{0x302E, AR0132_PLL_Pre_Clk_Div}, ++{0x3030, AR0132_PLL_Multiplier}, ++{0x3032, 0x0000}, // SCALING_MODE = 0 ++{0x3040, 0xC000}, // READ_MODE = read_mode_vert_flip | read_mode_horiz_mirror ++{0x3044, 0x0404}, // Dark Control = 1028 ++{0x30A6, 0x0001}, // Y Odd Inc. (A) = 1 ++{0x30A8, 0x0001}, // Y Odd Inc. (B) = 1 ++{0x30B0, AR0132_DigitalTest}, ++{AR0132_DELAY, 100}, ++#ifdef AR0132_EMBEDDED_LINE ++{0x3064, 0x1982}, // Embedded Data on ++#else ++{0x3064, 0x1802}, // Embedded Data off ++#endif ++{0x3100, 0x0084}, // WR= AECTRLREG, ++{0x3190, 0x6BA0}, ++{0x3194, 0x0E74}, ++{0x3196, 0x0ED8}, ++{0x3198, 0x0FA0}, ++{0x319E, 0x5040}, // resetvalue ++{0x31A2, 0x0FA0}, ++//FrontCamera Specific Section ++//Common ++#ifdef AR0132_EMBEDDED_LINE ++{0x3064, 0x1982}, ++#else ++{0x3064, 0x1802}, ++#endif ++{0x30B4, 0x0011}, ++{0x30ba, 0x0008}, ++{0x3180, 0xE000}, ++{0x3182, 0x012C}, ++{0x3190, 0x6BA0}, ++{0x3194, 0x0E74}, ++{0x3196, 0x0ED8}, ++{0x3198, 0x0FA0}, ++{0x319E, 0x5040}, ++{0x31A2, 0x0FA0}, ++//Context A:0 ++{0x3012, 0x0021}, ++{0x3014, 0x0000}, ++{0x30A6, 0x0001}, ++{0x3056, 0x0008}, ++{0x3058, 0x0008}, ++{0x305A, 0x0008}, ++{0x305C, 0x0008}, ++{0x305E, 0x0008}, ++{0x3082, 0x0014}, ++//Context B:0 ++{0x3016, 0x007F}, ++{0x3018, 0x0000}, ++{0x30A8, 0x0001}, ++{0x30BC, 0x0020}, ++{0x30BE, 0x0020}, ++{0x30C0, 0x0020}, ++{0x30C2, 0x0020}, ++{0x30C4, 0x0020}, ++{0x3084, 0x0028}, ++//not covered ++{0x301E, 0x00C8}, ++{0x3044, 0x0404}, ++{0x31D0, 0x0001}, ++{0x30B0, 0x2002}, ++}; +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..91223a0 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/max9286_max9271.c +@@ -0,0 +1,607 @@ ++/* ++ * 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/notifier.h> ++#include <linux/of_gpio.h> ++#include <linux/regulator/consumer.h> ++#include <linux/videodev2.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]; ++ struct regulator *poc_supply[4]; /* PoC power supply */ ++}; ++ ++static int force_conf_link; ++static int force_poc_trig; ++#ifndef MODULE ++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 __init int max9286_max9271_force_poc_trig(char *str) ++{ ++ /* force PoC triggering during reverse channel setup */ ++ /* to be used on systems with dedicated PoC and unstable ser-des lock */ ++ force_poc_trig = 1; ++ return 0; ++} ++early_param("force_poc_trig", max9286_max9271_force_poc_trig); ++#endif ++ ++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_sensor_reset(struct i2c_client *client, int addr, int reset_on) ++{ ++ struct max9286_max9271_priv *priv = i2c_get_clientdata(client); ++ ++ if (priv->gpio_resetb < 1 || priv->gpio_resetb > 5) ++ return; ++ ++ /* sensor reset/unreset */ ++ client->addr = addr; /* MAX9271-CAMx I2C */ ++ reg8_write(client, 0x0f, (0xfe & ~BIT(priv->gpio_resetb)) | /* set GPIOn value to reset/unreset */ ++ ((priv->active_low_resetb ? BIT(priv->gpio_resetb) : 0) ^ reset_on)); ++ reg8_write(client, 0x0e, 0x42 | BIT(priv->gpio_resetb)); /* set GPIOn direction output */ ++} ++ ++static void max9286_max9271_postinit(struct i2c_client *client, int addr) ++{ ++ struct max9286_max9271_priv *priv = i2c_get_clientdata(client); ++ int idx; ++ ++ for (idx = 0; idx < priv->links; idx++) { ++ 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 I2C */ ++ max9286_max9271_sensor_reset(client, client->addr, 0); /* sensor unreset */ ++ } ++ ++ 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 */ ++} ++ ++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; ++ char timeout_str[10]; ++ 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, 0x04, 0x43); /* wake-up, enable reverse_control/conf_link */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ reg8_write(client, 0x08, 0x1); /* reverse channel receiver high threshold enable */ ++ reg8_write(client, 0x97, 0x5f); /* enable reverse control channel programming (MAX96705-MAX96711 only) */ ++ 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_read(client, 0x1e, &val); /* read max9271 ID */ ++ if (val == MAX9271_ID || val == MAX96705_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 || val == MAX96705_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 == priv->timeout / 2 && force_poc_trig) { ++ if (!IS_ERR(priv->poc_supply[idx])) { ++ if (regulator_disable(priv->poc_supply[idx])) ++ dev_err(&client->dev, "fail to disable POC%d regulator\n", idx); ++ mdelay(200); ++ if (regulator_enable(priv->poc_supply[idx])) ++ dev_err(&client->dev, "fail to enable POC%d regulator\n", idx); ++ } ++ } ++ } ++ ++ max9286_max9271_sensor_reset(client, client->addr, 1); /* sensor reset */ ++ ++ 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: ++ sprintf(timeout_str, "retries=%d", priv->timeout - timeout); ++ dev_info(&client->dev, "link%d MAX9271 %sat 0x%x %s %s\n", idx, ++ ret == -EADDRINUSE ? "already " : "", priv->max9271_addr_map[idx], ++ ret == -ETIMEDOUT ? "not found: timeout GMSL link establish" : "", ++ priv->timeout - timeout? timeout_str : ""); ++ ++ 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 ++} ++ ++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++) { ++ if (!IS_ERR(priv->poc_supply[idx])) { ++ if (regulator_enable(priv->poc_supply[idx])) ++ dev_err(&client->dev, "fail to enable POC%d regulator\n", 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); ++ } ++ ++ 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; ++ char supply_name[10]; ++ ++ 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; ++ ++ for (i = 0; i < 4; i++) { ++ sprintf(supply_name, "POC%d", i); ++ priv->poc_supply[i] = devm_regulator_get_optional(&client->dev, supply_name); ++ } ++ ++ 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..6c2a9e0 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/max9286_max9271.h +@@ -0,0 +1,244 @@ ++/* ++ * 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 MAX96705_ID 0x41 ++#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; ++} ++ ++ ++static inline int reg16_read16(struct i2c_client *client, u16 reg, u16 *val) ++{ ++ int ret, retries; ++ u8 buf[2] = {reg >> 8, reg & 0xff}; ++ ++ for (retries = REG8_NUM_RETRIES; retries; retries--) { ++ ret = i2c_master_send(client, buf, 2); ++ if (ret == 2) { ++ ret = i2c_master_recv(client, buf, 2); ++ if (ret == 2) ++ break; ++ } ++ } ++ ++ if (ret < 0) { ++ dev_err(&client->dev, ++ "read fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } else { ++ *val = ((u16)buf[0] << 8) | buf[1]; ++ } ++ ++ return ret < 0 ? ret : 0; ++} ++ ++static inline int reg16_write16(struct i2c_client *client, u16 reg, u16 val) ++{ ++ int ret, retries; ++ u8 buf[4] = {reg >> 8, reg & 0xff, val >> 8, val & 0xff}; ++ ++ for (retries = REG8_NUM_RETRIES; retries; retries--) { ++ ret = i2c_master_send(client, buf, 4); ++ if (ret == 4) ++ break; ++ } ++ ++ if (ret < 0) { ++ dev_err(&client->dev, ++ "write fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } ++ ++ 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..6296647 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov10635.c +@@ -0,0 +1,758 @@ ++/* ++ * 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; ++ case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: ++ ret = 0; ++ 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 for OV10635\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 */ ++ } ++ ++ 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 */ ++ } ++ client->addr = tmp_addr; ++ ++ udelay(100); ++ ++ return 0; ++} ++ ++static int ov10635_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct ov10635_priv *priv; ++ struct v4l2_ctrl *ctrl; ++ 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); ++ ctrl = v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 9); ++ if (ctrl) ++ ctrl->flags &= ~V4L2_CTRL_FLAG_READ_ONLY; ++ 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..a0e510d +--- /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, (0x0d+2*0x20+0x15+38) >> 8}, ++{0x3833, (0x0d+2*0x20+0x15+38) & 0xff}, ++{0x3834, OV10635_VTS >> 8}, ++{0x3835, OV10635_VTS & 0xff}, ++{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..f2bb706 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov106xx.c +@@ -0,0 +1,106 @@ ++/* ++ * 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" ++#include "ar0132.c" ++ ++static enum { ++ ID_OV10635, ++ ID_OV490_OV10640, ++ ID_OV495_OV2775, ++ ID_AR0132, ++} 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; ++ } ++ ++ ret = ar0132_probe(client, did); ++ if (!ret) { ++ chip_id = ID_AR0132; ++ 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; ++ case ID_AR0132: ++ ar0132_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 or AR0132"); ++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..813c08e +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov490_ov10640.c +@@ -0,0 +1,1092 @@ ++/* ++ * 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_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 active_low_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 void ov490_reset(struct i2c_client *client) ++{ ++ struct ov490_priv *priv = to_ov490(client); ++ int tmp_addr; ++ ++ if (priv->max9286_addr) { ++ if (priv->gpio_resetb < 1 || priv->gpio_resetb > 5) ++ return; ++ ++ tmp_addr = client->addr; ++ /* get out from sensor reset */ ++ client->addr = priv->max9271_addr; /* MAX9271 I2C address */ ++ reg8_write(client, 0x0f, (0xfe & ~BIT(priv->gpio_resetb)) | ++ (priv->active_low_resetb ? 0 : BIT(priv->gpio_resetb))); /* set GPIOn value to reset */ ++ 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 */ ++ client->addr = tmp_addr; ++ } ++ ++ if (priv->ti964_addr) { ++ client->addr = priv->ti964_addr; /* TI964 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, 0x6e, 0x8a); /* set GPIO1 value to reset */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x6e, 0x9a); /* set GPIO1 value to un-reset */ ++ } ++ ++ if (priv->ti954_addr) { ++ client->addr = priv->ti954_addr; /* TI964 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, 0x6e, 0x8a); /* set GPIO1 value to reset */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x6e, 0x9a); /* set GPIO1 value to un-reset */ ++ } ++} ++ ++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 u8 ov490_ov10640_read(struct i2c_client *client, u16 addr) ++{ ++ u8 reg_val = 0; ++ ++ 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, 0x01); /* read operation */ ++ reg16_write(client, 0x5001, addr >> 8); ++ reg16_write(client, 0x5002, addr & 0xff); ++ 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, ®_val); ++ ++ return reg_val; ++} ++ ++static void ov490_ov10640_write(struct i2c_client *client, u16 addr, u8 val) ++{ ++ 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 operation */ ++ reg16_write(client, 0x5001, addr >> 8); ++ reg16_write(client, 0x5002, addr & 0xff); ++ reg16_write(client, 0x5003, val); ++ reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x00C0, 0xc1); ++} ++ ++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; ++ case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: ++ ret = 0; ++ 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; ++ int otp_bank0_allzero = 1; ++ ++#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 */ ++ ov490_ov10640_write(client, 0x349C, 1); ++ usleep_range(25000, 25500); /* wait 25 ms */ ++ ++ for (i = 0; i < 6; i++) { ++ /* first 6 bytes are equal on all ov10640 */ ++ priv->id[i] = ov490_ov10640_read(client, 0x349e + i + 6); ++ if (priv->id[i]) ++ otp_bank0_allzero = 0; ++ } ++ ++ if (otp_bank0_allzero) { ++ ov490_ov10640_write(client, 0x3495, 0x41); /* bank#1 */ ++ ov490_ov10640_write(client, 0x349C, 1); ++ usleep_range(25000, 25500); /* wait 25 ms */ ++ ++ for (i = 0; i < 6; i++) ++ priv->id[i] = ov490_ov10640_read(client, 0x34ae + 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; ++ int ret = 0, timeout, retry_timeout = 3; ++ ++ 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); ++ ++ 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; ++ ++again: ++ /* Check if firmware booted by reading stream-on status */ ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x29); ++ usleep_range(100, 150); /* wait 100 us */ ++ for (timeout = 300; timeout > 0; timeout--) { ++ reg16_read(client, 0xd000, &val); ++ if (val == 0x0c) ++ break; ++ mdelay(1); ++ } ++ ++ /* wait firmware apps started by reading OV10640 ID */ ++ for (;timeout > 0; timeout--) { ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x5000, 0x01); ++ reg16_write(client, 0x5001, 0x30); ++ reg16_write(client, 0x5002, 0x0a); ++ reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0xC0, 0xc1); ++ reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(1000, 1500); /* wait 1 ms */ ++ reg16_read(client, 0x5000, &val); ++ if (val == 0xa6) ++ break; ++ mdelay(1); ++ } ++ ++ if (!timeout) { ++ dev_err(&client->dev, "Timeout firmware boot wait, retrying\n"); ++ /* reset OV10640 using RESETB pin controlled by OV490 GPIO0 */ ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x0050, 0x01); ++ reg16_write(client, 0x0054, 0x01); ++ reg16_write(client, 0x0058, 0x00); ++ mdelay(10); ++ reg16_write(client, 0x0058, 0x01); ++ /* reset OV490 using RESETB pin controlled by serializer */ ++ ov490_reset(client); ++ if (retry_timeout--) ++ goto again; ++ } ++ ++ /* 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 PID %x%x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, ver, 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)) { ++ if (of_property_read_u32(rendpoint->parent->parent, "maxim,resetb-gpio", &priv->gpio_resetb)) { ++ priv->gpio_resetb = -1; ++ } else { ++ if (of_property_read_bool(rendpoint->parent->parent, "maxim,resetb-active-high")) ++ priv->active_low_resetb = false; ++ else ++ priv->active_low_resetb = true; ++ } ++ 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 for OV490\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 */ ++ } ++ 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 */ ++ } ++ 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; ++ struct v4l2_ctrl *ctrl; ++ 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); ++ ctrl = v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 9); ++ if (ctrl) ++ ctrl->flags &= ~V4L2_CTRL_FLAG_READ_ONLY; ++ 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..8c9ecf1 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov490_ov10640.h +@@ -0,0 +1,93 @@ ++/* ++ * 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}, ++/* ov490 EMB line disable in YUV and RAW data, NOTE: EMB line is still used in ISP and sensor */ ++{0xe000, 0x14}, ++#if 0 /* do not disable EMB line in ISP! */ ++{0x4017, 0x00}, ++#endif ++{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 ++/* ov10640 EMB line disable */ ++#if 0 /* do not disable EMB line in sensor! */ ++{0xfffe, 0x19}, ++{0x5000, 0x00}, ++{0x5001, 0x30}, ++{0x5002, 0x91}, ++{0x5003, 0x08}, ++{0xfffe, 0x80}, ++{0x00c0, 0xc1}, ++#endif ++/* Ov490 FSIN: app_fsin_from_fsync */ ++{0xfffe, 0x85}, ++{0x0008, 0x00}, ++{0x0009, 0x01}, ++{0x000A, 0x05}, // fsin0 src ++{0x000B, 0x00}, ++{0x0030, 0x02}, // fsin0_delay ++{0x0031, 0x00}, ++{0x0032, 0x00}, ++{0x0033, 0x00}, ++{0x0038, 0x02}, // fsin1_delay ++{0x0039, 0x00}, ++{0x003A, 0x00}, ++{0x003B, 0x00}, ++{0x0070, 0x2C}, // fsin0_length ++{0x0071, 0x01}, ++{0x0072, 0x00}, ++{0x0073, 0x00}, ++{0x0074, 0x64}, // fsin1_length ++{0x0075, 0x00}, ++{0x0076, 0x00}, ++{0x0077, 0x00}, ++{0x0000, 0x14}, ++{0x0001, 0x00}, ++{0x0002, 0x00}, ++{0x0003, 0x00}, ++{0x0004, 0x32}, // load fsin0,load fsin1,load other, it will be cleared automatically. ++{0x0005, 0x00}, ++{0x0006, 0x00}, ++{0x0007, 0x00}, ++{0xfffe, 0x80}, ++{0x0081, 0x00}, // 03;SENSOR FSIN ++/* ov10640 FSIN */ ++{0xfffe, 0x19}, ++{0x5000, 0x00}, ++{0x5001, 0x30}, ++{0x5002, 0x8c}, ++{0x5003, 0xb2}, ++{0xfffe, 0x80}, ++{0x00c0, 0xc1}, ++/* ov10640 HFLIP=1 by default */ ++{0xfffe, 0x19}, ++{0x5000, 0x01}, ++{0x5001, 0x00}, ++{0xfffe, 0x80}, ++{0x00c0, 0xdc}, ++}; +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..6dc0675 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov495_ov2775.c +@@ -0,0 +1,658 @@ ++/* ++ * 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_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; ++ /* 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; ++ case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: ++ ret = 0; ++ 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) ++{ ++ struct ov495_priv *priv = to_ov495(client); ++ int i; ++ ++#if 0 ++ /* read camera id from ov495 OTP memory */ ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x20); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x7384, 0x40); /* manual mode, bank#0 */ ++ reg16_write(client, 0x7381, 1); /* start OTP read */ ++ ++ usleep_range(25000, 26000); /* wait 25 ms */ ++ ++ for (i = 0; i < 6; i++) ++ reg16_read(client, 0x7300 + i + 4, &priv->id[i]); ++#else ++ /* read camera id from ov2775 OTP memory */ ++ reg16_write(client, 0x3516, 0x00); /* unlock write */ ++ reg16_write(client, 0x0FFC, 0); ++ reg16_write(client, 0x0500, 0x00); /* write 0x34a1 -> 1 */ ++ reg16_write(client, 0x0501, 0x34); ++ reg16_write(client, 0x0502, 0xa1); ++ reg16_write(client, 0x0503, 1); ++ reg16_write(client, 0x30C0, 0xc1); ++ ++ usleep_range(25000, 25500); /* wait 25 ms */ ++ ++ for (i = 0; i < 6; i++) { ++ reg16_write(client, 0x3516, 0x00); /* unlock write */ ++ reg16_write(client, 0x0500, 0x01); /* read (0x7a00 + i) */ ++ reg16_write(client, 0x0501, 0x7a); ++ reg16_write(client, 0x0502, 0x00 + i + (i < 3 ? 11 : 3)); /* take bytes 11,12,13,6,7,8 */ ++ reg16_write(client, 0x30C0, 0xc1); ++ usleep_range(1000, 1500); /* wait 1 ms */ ++ reg16_read(client, 0x0500, &priv->id[i]); ++ } ++#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; ++ 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); ++ ++ 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 */ ++ ov495_regs_wizard[3].val = 0x1e | (priv->port << 6); ++ /* 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 PID %x%x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, ver, 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); ++ ++ 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 for OV495\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; ++ struct v4l2_ctrl *ctrl; ++ 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); ++ ctrl = v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 9); ++ if (ctrl) ++ ctrl->flags &= ~V4L2_CTRL_FLAG_READ_ONLY; ++ 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..3f53689 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov495_ov2775.h +@@ -0,0 +1,23 @@ ++/* ++ * 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 struct ov495_reg ov495_regs_wizard[] = { ++{0x3516, 0x00}, /* unlock write */ ++{0xFFFD, 0x80}, ++{0xFFFE, 0x20}, ++{0x8017, 0x1e | (0 << 6)}, ++{0x7c10, 0x01}, /* UYVY */ ++}; +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..1672173 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ti954_ti9x3.c +@@ -0,0 +1,431 @@ ++/* ++ * 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/notifier.h> ++#include <linux/of_gpio.h> ++#include <linux/regulator/consumer.h> ++#include <linux/videodev2.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]; ++ struct regulator *poc_supply[4]; /* PoC power supply */ ++ 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 0 ++ /* FrameSync setup for REFCLK=25MHz, FPS=30: period_counts=1/2/FPS*25MHz =1/2/30*25Mhz =416666 -> FS_TIME=416666 */ ++ /* FrameSync setup for REFCLK=22.5MHz, FPS=30: period_counts=1/2/FPS*22.5Mhz=1/2/30*22.5Mhz=375000 -> FS_TIME=375000 */ ++// #define FS_TIME (priv->csi_rate == 1450 ? 376000 : 417666) ++ #define FS_TIME (priv->csi_rate == 1450 ? 385000 : 428000) // FPS=29.2 (new vendor's firmware AWB restriction?) ++ 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 REFCLK=25MHz, FPS=30: period_counts=1/FPS/12mks=1/30/12e-6=2777 -> HI=2, LO=2775 */ ++ /* FrameSync setup for REFCLK=22.5MHz, FPS=30: period_counts=1/FPS/13.333mks=1/30/13.333e-6=2500 -> HI=2, LO=2498 */ ++ #define FS_TIME (priv->csi_rate == 1450 ? (2498+15) : (2775+15)) ++ reg8_write(client, 0x19, 2 >> 8); /* FrameSync high time MSB */ ++ reg8_write(client, 0x1a, 2 & 0xff); /* FrameSync high time LSB */ ++ reg8_write(client, 0x1b, FS_TIME >> 8); /* FrameSync low time MSB */ ++ reg8_write(client, 0x1c, FS_TIME & 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, 0x88); /* Sensor reset: backchannel GPIO0/GPIO1 set low */ ++} ++ ++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++) { ++ if (!IS_ERR(priv->poc_supply[idx])) { ++ if (regulator_enable(priv->poc_supply[idx])) ++ dev_err(&client->dev, "fail to enable POC%d regulator\n", 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 = devm_gpio_request_one(&client->dev, 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; ++ char supply_name[10]; ++ ++ 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; ++ ++ for (i = 0; i < 4; i++) { ++ sprintf(supply_name, "POC%d", i); ++ priv->poc_supply[i] = devm_regulator_get_optional(&client->dev, supply_name); ++ } ++ ++ 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..770d306 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ti964_ti9x3.c +@@ -0,0 +1,399 @@ ++/* ++ * 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/notifier.h> ++#include <linux/of_gpio.h> ++#include <linux/regulator/consumer.h> ++#include <linux/videodev2.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]; ++ struct regulator *poc_supply[4]; /* PoC power supply */ ++}; ++ ++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 0 ++ /* FrameSync setup for REFCLK=25MHz, FPS=30: period_counts=1/2/FPS*25MHz =1/2/30*25Mhz =416666 -> FS_TIME=416666 */ ++ /* FrameSync setup for REFCLK=22.5MHz, FPS=30: period_counts=1/2/FPS*22.5Mhz=1/2/30*22.5Mhz=375000 -> FS_TIME=375000 */ ++// #define FS_TIME (priv->csi_rate == 1450 ? 376000 : 417666) ++ #define FS_TIME (priv->csi_rate == 1450 ? 385000 : 428000) // FPS=29.2 (new vendor's firmware AWB restriction?) ++ 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 REFCLK=25MHz, FPS=30: period_counts=1/FPS/12mks=1/30/12e-6=2777 -> HI=2, LO=2775 */ ++ /* FrameSync setup for REFCLK=22.5MHz, FPS=30: period_counts=1/FPS/13.333mks=1/30/13.333e-6=2500 -> HI=2, LO=2498 */ ++ #define FS_TIME (priv->csi_rate == 1450 ? (2498+15) : (2775+15)) ++ reg8_write(client, 0x19, 2 >> 8); /* FrameSync high time MSB */ ++ reg8_write(client, 0x1a, 2 & 0xff); /* FrameSync high time LSB */ ++ reg8_write(client, 0x1b, FS_TIME >> 8); /* FrameSync low time MSB */ ++ reg8_write(client, 0x1c, FS_TIME & 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, 0x88); /* Sensor reset: backchannel GPIO0/GPIO1 set low */ ++} ++ ++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++) { ++ if (!IS_ERR(priv->poc_supply[idx])) { ++ if (regulator_enable(priv->poc_supply[idx])) ++ dev_err(&client->dev, "fail to enable POC%d regulator\n", 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 = devm_gpio_request_one(&client->dev, 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; ++ char supply_name[10]; ++ ++ 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; ++ ++ for (i = 0; i < 4; i++) { ++ sprintf(supply_name, "POC%d", i); ++ priv->poc_supply[i] = devm_regulator_get_optional(&client->dev, supply_name); ++ } ++ ++ 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..69d3728 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ti9x4_ti9x3.h +@@ -0,0 +1,153 @@ ++/* ++ * 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; ++} ++ ++static inline int reg16_read16(struct i2c_client *client, u16 reg, u16 *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, 2); ++ if (ret == 2) ++ break; ++ } ++ } ++ ++ if (ret < 0) { ++ dev_err(&client->dev, ++ "read fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } else { ++ *val = ((u16)buf[0] << 8) | buf[1]; ++ } ++ ++ return ret < 0 ? ret : 0; ++} ++ ++static inline int reg16_write16(struct i2c_client *client, u16 reg, u16 val) ++{ ++ int ret, retries; ++ u8 buf[4] = {reg >> 8, reg & 0xff, val >> 8, val & 0xff}; ++ ++ for (retries = MAXIM_NUM_RETRIES; retries; retries--) { ++ ret = i2c_master_send(client, buf, 4); ++ if (ret == 4) ++ break; ++ } ++ ++ if (ret < 0) { ++ dev_err(&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 4d95da6..2ef27e8 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 + +@@ -70,6 +72,10 @@ + #define RCAR_CSI2_PHCLM 0x78 + #define RCAR_CSI2_PHDLM 0x7C + ++#define RCAR_CSI2_CSI0CLKFCPR 0x254 /* CSI0CLK Frequency Configuration Preset */ ++/* CSI0CLK frequency configuration bit */ ++#define CSI0CLKFREQRANGE(n) ((n & 0x3f) << 16) ++ + #define RCAR_CSI2_PHYCNT_SHUTDOWNZ (1 << 17) + #define RCAR_CSI2_PHYCNT_RSTZ (1 << 16) + #define RCAR_CSI2_PHYCNT_ENABLECLK (1 << 4) +@@ -106,6 +112,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 */ +@@ -159,6 +168,11 @@ + { } + }; + ++static const struct soc_device_attribute r8a7795[] = { ++ { .soc_id = "r8a7795", .revision = "ES2.0" }, ++ { } ++}; ++ + enum chip_id { + RCAR_GEN3, + RCAR_GEN2, +@@ -179,6 +193,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 +207,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 +219,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 +267,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) + { +@@ -265,7 +364,7 @@ static int rcar_csi2_set_phy_freq(struct rcar_csi2 *priv) + 0x16, 0x36, 0x56, 0x76, 0x18, /* 1150M, 1200M, 1250M, 1300M, 1350M */ + 0x38, 0x58, 0x78 /* 1400M, 1450M, 1500M */ + }; +- const uint32_t const hs_freq_range[43] = { ++ const uint32_t const hs_freq_range_m3[43] = { + 0x00, 0x10, 0x20, 0x30, 0x01, /* 0-4 */ + 0x11, 0x21, 0x31, 0x02, 0x12, /* 5-9 */ + 0x22, 0x32, 0x03, 0x13, 0x23, /* 10-14 */ +@@ -276,47 +375,33 @@ 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 hs_freq_range_h3[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, 0x25, 0x35, /* 15-19 */ ++ 0x05, 0x26, 0x36, 0x37, 0x07, /* 20-24 */ ++ 0x18, 0x28, 0x39, 0x09, 0x19, /* 25-29 */ ++ 0x29, 0x3A, 0x0A, 0x1A, 0x2A, /* 30-34 */ ++ 0x3B, 0x0B, 0x1B, 0x2B, 0x3C, /* 35-39 */ ++ 0x0C, 0x1C, 0x2C /* 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); +@@ -325,16 +410,14 @@ static int rcar_csi2_set_phy_freq(struct rcar_csi2 *priv) + iowrite32((hs_freq_range_v3m[bps_per_lane] << 16) | + RCAR_CSI2_PHTW_DWEN | RCAR_CSI2_PHTW_CWEN | 0x44, + priv->base + RCAR_CSI2_PHTW); ++ else if (soc_device_match(r8a7795)) ++ iowrite32(hs_freq_range_h3[bps_per_lane] << 16, ++ priv->base + RCAR_CSI2_PHYPLL); + else +- iowrite32(hs_freq_range[bps_per_lane] << 16, ++ /* h3 ws1.x is similar to m3 */ ++ iowrite32(hs_freq_range_m3[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 +475,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); +@@ -404,11 +497,27 @@ static int rcar_csi2_hwinit(struct rcar_csi2 *priv) + return -EINVAL; + } + ++ if (soc_device_match(r8a7795)) { ++ /* Set PHY Test Interface Write Register in R-Car H3(ES2.0) */ ++ iowrite32(0x01cc01e2, priv->base + RCAR_CSI2_PHTW); ++ iowrite32(0x010101e3, priv->base + RCAR_CSI2_PHTW); ++ iowrite32(0x010101e4, priv->base + RCAR_CSI2_PHTW); ++ iowrite32(0x01100104, priv->base + RCAR_CSI2_PHTW); ++ iowrite32(0x01030100, priv->base + RCAR_CSI2_PHTW); ++ iowrite32(0x01800107, priv->base + RCAR_CSI2_PHTW); ++ } ++ + /* set PHY frequency */ + ret = rcar_csi2_set_phy_freq(priv); + if (ret < 0) + return ret; + ++ /* Set CSI0CLK Frequency Configuration Preset Register ++ * in R-Car H3(ES2.0) ++ */ ++ if (soc_device_match(r8a7795)) ++ iowrite32(CSI0CLKFREQRANGE(32), priv->base + RCAR_CSI2_CSI0CLKFCPR); ++ + /* Enable lanes */ + iowrite32(tmp, priv->base + RCAR_CSI2_PHYCNT); + +@@ -469,32 +578,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 +642,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 +673,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 +689,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 +712,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 +723,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 +755,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 +788,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..496a8bd 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,10 @@ 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: ++ case MEDIA_BUS_FMT_SBGGR12_1X12: ++ vnmc |= VNMC_INF_RAW8 | VNMC_BPS; ++ break; + default: + break; + } +@@ -1021,6 +1031,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 +1057,10 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) + + dmr = VNDMR_EXRGB | VNDMR_DTMD_ARGB; + break; ++ case V4L2_PIX_FMT_SBGGR8: ++ case V4L2_PIX_FMT_SBGGR12: ++ dmr = 0; ++ break; + default: + goto e_format; + } +@@ -1061,7 +1079,9 @@ 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) && ++ (icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_SBGGR12) + && is_scaling(cam)) + vnmc |= VNMC_SCLE; + } +@@ -1211,6 +1231,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 +1385,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 +1424,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 +1440,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 +1479,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 +1506,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 +1686,19 @@ 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) && ++ (icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_SBGGR12) + && 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) || ++ (icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_SBGGR12)) ++ 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 +1939,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 +1978,22 @@ 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, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_SBGGR12, ++ .name = "Bayer 12 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 +2107,8 @@ 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: ++ case MEDIA_BUS_FMT_SBGGR12_1X12: + if (cam->extra_fmt) + break; + +@@ -2218,12 +2315,15 @@ 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: ++ case V4L2_PIX_FMT_SBGGR12: + default: + can_scale = false; + break; +@@ -2316,7 +2416,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 +2587,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 +2618,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 +2639,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 +2829,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 +2860,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 +2932,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 +3117,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-media-i2c-Add-ov5647-sensor.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0031-media-i2c-Add-ov5647-sensor.patch new file mode 100644 index 0000000..1cd366c --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0031-media-i2c-Add-ov5647-sensor.patch @@ -0,0 +1,952 @@ +From 8b97232e3ecbb4ee38bda454915e62914ef52fcc Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Thu, 1 Jun 2017 19:59:56 +0300 +Subject: [PATCH] media: i2c: Add ov5647 sensor + +Add ov5647 camera sensor driver + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + drivers/media/i2c/soc_camera/Kconfig | 6 + + drivers/media/i2c/soc_camera/Makefile | 1 + + drivers/media/i2c/soc_camera/ov5647.c | 649 ++++++++++++++++++++++++++++++++++ + drivers/media/i2c/soc_camera/ov5647.h | 242 +++++++++++++ + 4 files changed, 898 insertions(+) + create mode 100644 drivers/media/i2c/soc_camera/ov5647.c + create mode 100644 drivers/media/i2c/soc_camera/ov5647.h + +diff --git a/drivers/media/i2c/soc_camera/Kconfig b/drivers/media/i2c/soc_camera/Kconfig +index e1c65ca..c272aeb 100644 +--- a/drivers/media/i2c/soc_camera/Kconfig ++++ b/drivers/media/i2c/soc_camera/Kconfig +@@ -97,6 +97,12 @@ config SOC_CAMERA_OV5642 + help + This is a V4L2 camera driver for the OmniVision OV5642 sensor + ++config SOC_CAMERA_OV5647 ++ tristate "ov5647 camera support" ++ depends on SOC_CAMERA && I2C ++ help ++ This is a V4L2 camera driver for the OmniVision OV5647 sensor ++ + config SOC_CAMERA_OV6650 + tristate "ov6650 sensor support" + depends on SOC_CAMERA && I2C +diff --git a/drivers/media/i2c/soc_camera/Makefile b/drivers/media/i2c/soc_camera/Makefile +index 8e24d5d..a67fff8 100644 +--- a/drivers/media/i2c/soc_camera/Makefile ++++ b/drivers/media/i2c/soc_camera/Makefile +@@ -13,6 +13,7 @@ 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_OV5647) += ov5647.o + obj-$(CONFIG_SOC_CAMERA_OV6650) += ov6650.o + obj-$(CONFIG_SOC_CAMERA_OV772X) += ov772x.o + obj-$(CONFIG_SOC_CAMERA_OV9640) += ov9640.o +diff --git a/drivers/media/i2c/soc_camera/ov5647.c b/drivers/media/i2c/soc_camera/ov5647.c +new file mode 100644 +index 0000000..caccf39 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov5647.c +@@ -0,0 +1,649 @@ ++/* ++ * V4L2 driver for OmniVision OV5647 cameras. ++ * ++ * Based on Samsung S5K6AAFX SXGA 1/6" 1.3M CMOS Image Sensor driver ++ * Copyright (C) 2011 Sylwester Nawrocki <s.nawrocki@samsung.com> ++ * ++ * Based on Omnivision OV7670 Camera Driver ++ * Copyright (C) 2006-7 Jonathan Corbet <corbet@lwn.net> ++ * ++ * Copyright (C) 2016, Synopsys, Inc. ++ * ++ * Copyright (C) 2017 Cogent Embedded, Inc ++ */ ++ ++#include <linux/init.h> ++#include <linux/module.h> ++#include <linux/slab.h> ++#include <linux/i2c.h> ++#include <linux/delay.h> ++#include <linux/videodev2.h> ++#include <media/v4l2-device.h> ++#include <media/v4l2-ctrls.h> ++#include <media/v4l2-mediabus.h> ++#include <media/v4l2-image-sizes.h> ++#include <media/v4l2-of.h> ++#include <linux/io.h> ++ ++#include "ov5647.h" ++ ++static bool debug = true; ++module_param(debug, bool, 0644); ++MODULE_PARM_DESC(debug, "Debug level (0-1)"); ++ ++#define OV5647_I2C_ADDR 0x6c ++#define SENSOR_NAME "ov5647" ++ ++#define OV5647_REG_CHIPID_H 0x300A ++#define OV5647_REG_CHIPID_L 0x300B ++ ++#define REG_TERM 0xfffe ++#define VAL_TERM 0xfe ++#define REG_DLY 0xffff ++ ++/*define the voltage level of control signal*/ ++#define CSI_STBY_ON 1 ++#define CSI_STBY_OFF 0 ++#define CSI_RST_ON 0 ++#define CSI_RST_OFF 1 ++#define CSI_PWR_ON 1 ++#define CSI_PWR_OFF 0 ++#define CSI_AF_PWR_ON 1 ++#define CSI_AF_PWR_OFF 0 ++ ++#define OV5647_ROW_START 0x01 ++#define OV5647_ROW_START_MIN 0 ++#define OV5647_ROW_START_MAX 2004 ++#define OV5647_ROW_START_DEF 54 ++ ++#define OV5647_COLUMN_START 0x02 ++#define OV5647_COLUMN_START_MIN 0 ++#define OV5647_COLUMN_START_MAX 2750 ++#define OV5647_COLUMN_START_DEF 16 ++ ++#define OV5647_WINDOW_HEIGHT 0x03 ++#define OV5647_WINDOW_HEIGHT_MIN 2 ++#define OV5647_WINDOW_HEIGHT_MAX 2006 ++#define OV5647_WINDOW_HEIGHT_DEF 1944 ++ ++#define OV5647_WINDOW_WIDTH 0x04 ++#define OV5647_WINDOW_WIDTH_MIN 2 ++#define OV5647_WINDOW_WIDTH_MAX 2752 ++#define OV5647_WINDOW_WIDTH_DEF 2592 ++ ++enum power_seq_cmd { ++ CSI_SUBDEV_PWR_OFF = 0x00, ++ CSI_SUBDEV_PWR_ON = 0x01, ++}; ++ ++struct sensor_format_struct { ++ __u8 *desc; ++ u32 mbus_code; ++ enum v4l2_colorspace colorspace; ++ struct regval_list *regs; ++ int regs_size; ++ int bpp; ++}; ++ ++struct cfg_array { ++ struct regval_list *regs; ++ int size; ++}; ++ ++struct sensor_win_size { ++ int width; ++ int height; ++ unsigned int hoffset; ++ unsigned int voffset; ++ unsigned int hts; ++ unsigned int vts; ++ unsigned int pclk; ++ unsigned int mipi_bps; ++ unsigned int fps_fixed; ++ unsigned int bin_factor; ++ unsigned int intg_min; ++ unsigned int intg_max; ++ void *regs; ++ int regs_size; ++ int (*set_size)(struct v4l2_subdev *subdev); ++}; ++ ++struct ov5647 { ++ struct device *dev; ++ struct v4l2_subdev subdev; ++ struct media_pad pad; ++ struct mutex lock; ++ struct v4l2_mbus_framefmt format; ++ struct sensor_format_struct *fmt; ++ unsigned int width; ++ unsigned int height; ++ unsigned int capture_mode; ++ int hue; ++ struct v4l2_fract tpf; ++ struct sensor_win_size *current_wins; ++}; ++ ++static inline struct ov5647 *to_state(struct v4l2_subdev *subdev) ++{ ++ return container_of(subdev, struct ov5647, subdev); ++} ++ ++static struct sensor_format_struct sensor_formats[] = { ++ { ++ .mbus_code = OV5647_CODE, ++ .colorspace = V4L2_COLORSPACE_JPEG, ++ }, ++}; ++#define N_FMTS ARRAY_SIZE(sensor_formats) ++ ++static int ov5647_write(struct v4l2_subdev *sd, uint16_t reg, uint8_t val) ++{ ++ int ret; ++ unsigned char data[3] = { reg >> 8, reg & 0xff, val}; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ ret = i2c_master_send(client, data, 3); ++ if (ret < 3) { ++ printk( "%s: i2c write error, reg: %x, %d\n", ++ __func__, reg, ret); ++ return ret < 0 ? ret : -EIO; ++ } ++ ++ return 0; ++} ++ ++static int ov5647_read(struct v4l2_subdev *sd, uint16_t reg, uint8_t *val) ++{ ++ int ret; ++ unsigned char data_w[2] = { reg >> 8, reg & 0xff }; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ ++ ret = i2c_master_send(client, data_w, 2); ++ ++ if (ret < 2) { ++ printk("%s: i2c read error, reg: %x\n", ++ __func__, reg); ++ return ret < 0 ? ret : -EIO; ++ } ++ ++ ret = i2c_master_recv(client, val, 1); ++ ++ if (ret < 1) { ++ printk("%s: i2c read error, reg: %x\n", ++ __func__, reg); ++ return ret < 0 ? ret : -EIO; ++ } ++ ++ return 0; ++} ++ ++static int ov5647_write_array(struct v4l2_subdev *subdev, ++ struct regval_list *regs, int array_size) ++{ ++ int i = 0; ++ int ret = 0; ++ ++ if (!regs) ++ return -EINVAL; ++ ++ while (i < array_size) { ++ if (regs->addr == REG_DLY) ++ mdelay(regs->data); ++ else ++ ret = ov5647_write(subdev, regs->addr, regs->data); ++ ++ if (ret == -EIO) ++ return ret; ++ ++ i++; ++ regs++; ++ } ++ return 0; ++} ++ ++static void ov5647_set_virtual_channel(struct v4l2_subdev *subdev, int channel) ++{ ++#if 0 ++ u8 channel_id; ++ ++ ov5647_read(subdev, 0x4814, &channel_id); ++// channel_id = 0x1e; //override ++ ++ channel_id &= ~(3 << 6); ++ channel_id |= (channel << 6); ++ printk("0x4814 = 0x%02x\n", channel_id); ++ ov5647_write(subdev, 0x4814, channel_id); ++ ov5647_write(subdev, 0x4801, 0x8f); ++#endif ++} ++ ++void ov5647_stream_on(struct v4l2_subdev *subdev) ++{ ++ ov5647_write(subdev, 0x4202, 0x00); ++ ov5647_write(subdev, 0x300D, 0x00); ++} ++ ++void ov5647_stream_off(struct v4l2_subdev *subdev) ++{ ++ ov5647_write(subdev, 0x4202, 0x0f); ++ ov5647_write(subdev, 0x300D, 0x01); ++} ++ ++static int sensor_s_sw_stby(struct v4l2_subdev *subdev, int on_off) ++{ ++ int ret; ++ unsigned char rdval; ++ ++ ret = ov5647_read(subdev, 0x0100, &rdval); ++ if (ret != 0) ++ return ret; ++ ++ if (on_off == CSI_STBY_ON) ++ ret = ov5647_write(subdev, 0x0100, rdval&0xfe); ++ else ++ ret = ov5647_write(subdev, 0x0100, rdval|0x01); ++ ++ return ret; ++} ++ ++static int __sensor_init(struct v4l2_subdev *subdev) ++{ ++ int ret; ++ unsigned char rdval; ++ ++ ret = ov5647_read(subdev, 0x0100, &rdval); ++ if (ret != 0) ++ return ret; ++ ++ ov5647_write(subdev, 0x4800, 0x25); ++ ov5647_stream_off(subdev); ++ ++ ov5647_write(subdev, 0x100, 0); ++ /* reset */ ++ ov5647_write(subdev, 0x103, 1); ++ ov5647_write(subdev, 0x103, 1); ++ ov5647_write(subdev, 0x103, 1); ++ mdelay(10); ++ ++ ret = ov5647_write_array(subdev, ov5647_recommend_settings, ++ ARRAY_SIZE(ov5647_recommend_settings)); ++#if 1 ++ ret = ov5647_write_array(subdev, ov5647_snap_settings, ++ ARRAY_SIZE(ov5647_snap_settings)); ++#else ++ ret = ov5647_write_array(subdev, ov5647_prev_settings, ++ ARRAY_SIZE(ov5647_prev_settings)); ++#endif ++ ov5647_set_virtual_channel(subdev, 0); ++ ++ ov5647_write(subdev, 0x0100, 0x01); ++ ++ ov5647_write(subdev, 0x04800, 0x04); ++ ov5647_stream_on(subdev); ++ msleep(30); ++ ++ return 0; ++} ++ ++static int sensor_power(struct v4l2_subdev *subdev, int on) ++{ ++ int ret = 0; ++ struct ov5647 *ov5647 = to_state(subdev); ++ ++ mutex_lock(&ov5647->lock); ++ ++ switch (on) { ++ case CSI_SUBDEV_PWR_OFF: ++ ret = sensor_s_sw_stby(subdev, CSI_STBY_ON); ++ if (ret < 0) ++ printk("soft stby failed!\n"); ++ break; ++ case CSI_SUBDEV_PWR_ON: ++ ret = __sensor_init(subdev); ++ if (ret < 0) { ++ v4l2_err(subdev, "Camera not available, check power\n"); ++ break; ++ } ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ mutex_unlock(&ov5647->lock); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int sensor_get_register(struct v4l2_subdev *subdev, ++ struct v4l2_dbg_register *reg) ++{ ++ u8 val = 0; ++ int ret; ++ ++ ret = ov5647_read(subdev, (u16)reg->reg, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u8); ++ ++ return ret; ++} ++ ++static int sensor_set_register(struct v4l2_subdev *subdev, ++ const struct v4l2_dbg_register *reg) ++{ ++ ov5647_write(subdev, (u16)reg->reg, (u8)reg->val); ++ ++ return 0; ++} ++#endif ++ ++static const struct v4l2_subdev_core_ops sensor_core_ops = { ++ .s_power = sensor_power, ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = sensor_get_register, ++ .s_register = sensor_set_register, ++#endif ++}; ++ ++static int sensor_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ if (enable) ++ ov5647_stream_on(sd); ++ else ++ ov5647_stream_off(sd); ++ ++ return 0; ++} ++ ++static int sensor_enum_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ if (code->pad || code->index >= N_FMTS) ++ return -EINVAL; ++ ++ code->code = OV5647_CODE; ++ ++ return 0; ++} ++ ++static int sensor_try_fmt_internal(struct v4l2_subdev *subdev, ++ struct v4l2_mbus_framefmt *fmt, ++ struct sensor_format_struct **ret_fmt, ++ struct sensor_win_size **ret_wsize) ++{ ++ int index; ++ ++ for (index = 0; index < N_FMTS; index++) ++ if (sensor_formats[index].mbus_code == fmt->code) ++ break; ++ ++ if (index >= N_FMTS) ++ return -EINVAL; ++ ++ if (ret_fmt != NULL) ++ *ret_fmt = sensor_formats + index; ++ ++ fmt->field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static int sensor_s_fmt(struct v4l2_subdev *subdev, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *fmt) ++{ ++ int ret; ++ struct sensor_format_struct *sensor_fmt; ++ struct sensor_win_size *wsize = NULL; ++ struct ov5647 *info = to_state(subdev); ++ ++ ret = sensor_try_fmt_internal(subdev, &fmt->format, ++ &sensor_fmt, &wsize); ++ if (ret) ++ return ret; ++ ++ info->fmt = sensor_fmt; ++ info->width = OV5647_WIDTH; ++ info->height = OV5647_HEIGHT; ++ ++ return 0; ++} ++ ++static int sensor_g_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct ov5647 *info = to_state(sd); ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ ++ if (format->pad != 0) ++ return -EINVAL; ++ ++ mf->width = OV5647_WIDTH; ++ mf->height = OV5647_HEIGHT; ++ mf->code = OV5647_CODE; ++ mf->colorspace = info->fmt->colorspace; ++ mf->field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static int sensor_s_parm(struct v4l2_subdev *subdev, ++ struct v4l2_streamparm *parms) ++{ ++ struct v4l2_captureparm *cp = &parms->parm.capture; ++ struct ov5647 *info = to_state(subdev); ++ ++ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ ++ if (info->tpf.numerator == 0) ++ return -EINVAL; ++ ++ info->capture_mode = cp->capturemode; ++ ++ return 0; ++} ++ ++static int sensor_g_parm(struct v4l2_subdev *subdev, ++ struct v4l2_streamparm *parms) ++{ ++ struct v4l2_captureparm *cp = &parms->parm.capture; ++ struct ov5647 *info = to_state(subdev); ++ ++ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ ++ memset(cp, 0, sizeof(struct v4l2_captureparm)); ++ cp->capability = V4L2_CAP_TIMEPERFRAME; ++ cp->capturemode = info->capture_mode; ++ ++ return 0; ++} ++ ++static int sensor_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 const struct v4l2_subdev_pad_ops sensor_pad_ops = { ++ .enum_mbus_code = sensor_enum_fmt, ++ .set_fmt = sensor_s_fmt, ++ .get_fmt = sensor_g_fmt, ++}; ++ ++static const struct v4l2_subdev_video_ops sensor_video_ops = { ++ .s_stream = sensor_s_stream, ++ .s_parm = sensor_s_parm, ++ .g_parm = sensor_g_parm, ++ .g_mbus_config = sensor_g_mbus_config, ++}; ++ ++static const struct v4l2_subdev_ops subdev_ops = { ++ .core = &sensor_core_ops, ++ .video = &sensor_video_ops, ++ .pad = &sensor_pad_ops, ++}; ++ ++static int ov5647_detect(struct v4l2_subdev *sd) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ unsigned char id_h, id_l; ++ int ret; ++ ++ ret = sensor_power(sd, 1); ++ if (ret < 0) ++ return ret; ++ ++ ret = ov5647_read(sd, OV5647_REG_CHIPID_H, &id_h); ++ if (ret < 0) ++ return ret; ++ ret = ov5647_read(sd, OV5647_REG_CHIPID_L, &id_l); ++ if (ret < 0) ++ return ret; ++ ++ if ((id_h != 0x56) || (id_l != 0x47)) { ++ v4l2_info(sd, "Invalid device ID: %02x%02x\n", id_h, id_l); ++ return -ENODEV; ++ } ++ ++ v4l2_info(sd, "OV5647 detected at address 0x%02x\n", client->addr); ++ ++ ret = sensor_power(sd, 0); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++static int ov5647_registered(struct v4l2_subdev *subdev) ++{ ++ return 0; ++} ++ ++static int ov5647_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh) ++{ ++ struct v4l2_mbus_framefmt *format = ++ v4l2_subdev_get_try_format(subdev, fh->pad, 0); ++ struct v4l2_rect *crop = ++ v4l2_subdev_get_try_crop(subdev, fh->pad, 0); ++ ++ crop->left = 0; ++ crop->top = 0; ++ crop->width = OV5647_WIDTH; ++ crop->height = OV5647_HEIGHT; ++ ++ format->code = OV5647_CODE; ++ ++ format->width = OV5647_WIDTH; ++ format->height = OV5647_HEIGHT; ++ format->field = V4L2_FIELD_NONE; ++ format->colorspace = sensor_formats[0].colorspace; ++ ++ return sensor_power(subdev, 1); ++} ++ ++static int ov5647_close(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh) ++{ ++ return sensor_power(subdev, 0); ++} ++ ++static const struct v4l2_subdev_internal_ops ov5647_subdev_internal_ops = { ++ .registered = ov5647_registered, ++ .open = ov5647_open, ++ .close = ov5647_close, ++}; ++ ++static int ov5647_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct device *dev = &client->dev; ++ struct ov5647 *sensor; ++ int ret = 0; ++ struct v4l2_subdev *sd; ++ ++ sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL); ++ if (sensor == NULL) ++ return -ENOMEM; ++ ++ mutex_init(&sensor->lock); ++ sensor->dev = dev; ++ sensor->fmt = &sensor_formats[0]; ++ sensor->width = OV5647_WIDTH; ++ sensor->height = OV5647_HEIGHT; ++ ++ sd = &sensor->subdev; ++ v4l2_i2c_subdev_init(sd, client, &subdev_ops); ++ sensor->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; ++ ++ ret = ov5647_detect(sd); ++ if (ret < 0) { ++ v4l2_err(sd, "OV5647 not found!\n"); ++ goto out; ++ } ++ ++ sensor->pad.flags = MEDIA_PAD_FL_SOURCE; ++ sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; ++ ret = media_entity_pads_init(&sd->entity, 1, &sensor->pad); ++ if (ret < 0) ++ return ret; ++ ++ ret = v4l2_async_register_subdev(sd); ++ if (ret < 0) ++ media_entity_cleanup(&sd->entity); ++ ++out: ++ return ret; ++} ++ ++static int ov5647_remove(struct i2c_client *client) ++{ ++ struct v4l2_subdev *subdev = i2c_get_clientdata(client); ++ struct ov5647 *ov5647 = to_state(subdev); ++ ++ v4l2_async_unregister_subdev(&ov5647->subdev); ++ media_entity_cleanup(&ov5647->subdev.entity); ++ v4l2_device_unregister_subdev(subdev); ++ ++ return 0; ++} ++ ++static const struct i2c_device_id ov5647_id[] = { ++ { "ov5647", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, ov5647_id); ++ ++#if IS_ENABLED(CONFIG_OF) ++static const struct of_device_id ov5647_of_match[] = { ++ { .compatible = "ovti,ov5647" }, ++ { /* sentinel */ }, ++}; ++MODULE_DEVICE_TABLE(of, ov5647_of_match); ++#endif ++ ++static struct i2c_driver ov5647_driver = { ++ .driver = { ++ .of_match_table = of_match_ptr(ov5647_of_match), ++ .owner = THIS_MODULE, ++ .name = "ov5647", ++ }, ++ .probe = ov5647_probe, ++ .remove = ov5647_remove, ++ .id_table = ov5647_id, ++}; ++module_i2c_driver(ov5647_driver); ++ ++MODULE_AUTHOR("Ramiro Oliveira <roliveir@synopsys.com>"); ++MODULE_DESCRIPTION("A low-level driver for OmniVision ov5647 sensors"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/i2c/soc_camera/ov5647.h b/drivers/media/i2c/soc_camera/ov5647.h +new file mode 100644 +index 0000000..f854da8 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov5647.h +@@ -0,0 +1,242 @@ ++/* ++ * Copyright (c) 2012, The Linux Foundation. All rights reserved. ++ * 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 version 2 and ++ * only version 2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++//#define TEST_PATTERN ++ ++#define OV5647_WIDTH 2592 ++#define OV5647_HEIGHT 1944 ++ ++#define OV5647_CODE MEDIA_BUS_FMT_SBGGR8_1X8 ++//#define OV5647_CODE MEDIA_BUS_FMT_YUYV8_2X8 ++ ++struct regval_list { ++ uint16_t addr; ++ uint8_t data; ++}; ++ ++enum ov5647_test_mode_t { ++ TEST_OFF, ++ TEST_1, ++ TEST_2, ++ TEST_3 ++}; ++ ++struct regval_list ov5647_prev_settings[] = { ++ /*1280*960 Reference Setting 24M MCLK 2lane 280Mbps/lane 30fps ++ for back to preview*/ ++ {0x3035, 0x21}, ++ {0x3036, 0x37}, ++ {0x3821, 0x07}, ++ {0x3820, 0x41}, ++ {0x3612, 0x09}, ++ {0x3618, 0x00}, ++ {0x380c, 0x07}, ++ {0x380d, 0x68}, ++ {0x380e, 0x03}, ++ {0x380f, 0xd8}, ++ {0x3814, 0x31}, ++ {0x3815, 0x31}, ++ {0x3709, 0x52}, ++ {0x3808, 0x05}, // 1280 ++ {0x3809, 0x00}, ++ {0x380a, 0x03}, // 960 ++ {0x380b, 0xc0}, ++ {0x3800, 0x00}, ++ {0x3801, 0x18}, ++ {0x3802, 0x00}, ++ {0x3803, 0x0e}, ++ {0x3804, 0x0a}, ++ {0x3805, 0x27}, ++ {0x3806, 0x07}, ++ {0x3807, 0x95}, ++ {0x4004, 0x02}, ++}; ++struct regval_list ov5647_snap_settings[] = { ++ /*2608*1952 Reference Setting 24M MCLK 2lane 280Mbps/lane 30fps*/ ++ {0x3035, 0x21}, ++ {0x3036, 0x4f}, ++ {0x3821, 0x06}, ++ {0x3820, 0x00}, ++ {0x3612, 0x0b}, ++ {0x3618, 0x04}, ++ {0x380c, 0x0a}, ++ {0x380d, 0x8c}, ++ {0x380e, 0x07}, ++ {0x380f, 0xb0}, ++ {0x3814, 0x11}, ++ {0x3815, 0x11}, ++ {0x3709, 0x12}, ++#if 0 ++ {0x3808, 0x0a}, ++ {0x3809, 0x30}, ++ {0x380a, 0x07}, ++ {0x380b, 0xa0}, ++#else ++ {0x3808, OV5647_WIDTH >> 8}, ++ {0x3809, OV5647_WIDTH & 0xff}, ++ {0x380a, OV5647_HEIGHT >> 8}, ++ {0x380b, OV5647_HEIGHT & 0xff}, ++#endif ++ {0x3800, 0x00}, ++ {0x3801, 0x04}, ++ {0x3802, 0x00}, ++ {0x3803, 0x00}, ++ {0x3804, 0x0a}, ++ {0x3805, 0x3b}, ++ {0x3806, 0x07}, ++ {0x3807, 0xa3}, ++ {0x4004, 0x04}, ++}; ++struct regval_list ov5647_recommend_settings[] = { ++#ifdef TEST_PATTERN ++ {0x503d, 0x80}, ++#endif ++#if 0 ++ {0x4814, 0x1e}, ++ {0x4801, 0x8f}, ++#endif ++ {0x3035, 0x11}, ++ {0x303c, 0x11}, ++ {0x370c, 0x03}, ++ {0x5000, 0x06}, ++ {0x5003, 0x08}, ++ {0x5a00, 0x08}, ++ {0x3000, 0xff}, ++ {0x3001, 0xff}, ++ {0x3002, 0xff}, ++ {0x301d, 0xf0}, ++ {0x3a18, 0x00}, ++ {0x3a19, 0xf8}, ++ {0x3c01, 0x80}, ++ {0x3b07, 0x0c}, ++ {0x3708, 0x64}, ++ {0x3630, 0x2e}, ++ {0x3632, 0xe2}, ++ {0x3633, 0x23}, ++ {0x3634, 0x44}, ++ {0x3620, 0x64}, ++ {0x3621, 0xe0}, ++ {0x3600, 0x37}, ++ {0x3704, 0xa0}, ++ {0x3703, 0x5a}, ++ {0x3715, 0x78}, ++ {0x3717, 0x01}, ++ {0x3731, 0x02}, ++ {0x370b, 0x60}, ++ {0x3705, 0x1a}, ++ {0x3f05, 0x02}, ++ {0x3f06, 0x10}, ++ {0x3f01, 0x0a}, ++ {0x3a08, 0x01}, ++ {0x3a0f, 0x58}, ++ {0x3a10, 0x50}, ++ {0x3a1b, 0x58}, ++ {0x3a1e, 0x50}, ++ {0x3a11, 0x60}, ++ {0x3a1f, 0x28}, ++ {0x4001, 0x02}, ++ {0x4000, 0x09}, ++ {0x3000, 0x00}, ++ {0x3001, 0x00}, ++ {0x3002, 0x00}, ++ {0x3017, 0xe0}, ++ {0x301c, 0xfc}, ++ {0x3636, 0x06}, ++ {0x3016, 0x08}, ++ {0x3827, 0xec}, ++ {0x3018, 0x44}, ++ {0x3035, 0x21}, ++ {0x3106, 0xf5}, ++ {0x3034, 0x18}, ++ {0x301c, 0xf8}, ++ /*lens setting*/ ++ {0x5000, 0x86}, ++ {0x5800, 0x11}, ++ {0x5801, 0x0c}, ++ {0x5802, 0x0a}, ++ {0x5803, 0x0b}, ++ {0x5804, 0x0d}, ++ {0x5805, 0x13}, ++ {0x5806, 0x09}, ++ {0x5807, 0x05}, ++ {0x5808, 0x03}, ++ {0x5809, 0x03}, ++ {0x580a, 0x06}, ++ {0x580b, 0x08}, ++ {0x580c, 0x05}, ++ {0x580d, 0x01}, ++ {0x580e, 0x00}, ++ {0x580f, 0x00}, ++ {0x5810, 0x02}, ++ {0x5811, 0x06}, ++ {0x5812, 0x05}, ++ {0x5813, 0x01}, ++ {0x5814, 0x00}, ++ {0x5815, 0x00}, ++ {0x5816, 0x02}, ++ {0x5817, 0x06}, ++ {0x5818, 0x09}, ++ {0x5819, 0x05}, ++ {0x581a, 0x04}, ++ {0x581b, 0x04}, ++ {0x581c, 0x06}, ++ {0x581d, 0x09}, ++ {0x581e, 0x11}, ++ {0x581f, 0x0c}, ++ {0x5820, 0x0b}, ++ {0x5821, 0x0b}, ++ {0x5822, 0x0d}, ++ {0x5823, 0x13}, ++ {0x5824, 0x22}, ++ {0x5825, 0x26}, ++ {0x5826, 0x26}, ++ {0x5827, 0x24}, ++ {0x5828, 0x24}, ++ {0x5829, 0x24}, ++ {0x582a, 0x22}, ++ {0x582b, 0x20}, ++ {0x582c, 0x22}, ++ {0x582d, 0x26}, ++ {0x582e, 0x22}, ++ {0x582f, 0x22}, ++ {0x5830, 0x42}, ++ {0x5831, 0x22}, ++ {0x5832, 0x02}, ++ {0x5833, 0x24}, ++ {0x5834, 0x22}, ++ {0x5835, 0x22}, ++ {0x5836, 0x22}, ++ {0x5837, 0x26}, ++ {0x5838, 0x42}, ++ {0x5839, 0x26}, ++ {0x583a, 0x06}, ++ {0x583b, 0x26}, ++ {0x583c, 0x24}, ++ {0x583d, 0xce}, ++ /* manual AWB,manual AE,close Lenc,open WBC*/ ++ {0x3503, 0x03}, /*manual AE*/ ++ {0x3501, 0x10}, ++ {0x3502, 0x80}, ++ {0x350a, 0x00}, ++ {0x350b, 0x7f}, ++ {0x5001, 0x01}, /*manual AWB*/ ++ {0x5180, 0x08}, ++ {0x5186, 0x04}, ++ {0x5187, 0x00}, ++ {0x5188, 0x04}, ++ {0x5189, 0x00}, ++ {0x518a, 0x04}, ++ {0x518b, 0x00}, ++ {0x5000, 0x06}, /*No lenc,WBC on*/ ++}; +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0032-media-i2c-Add-ov5642-sensor.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0032-media-i2c-Add-ov5642-sensor.patch new file mode 100644 index 0000000..99183fa --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0032-media-i2c-Add-ov5642-sensor.patch @@ -0,0 +1,2173 @@ +From 79ff5931fa2dede0a4c2e22e7a83c2edddcc6c20 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Sun, 11 Jun 2017 00:50:59 +0300 +Subject: [PATCH] media: i2c: ov5642 sensor + +Add ov5642 camera sensor driver update + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + drivers/media/i2c/soc_camera/ov5642.c | 708 +++++----------------------- + drivers/media/i2c/soc_camera/ov5642.h | 592 ++++++++++++++++++++++++ + drivers/media/i2c/soc_camera/ov5642_720p.h | 711 +++++++++++++++++++++++++++++ + 3 files changed, 1418 insertions(+), 593 deletions(-) + create mode 100644 drivers/media/i2c/soc_camera/ov5642.h + create mode 100644 drivers/media/i2c/soc_camera/ov5642_720p.h + +diff --git a/drivers/media/i2c/soc_camera/ov5642.c b/drivers/media/i2c/soc_camera/ov5642.c +index bab9ac0..b58859e 100644 +--- a/drivers/media/i2c/soc_camera/ov5642.c ++++ b/drivers/media/i2c/soc_camera/ov5642.c +@@ -22,584 +22,16 @@ + #include <linux/videodev2.h> + #include <linux/module.h> + #include <linux/v4l2-mediabus.h> ++#include <linux/gpio.h> ++#include <linux/gpio/consumer.h> ++#include <linux/of_gpio.h> + + #include <media/soc_camera.h> + #include <media/v4l2-clk.h> + #include <media/v4l2-subdev.h> + +-/* OV5642 registers */ +-#define REG_CHIP_ID_HIGH 0x300a +-#define REG_CHIP_ID_LOW 0x300b +- +-#define REG_WINDOW_START_X_HIGH 0x3800 +-#define REG_WINDOW_START_X_LOW 0x3801 +-#define REG_WINDOW_START_Y_HIGH 0x3802 +-#define REG_WINDOW_START_Y_LOW 0x3803 +-#define REG_WINDOW_WIDTH_HIGH 0x3804 +-#define REG_WINDOW_WIDTH_LOW 0x3805 +-#define REG_WINDOW_HEIGHT_HIGH 0x3806 +-#define REG_WINDOW_HEIGHT_LOW 0x3807 +-#define REG_OUT_WIDTH_HIGH 0x3808 +-#define REG_OUT_WIDTH_LOW 0x3809 +-#define REG_OUT_HEIGHT_HIGH 0x380a +-#define REG_OUT_HEIGHT_LOW 0x380b +-#define REG_OUT_TOTAL_WIDTH_HIGH 0x380c +-#define REG_OUT_TOTAL_WIDTH_LOW 0x380d +-#define REG_OUT_TOTAL_HEIGHT_HIGH 0x380e +-#define REG_OUT_TOTAL_HEIGHT_LOW 0x380f +-#define REG_OUTPUT_FORMAT 0x4300 +-#define REG_ISP_CTRL_01 0x5001 +-#define REG_AVG_WINDOW_END_X_HIGH 0x5682 +-#define REG_AVG_WINDOW_END_X_LOW 0x5683 +-#define REG_AVG_WINDOW_END_Y_HIGH 0x5686 +-#define REG_AVG_WINDOW_END_Y_LOW 0x5687 +- +-/* active pixel array size */ +-#define OV5642_SENSOR_SIZE_X 2592 +-#define OV5642_SENSOR_SIZE_Y 1944 +- +-/* +- * About OV5642 resolution, cropping and binning: +- * This sensor supports it all, at least in the feature description. +- * Unfortunately, no combination of appropriate registers settings could make +- * the chip work the intended way. As it works with predefined register lists, +- * some undocumented registers are presumably changed there to achieve their +- * goals. +- * This driver currently only works for resolutions up to 720 lines with a +- * 1:1 scale. Hopefully these restrictions will be removed in the future. +- */ +-#define OV5642_MAX_WIDTH OV5642_SENSOR_SIZE_X +-#define OV5642_MAX_HEIGHT 720 +- +-/* default sizes */ +-#define OV5642_DEFAULT_WIDTH 1280 +-#define OV5642_DEFAULT_HEIGHT OV5642_MAX_HEIGHT +- +-/* minimum extra blanking */ +-#define BLANKING_EXTRA_WIDTH 500 +-#define BLANKING_EXTRA_HEIGHT 20 +- +-/* +- * the sensor's autoexposure is buggy when setting total_height low. +- * It tries to expose longer than 1 frame period without taking care of it +- * and this leads to weird output. So we set 1000 lines as minimum. +- */ +-#define BLANKING_MIN_HEIGHT 1000 +- +-struct regval_list { +- u16 reg_num; +- u8 value; +-}; +- +-static struct regval_list ov5642_default_regs_init[] = { +- { 0x3103, 0x93 }, +- { 0x3008, 0x82 }, +- { 0x3017, 0x7f }, +- { 0x3018, 0xfc }, +- { 0x3810, 0xc2 }, +- { 0x3615, 0xf0 }, +- { 0x3000, 0x0 }, +- { 0x3001, 0x0 }, +- { 0x3002, 0x0 }, +- { 0x3003, 0x0 }, +- { 0x3004, 0xff }, +- { 0x3030, 0x2b }, +- { 0x3011, 0x8 }, +- { 0x3010, 0x10 }, +- { 0x3604, 0x60 }, +- { 0x3622, 0x60 }, +- { 0x3621, 0x9 }, +- { 0x3709, 0x0 }, +- { 0x4000, 0x21 }, +- { 0x401d, 0x22 }, +- { 0x3600, 0x54 }, +- { 0x3605, 0x4 }, +- { 0x3606, 0x3f }, +- { 0x3c01, 0x80 }, +- { 0x300d, 0x22 }, +- { 0x3623, 0x22 }, +- { 0x5000, 0x4f }, +- { 0x5020, 0x4 }, +- { 0x5181, 0x79 }, +- { 0x5182, 0x0 }, +- { 0x5185, 0x22 }, +- { 0x5197, 0x1 }, +- { 0x5500, 0xa }, +- { 0x5504, 0x0 }, +- { 0x5505, 0x7f }, +- { 0x5080, 0x8 }, +- { 0x300e, 0x18 }, +- { 0x4610, 0x0 }, +- { 0x471d, 0x5 }, +- { 0x4708, 0x6 }, +- { 0x370c, 0xa0 }, +- { 0x5687, 0x94 }, +- { 0x501f, 0x0 }, +- { 0x5000, 0x4f }, +- { 0x5001, 0xcf }, +- { 0x4300, 0x30 }, +- { 0x4300, 0x30 }, +- { 0x460b, 0x35 }, +- { 0x471d, 0x0 }, +- { 0x3002, 0xc }, +- { 0x3002, 0x0 }, +- { 0x4713, 0x3 }, +- { 0x471c, 0x50 }, +- { 0x4721, 0x2 }, +- { 0x4402, 0x90 }, +- { 0x460c, 0x22 }, +- { 0x3815, 0x44 }, +- { 0x3503, 0x7 }, +- { 0x3501, 0x73 }, +- { 0x3502, 0x80 }, +- { 0x350b, 0x0 }, +- { 0x3818, 0xc8 }, +- { 0x3824, 0x11 }, +- { 0x3a00, 0x78 }, +- { 0x3a1a, 0x4 }, +- { 0x3a13, 0x30 }, +- { 0x3a18, 0x0 }, +- { 0x3a19, 0x7c }, +- { 0x3a08, 0x12 }, +- { 0x3a09, 0xc0 }, +- { 0x3a0a, 0xf }, +- { 0x3a0b, 0xa0 }, +- { 0x350c, 0x7 }, +- { 0x350d, 0xd0 }, +- { 0x3a0d, 0x8 }, +- { 0x3a0e, 0x6 }, +- { 0x3500, 0x0 }, +- { 0x3501, 0x0 }, +- { 0x3502, 0x0 }, +- { 0x350a, 0x0 }, +- { 0x350b, 0x0 }, +- { 0x3503, 0x0 }, +- { 0x3a0f, 0x3c }, +- { 0x3a10, 0x32 }, +- { 0x3a1b, 0x3c }, +- { 0x3a1e, 0x32 }, +- { 0x3a11, 0x80 }, +- { 0x3a1f, 0x20 }, +- { 0x3030, 0x2b }, +- { 0x3a02, 0x0 }, +- { 0x3a03, 0x7d }, +- { 0x3a04, 0x0 }, +- { 0x3a14, 0x0 }, +- { 0x3a15, 0x7d }, +- { 0x3a16, 0x0 }, +- { 0x3a00, 0x78 }, +- { 0x3a08, 0x9 }, +- { 0x3a09, 0x60 }, +- { 0x3a0a, 0x7 }, +- { 0x3a0b, 0xd0 }, +- { 0x3a0d, 0x10 }, +- { 0x3a0e, 0xd }, +- { 0x4407, 0x4 }, +- { 0x5193, 0x70 }, +- { 0x589b, 0x0 }, +- { 0x589a, 0xc0 }, +- { 0x401e, 0x20 }, +- { 0x4001, 0x42 }, +- { 0x401c, 0x6 }, +- { 0x3825, 0xac }, +- { 0x3827, 0xc }, +- { 0x528a, 0x1 }, +- { 0x528b, 0x4 }, +- { 0x528c, 0x8 }, +- { 0x528d, 0x10 }, +- { 0x528e, 0x20 }, +- { 0x528f, 0x28 }, +- { 0x5290, 0x30 }, +- { 0x5292, 0x0 }, +- { 0x5293, 0x1 }, +- { 0x5294, 0x0 }, +- { 0x5295, 0x4 }, +- { 0x5296, 0x0 }, +- { 0x5297, 0x8 }, +- { 0x5298, 0x0 }, +- { 0x5299, 0x10 }, +- { 0x529a, 0x0 }, +- { 0x529b, 0x20 }, +- { 0x529c, 0x0 }, +- { 0x529d, 0x28 }, +- { 0x529e, 0x0 }, +- { 0x529f, 0x30 }, +- { 0x5282, 0x0 }, +- { 0x5300, 0x0 }, +- { 0x5301, 0x20 }, +- { 0x5302, 0x0 }, +- { 0x5303, 0x7c }, +- { 0x530c, 0x0 }, +- { 0x530d, 0xc }, +- { 0x530e, 0x20 }, +- { 0x530f, 0x80 }, +- { 0x5310, 0x20 }, +- { 0x5311, 0x80 }, +- { 0x5308, 0x20 }, +- { 0x5309, 0x40 }, +- { 0x5304, 0x0 }, +- { 0x5305, 0x30 }, +- { 0x5306, 0x0 }, +- { 0x5307, 0x80 }, +- { 0x5314, 0x8 }, +- { 0x5315, 0x20 }, +- { 0x5319, 0x30 }, +- { 0x5316, 0x10 }, +- { 0x5317, 0x0 }, +- { 0x5318, 0x2 }, +- { 0x5380, 0x1 }, +- { 0x5381, 0x0 }, +- { 0x5382, 0x0 }, +- { 0x5383, 0x4e }, +- { 0x5384, 0x0 }, +- { 0x5385, 0xf }, +- { 0x5386, 0x0 }, +- { 0x5387, 0x0 }, +- { 0x5388, 0x1 }, +- { 0x5389, 0x15 }, +- { 0x538a, 0x0 }, +- { 0x538b, 0x31 }, +- { 0x538c, 0x0 }, +- { 0x538d, 0x0 }, +- { 0x538e, 0x0 }, +- { 0x538f, 0xf }, +- { 0x5390, 0x0 }, +- { 0x5391, 0xab }, +- { 0x5392, 0x0 }, +- { 0x5393, 0xa2 }, +- { 0x5394, 0x8 }, +- { 0x5480, 0x14 }, +- { 0x5481, 0x21 }, +- { 0x5482, 0x36 }, +- { 0x5483, 0x57 }, +- { 0x5484, 0x65 }, +- { 0x5485, 0x71 }, +- { 0x5486, 0x7d }, +- { 0x5487, 0x87 }, +- { 0x5488, 0x91 }, +- { 0x5489, 0x9a }, +- { 0x548a, 0xaa }, +- { 0x548b, 0xb8 }, +- { 0x548c, 0xcd }, +- { 0x548d, 0xdd }, +- { 0x548e, 0xea }, +- { 0x548f, 0x1d }, +- { 0x5490, 0x5 }, +- { 0x5491, 0x0 }, +- { 0x5492, 0x4 }, +- { 0x5493, 0x20 }, +- { 0x5494, 0x3 }, +- { 0x5495, 0x60 }, +- { 0x5496, 0x2 }, +- { 0x5497, 0xb8 }, +- { 0x5498, 0x2 }, +- { 0x5499, 0x86 }, +- { 0x549a, 0x2 }, +- { 0x549b, 0x5b }, +- { 0x549c, 0x2 }, +- { 0x549d, 0x3b }, +- { 0x549e, 0x2 }, +- { 0x549f, 0x1c }, +- { 0x54a0, 0x2 }, +- { 0x54a1, 0x4 }, +- { 0x54a2, 0x1 }, +- { 0x54a3, 0xed }, +- { 0x54a4, 0x1 }, +- { 0x54a5, 0xc5 }, +- { 0x54a6, 0x1 }, +- { 0x54a7, 0xa5 }, +- { 0x54a8, 0x1 }, +- { 0x54a9, 0x6c }, +- { 0x54aa, 0x1 }, +- { 0x54ab, 0x41 }, +- { 0x54ac, 0x1 }, +- { 0x54ad, 0x20 }, +- { 0x54ae, 0x0 }, +- { 0x54af, 0x16 }, +- { 0x54b0, 0x1 }, +- { 0x54b1, 0x20 }, +- { 0x54b2, 0x0 }, +- { 0x54b3, 0x10 }, +- { 0x54b4, 0x0 }, +- { 0x54b5, 0xf0 }, +- { 0x54b6, 0x0 }, +- { 0x54b7, 0xdf }, +- { 0x5402, 0x3f }, +- { 0x5403, 0x0 }, +- { 0x3406, 0x0 }, +- { 0x5180, 0xff }, +- { 0x5181, 0x52 }, +- { 0x5182, 0x11 }, +- { 0x5183, 0x14 }, +- { 0x5184, 0x25 }, +- { 0x5185, 0x24 }, +- { 0x5186, 0x6 }, +- { 0x5187, 0x8 }, +- { 0x5188, 0x8 }, +- { 0x5189, 0x7c }, +- { 0x518a, 0x60 }, +- { 0x518b, 0xb2 }, +- { 0x518c, 0xb2 }, +- { 0x518d, 0x44 }, +- { 0x518e, 0x3d }, +- { 0x518f, 0x58 }, +- { 0x5190, 0x46 }, +- { 0x5191, 0xf8 }, +- { 0x5192, 0x4 }, +- { 0x5193, 0x70 }, +- { 0x5194, 0xf0 }, +- { 0x5195, 0xf0 }, +- { 0x5196, 0x3 }, +- { 0x5197, 0x1 }, +- { 0x5198, 0x4 }, +- { 0x5199, 0x12 }, +- { 0x519a, 0x4 }, +- { 0x519b, 0x0 }, +- { 0x519c, 0x6 }, +- { 0x519d, 0x82 }, +- { 0x519e, 0x0 }, +- { 0x5025, 0x80 }, +- { 0x3a0f, 0x38 }, +- { 0x3a10, 0x30 }, +- { 0x3a1b, 0x3a }, +- { 0x3a1e, 0x2e }, +- { 0x3a11, 0x60 }, +- { 0x3a1f, 0x10 }, +- { 0x5688, 0xa6 }, +- { 0x5689, 0x6a }, +- { 0x568a, 0xea }, +- { 0x568b, 0xae }, +- { 0x568c, 0xa6 }, +- { 0x568d, 0x6a }, +- { 0x568e, 0x62 }, +- { 0x568f, 0x26 }, +- { 0x5583, 0x40 }, +- { 0x5584, 0x40 }, +- { 0x5580, 0x2 }, +- { 0x5000, 0xcf }, +- { 0x5800, 0x27 }, +- { 0x5801, 0x19 }, +- { 0x5802, 0x12 }, +- { 0x5803, 0xf }, +- { 0x5804, 0x10 }, +- { 0x5805, 0x15 }, +- { 0x5806, 0x1e }, +- { 0x5807, 0x2f }, +- { 0x5808, 0x15 }, +- { 0x5809, 0xd }, +- { 0x580a, 0xa }, +- { 0x580b, 0x9 }, +- { 0x580c, 0xa }, +- { 0x580d, 0xc }, +- { 0x580e, 0x12 }, +- { 0x580f, 0x19 }, +- { 0x5810, 0xb }, +- { 0x5811, 0x7 }, +- { 0x5812, 0x4 }, +- { 0x5813, 0x3 }, +- { 0x5814, 0x3 }, +- { 0x5815, 0x6 }, +- { 0x5816, 0xa }, +- { 0x5817, 0xf }, +- { 0x5818, 0xa }, +- { 0x5819, 0x5 }, +- { 0x581a, 0x1 }, +- { 0x581b, 0x0 }, +- { 0x581c, 0x0 }, +- { 0x581d, 0x3 }, +- { 0x581e, 0x8 }, +- { 0x581f, 0xc }, +- { 0x5820, 0xa }, +- { 0x5821, 0x5 }, +- { 0x5822, 0x1 }, +- { 0x5823, 0x0 }, +- { 0x5824, 0x0 }, +- { 0x5825, 0x3 }, +- { 0x5826, 0x8 }, +- { 0x5827, 0xc }, +- { 0x5828, 0xe }, +- { 0x5829, 0x8 }, +- { 0x582a, 0x6 }, +- { 0x582b, 0x4 }, +- { 0x582c, 0x5 }, +- { 0x582d, 0x7 }, +- { 0x582e, 0xb }, +- { 0x582f, 0x12 }, +- { 0x5830, 0x18 }, +- { 0x5831, 0x10 }, +- { 0x5832, 0xc }, +- { 0x5833, 0xa }, +- { 0x5834, 0xb }, +- { 0x5835, 0xe }, +- { 0x5836, 0x15 }, +- { 0x5837, 0x19 }, +- { 0x5838, 0x32 }, +- { 0x5839, 0x1f }, +- { 0x583a, 0x18 }, +- { 0x583b, 0x16 }, +- { 0x583c, 0x17 }, +- { 0x583d, 0x1e }, +- { 0x583e, 0x26 }, +- { 0x583f, 0x53 }, +- { 0x5840, 0x10 }, +- { 0x5841, 0xf }, +- { 0x5842, 0xd }, +- { 0x5843, 0xc }, +- { 0x5844, 0xe }, +- { 0x5845, 0x9 }, +- { 0x5846, 0x11 }, +- { 0x5847, 0x10 }, +- { 0x5848, 0x10 }, +- { 0x5849, 0x10 }, +- { 0x584a, 0x10 }, +- { 0x584b, 0xe }, +- { 0x584c, 0x10 }, +- { 0x584d, 0x10 }, +- { 0x584e, 0x11 }, +- { 0x584f, 0x10 }, +- { 0x5850, 0xf }, +- { 0x5851, 0xc }, +- { 0x5852, 0xf }, +- { 0x5853, 0x10 }, +- { 0x5854, 0x10 }, +- { 0x5855, 0xf }, +- { 0x5856, 0xe }, +- { 0x5857, 0xb }, +- { 0x5858, 0x10 }, +- { 0x5859, 0xd }, +- { 0x585a, 0xd }, +- { 0x585b, 0xc }, +- { 0x585c, 0xc }, +- { 0x585d, 0xc }, +- { 0x585e, 0xb }, +- { 0x585f, 0xc }, +- { 0x5860, 0xc }, +- { 0x5861, 0xc }, +- { 0x5862, 0xd }, +- { 0x5863, 0x8 }, +- { 0x5864, 0x11 }, +- { 0x5865, 0x18 }, +- { 0x5866, 0x18 }, +- { 0x5867, 0x19 }, +- { 0x5868, 0x17 }, +- { 0x5869, 0x19 }, +- { 0x586a, 0x16 }, +- { 0x586b, 0x13 }, +- { 0x586c, 0x13 }, +- { 0x586d, 0x12 }, +- { 0x586e, 0x13 }, +- { 0x586f, 0x16 }, +- { 0x5870, 0x14 }, +- { 0x5871, 0x12 }, +- { 0x5872, 0x10 }, +- { 0x5873, 0x11 }, +- { 0x5874, 0x11 }, +- { 0x5875, 0x16 }, +- { 0x5876, 0x14 }, +- { 0x5877, 0x11 }, +- { 0x5878, 0x10 }, +- { 0x5879, 0xf }, +- { 0x587a, 0x10 }, +- { 0x587b, 0x14 }, +- { 0x587c, 0x13 }, +- { 0x587d, 0x12 }, +- { 0x587e, 0x11 }, +- { 0x587f, 0x11 }, +- { 0x5880, 0x12 }, +- { 0x5881, 0x15 }, +- { 0x5882, 0x14 }, +- { 0x5883, 0x15 }, +- { 0x5884, 0x15 }, +- { 0x5885, 0x15 }, +- { 0x5886, 0x13 }, +- { 0x5887, 0x17 }, +- { 0x3710, 0x10 }, +- { 0x3632, 0x51 }, +- { 0x3702, 0x10 }, +- { 0x3703, 0xb2 }, +- { 0x3704, 0x18 }, +- { 0x370b, 0x40 }, +- { 0x370d, 0x3 }, +- { 0x3631, 0x1 }, +- { 0x3632, 0x52 }, +- { 0x3606, 0x24 }, +- { 0x3620, 0x96 }, +- { 0x5785, 0x7 }, +- { 0x3a13, 0x30 }, +- { 0x3600, 0x52 }, +- { 0x3604, 0x48 }, +- { 0x3606, 0x1b }, +- { 0x370d, 0xb }, +- { 0x370f, 0xc0 }, +- { 0x3709, 0x1 }, +- { 0x3823, 0x0 }, +- { 0x5007, 0x0 }, +- { 0x5009, 0x0 }, +- { 0x5011, 0x0 }, +- { 0x5013, 0x0 }, +- { 0x519e, 0x0 }, +- { 0x5086, 0x0 }, +- { 0x5087, 0x0 }, +- { 0x5088, 0x0 }, +- { 0x5089, 0x0 }, +- { 0x302b, 0x0 }, +- { 0x3503, 0x7 }, +- { 0x3011, 0x8 }, +- { 0x350c, 0x2 }, +- { 0x350d, 0xe4 }, +- { 0x3621, 0xc9 }, +- { 0x370a, 0x81 }, +- { 0xffff, 0xff }, +-}; +- +-static struct regval_list ov5642_default_regs_finalise[] = { +- { 0x3810, 0xc2 }, +- { 0x3818, 0xc9 }, +- { 0x381c, 0x10 }, +- { 0x381d, 0xa0 }, +- { 0x381e, 0x5 }, +- { 0x381f, 0xb0 }, +- { 0x3820, 0x0 }, +- { 0x3821, 0x0 }, +- { 0x3824, 0x11 }, +- { 0x3a08, 0x1b }, +- { 0x3a09, 0xc0 }, +- { 0x3a0a, 0x17 }, +- { 0x3a0b, 0x20 }, +- { 0x3a0d, 0x2 }, +- { 0x3a0e, 0x1 }, +- { 0x401c, 0x4 }, +- { 0x5682, 0x5 }, +- { 0x5683, 0x0 }, +- { 0x5686, 0x2 }, +- { 0x5687, 0xcc }, +- { 0x5001, 0x4f }, +- { 0x589b, 0x6 }, +- { 0x589a, 0xc5 }, +- { 0x3503, 0x0 }, +- { 0x460c, 0x20 }, +- { 0x460b, 0x37 }, +- { 0x471c, 0xd0 }, +- { 0x471d, 0x5 }, +- { 0x3815, 0x1 }, +- { 0x3818, 0xc1 }, +- { 0x501f, 0x0 }, +- { 0x5002, 0xe0 }, +- { 0x4300, 0x32 }, /* UYVY */ +- { 0x3002, 0x1c }, +- { 0x4800, 0x14 }, +- { 0x4801, 0xf }, +- { 0x3007, 0x3b }, +- { 0x300e, 0x4 }, +- { 0x4803, 0x50 }, +- { 0x3815, 0x1 }, +- { 0x4713, 0x2 }, +- { 0x4842, 0x1 }, +- { 0x300f, 0xe }, +- { 0x3003, 0x3 }, +- { 0x3003, 0x1 }, +- { 0xffff, 0xff }, +-}; ++#define USE_PREDEF ++#include "ov5642.h" + + struct ov5642_datafmt { + u32 code; +@@ -608,6 +40,7 @@ struct ov5642_datafmt { + + struct ov5642 { + struct v4l2_subdev subdev; ++ struct media_pad pad; + const struct ov5642_datafmt *fmt; + struct v4l2_rect crop_rect; + struct v4l2_clk *clk; +@@ -615,10 +48,14 @@ struct ov5642 { + /* blanking information */ + int total_width; + int total_height; ++ ++ struct soc_camera_subdev_desc ssdd_dt; ++ struct gpio_desc *resetb_gpio; ++ struct gpio_desc *pwdn_gpio; + }; + + static const struct ov5642_datafmt ov5642_colour_fmts[] = { +- {MEDIA_BUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_JPEG}, ++ {MEDIA_BUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG}, + }; + + static struct ov5642 *to_ov5642(const struct i2c_client *client) +@@ -676,10 +113,7 @@ static int reg_write(struct i2c_client *client, u16 reg, u8 val) + return 0; + } + +-/* +- * convenience function to write 16 bit register values that are split up +- * into two consecutive high and low parts +- */ ++#if 0 + static int reg_write16(struct i2c_client *client, u16 reg, u16 val16) + { + int ret; +@@ -689,6 +123,7 @@ static int reg_write16(struct i2c_client *client, u16 reg, u16 val16) + return ret; + return reg_write(client, reg + 1, val16 & 0x00ff); + } ++#endif + + #ifdef CONFIG_VIDEO_ADV_DEBUG + static int ov5642_get_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) +@@ -733,6 +168,7 @@ static int ov5642_write_array(struct i2c_client *client, + return 0; + } + ++#ifndef USE_PREDEF + static int ov5642_set_resolution(struct v4l2_subdev *sd) + { + struct i2c_client *client = v4l2_get_subdevdata(sd); +@@ -785,6 +221,7 @@ static int ov5642_set_resolution(struct v4l2_subdev *sd) + + return ret; + } ++#endif + + static int ov5642_set_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, +@@ -866,15 +303,15 @@ static int ov5642_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a) + priv->total_height = max_t(int, rect.height + + BLANKING_EXTRA_HEIGHT, + BLANKING_MIN_HEIGHT); +- priv->crop_rect.width = rect.width; +- priv->crop_rect.height = rect.height; +- ++#ifdef USE_PREDEF ++ ret = ov5642_write_array(client, OV5642_720P_30FPS); ++#else + ret = ov5642_write_array(client, ov5642_default_regs_init); + if (!ret) + ret = ov5642_set_resolution(sd); + if (!ret) + ret = ov5642_write_array(client, ov5642_default_regs_finalise); +- ++#endif + return ret; + } + +@@ -909,10 +346,10 @@ static int ov5642_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) + static int ov5642_g_mbus_config(struct v4l2_subdev *sd, + struct v4l2_mbus_config *cfg) + { +- cfg->type = V4L2_MBUS_CSI2; +- cfg->flags = V4L2_MBUS_CSI2_2_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | +- V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; +- ++ cfg->type = V4L2_MBUS_PARALLEL; ++ cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_PCLK_SAMPLE_RISING | ++ V4L2_MBUS_HSYNC_ACTIVE_LOW | V4L2_MBUS_VSYNC_ACTIVE_HIGH | ++ V4L2_MBUS_DATA_ACTIVE_HIGH; + return 0; + } + +@@ -930,12 +367,15 @@ static int ov5642_s_power(struct v4l2_subdev *sd, int on) + if (ret < 0) + return ret; + ++#ifdef USE_PREDEF ++ ret = ov5642_write_array(client, OV5642_720P_30FPS); ++#else + ret = ov5642_write_array(client, ov5642_default_regs_init); + if (!ret) + ret = ov5642_set_resolution(sd); + if (!ret) + ret = ov5642_write_array(client, ov5642_default_regs_finalise); +- ++#endif + return ret; + } + +@@ -966,6 +406,63 @@ static struct v4l2_subdev_ops ov5642_subdev_ops = { + .pad = &ov5642_subdev_pad_ops, + }; + ++/* OF probe functions */ ++static int ov5642_hw_power(struct device *dev, int on) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct ov5642 *priv = to_ov5642(client); ++ ++ dev_dbg(&client->dev, "%s: %s the camera\n", ++ __func__, on ? "ENABLE" : "DISABLE"); ++ ++ if (priv->pwdn_gpio) ++ gpiod_direction_output(priv->pwdn_gpio, !on); ++ ++ return 0; ++} ++ ++static int ov5642_hw_reset(struct device *dev) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct ov5642 *priv = to_ov5642(client); ++ ++ if (priv->resetb_gpio) { ++ /* Active the resetb pin to perform a reset pulse */ ++ gpiod_direction_output(priv->resetb_gpio, 1); ++ usleep_range(3000, 5000); ++ gpiod_direction_output(priv->resetb_gpio, 0); ++ } ++ ++ return 0; ++} ++ ++static int ov5642_probe_dt(struct i2c_client *client, ++ struct ov5642 *priv) ++{ ++ /* Request the reset GPIO deasserted */ ++ priv->resetb_gpio = devm_gpiod_get_optional(&client->dev, "resetb", ++ GPIOD_OUT_LOW); ++ if (!priv->resetb_gpio) ++ dev_dbg(&client->dev, "resetb gpio is not assigned!\n"); ++ else if (IS_ERR(priv->resetb_gpio)) ++ return PTR_ERR(priv->resetb_gpio); ++ ++ /* Request the power down GPIO asserted */ ++ priv->pwdn_gpio = devm_gpiod_get_optional(&client->dev, "pwdn", ++ GPIOD_OUT_HIGH); ++ if (!priv->pwdn_gpio) ++ dev_dbg(&client->dev, "pwdn gpio is not assigned!\n"); ++ else if (IS_ERR(priv->pwdn_gpio)) ++ return PTR_ERR(priv->pwdn_gpio); ++ ++ /* Initialize the soc_camera_subdev_desc */ ++ priv->ssdd_dt.power = ov5642_hw_power; ++ priv->ssdd_dt.reset = ov5642_hw_reset; ++ client->dev.platform_data = &priv->ssdd_dt; ++ ++ return 0; ++} ++ + static int ov5642_video_probe(struct i2c_client *client) + { + struct v4l2_subdev *subdev = i2c_get_clientdata(client); +@@ -1008,19 +505,23 @@ static int ov5642_probe(struct i2c_client *client, + const struct i2c_device_id *did) + { + struct ov5642 *priv; ++ struct v4l2_subdev *sd; + struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client); + int ret; + +- if (!ssdd) { +- dev_err(&client->dev, "OV5642: missing platform data!\n"); +- return -EINVAL; +- } +- + priv = devm_kzalloc(&client->dev, sizeof(struct ov5642), GFP_KERNEL); + if (!priv) + return -ENOMEM; + ++ if (!ssdd) { ++ ret = ov5642_probe_dt(client, priv); ++ if (ret) ++ return ret; ++ } ++ ++ sd = &priv->subdev; + v4l2_i2c_subdev_init(&priv->subdev, client, &ov5642_subdev_ops); ++ priv->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + + priv->fmt = &ov5642_colour_fmts[0]; + +@@ -1036,8 +537,20 @@ static int ov5642_probe(struct i2c_client *client, + return PTR_ERR(priv->clk); + + ret = ov5642_video_probe(client); +- if (ret < 0) ++ if (ret < 0) { + v4l2_clk_put(priv->clk); ++ return ret; ++ } ++ ++ priv->pad.flags = MEDIA_PAD_FL_SOURCE; ++ sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; ++ ret = media_entity_pads_init(&sd->entity, 1, &priv->pad); ++ if (ret < 0) ++ return ret; ++ ++ ret = v4l2_async_register_subdev(sd); ++ if (ret < 0) ++ media_entity_cleanup(&sd->entity); + + return ret; + } +@@ -1060,8 +573,17 @@ static const struct i2c_device_id ov5642_id[] = { + }; + MODULE_DEVICE_TABLE(i2c, ov5642_id); + ++#if IS_ENABLED(CONFIG_OF) ++static const struct of_device_id ov5642_of_match[] = { ++ { .compatible = "ovti,ov5642" }, ++ { /* sentinel */ }, ++}; ++MODULE_DEVICE_TABLE(of, ov5642_of_match); ++#endif ++ + static struct i2c_driver ov5642_i2c_driver = { + .driver = { ++ .of_match_table = of_match_ptr(ov5642_of_match), + .name = "ov5642", + }, + .probe = ov5642_probe, +diff --git a/drivers/media/i2c/soc_camera/ov5642.h b/drivers/media/i2c/soc_camera/ov5642.h +new file mode 100644 +index 0000000..ac47a16 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov5642.h +@@ -0,0 +1,592 @@ ++#ifndef _OV5642_H_ ++#define _OV5642_H_ ++ ++ ++/* OV5642 registers */ ++#define REG_CHIP_ID_HIGH 0x300a ++#define REG_CHIP_ID_LOW 0x300b ++ ++#define REG_WINDOW_START_X_HIGH 0x3800 ++#define REG_WINDOW_START_X_LOW 0x3801 ++#define REG_WINDOW_START_Y_HIGH 0x3802 ++#define REG_WINDOW_START_Y_LOW 0x3803 ++#define REG_WINDOW_WIDTH_HIGH 0x3804 ++#define REG_WINDOW_WIDTH_LOW 0x3805 ++#define REG_WINDOW_HEIGHT_HIGH 0x3806 ++#define REG_WINDOW_HEIGHT_LOW 0x3807 ++#define REG_OUT_WIDTH_HIGH 0x3808 ++#define REG_OUT_WIDTH_LOW 0x3809 ++#define REG_OUT_HEIGHT_HIGH 0x380a ++#define REG_OUT_HEIGHT_LOW 0x380b ++#define REG_OUT_TOTAL_WIDTH_HIGH 0x380c ++#define REG_OUT_TOTAL_WIDTH_LOW 0x380d ++#define REG_OUT_TOTAL_HEIGHT_HIGH 0x380e ++#define REG_OUT_TOTAL_HEIGHT_LOW 0x380f ++#define REG_OUTPUT_FORMAT 0x4300 ++#define REG_ISP_CTRL_00 0x5000 ++#define REG_ISP_CTRL_01 0x5001 ++#define REG_AVG_WINDOW_START_X_HIGH 0x5680 ++#define REG_AVG_WINDOW_START_X_LOW 0x5681 ++#define REG_AVG_WINDOW_END_X_HIGH 0x5682 ++#define REG_AVG_WINDOW_END_X_LOW 0x5683 ++#define REG_AVG_WINDOW_START_Y_HIGH 0x5684 ++#define REG_AVG_WINDOW_START_Y_LOW 0x5685 ++#define REG_AVG_WINDOW_END_Y_HIGH 0x5686 ++#define REG_AVG_WINDOW_END_Y_LOW 0x5687 ++ ++/* active pixel array size */ ++#define OV5642_SENSOR_SIZE_X 2592 ++#define OV5642_SENSOR_SIZE_Y 1944 ++ ++/* ++ * About OV5642 resolution, cropping and binning: ++ * This sensor supports it all, at least in the feature description. ++ * Unfortunately, no combination of appropriate registers settings could make ++ * the chip work the intended way. As it works with predefined register lists, ++ * some undocumented registers are presumably changed there to achieve their ++ * goals. ++ * This driver currently only works for resolutions up to 720 lines with a ++ * 1:1 scale. Hopefully these restrictions will be removed in the future. ++ */ ++#define OV5642_MAX_WIDTH OV5642_SENSOR_SIZE_X ++#define OV5642_MAX_HEIGHT 720 ++ ++/* default sizes */ ++#define OV5642_DEFAULT_WIDTH 1280 ++#define OV5642_DEFAULT_HEIGHT OV5642_MAX_HEIGHT ++ ++/* minimum extra blanking */ ++#define BLANKING_EXTRA_WIDTH 500 ++#define BLANKING_EXTRA_HEIGHT 20 ++ ++/* ++ * the sensor's autoexposure is buggy when setting total_height low. ++ * It tries to expose longer than 1 frame period without taking care of it ++ * and this leads to weird output. So we set 1000 lines as minimum. ++ */ ++#define BLANKING_MIN_HEIGHT 1000 ++ ++struct regval_list { ++ u16 reg_num; ++ u8 value; ++}; ++ ++#ifdef USE_PREDEF ++ #include "ov5642_720p.h" ++#endif ++ ++#ifndef USE_PREDEF ++ ++static struct regval_list ov5642_default_regs_init[] = { ++ { 0x3103, 0x93 }, ++ { 0x3008, 0x82 }, ++ { 0x3017, 0x7f }, ++ { 0x3018, 0xfc }, ++ { 0x3810, 0xc2 }, ++ { 0x3615, 0xf0 }, ++ { 0x3000, 0x0 }, ++ { 0x3001, 0x0 }, ++ { 0x3002, 0x0 }, ++ { 0x3003, 0x0 }, ++ { 0x3004, 0xff }, ++ { 0x3030, 0x2b }, ++ { 0x3011, 0x8 }, ++ { 0x3010, 0x10 }, ++ { 0x3604, 0x60 }, ++ { 0x3622, 0x60 }, ++ { 0x3621, 0x9 }, ++ { 0x3709, 0x0 }, ++ { 0x4000, 0x21 }, ++ { 0x401d, 0x22 }, ++ { 0x3600, 0x54 }, ++ { 0x3605, 0x4 }, ++ { 0x3606, 0x3f }, ++ { 0x3c01, 0x80 }, ++ { 0x300d, 0x22 }, ++ { 0x3623, 0x22 }, ++ { 0x5000, 0x4f }, ++ { 0x5020, 0x4 }, ++ { 0x5181, 0x79 }, ++ { 0x5182, 0x0 }, ++ { 0x5185, 0x22 }, ++ { 0x5197, 0x1 }, ++ { 0x5500, 0xa }, ++ { 0x5504, 0x0 }, ++ { 0x5505, 0x7f }, ++ { 0x5080, 0x8 }, ++ { 0x300e, 0x18 }, ++ { 0x4610, 0x0 }, ++ { 0x471d, 0x5 }, ++ { 0x4708, 0x6 }, ++ { 0x370c, 0xa0 }, ++ { 0x5687, 0x94 }, ++ { 0x501f, 0x0 }, ++ { 0x5000, 0x4f }, ++ { 0x5001, 0xcf }, ++ { 0x4300, 0x30 }, ++ { 0x4300, 0x30 }, ++ { 0x460b, 0x35 }, ++ { 0x471d, 0x0 }, ++ { 0x3002, 0xc }, ++ { 0x3002, 0x0 }, ++ { 0x4713, 0x3 }, ++ { 0x471c, 0x50 }, ++ { 0x4721, 0x2 }, ++ { 0x4402, 0x90 }, ++ { 0x460c, 0x22 }, ++ { 0x3815, 0x44 }, ++ { 0x3503, 0x7 }, ++ { 0x3501, 0x73 }, ++ { 0x3502, 0x80 }, ++ { 0x350b, 0x0 }, ++ { 0x3818, 0xc8 }, ++ { 0x3824, 0x11 }, ++ { 0x3a00, 0x78 }, ++ { 0x3a1a, 0x4 }, ++ { 0x3a13, 0x30 }, ++ { 0x3a18, 0x0 }, ++ { 0x3a19, 0x7c }, ++ { 0x3a08, 0x12 }, ++ { 0x3a09, 0xc0 }, ++ { 0x3a0a, 0xf }, ++ { 0x3a0b, 0xa0 }, ++ { 0x350c, 0x7 }, ++ { 0x350d, 0xd0 }, ++ { 0x3a0d, 0x8 }, ++ { 0x3a0e, 0x6 }, ++ { 0x3500, 0x0 }, ++ { 0x3501, 0x0 }, ++ { 0x3502, 0x0 }, ++ { 0x350a, 0x0 }, ++ { 0x350b, 0x0 }, ++ { 0x3503, 0x0 }, ++ { 0x3a0f, 0x3c }, ++ { 0x3a10, 0x32 }, ++ { 0x3a1b, 0x3c }, ++ { 0x3a1e, 0x32 }, ++ { 0x3a11, 0x80 }, ++ { 0x3a1f, 0x20 }, ++ { 0x3030, 0x2b }, ++ { 0x3a02, 0x0 }, ++ { 0x3a03, 0x7d }, ++ { 0x3a04, 0x0 }, ++ { 0x3a14, 0x0 }, ++ { 0x3a15, 0x7d }, ++ { 0x3a16, 0x0 }, ++ { 0x3a00, 0x78 }, ++ { 0x3a08, 0x9 }, ++ { 0x3a09, 0x60 }, ++ { 0x3a0a, 0x7 }, ++ { 0x3a0b, 0xd0 }, ++ { 0x3a0d, 0x10 }, ++ { 0x3a0e, 0xd }, ++ { 0x4407, 0x4 }, ++ { 0x5193, 0x70 }, ++ { 0x589b, 0x0 }, ++ { 0x589a, 0xc0 }, ++ { 0x401e, 0x20 }, ++ { 0x4001, 0x42 }, ++ { 0x401c, 0x6 }, ++ { 0x3825, 0xac }, ++ { 0x3827, 0xc }, ++ { 0x528a, 0x1 }, ++ { 0x528b, 0x4 }, ++ { 0x528c, 0x8 }, ++ { 0x528d, 0x10 }, ++ { 0x528e, 0x20 }, ++ { 0x528f, 0x28 }, ++ { 0x5290, 0x30 }, ++ { 0x5292, 0x0 }, ++ { 0x5293, 0x1 }, ++ { 0x5294, 0x0 }, ++ { 0x5295, 0x4 }, ++ { 0x5296, 0x0 }, ++ { 0x5297, 0x8 }, ++ { 0x5298, 0x0 }, ++ { 0x5299, 0x10 }, ++ { 0x529a, 0x0 }, ++ { 0x529b, 0x20 }, ++ { 0x529c, 0x0 }, ++ { 0x529d, 0x28 }, ++ { 0x529e, 0x0 }, ++ { 0x529f, 0x30 }, ++ { 0x5282, 0x0 }, ++ { 0x5300, 0x0 }, ++ { 0x5301, 0x20 }, ++ { 0x5302, 0x0 }, ++ { 0x5303, 0x7c }, ++ { 0x530c, 0x0 }, ++ { 0x530d, 0xc }, ++ { 0x530e, 0x20 }, ++ { 0x530f, 0x80 }, ++ { 0x5310, 0x20 }, ++ { 0x5311, 0x80 }, ++ { 0x5308, 0x20 }, ++ { 0x5309, 0x40 }, ++ { 0x5304, 0x0 }, ++ { 0x5305, 0x30 }, ++ { 0x5306, 0x0 }, ++ { 0x5307, 0x80 }, ++ { 0x5314, 0x8 }, ++ { 0x5315, 0x20 }, ++ { 0x5319, 0x30 }, ++ { 0x5316, 0x10 }, ++ { 0x5317, 0x0 }, ++ { 0x5318, 0x2 }, ++ { 0x5380, 0x1 }, ++ { 0x5381, 0x0 }, ++ { 0x5382, 0x0 }, ++ { 0x5383, 0x4e }, ++ { 0x5384, 0x0 }, ++ { 0x5385, 0xf }, ++ { 0x5386, 0x0 }, ++ { 0x5387, 0x0 }, ++ { 0x5388, 0x1 }, ++ { 0x5389, 0x15 }, ++ { 0x538a, 0x0 }, ++ { 0x538b, 0x31 }, ++ { 0x538c, 0x0 }, ++ { 0x538d, 0x0 }, ++ { 0x538e, 0x0 }, ++ { 0x538f, 0xf }, ++ { 0x5390, 0x0 }, ++ { 0x5391, 0xab }, ++ { 0x5392, 0x0 }, ++ { 0x5393, 0xa2 }, ++ { 0x5394, 0x8 }, ++ { 0x5480, 0x14 }, ++ { 0x5481, 0x21 }, ++ { 0x5482, 0x36 }, ++ { 0x5483, 0x57 }, ++ { 0x5484, 0x65 }, ++ { 0x5485, 0x71 }, ++ { 0x5486, 0x7d }, ++ { 0x5487, 0x87 }, ++ { 0x5488, 0x91 }, ++ { 0x5489, 0x9a }, ++ { 0x548a, 0xaa }, ++ { 0x548b, 0xb8 }, ++ { 0x548c, 0xcd }, ++ { 0x548d, 0xdd }, ++ { 0x548e, 0xea }, ++ { 0x548f, 0x1d }, ++ { 0x5490, 0x5 }, ++ { 0x5491, 0x0 }, ++ { 0x5492, 0x4 }, ++ { 0x5493, 0x20 }, ++ { 0x5494, 0x3 }, ++ { 0x5495, 0x60 }, ++ { 0x5496, 0x2 }, ++ { 0x5497, 0xb8 }, ++ { 0x5498, 0x2 }, ++ { 0x5499, 0x86 }, ++ { 0x549a, 0x2 }, ++ { 0x549b, 0x5b }, ++ { 0x549c, 0x2 }, ++ { 0x549d, 0x3b }, ++ { 0x549e, 0x2 }, ++ { 0x549f, 0x1c }, ++ { 0x54a0, 0x2 }, ++ { 0x54a1, 0x4 }, ++ { 0x54a2, 0x1 }, ++ { 0x54a3, 0xed }, ++ { 0x54a4, 0x1 }, ++ { 0x54a5, 0xc5 }, ++ { 0x54a6, 0x1 }, ++ { 0x54a7, 0xa5 }, ++ { 0x54a8, 0x1 }, ++ { 0x54a9, 0x6c }, ++ { 0x54aa, 0x1 }, ++ { 0x54ab, 0x41 }, ++ { 0x54ac, 0x1 }, ++ { 0x54ad, 0x20 }, ++ { 0x54ae, 0x0 }, ++ { 0x54af, 0x16 }, ++ { 0x54b0, 0x1 }, ++ { 0x54b1, 0x20 }, ++ { 0x54b2, 0x0 }, ++ { 0x54b3, 0x10 }, ++ { 0x54b4, 0x0 }, ++ { 0x54b5, 0xf0 }, ++ { 0x54b6, 0x0 }, ++ { 0x54b7, 0xdf }, ++ { 0x5402, 0x3f }, ++ { 0x5403, 0x0 }, ++ { 0x3406, 0x0 }, ++ { 0x5180, 0xff }, ++ { 0x5181, 0x52 }, ++ { 0x5182, 0x11 }, ++ { 0x5183, 0x14 }, ++ { 0x5184, 0x25 }, ++ { 0x5185, 0x24 }, ++ { 0x5186, 0x6 }, ++ { 0x5187, 0x8 }, ++ { 0x5188, 0x8 }, ++ { 0x5189, 0x7c }, ++ { 0x518a, 0x60 }, ++ { 0x518b, 0xb2 }, ++ { 0x518c, 0xb2 }, ++ { 0x518d, 0x44 }, ++ { 0x518e, 0x3d }, ++ { 0x518f, 0x58 }, ++ { 0x5190, 0x46 }, ++ { 0x5191, 0xf8 }, ++ { 0x5192, 0x4 }, ++ { 0x5193, 0x70 }, ++ { 0x5194, 0xf0 }, ++ { 0x5195, 0xf0 }, ++ { 0x5196, 0x3 }, ++ { 0x5197, 0x1 }, ++ { 0x5198, 0x4 }, ++ { 0x5199, 0x12 }, ++ { 0x519a, 0x4 }, ++ { 0x519b, 0x0 }, ++ { 0x519c, 0x6 }, ++ { 0x519d, 0x82 }, ++ { 0x519e, 0x0 }, ++ { 0x5025, 0x80 }, ++ { 0x3a0f, 0x38 }, ++ { 0x3a10, 0x30 }, ++ { 0x3a1b, 0x3a }, ++ { 0x3a1e, 0x2e }, ++ { 0x3a11, 0x60 }, ++ { 0x3a1f, 0x10 }, ++ { 0x5688, 0xa6 }, ++ { 0x5689, 0x6a }, ++ { 0x568a, 0xea }, ++ { 0x568b, 0xae }, ++ { 0x568c, 0xa6 }, ++ { 0x568d, 0x6a }, ++ { 0x568e, 0x62 }, ++ { 0x568f, 0x26 }, ++ { 0x5583, 0x40 }, ++ { 0x5584, 0x40 }, ++ { 0x5580, 0x2 }, ++ { 0x5000, 0xcf }, ++ { 0x5800, 0x27 }, ++ { 0x5801, 0x19 }, ++ { 0x5802, 0x12 }, ++ { 0x5803, 0xf }, ++ { 0x5804, 0x10 }, ++ { 0x5805, 0x15 }, ++ { 0x5806, 0x1e }, ++ { 0x5807, 0x2f }, ++ { 0x5808, 0x15 }, ++ { 0x5809, 0xd }, ++ { 0x580a, 0xa }, ++ { 0x580b, 0x9 }, ++ { 0x580c, 0xa }, ++ { 0x580d, 0xc }, ++ { 0x580e, 0x12 }, ++ { 0x580f, 0x19 }, ++ { 0x5810, 0xb }, ++ { 0x5811, 0x7 }, ++ { 0x5812, 0x4 }, ++ { 0x5813, 0x3 }, ++ { 0x5814, 0x3 }, ++ { 0x5815, 0x6 }, ++ { 0x5816, 0xa }, ++ { 0x5817, 0xf }, ++ { 0x5818, 0xa }, ++ { 0x5819, 0x5 }, ++ { 0x581a, 0x1 }, ++ { 0x581b, 0x0 }, ++ { 0x581c, 0x0 }, ++ { 0x581d, 0x3 }, ++ { 0x581e, 0x8 }, ++ { 0x581f, 0xc }, ++ { 0x5820, 0xa }, ++ { 0x5821, 0x5 }, ++ { 0x5822, 0x1 }, ++ { 0x5823, 0x0 }, ++ { 0x5824, 0x0 }, ++ { 0x5825, 0x3 }, ++ { 0x5826, 0x8 }, ++ { 0x5827, 0xc }, ++ { 0x5828, 0xe }, ++ { 0x5829, 0x8 }, ++ { 0x582a, 0x6 }, ++ { 0x582b, 0x4 }, ++ { 0x582c, 0x5 }, ++ { 0x582d, 0x7 }, ++ { 0x582e, 0xb }, ++ { 0x582f, 0x12 }, ++ { 0x5830, 0x18 }, ++ { 0x5831, 0x10 }, ++ { 0x5832, 0xc }, ++ { 0x5833, 0xa }, ++ { 0x5834, 0xb }, ++ { 0x5835, 0xe }, ++ { 0x5836, 0x15 }, ++ { 0x5837, 0x19 }, ++ { 0x5838, 0x32 }, ++ { 0x5839, 0x1f }, ++ { 0x583a, 0x18 }, ++ { 0x583b, 0x16 }, ++ { 0x583c, 0x17 }, ++ { 0x583d, 0x1e }, ++ { 0x583e, 0x26 }, ++ { 0x583f, 0x53 }, ++ { 0x5840, 0x10 }, ++ { 0x5841, 0xf }, ++ { 0x5842, 0xd }, ++ { 0x5843, 0xc }, ++ { 0x5844, 0xe }, ++ { 0x5845, 0x9 }, ++ { 0x5846, 0x11 }, ++ { 0x5847, 0x10 }, ++ { 0x5848, 0x10 }, ++ { 0x5849, 0x10 }, ++ { 0x584a, 0x10 }, ++ { 0x584b, 0xe }, ++ { 0x584c, 0x10 }, ++ { 0x584d, 0x10 }, ++ { 0x584e, 0x11 }, ++ { 0x584f, 0x10 }, ++ { 0x5850, 0xf }, ++ { 0x5851, 0xc }, ++ { 0x5852, 0xf }, ++ { 0x5853, 0x10 }, ++ { 0x5854, 0x10 }, ++ { 0x5855, 0xf }, ++ { 0x5856, 0xe }, ++ { 0x5857, 0xb }, ++ { 0x5858, 0x10 }, ++ { 0x5859, 0xd }, ++ { 0x585a, 0xd }, ++ { 0x585b, 0xc }, ++ { 0x585c, 0xc }, ++ { 0x585d, 0xc }, ++ { 0x585e, 0xb }, ++ { 0x585f, 0xc }, ++ { 0x5860, 0xc }, ++ { 0x5861, 0xc }, ++ { 0x5862, 0xd }, ++ { 0x5863, 0x8 }, ++ { 0x5864, 0x11 }, ++ { 0x5865, 0x18 }, ++ { 0x5866, 0x18 }, ++ { 0x5867, 0x19 }, ++ { 0x5868, 0x17 }, ++ { 0x5869, 0x19 }, ++ { 0x586a, 0x16 }, ++ { 0x586b, 0x13 }, ++ { 0x586c, 0x13 }, ++ { 0x586d, 0x12 }, ++ { 0x586e, 0x13 }, ++ { 0x586f, 0x16 }, ++ { 0x5870, 0x14 }, ++ { 0x5871, 0x12 }, ++ { 0x5872, 0x10 }, ++ { 0x5873, 0x11 }, ++ { 0x5874, 0x11 }, ++ { 0x5875, 0x16 }, ++ { 0x5876, 0x14 }, ++ { 0x5877, 0x11 }, ++ { 0x5878, 0x10 }, ++ { 0x5879, 0xf }, ++ { 0x587a, 0x10 }, ++ { 0x587b, 0x14 }, ++ { 0x587c, 0x13 }, ++ { 0x587d, 0x12 }, ++ { 0x587e, 0x11 }, ++ { 0x587f, 0x11 }, ++ { 0x5880, 0x12 }, ++ { 0x5881, 0x15 }, ++ { 0x5882, 0x14 }, ++ { 0x5883, 0x15 }, ++ { 0x5884, 0x15 }, ++ { 0x5885, 0x15 }, ++ { 0x5886, 0x13 }, ++ { 0x5887, 0x17 }, ++ { 0x3710, 0x10 }, ++ { 0x3632, 0x51 }, ++ { 0x3702, 0x10 }, ++ { 0x3703, 0xb2 }, ++ { 0x3704, 0x18 }, ++ { 0x370b, 0x40 }, ++ { 0x370d, 0x3 }, ++ { 0x3631, 0x1 }, ++ { 0x3632, 0x52 }, ++ { 0x3606, 0x24 }, ++ { 0x3620, 0x96 }, ++ { 0x5785, 0x7 }, ++ { 0x3a13, 0x30 }, ++ { 0x3600, 0x52 }, ++ { 0x3604, 0x48 }, ++ { 0x3606, 0x1b }, ++ { 0x370d, 0xb }, ++ { 0x370f, 0xc0 }, ++ { 0x3709, 0x1 }, ++ { 0x3823, 0x0 }, ++ { 0x5007, 0x0 }, ++ { 0x5009, 0x0 }, ++ { 0x5011, 0x0 }, ++ { 0x5013, 0x0 }, ++ { 0x519e, 0x0 }, ++ { 0x5086, 0x0 }, ++ { 0x5087, 0x0 }, ++ { 0x5088, 0x0 }, ++ { 0x5089, 0x0 }, ++ { 0x302b, 0x0 }, ++ { 0x3503, 0x7 }, ++ { 0x3011, 0x8 }, ++ { 0x350c, 0x2 }, ++ { 0x350d, 0xe4 }, ++ { 0x3621, 0xc9 }, ++ { 0x370a, 0x81 }, ++ { 0xffff, 0xff }, ++}; ++ ++static struct regval_list ov5642_default_regs_finalise[] = { ++ { 0x3810, 0xc2 }, ++ { 0x3818, 0xc9 }, ++ { 0x381c, 0x10 }, ++ { 0x381d, 0xa0 }, ++ { 0x381e, 0x5 }, ++ { 0x381f, 0xb0 }, ++ { 0x3820, 0x0 }, ++ { 0x3821, 0x0 }, ++ { 0x3824, 0x11 }, ++ { 0x3a08, 0x1b }, ++ { 0x3a09, 0xc0 }, ++ { 0x3a0a, 0x17 }, ++ { 0x3a0b, 0x20 }, ++ { 0x3a0d, 0x2 }, ++ { 0x3a0e, 0x1 }, ++ { 0x401c, 0x4 }, ++ { 0x5682, 0x5 }, ++ { 0x5683, 0x0 }, ++ { 0x5686, 0x2 }, ++ { 0x5687, 0xcc }, ++ { 0x5001, 0x4f }, ++ { 0x589b, 0x6 }, ++ { 0x589a, 0xc5 }, ++ { 0x3503, 0x0 }, ++ { 0x460c, 0x20 }, ++ { 0x460b, 0x37 }, ++ { 0x471c, 0xd0 }, ++ { 0x471d, 0x5 }, ++ { 0x3815, 0x1 }, ++ { 0x3818, 0xc1 }, ++ { 0x501f, 0x0 }, ++ { 0x5002, 0xe0 }, ++ { 0x4300, 0x32 }, /* UYVY */ ++ { 0x3002, 0x1c }, ++ { 0x4800, 0x14 }, ++ { 0x4801, 0xf }, ++ { 0x3007, 0x3b }, ++ { 0x300e, 0x4 }, ++ { 0x4803, 0x50 }, ++ { 0x3815, 0x1 }, ++ { 0x4713, 0x2 }, ++ { 0x4842, 0x1 }, ++ { 0x300f, 0xe }, ++ { 0x3003, 0x3 }, ++ { 0x3003, 0x1 }, ++ { 0xffff, 0xff }, ++}; ++ ++#endif ++ ++#endif /* _OV5642_H_ */ +diff --git a/drivers/media/i2c/soc_camera/ov5642_720p.h b/drivers/media/i2c/soc_camera/ov5642_720p.h +new file mode 100644 +index 0000000..d5a52e3 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov5642_720p.h +@@ -0,0 +1,711 @@ ++/* Settings array from ++ * From 5e8e49e226b29c144ddf482afe7d3ad659c9897f Mon Sep 17 00:00:00 2001 ++ * From: Kazuya Nishimura <kazuya.nishimura@windriver.com> ++ * Date: Mon, 20 Oct 2014 15:12:56 +0900 ++ * Subject: [PATCH] Enabled VIN driver for MMB ++ */ ++ ++/* 720p 30fps @ 1280x720 */ ++/* for the setting , 24MHz Mlck input and 90MHz Plck output */ ++/* refer to OV5642.c */ ++ ++static struct regval_list OV5642_720P_30FPS[] = ++{ ++ {0x3103, 0x93}, ++ {0x3008, 0x82}, ++ {0x3017, 0x7f}, ++ {0x3018, 0xfc}, ++ /* drive capability 4x */ ++ { 0x302c, (3 << 5) | 0x02 }, ++ {0x3810, 0xc2}, ++ {0x3615, 0xf0}, ++ {0x3000, 0x00}, ++ {0x3001, 0x00}, ++ {0x3002, 0x00}, ++ {0x3003, 0x00}, ++ {0x3000, 0xf8}, ++ {0x3001, 0x48}, ++ {0x3002, 0x5c}, ++ {0x3003, 0x02}, ++ {0x3004, 0x07}, ++ {0x3005, 0xb7}, ++ {0x3006, 0x43}, ++ {0x3007, 0x37}, ++ {0x3011, 0x0f}, //PLL CONTROL 02 : Bit[5:0] PLL DIVP divider ++ {0x3010, 0x10}, //PLL CONTROL 01 : Bit[7:4] PLL DIVS, Bit[3:0] PLL DIVM (MIPI divider ratio) ++ //29-30fps ++ {0x460c, 0x22}, ++ {0x3815, 0x04}, ++ {0x370d, 0x06}, ++ {0x370c, 0xa0}, ++ {0x3602, 0xfc}, ++ {0x3612, 0xff}, ++ {0x3634, 0xc0}, ++ {0x3613, 0x00}, ++ {0x3605, 0x7c}, ++ {0x3621, 0x09}, ++ {0x3622, 0x00}, ++ {0x3604, 0x40}, ++ {0x3603, 0xa7}, ++ {0x3603, 0x27}, ++ {0x4000, 0x21}, ++ {0x401d, 0x02}, ++ {0x3600, 0x54}, ++ {0x3605, 0x04}, ++ {0x3606, 0x3f}, ++ {0x3c01, 0x80}, ++ {REG_ISP_CTRL_00, 0x4f}, ++ {0x4300, 0x32}, /* YUV422: UYVY... */ ++ {0x5020, 0x04}, ++ {0x5181, 0x79}, ++ {0x5182, 0x00}, ++ {0x5185, 0x22}, ++ {0x5197, 0x01}, ++ {REG_ISP_CTRL_01, 0xff}, ++ {0x5500, 0x0a}, ++ {0x5504, 0x00}, ++ {0x5505, 0x7f}, ++ {0x5080, 0x08}, ++ {0x300e, 0x18}, ++ {0x4610, 0x00}, ++ {0x471d, 0x05}, ++ {0x4708, 0x06}, ++ /* POLARITY CTRL 00 ++ * [0] VSYNC - act low ++ * [1] HREF - act low ++ * [2] gate PCLK under HREF - no ++ * [3] gate PCLK under VSYNK - no ++ * [5] PCLK - falling edge ++ */ ++ {0x4740, 0x20}, ++ {0x3710, 0x10}, ++ {0x3632, 0x41}, ++ {0x3702, 0x40}, ++ {0x3620, 0x37}, ++ {0x3631, 0x01}, ++ {REG_OUT_WIDTH_HIGH, 0x02}, // TIMING DVPHO Bit[3:0] DVP output horizontal width high byte ++ {REG_OUT_WIDTH_LOW, 0x80}, // TIMING DVPHO Bit[7:0] DVP output horizontal width low byte ++ // 0x280 => 640 ++ {REG_OUT_HEIGHT_HIGH, 0x01}, // TIMING DVPVO Bit[3:0] DVP output vertical height high byte ++ {REG_OUT_HEIGHT_LOW, 0xe0}, // TIMING DVPVO Bit[7:0] DVP output vertical height low byte ++ // 0x1e0 => 480 ++ {REG_OUT_TOTAL_HEIGHT_HIGH, 0x07}, // TIMING VTS Bit[3:0] Total vertical size high byte [11:8] ++ {REG_OUT_TOTAL_HEIGHT_LOW, 0xd0}, // TIMING VTS Bit[7:0] Total vertical size low byte [7:0] ++ // 0x7d0 => 2000 ++ {0x501f, 0x00}, ++ {REG_ISP_CTRL_00, 0x4f}, ++ {REG_OUTPUT_FORMAT, 0x32}, //UYVY ++ {0x3503, 0x07}, ++ {0x3501, 0x73}, ++ {0x3502, 0x80}, ++ {0x350b, 0x00}, ++ {0x3503, 0x07}, ++ {0x3824, 0x11}, ++ {0x3501, 0x1e}, ++ {0x3502, 0x80}, ++ {0x350b, 0x7f}, ++ {REG_OUT_TOTAL_WIDTH_HIGH, 0x0c}, ++ {REG_OUT_TOTAL_WIDTH_LOW, 0x80}, ++ {REG_OUT_TOTAL_HEIGHT_HIGH, 0x03}, // TIMING VTS Bit[3:0] Total vertical size high byte [11:8] ++ {REG_OUT_TOTAL_HEIGHT_LOW, 0xe8}, // TIMING VTS Bit[7:0] Total vertical size low byte [7:0] ++ // 0x3e8 => 1000 ++ {0x3a0d, 0x04}, ++ {0x3a0e, 0x03}, ++ {0x3818, 0xc1}, ++ {0x3705, 0xdb}, ++ {0x370a, 0x81}, ++ {REG_WINDOW_START_X_LOW, 0x80}, ++ {0x3621, 0xc7}, ++ {REG_WINDOW_START_X_LOW, 0x50}, ++ {REG_WINDOW_START_Y_LOW, 0x08}, ++ {0x3827, 0x08}, ++ {0x3810, 0xc0}, ++ {REG_WINDOW_WIDTH_HIGH, 0x05}, ++ {REG_WINDOW_WIDTH_LOW, 0x00}, ++ {REG_AVG_WINDOW_END_X_HIGH, 0x05}, ++ {REG_AVG_WINDOW_END_X_LOW, 0x00}, ++ {REG_WINDOW_HEIGHT_HIGH, 0x03}, ++ {REG_WINDOW_HEIGHT_LOW, 0xc0}, ++ {REG_AVG_WINDOW_END_Y_HIGH, 0x03}, ++ {REG_AVG_WINDOW_END_Y_LOW, 0xc0}, ++ {0x3a00, 0x78}, ++ {0x3a1a, 0x04}, ++ {0x3a13, 0x30}, ++ {0x3a18, 0x00}, ++ {0x3a19, 0x7c}, ++ {0x3a08, 0x12}, ++ {0x3a09, 0xc0}, ++ {0x3a0a, 0x0f}, ++ {0x3a0b, 0xa0}, ++ {0x3004, 0xff}, ++ {0x350c, 0x07}, ++ {0x350d, 0xd0}, ++ {0x3500, 0x00}, ++ {0x3501, 0x00}, ++ {0x3502, 0x00}, ++ {0x350a, 0x00}, ++ {0x350b, 0x00}, ++ {0x3503, 0x00}, ++ {0x528a, 0x02}, ++ {0x528b, 0x04}, ++ {0x528c, 0x08}, ++ {0x528d, 0x08}, ++ {0x528e, 0x08}, ++ {0x528f, 0x10}, ++ {0x5290, 0x10}, ++ {0x5292, 0x00}, ++ {0x5293, 0x02}, ++ {0x5294, 0x00}, ++ {0x5295, 0x02}, ++ {0x5296, 0x00}, ++ {0x5297, 0x02}, ++ {0x5298, 0x00}, ++ {0x5299, 0x02}, ++ {0x529a, 0x00}, ++ {0x529b, 0x02}, ++ {0x529c, 0x00}, ++ {0x529d, 0x02}, ++ {0x529e, 0x00}, ++ {0x529f, 0x02}, ++ {0x3a0f, 0x3c}, ++ {0x3a10, 0x30}, ++ {0x3a1b, 0x3c}, ++ {0x3a1e, 0x30}, ++ {0x3a11, 0x70}, ++ {0x3a1f, 0x10}, ++ {0x3030, 0x0b}, ++ {0x3a02, 0x00}, ++ {0x3a03, 0x7d}, ++ {0x3a04, 0x00}, ++ {0x3a14, 0x00}, ++ {0x3a15, 0x7d}, ++ {0x3a16, 0x00}, ++ {0x3a00, 0x78}, ++ {0x3a08, 0x09}, ++ {0x3a09, 0x60}, ++ {0x3a0a, 0x07}, ++ {0x3a0b, 0xd0}, ++ {0x3a0d, 0x08}, ++ {0x3a0e, 0x06}, ++ {0x5193, 0x70}, ++ {0x3620, 0x57}, ++ {0x3703, 0x98}, ++ {0x3704, 0x1c}, ++ {0x589b, 0x04}, ++ {0x589a, 0xc5}, ++ {0x528a, 0x00}, ++ {0x528b, 0x02}, ++ {0x528c, 0x08}, ++ {0x528d, 0x10}, ++ {0x528e, 0x20}, ++ {0x528f, 0x28}, ++ {0x5290, 0x30}, ++ {0x5292, 0x00}, ++ {0x5293, 0x00}, ++ {0x5294, 0x00}, ++ {0x5295, 0x02}, ++ {0x5296, 0x00}, ++ {0x5297, 0x08}, ++ {0x5298, 0x00}, ++ {0x5299, 0x10}, ++ {0x529a, 0x00}, ++ {0x529b, 0x20}, ++ {0x529c, 0x00}, ++ {0x529d, 0x28}, ++ {0x529e, 0x00}, ++ {0x529f, 0x30}, ++ {0x5282, 0x00}, ++ {0x5300, 0x00}, ++ {0x5301, 0x20}, ++ {0x5302, 0x00}, ++ {0x5303, 0x7c}, ++ {0x530c, 0x00}, ++ {0x530d, 0x0c}, ++ {0x530e, 0x20}, ++ {0x530f, 0x80}, ++ {0x5310, 0x20}, ++ {0x5311, 0x80}, ++ {0x5308, 0x20}, ++ {0x5309, 0x40}, ++ {0x5304, 0x00}, ++ {0x5305, 0x30}, ++ {0x5306, 0x00}, ++ {0x5307, 0x80}, ++ {0x5314, 0x08}, ++ {0x5315, 0x20}, ++ {0x5319, 0x30}, ++ {0x5316, 0x10}, ++ {0x5317, 0x08}, ++ {0x5318, 0x02}, ++ {0x5380, 0x01}, ++ {0x5381, 0x00}, ++ {0x5382, 0x00}, ++ {0x5383, 0x4e}, ++ {0x5384, 0x00}, ++ {0x5385, 0x0f}, ++ {0x5386, 0x00}, ++ {0x5387, 0x00}, ++ {0x5388, 0x01}, ++ {0x5389, 0x15}, ++ {0x538a, 0x00}, ++ {0x538b, 0x31}, ++ {0x538c, 0x00}, ++ {0x538d, 0x00}, ++ {0x538e, 0x00}, ++ {0x538f, 0x0f}, ++ {0x5390, 0x00}, ++ {0x5391, 0xab}, ++ {0x5392, 0x00}, ++ {0x5393, 0xa2}, ++ {0x5394, 0x08}, ++ {0x5480, 0x14}, ++ {0x5481, 0x21}, ++ {0x5482, 0x36}, ++ {0x5483, 0x57}, ++ {0x5484, 0x65}, ++ {0x5485, 0x71}, ++ {0x5486, 0x7d}, ++ {0x5487, 0x87}, ++ {0x5488, 0x91}, ++ {0x5489, 0x9a}, ++ {0x548a, 0xaa}, ++ {0x548b, 0xb8}, ++ {0x548c, 0xcd}, ++ {0x548d, 0xdd}, ++ {0x548e, 0xea}, ++ {0x548f, 0x10}, ++ {0x5490, 0x05}, ++ {0x5491, 0x00}, ++ {0x5492, 0x04}, ++ {0x5493, 0x20}, ++ {0x5494, 0x03}, ++ {0x5495, 0x60}, ++ {0x5496, 0x02}, ++ {0x5497, 0xb8}, ++ {0x5498, 0x02}, ++ {0x5499, 0x86}, ++ {0x549a, 0x02}, ++ {0x549b, 0x5b}, ++ {0x549c, 0x02}, ++ {0x549d, 0x3b}, ++ {0x549e, 0x02}, ++ {0x549f, 0x1c}, ++ {0x54a0, 0x02}, ++ {0x54a1, 0x04}, ++ {0x54a2, 0x01}, ++ {0x54a3, 0xed}, ++ {0x54a4, 0x01}, ++ {0x54a5, 0xc5}, ++ {0x54a6, 0x01}, ++ {0x54a7, 0xa5}, ++ {0x54a8, 0x01}, ++ {0x54a9, 0x6c}, ++ {0x54aa, 0x01}, ++ {0x54ab, 0x41}, ++ {0x54ac, 0x01}, ++ {0x54ad, 0x20}, ++ {0x54ae, 0x00}, ++ {0x54af, 0x16}, ++ {0x3406, 0x00}, ++ {0x5192, 0x04}, ++ {0x5191, 0xf8}, ++ {0x5193, 0x70}, ++ {0x5194, 0xf0}, ++ {0x5195, 0xf0}, ++ {0x518d, 0x3d}, ++ {0x518f, 0x54}, ++ {0x518e, 0x3d}, ++ {0x5190, 0x54}, ++ {0x518b, 0xc0}, ++ {0x518c, 0xbd}, ++ {0x5187, 0x18}, ++ {0x5188, 0x18}, ++ {0x5189, 0x6e}, ++ {0x518a, 0x68}, ++ {0x5186, 0x1c}, ++ {0x5181, 0x50}, ++ {0x5184, 0x25}, ++ {0x5182, 0x11}, ++ {0x5183, 0x14}, ++ {0x5184, 0x25}, ++ {0x5185, 0x24}, ++ {0x5025, 0x82}, ++ {0x3a0f, 0x7e}, ++ {0x3a10, 0x72}, ++ {0x3a1b, 0x80}, ++ {0x3a1e, 0x70}, ++ {0x3a11, 0xd0}, ++ {0x3a1f, 0x40}, ++ {0x5583, 0x40}, ++ {0x5584, 0x40}, ++ {0x5580, 0x02}, ++ {0x3633, 0x07}, ++ {0x3702, 0x10}, ++ {0x3703, 0xb2}, ++ {0x3704, 0x18}, ++ {0x370b, 0x40}, ++ {0x370d, 0x02}, ++ {0x3620, 0x52}, ++ {0x3c00, 0x04}, ++ ++ {REG_ISP_CTRL_01, 0xFF}, ++ {0x5583, 0x50}, ++ {0x5584, 0x50}, ++ {0x5580, 0x02}, ++ {0x3c01, 0x80}, ++ {0x3c00, 0x04}, ++ {0x5800, 0x27}, ++ {0x5801, 0x22}, ++ {0x5802, 0x1b}, ++ {0x5803, 0x17}, ++ {0x5804, 0x16}, ++ {0x5805, 0x18}, ++ {0x5806, 0x20}, ++ {0x5807, 0x20}, ++ {0x5808, 0x1b}, ++ {0x5809, 0x15}, ++ {0x580a, 0x0f}, ++ {0x580b, 0x0d}, ++ {0x580c, 0x0d}, ++ {0x580d, 0x0e}, ++ {0x580e, 0x11}, ++ {0x580f, 0x18}, ++ {0x5810, 0x10}, ++ {0x5811, 0x0d}, ++ {0x5812, 0x08}, ++ {0x5813, 0x05}, ++ {0x5814, 0x04}, ++ {0x5815, 0x06}, ++ {0x5816, 0x09}, ++ {0x5817, 0x0e}, ++ {0x5818, 0x0d}, ++ {0x5819, 0x09}, ++ {0x581a, 0x03}, ++ {0x581b, 0x00}, ++ {0x581c, 0x00}, ++ {0x581d, 0x01}, ++ {0x581e, 0x05}, ++ {0x581f, 0x0b}, ++ {0x5820, 0x0d}, ++ {0x5821, 0x09}, ++ {0x5822, 0x03}, ++ {0x5823, 0x00}, ++ {0x5824, 0x00}, ++ {0x5825, 0x01}, ++ {0x5826, 0x05}, ++ {0x5827, 0x0b}, ++ {0x5828, 0x10}, ++ {0x5829, 0x0c}, ++ {0x582a, 0x08}, ++ {0x582b, 0x04}, ++ {0x582c, 0x03}, ++ {0x582d, 0x05}, ++ {0x582e, 0x09}, ++ {0x582f, 0x0e}, ++ {0x5830, 0x1b}, ++ {0x5831, 0x14}, ++ {0x5832, 0x0f}, ++ {0x5833, 0x0c}, ++ {0x5834, 0x0c}, ++ {0x5835, 0x0d}, ++ {0x5836, 0x10}, ++ {0x5837, 0x19}, ++ {0x5838, 0x25}, ++ {0x5839, 0x23}, ++ {0x583a, 0x1a}, ++ {0x583b, 0x16}, ++ {0x583c, 0x15}, ++ {0x583d, 0x18}, ++ {0x583e, 0x1f}, ++ {0x583f, 0x25}, ++ {0x5840, 0x10}, ++ {0x5841, 0x0e}, ++ {0x5842, 0x0e}, ++ {0x5843, 0x0e}, ++ {0x5844, 0x0f}, ++ {0x5845, 0x0a}, ++ {0x5846, 0x08}, ++ {0x5847, 0x0f}, ++ {0x5848, 0x0f}, ++ {0x5849, 0x0f}, ++ {0x584a, 0x0c}, ++ {0x584b, 0x0f}, ++ {0x584c, 0x09}, ++ {0x584d, 0x10}, ++ {0x584e, 0x11}, ++ {0x584f, 0x10}, ++ {0x5850, 0x0f}, ++ {0x5851, 0x0e}, ++ {0x5852, 0x08}, ++ {0x5853, 0x10}, ++ {0x5854, 0x10}, ++ {0x5855, 0x10}, ++ {0x5856, 0x0e}, ++ {0x5857, 0x0e}, ++ {0x5858, 0x0a}, ++ {0x5859, 0x0e}, ++ {0x585a, 0x0e}, ++ {0x585b, 0x0e}, ++ {0x585c, 0x0e}, ++ {0x585d, 0x0d}, ++ {0x585e, 0x08}, ++ {0x585f, 0x0b}, ++ {0x5860, 0x0a}, ++ {0x5861, 0x0a}, ++ {0x5862, 0x09}, ++ {0x5863, 0x0d}, ++ {0x5864, 0x13}, ++ {0x5865, 0x0e}, ++ {0x5866, 0x10}, ++ {0x5867, 0x10}, ++ {0x5868, 0x0e}, ++ {0x5869, 0x11}, ++ {0x586a, 0x12}, ++ {0x586b, 0x10}, ++ {0x586c, 0x10}, ++ {0x586d, 0x10}, ++ {0x586e, 0x10}, ++ {0x586f, 0x11}, ++ {0x5870, 0x15}, ++ {0x5871, 0x10}, ++ {0x5872, 0x10}, ++ {0x5873, 0x10}, ++ {0x5874, 0x11}, ++ {0x5875, 0x11}, ++ {0x5876, 0x14}, ++ {0x5877, 0x0f}, ++ {0x5878, 0x10}, ++ {0x5879, 0x10}, ++ {0x587a, 0x10}, ++ {0x587b, 0x11}, ++ {0x587c, 0x12}, ++ {0x587d, 0x0f}, ++ {0x587e, 0x0f}, ++ {0x587f, 0x10}, ++ {0x5880, 0x10}, ++ {0x5881, 0x0f}, ++ {0x5882, 0x12}, ++ {0x5883, 0x0e}, ++ {0x5884, 0x10}, ++ {0x5885, 0x10}, ++ {0x5886, 0x0e}, ++ {0x5887, 0x0e}, ++ {0x5180, 0xff}, ++ {0x5181, 0x52}, ++ {0x5182, 0x11}, ++ {0x5183, 0x14}, ++ {0x5184, 0x25}, ++ {0x5185, 0x24}, ++ {0x5186, 0x14}, ++ {0x5187, 0x14}, ++ {0x5188, 0x14}, ++ {0x5189, 0x6c}, ++ {0x518a, 0x60}, ++ {0x518b, 0xbd}, ++ {0x518c, 0x9c}, ++ {0x518d, 0x3d}, ++ {0x518e, 0x34}, ++ {0x518f, 0x57}, ++ {0x5190, 0x4a}, ++ {0x5191, 0xf8}, ++ {0x5192, 0x04}, ++ {0x5193, 0x70}, ++ {0x5194, 0xf0}, ++ {0x5195, 0xf0}, ++ {0x5196, 0x03}, ++ {0x5197, 0x01}, ++ {0x5198, 0x04}, ++ {0x5199, 0x00}, ++ {0x519a, 0x04}, ++ {0x519b, 0x35}, ++ {0x519c, 0x08}, ++ {0x519d, 0xb8}, ++ {0x519e, 0xa0}, ++ {0x528a, 0x00}, ++ {0x528b, 0x01}, ++ {0x528c, 0x04}, ++ {0x528d, 0x08}, ++ {0x528e, 0x10}, ++ {0x528f, 0x20}, ++ {0x5290, 0x30}, ++ {0x5292, 0x00}, ++ {0x5293, 0x00}, ++ {0x5294, 0x00}, ++ {0x5295, 0x01}, ++ {0x5296, 0x00}, ++ {0x5297, 0x04}, ++ {0x5298, 0x00}, ++ {0x5299, 0x08}, ++ {0x529a, 0x00}, ++ {0x529b, 0x10}, ++ {0x529c, 0x00}, ++ {0x529d, 0x20}, ++ {0x529e, 0x00}, ++ {0x529f, 0x30}, ++ {0x5282, 0x00}, ++ {0x5300, 0x00}, ++ {0x5301, 0x20}, ++ {0x5302, 0x00}, ++ {0x5303, 0x7c}, ++ {0x530c, 0x00}, ++ {0x530d, 0x10}, ++ {0x530e, 0x20}, ++ {0x530f, 0x80}, ++ {0x5310, 0x20}, ++ {0x5311, 0x80}, ++ {0x5308, 0x20}, ++ {0x5309, 0x40}, ++ {0x5304, 0x00}, ++ {0x5305, 0x30}, ++ {0x5306, 0x00}, ++ {0x5307, 0x80}, ++ {0x5314, 0x08}, ++ {0x5315, 0x20}, ++ {0x5319, 0x30}, ++ {0x5316, 0x10}, ++ {0x5317, 0x00}, ++ {0x5318, 0x02}, ++ {0x5380, 0x01}, ++ {0x5381, 0x00}, ++ {0x5382, 0x00}, ++ {0x5383, 0x1f}, ++ {0x5384, 0x00}, ++ {0x5385, 0x06}, ++ {0x5386, 0x00}, ++ {0x5387, 0x00}, ++ {0x5388, 0x00}, ++ {0x5389, 0xE1}, ++ {0x538A, 0x00}, ++ {0x538B, 0x2B}, ++ {0x538C, 0x00}, ++ {0x538D, 0x00}, ++ {0x538E, 0x00}, ++ {0x538F, 0x10}, ++ {0x5390, 0x00}, ++ {0x5391, 0xB3}, ++ {0x5392, 0x00}, ++ {0x5393, 0xA6}, ++ {0x5394, 0x08}, ++ {0x5480, 0x14}, ++ {0x5481, 0x21}, ++ {0x5482, 0x36}, ++ {0x5483, 0x57}, ++ {0x5484, 0x65}, ++ {0x5485, 0x71}, ++ {0x5486, 0x7D}, ++ {0x5487, 0x87}, ++ {0x5488, 0x91}, ++ {0x5489, 0x9A}, ++ {0x548A, 0xAA}, ++ {0x548B, 0xB8}, ++ {0x548C, 0xCD}, ++ {0x548D, 0xDD}, ++ {0x548E, 0xEA}, ++ {0x548F, 0x1d}, ++ {0x5490, 0x05}, ++ {0x5491, 0x00}, ++ {0x5492, 0x04}, ++ {0x5493, 0x20}, ++ {0x5494, 0x03}, ++ {0x5495, 0x60}, ++ {0x5496, 0x02}, ++ {0x5497, 0xB8}, ++ {0x5498, 0x02}, ++ {0x5499, 0x86}, ++ {0x549A, 0x02}, ++ {0x549B, 0x5B}, ++ {0x549C, 0x02}, ++ {0x549D, 0x3B}, ++ {0x549E, 0x02}, ++ {0x549F, 0x1C}, ++ {0x54A0, 0x02}, ++ {0x54A1, 0x04}, ++ {0x54A2, 0x01}, ++ {0x54A3, 0xED}, ++ {0x54A4, 0x01}, ++ {0x54A5, 0xC5}, ++ {0x54A6, 0x01}, ++ {0x54A7, 0xA5}, ++ {0x54A8, 0x01}, ++ {0x54A9, 0x6C}, ++ {0x54AA, 0x01}, ++ {0x54AB, 0x41}, ++ {0x54AC, 0x01}, ++ {0x54AD, 0x20}, ++ {0x54AE, 0x00}, ++ {0x54AF, 0x16}, ++ {0x54B0, 0x01}, ++ {0x54B1, 0x20}, ++ {0x54B2, 0x00}, ++ {0x54B3, 0x10}, ++ {0x54B4, 0x00}, ++ {0x54B5, 0xf0}, ++ {0x54B6, 0x00}, ++ {0x54B7, 0xDF}, ++ {0x5402, 0x3f}, ++ {0x5403, 0x00}, ++ {0x5500, 0x10}, ++ {0x5502, 0x00}, ++ {0x5503, 0x06}, ++ {0x5504, 0x00}, ++ {0x5505, 0x7f}, ++ {0x5025, 0x80}, ++ {0x3a0f, 0x48}, //0x30 ++ {0x3a10, 0x38}, //0x28 ++ {0x3a1b, 0x50}, //0x30 ++ {0x3a1e, 0x30}, //0x28 ++ {0x3a11, 0x71}, //0x61 ++ {0x3a1f, 0x10}, ++ {0x5688, 0xfd}, ++ {0x5689, 0xdf}, ++ {0x568a, 0xfe}, ++ {0x568b, 0xef}, ++ {0x568c, 0xfe}, ++ {0x568d, 0xef}, ++ {0x568e, 0xaa}, ++ {0x568f, 0xaa}, ++ ++ {REG_WINDOW_START_X_HIGH, 0x1 }, ++ {REG_WINDOW_START_X_LOW, 0x50}, ++ //0x150 = 336 ++ {REG_WINDOW_START_Y_HIGH, 0x0 }, ++ {REG_WINDOW_START_Y_LOW, 0x8 }, ++ //0x8 = 8 ++ {REG_WINDOW_WIDTH_HIGH, 0x5 }, ++ {REG_WINDOW_WIDTH_LOW, 0x0 }, ++ //0x500 = 1280 ++ {REG_WINDOW_HEIGHT_HIGH, 0x3 }, ++ {REG_WINDOW_HEIGHT_LOW, 0xc0}, ++ //0x3c0 = 960 ++ {REG_OUT_WIDTH_HIGH, 0x5 }, // TIMING DVPHO Bit[3:0] DVP output horizontal width high byte ++ {REG_OUT_WIDTH_LOW, 0x00}, // TIMING DVPHO Bit[7:0] DVP output horizontal width low byte ++ // 0x500 => 1280 ++ {REG_OUT_HEIGHT_HIGH, 0x2 }, // TIMING DVPVO Bit[3:0] DVP output vertical height high byte ++// {REG_OUT_HEIGHT_LOW, 0xd0}, // TIMING DVPVO Bit[7:0] DVP output vertical height low byte ++ // 0x2d0 => 720 ++ {REG_OUT_HEIGHT_LOW, 0xd5}, // TIMING DVPVO Bit[7:0] DVP output vertical height low byte ++ // 0x2d5 => 725 ++ {REG_OUT_TOTAL_WIDTH_HIGH, 0xc }, // TIMING HTS Bit[3:0] Total horizontal size high byte [11:8] ++ {REG_OUT_TOTAL_WIDTH_LOW, 0x80}, // TIMING HTS Bit[7:0] Total horizontal size low byte [7:0] ++ // 0xc80 => 3200 ++ {REG_OUT_TOTAL_HEIGHT_HIGH, 0x3 }, // TIMING VTS Bit[3:0] Total vertical size high byte [11:8] ++ {REG_OUT_TOTAL_HEIGHT_LOW, 0xe8}, // TIMING VTS Bit[7:0] Total vertical size low byte [7:0] ++ // 0x3e8 => 1000 ++ {REG_ISP_CTRL_01, 0x7f}, ++ {REG_AVG_WINDOW_START_X_HIGH, 0x0 }, ++ {REG_AVG_WINDOW_START_X_LOW, 0x0 }, ++ {REG_AVG_WINDOW_END_X_HIGH, 0x5 }, ++ {REG_AVG_WINDOW_END_X_LOW, 0x0 }, ++ {REG_AVG_WINDOW_START_Y_HIGH, 0x0 }, ++ {REG_AVG_WINDOW_START_Y_LOW, 0x0 }, ++ {REG_AVG_WINDOW_END_Y_HIGH, 0x3 }, ++ //{REG_AVG_WINDOW_END_Y_LOW, 0xc0}, ++ {REG_AVG_WINDOW_END_Y_LOW, 0xc0}, ++ {0x3815, 0x02}, ++ {0x3503, 0x00}, ++ //{0x4730, 0x01}, ++ {0x4730, 0x00}, ++ {REG_OUTPUT_FORMAT, 0x32}, ++ ++ {0xffff, 0xff}, ++}; +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0033-media-soc-camera-fix-parallel-i-f-in-VIN.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0033-media-soc-camera-fix-parallel-i-f-in-VIN.patch new file mode 100644 index 0000000..c56049a --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0033-media-soc-camera-fix-parallel-i-f-in-VIN.patch @@ -0,0 +1,69 @@ +From 112395ed601c67a6ba935cec0107335e966888dc Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Fri, 14 Jul 2017 21:55:20 +0300 +Subject: [PATCH] media: soc_camera: fix parallel i/f in VIN + +This fixes parallel interface in VIN + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + drivers/media/platform/soc_camera/rcar_vin.c | 18 ++++++++++-------- + 1 file changed, 10 insertions(+), 8 deletions(-) + +diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c +index f5c2528..a9cb72d 100644 +--- a/drivers/media/platform/soc_camera/rcar_vin.c ++++ b/drivers/media/platform/soc_camera/rcar_vin.c +@@ -149,6 +149,9 @@ + /* Video n Data Mode Register 2 bits */ + #define VNDMR2_VPS (1 << 30) + #define VNDMR2_HPS (1 << 29) ++#define VNDMR2_CES (1 << 28) ++#define VNDMR2_DES (1 << 27) ++#define VNDMR2_CHS (1 << 23) + #define VNDMR2_FTEV (1 << 17) + #define VNDMR2_VLV(n) ((n & 0xf) << 12) + +@@ -1850,10 +1853,15 @@ static int rcar_vin_set_bus_param(struct soc_camera_device *icd) + 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; ++ ++ val |= VNDMR2_CES; ++ dev_dbg(icd->parent, "VNDMR2=0x%x\n", val); ++ + iowrite32(val, priv->base + VNDMR2_REG); + + ret = rcar_vin_set_rect(icd); +@@ -2937,8 +2945,8 @@ static int rcar_vin_probe(struct platform_device *pdev) + priv->max_height = 2048; + } + +- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_V3M) { ++ if ((priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || ++ priv->chip == RCAR_V3M) && !of_property_read_string(np, "csi,select", &str)) { + u32 ifmd = 0; + bool match_flag = false; + const struct vin_gen3_ifmd *gen3_ifmd_table = NULL; +@@ -2973,12 +2981,6 @@ static int rcar_vin_probe(struct platform_device *pdev) + 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) +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0034-media-soc_camera-Fix-VIDIOC_S_SELECTION-ioctl-miscal.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0034-media-soc_camera-Fix-VIDIOC_S_SELECTION-ioctl-miscal.patch new file mode 100644 index 0000000..fb15260 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0034-media-soc_camera-Fix-VIDIOC_S_SELECTION-ioctl-miscal.patch @@ -0,0 +1,67 @@ +From 4b971606c7ef3e85be57b31d2583e169f983d91f Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Mon, 31 Jul 2017 19:26:05 +0300 +Subject: [PATCH] media: soc_camera: Fix VIDIOC_S_SELECTION ioctl + miscalculation + +This patch corrects the miscalculation of the capture buffer +size and clipping data update in VIDIOC_S_SELECTION sequence. + +Patch isbased on work by: Koji Matsuoka <koji.matsuoka.xm@renesas.com> + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + drivers/media/platform/soc_camera/soc_scale_crop.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/drivers/media/platform/soc_camera/soc_scale_crop.c b/drivers/media/platform/soc_camera/soc_scale_crop.c +index f77252d..79a7d95 100644 +--- a/drivers/media/platform/soc_camera/soc_scale_crop.c ++++ b/drivers/media/platform/soc_camera/soc_scale_crop.c +@@ -72,14 +72,14 @@ static void update_subrect(struct v4l2_rect *rect, struct v4l2_rect *subrect) + + if (rect->left > subrect->left) + subrect->left = rect->left; +- else if (rect->left + rect->width > ++ else if (rect->left + rect->width < + subrect->left + subrect->width) + subrect->left = rect->left + rect->width - + subrect->width; + + if (rect->top > subrect->top) + subrect->top = rect->top; +- else if (rect->top + rect->height > ++ else if (rect->top + rect->height < + subrect->top + subrect->height) + subrect->top = rect->top + rect->height - + subrect->height; +@@ -125,6 +125,7 @@ int soc_camera_client_s_selection(struct v4l2_subdev *sd, + dev_dbg(dev, "Camera S_SELECTION successful for %dx%d@%d:%d\n", + rect->width, rect->height, rect->left, rect->top); + *target_rect = *cam_rect; ++ *subrect = *rect; + return 0; + } + +@@ -216,6 +217,7 @@ int soc_camera_client_s_selection(struct v4l2_subdev *sd, + + if (!ret) { + *target_rect = *cam_rect; ++ *subrect = *rect; + update_subrect(target_rect, subrect); + } + +@@ -296,9 +298,7 @@ static int client_set_fmt(struct soc_camera_device *icd, + if (ret < 0) + return ret; + +- if (host_1to1) +- *subrect = *rect; +- else ++ if (!host_1to1) + update_subrect(rect, subrect); + + return 0; +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0035-regulator-fixed-probe-after-i2c.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0035-regulator-fixed-probe-after-i2c.patch new file mode 100644 index 0000000..31c79ce --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0035-regulator-fixed-probe-after-i2c.patch @@ -0,0 +1,53 @@ +From ef0ae334de1e1b318f4fb26bc8045451318a60c4 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Sun, 26 Nov 2017 21:35:54 +0300 +Subject: [PATCH] regulator: fixed: probe after i2c + +This is a workaround for LVDS cameras that use I2C gpio expanders. +Set fixed regulator booted after i2c expander to have PoC +power controlled in LVDS driver. + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + drivers/Makefile | 4 +++- + drivers/regulator/fixed.c | 2 +- + 2 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/Makefile b/drivers/Makefile +index 194d20b..f49ed8f 100644 +--- a/drivers/Makefile ++++ b/drivers/Makefile +@@ -41,6 +41,8 @@ obj-y += soc/ + obj-$(CONFIG_VIRTIO) += virtio/ + obj-$(CONFIG_XEN) += xen/ + ++obj-y += i2c/ ++ + # regulators early, since some subsystems rely on them to initialize + obj-$(CONFIG_REGULATOR) += regulator/ + +@@ -105,7 +107,7 @@ obj-$(CONFIG_SERIO) += input/serio/ + obj-$(CONFIG_GAMEPORT) += input/gameport/ + obj-$(CONFIG_INPUT) += input/ + obj-$(CONFIG_RTC_LIB) += rtc/ +-obj-y += i2c/ media/ ++obj-y += media/ + obj-$(CONFIG_PPS) += pps/ + obj-$(CONFIG_PTP_1588_CLOCK) += ptp/ + obj-$(CONFIG_W1) += w1/ +diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c +index 988a747..44a169c 100644 +--- a/drivers/regulator/fixed.c ++++ b/drivers/regulator/fixed.c +@@ -211,7 +211,7 @@ static int __init regulator_fixed_voltage_init(void) + { + return platform_driver_register(®ulator_fixed_voltage_driver); + } +-subsys_initcall(regulator_fixed_voltage_init); ++module_init(regulator_fixed_voltage_init); + + static void __exit regulator_fixed_voltage_exit(void) + { +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch new file mode 100644 index 0000000..9db9056 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch @@ -0,0 +1,17543 @@ +From 51718d8f768ba719a8a295e013e3456e13b70a98 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Fri, 14 Jul 2017 15:05:42 +0300 +Subject: [PATCH] arm64: dts: renesas: add ADAS boards + +Salvator-X.View board on R8A7795 ES1.x SoC +Salvator-X.View board on R8A7795 SoC +Salvator-X.View board on R8A7796 SoC +H3ULCB.View board on R8A7795 ES1.x SoC +H3ULCB.View board on R8A7795 SoC +M3ULCB.View board on R8A7796 SoC +H3ULCB.HAD board on R8A7795 ES1.x SoC +H3ULCB.HAD board on R8A7795 SoC +Kingfisher board on R8A7795 ES1.x SoC +Kingfisher board on R8A7795 SoC +Kingfisher board on R8A7796 SoC +Kingfisher board on R8A7797 SoC +Videobox board on R8A7795 ES1.x SoC +Videobox board on R8A7795 SoC +Eagle board on R8A7797 SoC +V3MSK board on R8A7797 SoC +V3MSK.View board on R8A7797 SoC +Videobox Mini board on R8A7795 ES1.x SoC +Videobox Mini board on R8A7795 SoC +Videobox Mini board on R8A7797 SoC + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + arch/arm64/boot/dts/renesas/Makefile | 19 + + arch/arm64/boot/dts/renesas/legacy/Makefile | 8 + + .../renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts | 1710 +++++++++++++++++++ + .../renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts | 441 +++++ + .../dts/renesas/legacy/r8a7795-h3ulcb-kf-v0.dts | 1724 +++++++++++++++++++ + .../dts/renesas/legacy/r8a7795-h3ulcb-kf-v1.dts | 465 ++++++ + .../dts/renesas/legacy/r8a7796-m3ulcb-kf-v0.dts | 1214 ++++++++++++++ + .../dts/renesas/legacy/r8a7796-m3ulcb-kf-v1.dts | 465 ++++++ + .../dts/renesas/legacy/r8a7797-v3msk-kf-v0.dts | 82 + + .../boot/dts/renesas/legacy/ulcb-kf-cmos.dtsi | 75 + + .../arm64/boot/dts/renesas/legacy/ulcb-kf-rpi.dtsi | 77 + + .../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 | 225 +++ + .../boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts | 39 + + .../boot/dts/renesas/r8a7795-es1-h3ulcb-vb.dts | 69 + + .../boot/dts/renesas/r8a7795-es1-h3ulcb-vbm.dts | 26 + + .../boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts | 546 +++++++ + .../dts/renesas/r8a7795-es1-salvator-x-view.dts | 552 +++++++ + .../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 | 219 +++ + arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts | 39 + + arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vb.dts | 68 + + arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vbm.dts | 26 + + .../arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts | 546 +++++++ + .../boot/dts/renesas/r8a7795-salvator-x-view.dts | 552 +++++++ + arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts | 40 + + .../arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts | 287 ++++ + .../boot/dts/renesas/r8a7796-salvator-x-view.dts | 318 ++++ + arch/arm64/boot/dts/renesas/r8a7797-eagle.dts | 560 +++++++ + arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts | 578 +++++++ + arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts | 518 ++++++ + arch/arm64/boot/dts/renesas/r8a7797-v3msk-view.dts | 298 ++++ + arch/arm64/boot/dts/renesas/r8a7797-v3msk.dts | 314 ++++ + arch/arm64/boot/dts/renesas/ulcb-kf-cn11.dtsi | 545 ++++++ + arch/arm64/boot/dts/renesas/ulcb-kf-most.dtsi | 30 + + arch/arm64/boot/dts/renesas/ulcb-kf-sd3.dtsi | 46 + + arch/arm64/boot/dts/renesas/ulcb-kf.dtsi | 1541 +++++++++++++++++ + arch/arm64/boot/dts/renesas/ulcb-vb-cn12.dtsi | 515 ++++++ + arch/arm64/boot/dts/renesas/ulcb-vb.dtsi | 1726 ++++++++++++++++++++ + arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi | 578 +++++++ + 42 files changed, 17171 insertions(+) + create mode 100644 arch/arm64/boot/dts/renesas/legacy/Makefile + create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts + create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts + create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-h3ulcb-kf-v0.dts + create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-h3ulcb-kf-v1.dts + create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7796-m3ulcb-kf-v0.dts + create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7796-m3ulcb-kf-v1.dts + create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7797-v3msk-kf-v0.dts + create mode 100644 arch/arm64/boot/dts/renesas/legacy/ulcb-kf-cmos.dtsi + create mode 100644 arch/arm64/boot/dts/renesas/legacy/ulcb-kf-rpi.dtsi + 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 + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-vb.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-vbm.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts + 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 + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vb.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vbm.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7796-salvator-x-view.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-eagle.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-v3msk-view.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-v3msk.dts + create mode 100644 arch/arm64/boot/dts/renesas/ulcb-kf-cn11.dtsi + create mode 100644 arch/arm64/boot/dts/renesas/ulcb-kf-most.dtsi + create mode 100644 arch/arm64/boot/dts/renesas/ulcb-kf-sd3.dtsi + create mode 100644 arch/arm64/boot/dts/renesas/ulcb-kf.dtsi + create mode 100644 arch/arm64/boot/dts/renesas/ulcb-vb-cn12.dtsi + create mode 100644 arch/arm64/boot/dts/renesas/ulcb-vb.dtsi + create mode 100644 arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi + +diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile +index f9c71df..af88350 100644 +--- a/arch/arm64/boot/dts/renesas/Makefile ++++ b/arch/arm64/boot/dts/renesas/Makefile +@@ -6,5 +6,24 @@ dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-xs.dtb + dtb-$(CONFIG_ARCH_R8A77965) += r8a77965-salvator-x.dtb + dtb-$(CONFIG_ARCH_R8A77965) += r8a77965-salvator-xs.dtb + ++# ADAS boards ++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 r8a7795-es1-salvator-x-view.dtb ++dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-view.dtb r8a7795-es1-h3ulcb-view.dtb ++dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-had-alfa.dtb r8a7795-h3ulcb-had-beta.dtb r8a7795-es1-h3ulcb-had-alfa.dtb r8a7795-es1-h3ulcb-had-beta.dtb ++dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-kf.dtb r8a7795-es1-h3ulcb-kf.dtb ++dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-vb.dtb r8a7795-es1-h3ulcb-vb.dtb ++dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-vbm.dtb r8a7795-es1-h3ulcb-vbm.dtb ++dtb-$(CONFIG_ARCH_R8A7797) += r8a7797-eagle.dtb ++dtb-$(CONFIG_ARCH_R8A7797) += r8a7797-v3msk.dtb ++dtb-$(CONFIG_ARCH_R8A7797) += r8a7797-v3msk-view.dtb ++dtb-$(CONFIG_ARCH_R8A7797) += r8a7797-v3msk-kf.dtb ++dtb-$(CONFIG_ARCH_R8A7797) += r8a7797-v3msk-vbm.dtb ++ ++# ADAS legacy boards ++subdir-y := legacy ++ + always := $(dtb-y) + clean-files := *.dtb +diff --git a/arch/arm64/boot/dts/renesas/legacy/Makefile b/arch/arm64/boot/dts/renesas/legacy/Makefile +new file mode 100644 +index 0000000..7f25079 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/legacy/Makefile +@@ -0,0 +1,8 @@ ++# Legacy KF board: V0, V1 (V2 is the same as V1), V3 is latest and deployed in default directory ++dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-h3ulcb-kf-v0.dtb r8a7795-es1-h3ulcb-kf-v1.dtb ++dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-m3ulcb-kf-v0.dtb r8a7796-m3ulcb-kf-v1.dtb ++dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-kf-v0.dtb r8a7795-h3ulcb-kf-v1.dtb ++dtb-$(CONFIG_ARCH_R8A7797) += r8a7797-v3msk-kf-v0.dtb ++ ++always := $(dtb-y) ++clean-files := *.dtb +diff --git a/arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts b/arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts +new file mode 100644 +index 0000000..2fee788 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts +@@ -0,0 +1,1710 @@ ++/* ++ * Device Tree Source for the H3ULCB Kingfisher V0 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 V0 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; ++ }; ++ ++ vcc_sdhi3: regulator@41 { ++ compatible = "regulator-fixed"; ++ ++ regulator-name = "SDHI3 Vcc"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++ }; ++ ++ vccq_sdhi3: regulator@5 { ++ compatible = "regulator-fixed"; ++ ++ regulator-name = "SDHI3 VccQ"; ++ 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"; ++ shutdown-gpios = <&gpio_ext_20 3 GPIO_ACTIVE_HIGH>; ++ /* 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>; ++ }; ++ }; ++ ++ 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"; ++ }; ++ ++ usb0_pins: usb0 { ++ groups = "usb0"; ++ function = "usb0"; ++ }; ++ ++ can0_pins: can0 { ++ groups = "can0_data_a"; ++ function = "can0"; ++ }; ++ ++ can1_pins: can1 { ++ groups = "can1_data"; ++ function = "can1"; ++ }; ++ ++ canfd0_pins: canfd0 { ++ groups = "canfd0_data_a"; ++ function = "canfd0"; ++ }; ++ ++ canfd1_pins: canfd1 { ++ groups = "canfd1_data"; ++ function = "canfd1"; ++ }; ++}; ++ ++&du { ++ ports { ++ port@3 { ++ endpoint { ++ remote-endpoint = <&lvds_enc_in>; ++ }; ++ }; ++ }; ++}; ++ ++&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"; ++ uart-has-rtscts; ++ ++ 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: pca9548@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) */ ++ }; ++ ++ 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 = <&_en_reg>; ++ VCCDA2-supply = <&_en_reg>; ++ }; ++ ++ lsm9ds0_acc_mag@1d { ++ compatible = "st,lsm9ds0_accel_magn"; ++ 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>; ++ ++ cmos_pwdn { ++ gpio-hog; ++ gpios = <8 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "CMOS PWDN"; ++ }; ++ cmos_rst { ++ gpio-hog; ++ gpios = <9 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "CMOS RST"; ++ }; ++ /* pin 12 - CAM_CLK */ ++ rpi_cam_io_1 { ++ gpio-hog; ++ gpios = <10 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "RaspB_IO1"; ++ }; ++ /* pin 11 - CAM_GPIO - assume pwdn */ ++ rpi_cam_io_0 { ++ gpio-hog; ++ gpios = <11 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "RaspB_IO0"; ++ }; ++ }; ++ ++ i2cswitch4: pca9548@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>; ++ /* Slot A (CN10) */ ++ ++ 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 @ 0x2c */ ++ max9286-max9271@0 { ++ compatible = "maxim,max9286-max9271"; ++ reg = <0x2c>; ++ 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>; ++ /* Slot B (CN11) */ ++ ++ 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 @ 0x2c */ ++ max9286-max9271@1 { ++ compatible = "maxim,max9286-max9271"; ++ reg = <0x2c>; ++ 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@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ /* Slot B (CN11) */ ++ ++ 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>; ++ input; ++ line-name = "Video-B cfg1"; ++ }; ++ video_b_des_cfg0 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ 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>; ++ input; ++ line-name = "Video-B cfg2"; ++ }; ++ video_b_des_cfg1 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-B cfg1"; ++ }; ++ video_b_des_cfg0 { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ input; ++ 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"; ++ }; ++ video_b_cam_pwr2 { ++ gpio-hog; ++ gpios = <10 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR2"; ++ }; ++ video_b_cam_pwr3 { ++ gpio-hog; ++ gpios = <11 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR3"; ++ }; ++ video_b_des_shdn { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B DES_SHDN"; ++ }; ++ video_b_led { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-B LED"; ++ }; ++ }; ++ }; ++ ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ /* Slot A (CN10) */ ++ ++ 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>; ++ input; ++ line-name = "Video-A cfg1"; ++ }; ++ video_a_des_cfg0 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ 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>; ++ input; ++ line-name = "Video-A cfg2"; ++ }; ++ video_a_des_cfg1 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-A cfg1"; ++ }; ++ video_a_des_cfg0 { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ input; ++ 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"; ++ }; ++ video_a_cam_pwr2 { ++ gpio-hog; ++ gpios = <10 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR2"; ++ }; ++ video_a_cam_pwr3 { ++ gpio-hog; ++ gpios = <11 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR3"; ++ }; ++ video_a_des_shdn { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A DES_SHDN"; ++ }; ++ video_a_led { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-A LED"; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&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>; ++ }; ++ }; ++}; ++ ++&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>; ++ }; ++}; ++ ++&usb2_phy0 { ++ pinctrl-0 = <&usb0_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&hsusb { ++ status = "okay"; ++}; ++ ++&ehci0 { ++ status = "okay"; ++}; ++ ++&ohci0 { ++ status = "okay"; ++}; ++ ++&xhci0 { ++ status = "okay"; ++}; ++ ++&msiof1 { ++ status = "disabled"; ++}; ++ ++&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"; ++ ++ channel0 { ++ status = "okay"; ++ }; ++ ++ channel1 { ++ status = "okay"; ++ }; ++}; ++ ++&ssi8 { ++ shared-pin; ++}; +diff --git a/arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts b/arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts +new file mode 100644 +index 0000000..ac6a12b +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts +@@ -0,0 +1,441 @@ ++/* ++ * Device Tree Source for the H3ULCB Kingfisher V1 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-kf-v0.dts" ++ ++/ { ++ model = "Renesas H3ULCB Kingfisher V1 board based on r8a7795"; ++ ++ aliases { ++ serial1 = &hscif0; ++ serial2 = &hscif1; ++ serial3 = &scif1; ++ }; ++ ++ wlan_en: regulator@4 { ++ compatible = "regulator-fixed"; ++ regulator-name = "wlan-en-regulator"; ++ ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ gpio = <&gpio_ext_74 4 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ codec_en_reg: regulator@6 { ++ compatible = "regulator-fixed"; ++ regulator-name = "codec-en-regulator"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ gpio = <&gpio_ext_74 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_74 0 0>; ++ ++ startup-delay-us = <0>; ++ enable-active-high; ++ }; ++ ++ /delete-node/regulator@8; ++ ++ sdio_switch: regulator@9 { ++ compatible = "regulator-fixed"; ++ regulator-name = "wifi_on"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&gpio_ext_74 5 0>; ++ enable-active-low; ++ regulator-always-on; ++ }; ++ ++ /delete-node/regulator@10; ++ ++ radio_switch: regulator@11 { ++ compatible = "regulator-fixed"; ++ regulator-name = "radio_on"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&gpio_ext_74 13 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ regulator-always-on; ++ }; ++ ++ kim { ++ shutdown-gpios = <&gpio_ext_74 3 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ hdmi-out { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi_con: endpoint { ++ remote-endpoint = <&adv7513_out>; ++ }; ++ }; ++ }; ++}; ++ ++&pfc { ++ /delete-node/hscif4; ++ ++ scif1_pins: scif1 { ++ groups = "scif1_data_b"; ++ function = "scif1"; ++ }; ++ ++ hscif0_pins: hscif0 { ++ groups = "hscif0_data", "hscif0_ctrl"; ++ function = "hscif0"; ++ }; ++ ++ hscif1_pins: hscif1 { ++ groups = "hscif1_data_a", "hscif1_ctrl_a"; ++ function = "hscif1"; ++ }; ++ ++ du_pins: du { ++ groups = "du_rgb888", "du_sync", "du_clk_out_0", "du_disp"; ++ function = "du"; ++ }; ++}; ++ ++&du { ++ pinctrl-0 = <&du_pins>; ++ pinctrl-names = "default"; ++ ++ ports { ++ port@0 { ++ endpoint { ++ remote-endpoint = <&adv7513_in>; ++ }; ++ }; ++ }; ++}; ++ ++&gpio0 { ++ /delete-node/video_a_irq; ++ /delete-node/video_b_irq; ++ /delete-node/gpioext_2_20_irq; ++}; ++ ++&gpio1 { ++ /delete-node/gpioext_2_21_irq; ++ /delete-node/wifi_irq; ++}; ++ ++&gpio2 { ++ bl_pwm { ++ gpio-hog; ++ gpios = <3 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "BL PWM 100%"; ++ }; ++}; ++ ++&gpio5 { ++ /delete-node/touch_irq; ++ /delete-node/bt_strap; ++}; ++ ++&gpio7 { ++ /delete-node/gpioext_2_21_irq; ++}; ++ ++&scif1 { ++ pinctrl-0 = <&scif1_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&hscif0 { ++ pinctrl-0 = <&hscif0_pins>; ++ pinctrl-names = "default"; ++ uart-has-rtscts; ++ ++ status = "okay"; ++}; ++ ++&hscif1 { ++ pinctrl-0 = <&hscif1_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&hscif4 { ++ /delete-property/pinctrl-0; ++ /delete-property/pinctrl-names; ++ ++ status = "disabled"; ++}; ++ ++&i2c2 { ++ /delete-node/pca9535@20; ++ /delete-node/pca9535@21; ++ ++ gpio_ext_74: pca9539@74 { ++ compatible = "nxp,pca9539"; ++ reg = <0x74>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ interrupt-parent = <&gpio6>; ++ interrupts = <8 IRQ_TYPE_EDGE_FALLING>; ++ ++ hub_pwen { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "HUB pwen"; ++ }; ++ hub_rst { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "HUB rst"; ++ }; ++ otg_offvbus { ++ gpio-hog; ++ gpios = <8 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "OTG off VBUSn"; ++ }; ++ otg_extlpn { ++ gpio-hog; ++ gpios = <9 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "OTG EXTLPn"; ++ }; ++ otg_stat1 { ++ gpio-hog; ++ gpios = <10 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "OTG Stat1"; ++ }; ++ otg_stat2 { ++ gpio-hog; ++ gpios = <11 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "OTG Stat2"; ++ }; ++ }; ++ ++ gpio_ext_75: pca9539@75 { ++ compatible = "nxp,pca9539"; ++ reg = <0x75>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ interrupt-parent = <&gpio6>; ++ interrupts = <4 IRQ_TYPE_EDGE_FALLING>; ++ ++ gps_rst { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "GPS rst"; ++ }; ++ fpdl_shdn { ++ gpio-hog; ++ gpios = <9 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "FPDLink shdn"; ++ }; ++ }; ++}; ++ ++&i2cswitch2 { ++ reg = <0x71>; ++ reset-gpios= <&gpio5 3 GPIO_ACTIVE_LOW>; ++ ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ ++ hdmi@3d { ++ compatible = "adi,adv7511w"; ++ reg = <0x3d>; ++// interrupt-parent = <&gpio2>; ++// interrupts = <0 IRQ_TYPE_EDGE_BOTH>; ++ pd-gpios = <&gpio_ext_75 5 GPIO_ACTIVE_LOW>; ++ ++ adi,input-depth = <8>; ++ adi,input-colorspace = "rgb"; ++ adi,input-clock = "1x"; ++ adi,input-style = <1>; ++ adi,input-justification = "evenly"; ++ adi,clock-delay = <1200>; ++ adi,clock-max-rate = <100000>; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ adv7513_in: endpoint { ++ remote-endpoint = <&du_out_rgb>; ++ }; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ adv7513_out: endpoint { ++ remote-endpoint = <&hdmi_con>; ++ }; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&i2c4 { ++ /delete-node/pca9535@21; ++ ++ gpio_ext_76: pca9539@76 { ++ compatible = "nxp,pca9539"; ++ reg = <0x76>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ interrupt-parent = <&gpio7>; ++ interrupts = <3 IRQ_TYPE_EDGE_FALLING>; ++ ++ port_b_a0 { ++ gpio-hog; ++ gpios = <0 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-B A0"; ++ }; ++ port_b_a1 { ++ gpio-hog; ++ gpios = <1 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B A1"; ++ }; ++ port_a_a0 { ++ gpio-hog; ++ gpios = <2 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-A A0"; ++ }; ++ port_a_a1 { ++ gpio-hog; ++ gpios = <3 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A A1"; ++ }; ++ cmos_pwdn { ++ gpio-hog; ++ gpios = <8 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "CMOS PWDN"; ++ }; ++ cmos_rst { ++ gpio-hog; ++ gpios = <9 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "CMOS RST"; ++ }; ++ /* pin 12 - CAM_CLK */ ++ rpi_cam_io_1 { ++ gpio-hog; ++ gpios = <10 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "RaspB_IO1"; ++ }; ++ /* pin 11 - CAM_GPIO - assume pwdn */ ++ rpi_cam_io_0 { ++ gpio-hog; ++ gpios = <11 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "RaspB_IO0"; ++ }; ++ sam_rst { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "SAM RST"; ++ }; ++ sam_pwr { ++ gpio-hog; ++ gpios = <5 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "SAM PWR"; ++ }; ++ /* 0 - FPDLink output, 1 - LVDS output */ ++ lvds_vs_fpdl { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "LVDS switch"; ++ }; ++ }; ++ ++ gpio_ext_77: pca9539@77 { ++ compatible = "nxp,pca9539"; ++ reg = <0x77>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ interrupt-parent = <&gpio5>; ++ interrupts = <9 IRQ_TYPE_EDGE_FALLING>; ++ ++ mpcie_wake { ++ gpio-hog; ++ gpios = <0 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "mPCIe WAKE#"; ++ }; ++ mpcie_wdisable { ++ gpio-hog; ++ gpios = <1 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "mPCIe W_DISABLE"; ++ }; ++ mpcie_clreq { ++ gpio-hog; ++ gpios = <2 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "mPCIe CLKREQ#"; ++ }; ++ mpcie_ovc { ++ gpio-hog; ++ gpios = <3 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "mPCIe OVC"; ++ }; ++ }; ++}; ++ ++&i2cswitch4 { ++ reg = <0x71>; ++ reset-gpios= <&gpio3 15 GPIO_ACTIVE_LOW>; ++}; ++ ++&wlcore { ++ interrupts = <25 IRQ_TYPE_EDGE_FALLING>; ++}; +diff --git a/arch/arm64/boot/dts/renesas/legacy/r8a7795-h3ulcb-kf-v0.dts b/arch/arm64/boot/dts/renesas/legacy/r8a7795-h3ulcb-kf-v0.dts +new file mode 100644 +index 0000000..78c766b +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/legacy/r8a7795-h3ulcb-kf-v0.dts +@@ -0,0 +1,1724 @@ ++/* ++ * Device Tree Source for the H3ULCB Kingfisher V0 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 V0 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; ++ }; ++ ++ vcc_sdhi3: regulator@41 { ++ compatible = "regulator-fixed"; ++ ++ regulator-name = "SDHI3 Vcc"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++ }; ++ ++ vccq_sdhi3: regulator@5 { ++ compatible = "regulator-fixed"; ++ ++ regulator-name = "SDHI3 VccQ"; ++ 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"; ++ shutdown-gpios = <&gpio_ext_20 3 GPIO_ACTIVE_HIGH>; ++ /* 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>; ++ }; ++ }; ++ ++ 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"; ++ }; ++ ++ usb0_pins: usb0 { ++ groups = "usb0"; ++ function = "usb0"; ++ }; ++ ++ can0_pins: can0 { ++ groups = "can0_data_a"; ++ function = "can0"; ++ }; ++ ++ can1_pins: can1 { ++ groups = "can1_data"; ++ function = "can1"; ++ }; ++ ++ canfd0_pins: canfd0 { ++ groups = "canfd0_data_a"; ++ function = "canfd0"; ++ }; ++ ++ canfd1_pins: canfd1 { ++ groups = "canfd1_data"; ++ function = "canfd1"; ++ }; ++}; ++ ++&du { ++ ports { ++ port@3 { ++ endpoint { ++ remote-endpoint = <&lvds_enc_in>; ++ }; ++ }; ++ }; ++}; ++ ++&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"; ++ uart-has-rtscts; ++ ++ 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: pca9548@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) */ ++ }; ++ ++ 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 = <&_en_reg>; ++ VCCDA2-supply = <&_en_reg>; ++ }; ++ ++ lsm9ds0_acc_mag@1d { ++ compatible = "st,lsm9ds0_accel_magn"; ++ 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>; ++ ++ cmos_pwdn { ++ gpio-hog; ++ gpios = <8 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "CMOS PWDN"; ++ }; ++ cmos_rst { ++ gpio-hog; ++ gpios = <9 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "CMOS RST"; ++ }; ++ /* pin 12 - CAM_CLK */ ++ rpi_cam_io_1 { ++ gpio-hog; ++ gpios = <10 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "RaspB_IO1"; ++ }; ++ /* pin 11 - CAM_GPIO - assume pwdn */ ++ rpi_cam_io_0 { ++ gpio-hog; ++ gpios = <11 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "RaspB_IO0"; ++ }; ++ }; ++ ++ i2cswitch4: pca9548@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>; ++ /* Slot A (CN10) */ ++ ++ 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 @ 0x2c */ ++ max9286-max9271@0 { ++ compatible = "maxim,max9286-max9271"; ++ reg = <0x2c>; ++ 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>; ++ /* Slot B (CN11) */ ++ ++ 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 @ 0x2c */ ++ max9286-max9271@1 { ++ compatible = "maxim,max9286-max9271"; ++ reg = <0x2c>; ++ 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@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ /* Slot B (CN11) */ ++ ++ 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>; ++ input; ++ line-name = "Video-B cfg1"; ++ }; ++ video_b_des_cfg0 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ 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>; ++ input; ++ line-name = "Video-B cfg2"; ++ }; ++ video_b_des_cfg1 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-B cfg1"; ++ }; ++ video_b_des_cfg0 { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ input; ++ 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"; ++ }; ++ video_b_cam_pwr2 { ++ gpio-hog; ++ gpios = <10 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR2"; ++ }; ++ video_b_cam_pwr3 { ++ gpio-hog; ++ gpios = <11 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR3"; ++ }; ++ video_b_des_shdn { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B DES_SHDN"; ++ }; ++ video_b_led { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-B LED"; ++ }; ++ }; ++ }; ++ ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ /* Slot A (CN10) */ ++ ++ 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>; ++ input; ++ line-name = "Video-A cfg1"; ++ }; ++ video_a_des_cfg0 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ 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>; ++ input; ++ line-name = "Video-A cfg2"; ++ }; ++ video_a_des_cfg1 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-A cfg1"; ++ }; ++ video_a_des_cfg0 { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ input; ++ 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"; ++ }; ++ video_a_cam_pwr2 { ++ gpio-hog; ++ gpios = <10 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR2"; ++ }; ++ video_a_cam_pwr3 { ++ gpio-hog; ++ gpios = <11 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR3"; ++ }; ++ video_a_des_shdn { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A DES_SHDN"; ++ }; ++ video_a_led { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-A LED"; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&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>; ++ }; ++ }; ++}; ++ ++&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>; ++ }; ++}; ++ ++&usb2_phy0 { ++ pinctrl-0 = <&usb0_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&hsusb0 { ++ status = "okay"; ++}; ++ ++&ehci0 { ++ status = "okay"; ++}; ++ ++&ohci0 { ++ status = "okay"; ++}; ++ ++&xhci0 { ++ status = "okay"; ++}; ++ ++&msiof1 { ++ status = "disabled"; ++}; ++ ++&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"; ++ ++ channel0 { ++ status = "okay"; ++ }; ++ ++ channel1 { ++ status = "okay"; ++ }; ++}; ++ ++&ssi8 { ++ shared-pin; ++}; ++ ++/* uncomment to enable CN47: SD on SDHI3 */ ++//#include "../ulcb-kf-sd3.dtsi" ++/* CN48 (Raspberry Pi) on VIN4 */ ++//#include "ulcb-kf-rpi.dtsi" ++/* CN29: (CMOS camera) on VIN5 */ ++//#include "ulcb-kf-cmos.dtsi" +diff --git a/arch/arm64/boot/dts/renesas/legacy/r8a7795-h3ulcb-kf-v1.dts b/arch/arm64/boot/dts/renesas/legacy/r8a7795-h3ulcb-kf-v1.dts +new file mode 100644 +index 0000000..14b6f52 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/legacy/r8a7795-h3ulcb-kf-v1.dts +@@ -0,0 +1,465 @@ ++/* ++ * Device Tree Source for the H3ULCB Kingfisher V1 board ++ * ++ * 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-kf-v0.dts" ++ ++/ { ++ model = "Renesas H3ULCB Kingfisher V1 board based on r8a7795"; ++ ++ aliases { ++ serial1 = &hscif0; ++ serial2 = &hscif1; ++ serial3 = &scif1; ++ }; ++ ++ wlan_en: regulator@4 { ++ compatible = "regulator-fixed"; ++ regulator-name = "wlan-en-regulator"; ++ ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ gpio = <&gpio_ext_74 4 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ codec_en_reg: regulator@6 { ++ compatible = "regulator-fixed"; ++ regulator-name = "codec-en-regulator"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ gpio = <&gpio_ext_74 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_74 0 0>; ++ ++ startup-delay-us = <0>; ++ enable-active-high; ++ }; ++ ++ /delete-node/regulator@8; ++ ++ sdio_switch: regulator@9 { ++ compatible = "regulator-fixed"; ++ regulator-name = "wifi_on"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&gpio_ext_74 5 0>; ++ enable-active-low; ++ regulator-always-on; ++ }; ++ ++ /delete-node/regulator@10; ++ ++ radio_switch: regulator@11 { ++ compatible = "regulator-fixed"; ++ regulator-name = "radio_on"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&gpio_ext_74 13 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ regulator-always-on; ++ }; ++ ++ mpcie_3v3: regulator@12 { ++ compatible = "regulator-fixed"; ++ regulator-name = "mPCIe 3v3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&gpio_ext_77 14 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ mpcie_1v8: regulator@13 { ++ compatible = "regulator-fixed"; ++ regulator-name = "mPCIe 1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ gpio = <&gpio_ext_77 15 GPIO_ACTIVE_HIGH>; ++ startup-delay-us = <200000>; ++ enable-active-high; ++ }; ++ ++ kim { ++ shutdown-gpios = <&gpio_ext_74 3 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ hdmi-out { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi_con: endpoint { ++ remote-endpoint = <&adv7513_out>; ++ }; ++ }; ++ }; ++}; ++ ++&pfc { ++ /delete-node/hscif4; ++ ++ scif1_pins: scif1 { ++ groups = "scif1_data_b"; ++ function = "scif1"; ++ }; ++ ++ hscif0_pins: hscif0 { ++ groups = "hscif0_data", "hscif0_ctrl"; ++ function = "hscif0"; ++ }; ++ ++ hscif1_pins: hscif1 { ++ groups = "hscif1_data_a", "hscif1_ctrl_a"; ++ function = "hscif1"; ++ }; ++ ++ du_pins: du { ++ groups = "du_rgb888", "du_sync", "du_clk_out_0", "du_disp"; ++ function = "du"; ++ }; ++}; ++ ++&du { ++ pinctrl-0 = <&du_pins>; ++ pinctrl-names = "default"; ++ ++ ports { ++ port@0 { ++ endpoint { ++ remote-endpoint = <&adv7513_in>; ++ }; ++ }; ++ }; ++}; ++ ++&gpio0 { ++ /delete-node/video_a_irq; ++ /delete-node/video_b_irq; ++ /delete-node/gpioext_2_20_irq; ++}; ++ ++&gpio1 { ++ /delete-node/gpioext_2_21_irq; ++ /delete-node/wifi_irq; ++}; ++ ++&gpio2 { ++ bl_pwm { ++ gpio-hog; ++ gpios = <3 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "BL PWM 100%"; ++ }; ++}; ++ ++&gpio5 { ++ /delete-node/touch_irq; ++ /delete-node/bt_strap; ++}; ++ ++&gpio7 { ++ /delete-node/gpioext_2_21_irq; ++}; ++ ++&scif1 { ++ pinctrl-0 = <&scif1_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&hscif0 { ++ pinctrl-0 = <&hscif0_pins>; ++ pinctrl-names = "default"; ++ uart-has-rtscts; ++ ++ status = "okay"; ++}; ++ ++&hscif1 { ++ pinctrl-0 = <&hscif1_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&hscif4 { ++ /delete-property/pinctrl-0; ++ /delete-property/pinctrl-names; ++ ++ status = "disabled"; ++}; ++ ++&i2c2 { ++ /delete-node/pca9535@20; ++ /delete-node/pca9535@21; ++ ++ gpio_ext_74: pca9539@74 { ++ compatible = "nxp,pca9539"; ++ reg = <0x74>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ interrupt-parent = <&gpio6>; ++ interrupts = <8 IRQ_TYPE_EDGE_FALLING>; ++ ++ hub_pwen { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "HUB pwen"; ++ }; ++ hub_rst { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "HUB rst"; ++ }; ++ otg_offvbus { ++ gpio-hog; ++ gpios = <8 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "OTG off VBUSn"; ++ }; ++ otg_extlpn { ++ gpio-hog; ++ gpios = <9 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "OTG EXTLPn"; ++ }; ++ otg_stat1 { ++ gpio-hog; ++ gpios = <10 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "OTG Stat1"; ++ }; ++ otg_stat2 { ++ gpio-hog; ++ gpios = <11 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "OTG Stat2"; ++ }; ++ }; ++ ++ gpio_ext_75: pca9539@75 { ++ compatible = "nxp,pca9539"; ++ reg = <0x75>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ interrupt-parent = <&gpio6>; ++ interrupts = <4 IRQ_TYPE_EDGE_FALLING>; ++ ++ gps_rst { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "GPS rst"; ++ }; ++ fpdl_shdn { ++ gpio-hog; ++ gpios = <9 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "FPDLink shdn"; ++ }; ++ }; ++}; ++ ++&i2cswitch2 { ++ reg = <0x71>; ++ reset-gpios= <&gpio5 3 GPIO_ACTIVE_LOW>; ++ ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ ++ hdmi@3d { ++ compatible = "adi,adv7511w"; ++ reg = <0x3d>; ++// interrupt-parent = <&gpio2>; ++// interrupts = <0 IRQ_TYPE_EDGE_BOTH>; ++ pd-gpios = <&gpio_ext_75 5 GPIO_ACTIVE_LOW>; ++ ++ adi,input-depth = <8>; ++ adi,input-colorspace = "rgb"; ++ adi,input-clock = "1x"; ++ adi,input-style = <1>; ++ adi,input-justification = "evenly"; ++ adi,clock-delay = <1200>; ++ adi,clock-max-rate = <100000>; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ adv7513_in: endpoint { ++ remote-endpoint = <&du_out_rgb>; ++ }; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ adv7513_out: endpoint { ++ remote-endpoint = <&hdmi_con>; ++ }; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&i2c4 { ++ /delete-node/pca9535@21; ++ ++ gpio_ext_76: pca9539@76 { ++ compatible = "nxp,pca9539"; ++ reg = <0x76>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ interrupt-parent = <&gpio7>; ++ interrupts = <3 IRQ_TYPE_EDGE_FALLING>; ++ ++ port_b_a0 { ++ gpio-hog; ++ gpios = <0 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-B A0"; ++ }; ++ port_b_a1 { ++ gpio-hog; ++ gpios = <1 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B A1"; ++ }; ++ port_a_a0 { ++ gpio-hog; ++ gpios = <2 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-A A0"; ++ }; ++ port_a_a1 { ++ gpio-hog; ++ gpios = <3 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A A1"; ++ }; ++ cmos_pwdn { ++ gpio-hog; ++ gpios = <8 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "CMOS PWDN"; ++ }; ++ cmos_rst { ++ gpio-hog; ++ gpios = <9 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "CMOS RST"; ++ }; ++ /* pin 12 - CAM_CLK */ ++ rpi_cam_io_1 { ++ gpio-hog; ++ gpios = <10 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "RaspB_IO1"; ++ }; ++ /* pin 11 - CAM_GPIO - assume pwdn */ ++ rpi_cam_io_0 { ++ gpio-hog; ++ gpios = <11 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "RaspB_IO0"; ++ }; ++ sam_rst { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "SAM RST"; ++ }; ++ sam_pwr { ++ gpio-hog; ++ gpios = <5 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "SAM PWR"; ++ }; ++ /* 0 - FPDLink output, 1 - LVDS output */ ++ lvds_vs_fpdl { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "LVDS switch"; ++ }; ++ }; ++ ++ gpio_ext_77: pca9539@77 { ++ compatible = "nxp,pca9539"; ++ reg = <0x77>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ interrupt-parent = <&gpio5>; ++ interrupts = <9 IRQ_TYPE_EDGE_FALLING>; ++ ++ mpcie_wake { ++ gpio-hog; ++ gpios = <0 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "mPCIe WAKE#"; ++ }; ++ mpcie_wdisable { ++ gpio-hog; ++ gpios = <1 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "mPCIe W_DISABLE"; ++ }; ++ mpcie_clreq { ++ gpio-hog; ++ gpios = <2 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "mPCIe CLKREQ#"; ++ }; ++ mpcie_ovc { ++ gpio-hog; ++ gpios = <3 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "mPCIe OVC"; ++ }; ++ }; ++}; ++ ++&i2cswitch4 { ++ reg = <0x71>; ++ reset-gpios= <&gpio3 15 GPIO_ACTIVE_LOW>; ++}; ++ ++&wlcore { ++ interrupts = <25 IRQ_TYPE_EDGE_FALLING>; ++}; ++ ++&pciec1 { ++ pcie3v3-supply = <&mpcie_3v3>; ++ pcie1v8-supply = <&mpcie_1v8>; ++}; +diff --git a/arch/arm64/boot/dts/renesas/legacy/r8a7796-m3ulcb-kf-v0.dts b/arch/arm64/boot/dts/renesas/legacy/r8a7796-m3ulcb-kf-v0.dts +new file mode 100644 +index 0000000..ffa1879 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/legacy/r8a7796-m3ulcb-kf-v0.dts +@@ -0,0 +1,1214 @@ ++/* ++ * Device Tree Source for the M3ULCB Kingfisher V0 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 V0 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; ++ }; ++ ++ vcc_sdhi3: regulator@41 { ++ compatible = "regulator-fixed"; ++ ++ regulator-name = "SDHI3 Vcc"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++ }; ++ ++ vccq_sdhi3: regulator@5 { ++ compatible = "regulator-fixed"; ++ ++ regulator-name = "SDHI3 VccQ"; ++ 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"; ++ shutdown-gpios = <&gpio_ext_20 3 GPIO_ACTIVE_HIGH>; ++ /* 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>; ++ }; ++ }; ++ ++ 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 = "ssi0129_ctrl", "ssi0_data", "ssi1_data_a"; ++ function = "ssi"; ++ }; ++ ++ sound_2_pins: sound2 { ++ groups = "ssi6_ctrl", "ssi6_data"; ++ function = "ssi"; ++ }; ++ ++ usb0_pins: usb0 { ++ groups = "usb0"; ++ function = "usb0"; ++ }; ++ ++ can0_pins: can0 { ++ groups = "can0_data_a"; ++ function = "can0"; ++ }; ++ ++ can1_pins: can1 { ++ groups = "can1_data"; ++ function = "can1"; ++ }; ++ ++ canfd0_pins: canfd0 { ++ groups = "canfd0_data_a"; ++ function = "canfd0"; ++ }; ++ ++ canfd1_pins: canfd1 { ++ groups = "canfd1_data"; ++ function = "canfd1"; ++ }; ++}; ++ ++&du { ++ ports { ++ port@2 { ++ endpoint { ++ remote-endpoint = <&lvds_enc_in>; ++ }; ++ }; ++ }; ++}; ++ ++&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"; ++ uart-has-rtscts; ++ ++ 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: pca9548@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) */ ++ }; ++ ++ 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 = <&_en_reg>; ++ VCCDA2-supply = <&_en_reg>; ++ }; ++ ++ lsm9ds0_acc_mag@1d { ++ compatible = "st,lsm9ds0_accel_magn"; ++ 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>; ++ ++ cmos_pwdn { ++ gpio-hog; ++ gpios = <8 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "CMOS PWDN"; ++ }; ++ cmos_rst { ++ gpio-hog; ++ gpios = <9 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "CMOS RST"; ++ }; ++ /* pin 12 - CAM_CLK */ ++ rpi_cam_io_1 { ++ gpio-hog; ++ gpios = <10 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "RaspB_IO1"; ++ }; ++ /* pin 11 - CAM_GPIO - assume pwdn */ ++ rpi_cam_io_0 { ++ gpio-hog; ++ gpios = <11 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "RaspB_IO0"; ++ }; ++ }; ++ ++ i2cswitch4: pca9548@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>; ++ /* Slot A (CN10) */ ++ ++ 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 @ 0x2c */ ++ max9286-max9271@0 { ++ compatible = "maxim,max9286-max9271"; ++ reg = <0x2c>; ++ 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@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ /* Slot A (CN10) */ ++ ++ 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>; ++ input; ++ line-name = "Video-A cfg1"; ++ }; ++ video_a_des_cfg0 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ 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>; ++ input; ++ line-name = "Video-A cfg2"; ++ }; ++ video_a_des_cfg1 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-A cfg1"; ++ }; ++ video_a_des_cfg0 { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ input; ++ 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"; ++ }; ++ video_a_cam_pwr2 { ++ gpio-hog; ++ gpios = <10 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR2"; ++ }; ++ video_a_cam_pwr3 { ++ gpio-hog; ++ gpios = <11 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR3"; ++ }; ++ video_a_des_shdn { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A DES_SHDN"; ++ }; ++ video_a_led { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-A LED"; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&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>; ++ }; ++ }; ++}; ++ ++&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>; ++ }; ++}; ++ ++&usb2_phy0 { ++ pinctrl-0 = <&usb0_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&hsusb { ++ status = "okay"; ++}; ++ ++&ehci0 { ++ status = "okay"; ++}; ++ ++&ohci0 { ++ status = "okay"; ++}; ++ ++&xhci0 { ++ status = "okay"; ++}; ++ ++&msiof1 { ++ status = "disabled"; ++}; ++ ++&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"; ++ ++ channel0 { ++ status = "okay"; ++ }; ++ ++ channel1 { ++ status = "okay"; ++ }; ++}; ++ ++&ssi8 { ++ shared-pin; ++}; ++ ++/* uncomment to enable CN47: SD on SDHI3 */ ++//#include "../ulcb-kf-sd3.dtsi" ++/* CN48 (Raspberry Pi) on VIN4 */ ++#include "ulcb-kf-rpi.dtsi" ++/* CN29: (CMOS camera) on VIN5 */ ++#include "ulcb-kf-cmos.dtsi" +diff --git a/arch/arm64/boot/dts/renesas/legacy/r8a7796-m3ulcb-kf-v1.dts b/arch/arm64/boot/dts/renesas/legacy/r8a7796-m3ulcb-kf-v1.dts +new file mode 100644 +index 0000000..637c840 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/legacy/r8a7796-m3ulcb-kf-v1.dts +@@ -0,0 +1,465 @@ ++/* ++ * Device Tree Source for the M3ULCB Kingfisher V1 board ++ * ++ * 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-kf-v0.dts" ++ ++/ { ++ model = "Renesas M3ULCB Kingfisher V1 board based on r8a7796"; ++ ++ aliases { ++ serial1 = &hscif0; ++ serial2 = &hscif1; ++ serial3 = &scif1; ++ }; ++ ++ wlan_en: regulator@4 { ++ compatible = "regulator-fixed"; ++ regulator-name = "wlan-en-regulator"; ++ ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ gpio = <&gpio_ext_74 4 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ codec_en_reg: regulator@6 { ++ compatible = "regulator-fixed"; ++ regulator-name = "codec-en-regulator"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ gpio = <&gpio_ext_74 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_74 0 0>; ++ ++ startup-delay-us = <0>; ++ enable-active-high; ++ }; ++ ++ /delete-node/regulator@8; ++ ++ sdio_switch: regulator@9 { ++ compatible = "regulator-fixed"; ++ regulator-name = "wifi_on"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&gpio_ext_74 5 0>; ++ enable-active-low; ++ regulator-always-on; ++ }; ++ ++ /delete-node/regulator@10; ++ ++ radio_switch: regulator@11 { ++ compatible = "regulator-fixed"; ++ regulator-name = "radio_on"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&gpio_ext_74 13 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ regulator-always-on; ++ }; ++ ++ mpcie_3v3: regulator@12 { ++ compatible = "regulator-fixed"; ++ regulator-name = "mPCIe 3v3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&gpio_ext_77 14 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ mpcie_1v8: regulator@13 { ++ compatible = "regulator-fixed"; ++ regulator-name = "mPCIe 1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ gpio = <&gpio_ext_77 15 GPIO_ACTIVE_HIGH>; ++ startup-delay-us = <200000>; ++ enable-active-high; ++ }; ++ ++ kim { ++ shutdown-gpios = <&gpio_ext_74 3 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ hdmi-out { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi_con: endpoint { ++ remote-endpoint = <&adv7513_out>; ++ }; ++ }; ++ }; ++}; ++ ++&pfc { ++ /delete-node/hscif4; ++ ++ scif1_pins: scif1 { ++ groups = "scif1_data_b"; ++ function = "scif1"; ++ }; ++ ++ hscif0_pins: hscif0 { ++ groups = "hscif0_data", "hscif0_ctrl"; ++ function = "hscif0"; ++ }; ++ ++ hscif1_pins: hscif1 { ++ groups = "hscif1_data_a", "hscif1_ctrl_a"; ++ function = "hscif1"; ++ }; ++ ++ du_pins: du { ++ groups = "du_rgb888", "du_sync", "du_clk_out_0", "du_disp"; ++ function = "du"; ++ }; ++}; ++ ++&du { ++ pinctrl-0 = <&du_pins>; ++ pinctrl-names = "default"; ++ ++ ports { ++ port@0 { ++ endpoint { ++ remote-endpoint = <&adv7513_in>; ++ }; ++ }; ++ }; ++}; ++ ++&gpio0 { ++ /delete-node/video_a_irq; ++ /delete-node/video_b_irq; ++ /delete-node/gpioext_2_20_irq; ++}; ++ ++&gpio1 { ++ /delete-node/gpioext_2_21_irq; ++ /delete-node/wifi_irq; ++}; ++ ++&gpio2 { ++ bl_pwm { ++ gpio-hog; ++ gpios = <3 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "BL PWM 100%"; ++ }; ++}; ++ ++&gpio5 { ++ /delete-node/touch_irq; ++ /delete-node/bt_strap; ++}; ++ ++&gpio7 { ++ /delete-node/gpioext_2_21_irq; ++}; ++ ++&scif1 { ++ pinctrl-0 = <&scif1_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&hscif0 { ++ pinctrl-0 = <&hscif0_pins>; ++ pinctrl-names = "default"; ++ uart-has-rtscts; ++ ++ status = "okay"; ++}; ++ ++&hscif1 { ++ pinctrl-0 = <&hscif1_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&hscif4 { ++ /delete-property/pinctrl-0; ++ /delete-property/pinctrl-names; ++ ++ status = "disabled"; ++}; ++ ++&i2c2 { ++ /delete-node/pca9535@20; ++ /delete-node/pca9535@21; ++ ++ gpio_ext_74: pca9539@74 { ++ compatible = "nxp,pca9539"; ++ reg = <0x74>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ interrupt-parent = <&gpio6>; ++ interrupts = <8 IRQ_TYPE_EDGE_FALLING>; ++ ++ hub_pwen { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "HUB pwen"; ++ }; ++ hub_rst { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "HUB rst"; ++ }; ++ otg_offvbus { ++ gpio-hog; ++ gpios = <8 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "OTG off VBUSn"; ++ }; ++ otg_extlpn { ++ gpio-hog; ++ gpios = <9 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "OTG EXTLPn"; ++ }; ++ otg_stat1 { ++ gpio-hog; ++ gpios = <10 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "OTG Stat1"; ++ }; ++ otg_stat2 { ++ gpio-hog; ++ gpios = <11 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "OTG Stat2"; ++ }; ++ }; ++ ++ gpio_ext_75: pca9539@75 { ++ compatible = "nxp,pca9539"; ++ reg = <0x75>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ interrupt-parent = <&gpio6>; ++ interrupts = <4 IRQ_TYPE_EDGE_FALLING>; ++ ++ gps_rst { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "GPS rst"; ++ }; ++ fpdl_shdn { ++ gpio-hog; ++ gpios = <9 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "FPDLink shdn"; ++ }; ++ }; ++}; ++ ++&i2cswitch2 { ++ reg = <0x71>; ++ reset-gpios= <&gpio5 3 GPIO_ACTIVE_LOW>; ++ ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ ++ hdmi@3d { ++ compatible = "adi,adv7511w"; ++ reg = <0x3d>; ++// interrupt-parent = <&gpio2>; ++// interrupts = <0 IRQ_TYPE_EDGE_BOTH>; ++ pd-gpios = <&gpio_ext_75 5 GPIO_ACTIVE_LOW>; ++ ++ adi,input-depth = <8>; ++ adi,input-colorspace = "rgb"; ++ adi,input-clock = "1x"; ++ adi,input-style = <1>; ++ adi,input-justification = "evenly"; ++ adi,clock-delay = <1200>; ++ adi,clock-max-rate = <100000>; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ adv7513_in: endpoint { ++ remote-endpoint = <&du_out_rgb>; ++ }; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ adv7513_out: endpoint { ++ remote-endpoint = <&hdmi_con>; ++ }; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&i2c4 { ++ /delete-node/pca9535@21; ++ ++ gpio_ext_76: pca9539@76 { ++ compatible = "nxp,pca9539"; ++ reg = <0x76>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ interrupt-parent = <&gpio7>; ++ interrupts = <3 IRQ_TYPE_EDGE_FALLING>; ++ ++ port_b_a0 { ++ gpio-hog; ++ gpios = <0 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-B A0"; ++ }; ++ port_b_a1 { ++ gpio-hog; ++ gpios = <1 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B A1"; ++ }; ++ port_a_a0 { ++ gpio-hog; ++ gpios = <2 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-A A0"; ++ }; ++ port_a_a1 { ++ gpio-hog; ++ gpios = <3 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A A1"; ++ }; ++ cmos_pwdn { ++ gpio-hog; ++ gpios = <8 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "CMOS PWDN"; ++ }; ++ cmos_rst { ++ gpio-hog; ++ gpios = <9 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "CMOS RST"; ++ }; ++ /* pin 12 - CAM_CLK */ ++ rpi_cam_io_1 { ++ gpio-hog; ++ gpios = <10 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "RaspB_IO1"; ++ }; ++ /* pin 11 - CAM_GPIO - assume pwdn */ ++ rpi_cam_io_0 { ++ gpio-hog; ++ gpios = <11 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "RaspB_IO0"; ++ }; ++ sam_rst { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "SAM RST"; ++ }; ++ sam_pwr { ++ gpio-hog; ++ gpios = <5 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "SAM PWR"; ++ }; ++ /* 0 - FPDLink output, 1 - LVDS output */ ++ lvds_vs_fpdl { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "LVDS switch"; ++ }; ++ }; ++ ++ gpio_ext_77: pca9539@77 { ++ compatible = "nxp,pca9539"; ++ reg = <0x77>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ interrupt-parent = <&gpio5>; ++ interrupts = <9 IRQ_TYPE_EDGE_FALLING>; ++ ++ mpcie_wake { ++ gpio-hog; ++ gpios = <0 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "mPCIe WAKE#"; ++ }; ++ mpcie_wdisable { ++ gpio-hog; ++ gpios = <1 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "mPCIe W_DISABLE"; ++ }; ++ mpcie_clreq { ++ gpio-hog; ++ gpios = <2 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "mPCIe CLKREQ#"; ++ }; ++ mpcie_ovc { ++ gpio-hog; ++ gpios = <3 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "mPCIe OVC"; ++ }; ++ }; ++}; ++ ++&i2cswitch4 { ++ reg = <0x71>; ++ reset-gpios= <&gpio3 15 GPIO_ACTIVE_LOW>; ++}; ++ ++&wlcore { ++ interrupts = <25 IRQ_TYPE_EDGE_FALLING>; ++}; ++ ++&pciec1 { ++ pcie3v3-supply = <&mpcie_3v3>; ++ pcie1v8-supply = <&mpcie_1v8>; ++}; +diff --git a/arch/arm64/boot/dts/renesas/legacy/r8a7797-v3msk-kf-v0.dts b/arch/arm64/boot/dts/renesas/legacy/r8a7797-v3msk-kf-v0.dts +new file mode 100644 +index 0000000..674d3bf +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/legacy/r8a7797-v3msk-kf-v0.dts +@@ -0,0 +1,82 @@ ++/* ++ * Device Tree Source for the V3MSK Kingfisher V0 board on r8a7797 ++ * ++ * 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 "../r8a7797-v3msk-kf.dts" ++ ++/ { ++ model = "Renesas V3MSK Kingfisher V0 board based on r8a7797"; ++}; ++ ++&i2cswitch4 { ++ reg = <0x74>; ++}; ++ ++&msiof1 { ++ pinctrl-0 = <&msiof1_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ spidev@0 { ++ compatible = "renesas,sh-msiof"; ++ reg = <0>; ++ spi-max-frequency = <66666666>; ++ spi-cpha; ++ spi-cpol; ++ }; ++}; ++ ++&msiof2 { ++ pinctrl-0 = <&msiof2_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ 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 = "okay"; ++ ++ spidev@0 { ++ compatible = "renesas,sh-msiof"; ++ reg = <0>; ++ spi-max-frequency = <66666666>; ++ spi-cpha; ++ spi-cpol; ++ }; ++}; ++ ++&pfc { ++ msiof1_pins: spi2 { ++ groups = "msiof1_clk", "msiof1_sync", "msiof1_rxd", ++ "msiof1_txd"; ++ function = "msiof1"; ++ }; ++ ++ msiof2_pins: spi3 { ++ groups = "msiof2_clk", "msiof2_sync", "msiof2_rxd", ++ "msiof2_txd"; ++ function = "msiof2"; ++ }; ++ ++ msiof3_pins: spi4 { ++ groups = "msiof3_clk", "msiof3_sync", "msiof3_rxd", ++ "msiof3_txd"; ++ function = "msiof3"; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/renesas/legacy/ulcb-kf-cmos.dtsi b/arch/arm64/boot/dts/renesas/legacy/ulcb-kf-cmos.dtsi +new file mode 100644 +index 0000000..2145f5e +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/legacy/ulcb-kf-cmos.dtsi +@@ -0,0 +1,75 @@ ++/* ++ * Device Tree Source for the H3ULCB Kingfisher board: ++ * this adding conflicting resource on VIN5 for CMOS camera ++ * ++ * 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. ++ */ ++ ++/ { ++ camera_clk: camera_clk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <24000000>; ++ clock-output-names = "mclk"; ++ }; ++}; ++ ++&pfc { ++ vin5_pins: vin5 { ++ groups = "vin5_data8", "vin5_sync", "vin5_clk"; ++ function = "vin5"; ++ }; ++}; ++ ++&i2cswitch4 { ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ ++ cmos_camera: ov5642@3c { ++ compatible = "ovti,ov5642"; ++ reg = <0x3c>; ++ clocks = <&camera_clk>; ++ clock-names = "mclk"; ++ ++ port@0 { ++ cmos_camera_in: endpoint { ++ remote-endpoint = <&vin5ep0>; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&vin5 { ++ pinctrl-0 = <&vin5_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin5ep0: endpoint@0 { ++ /delete-property/csi,select; ++ /delete-property/virtual,channel; ++ /delete-property/data-lanes; ++ bus-width = <8>; ++ /* #HSYNC, #VSYNC */ ++ vsync-active = <1>; ++ hsync-active = <0>; ++ remote-endpoint = <&cmos_camera_in>; ++ }; ++ }; ++ port@1 { ++ /delete-node/endpoint; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/renesas/legacy/ulcb-kf-rpi.dtsi b/arch/arm64/boot/dts/renesas/legacy/ulcb-kf-rpi.dtsi +new file mode 100644 +index 0000000..bcd9865 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/legacy/ulcb-kf-rpi.dtsi +@@ -0,0 +1,77 @@ ++/* ++ * Device Tree Source for the H3ULCB Kingfisher board: ++ * this adding conflicting resource on VIN4 for Raspberry Pi camera ++ * ++ * 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. ++ */ ++ ++&i2cswitch4 { ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ ++ rpi_camera: ov5647@36 { ++ compatible = "ovti,ov5647"; ++ reg = <0x36>; ++ ++ port@0 { ++ rpi_camera_in: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ remote-endpoint = <&vin4ep0>; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&vin4 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin4ep0: endpoint { ++ csi,select = "csi20"; ++ virtual,channel = <0>; ++ remote-endpoint = <&rpi_camera_in>; ++ data-lanes = <1 2>; ++ }; ++ }; ++ port@1 { ++ csi2ep0: endpoint { ++ remote-endpoint = <&csi2_20_ep>; ++ }; ++ }; ++ }; ++}; ++ ++&csi2_20 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "raw8"; ++ receive,vc = <0>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi2_20_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ csi-rate = <280>; ++ }; ++ }; ++}; +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..d50ff7a +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-had.dtsi +@@ -0,0 +1,225 @@ ++/* ++ * 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 { ++ serial1 = &scif1; ++ 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"; ++}; +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..849afae +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts +@@ -0,0 +1,39 @@ ++/* ++ * 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" ++#include "ulcb-kf.dtsi" ++ ++/ { ++ model = "Renesas H3ULCB Kingfisher board based on r8a7795"; ++}; ++ ++&du { ++ ports { ++ port@0 { ++ endpoint { ++ remote-endpoint = <&adv7513_in>; ++ }; ++ }; ++ port@3 { ++ endpoint { ++ remote-endpoint = <&lvds_enc_in>; ++ }; ++ }; ++ }; ++}; ++ ++&hsusb { ++ status = "okay"; ++}; ++ ++/* use CN11 instead default CN29/CN48 (H3 only) */ ++//#include "ulcb-kf-cn11.dtsi" +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-vb.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-vb.dts +new file mode 100644 +index 0000000..549a717 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-vb.dts +@@ -0,0 +1,69 @@ ++/* ++ * Device Tree Source for the H3ULCB Videobox 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" ++#include "ulcb-vb.dtsi" ++ ++/ { ++ model = "Renesas H3ULCB Videobox board based on r8a7795"; ++ ++ hdmi1-out { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi1_con: endpoint { ++ remote-endpoint = <&rcar_dw_hdmi1_out>; ++ }; ++ }; ++ }; ++}; ++ ++&du { ++ ports { ++ port@2 { ++ endpoint { ++ remote-endpoint = <&rcar_dw_hdmi1_in>; ++ }; ++ }; ++ port@3 { ++ endpoint { ++ remote-endpoint = <&lvds_enc_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>; ++ }; ++ }; ++ }; ++}; ++ ++&hsusb { ++ status = "okay"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-vbm.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-vbm.dts +new file mode 100644 +index 0000000..323722c +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-vbm.dts +@@ -0,0 +1,26 @@ ++/* ++ * Device Tree Source for the H3ULCB Videobox Mini board on r8a7795 ES1.x ++ * ++ * 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" ++#include "ulcb-vbm.dtsi" ++ ++/ { ++ model = "Renesas H3ULCB Videobox Mini board based on r8a7795"; ++}; ++ ++&du { ++ ports { ++ port@3 { ++ endpoint { ++ remote-endpoint = <&lvds_enc_in>; ++ }; ++ }; ++ }; ++}; +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>; ++ }; ++ }; ++}; +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"; ++}; +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..4a00426 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-had.dtsi +@@ -0,0 +1,219 @@ ++/* ++ * 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 { ++ serial1 = &scif1; ++ 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"; ++ }; ++}; +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..4fe67f8 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts +@@ -0,0 +1,39 @@ ++/* ++ * 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" ++#include "ulcb-kf.dtsi" ++ ++/ { ++ model = "Renesas H3ULCB Kingfisher board based on r8a7795"; ++}; ++ ++&du { ++ ports { ++ port@0 { ++ endpoint { ++ remote-endpoint = <&adv7513_in>; ++ }; ++ }; ++ port@3 { ++ endpoint { ++ remote-endpoint = <&lvds_enc_in>; ++ }; ++ }; ++ }; ++}; ++ ++&hsusb0 { ++ status = "okay"; ++}; ++ ++/* use CN11 instead default CN29/CN48 (H3 only) */ ++//#include "ulcb-kf-cn11.dtsi" +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vb.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vb.dts +new file mode 100644 +index 0000000..330bba2 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vb.dts +@@ -0,0 +1,68 @@ ++/* ++ * Device Tree Source for the H3ULCB Videobox board on r8a7795 ++ * ++ * 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" ++#include "ulcb-vb.dtsi" ++ ++/ { ++ model = "Renesas H3ULCB Videobox board based on r8a7795"; ++ ++ hdmi1-out { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi1_con: endpoint { ++ remote-endpoint = <&rcar_dw_hdmi1_out>; ++ }; ++ }; ++ }; ++}; ++ ++&du { ++ ports { ++ port@2 { ++ endpoint { ++ remote-endpoint = <&rcar_dw_hdmi1_in>; ++ }; ++ }; ++ port@3 { ++ endpoint { ++ remote-endpoint = <&lvds_enc_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>; ++ }; ++ }; ++ }; ++}; ++ ++&hsusb0 { ++ status = "okay"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vbm.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vbm.dts +new file mode 100644 +index 0000000..87f1889 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vbm.dts +@@ -0,0 +1,26 @@ ++/* ++ * Device Tree Source for the H3ULCB Videobox Mini board on r8a7795 ES1.x ++ * ++ * 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" ++#include "ulcb-vbm.dtsi" ++ ++/ { ++ model = "Renesas H3ULCB Videobox Mini board based on r8a7795"; ++}; ++ ++&du { ++ ports { ++ port@3 { ++ endpoint { ++ remote-endpoint = <&lvds_enc_in>; ++ }; ++ }; ++ }; ++}; +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..2c24b85 +--- /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>; ++ }; ++ }; ++}; +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..fb12a39f3 +--- /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"; ++}; +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..a409402 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts +@@ -0,0 +1,40 @@ ++/* ++ * 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" ++#include "ulcb-kf.dtsi" ++ ++/ { ++ model = "Renesas M3ULCB Kingfisher board based on r8a7796"; ++}; ++ ++&du { ++ ports { ++ port@0 { ++ endpoint { ++ remote-endpoint = <&adv7513_in>; ++ }; ++ }; ++ port@2 { ++ endpoint { ++ remote-endpoint = <&lvds_enc_in>; ++ }; ++ }; ++ }; ++}; ++ ++&hsusb { ++ status = "okay"; ++}; ++ ++&xhci0 { ++ status = "disabled"; ++}; +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>; ++ }; ++ }; ++}; +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"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7797-eagle.dts b/arch/arm64/boot/dts/renesas/r8a7797-eagle.dts +new file mode 100644 +index 0000000..3fb3bf1 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7797-eagle.dts +@@ -0,0 +1,560 @@ ++/* ++ * Device Tree Source for the Eagle board ++ * ++ * 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. ++ */ ++ ++/dts-v1/; ++#include "r8a7797.dtsi" ++#include <dt-bindings/gpio/gpio.h> ++ ++/ { ++ model = "Renesas Eagle board based on r8a7797"; ++ compatible = "renesas,eagle", "renesas,r8a7797"; ++ ++ aliases { ++ serial0 = &scif0; ++ 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 0x38000000>; ++ }; ++ ++ reserved-memory { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ /* device specific region for Lossy Decompression */ ++ lossy_decompress: linux,lossy_decompress { ++ no-map; ++ reg = <0x00000000 0x6c000000 0x0 0x03000000>; ++ }; ++ ++ /* global autoconfigured region for contiguous allocations */ ++ linux,cma { ++ compatible = "shared-dma-pool"; ++ reusable; ++ reg = <0x00000000 0x6f000000 0x0 0x10000000>; ++ linux,cma-default; ++ }; ++ ++ /* device specific region for contiguous allocations */ ++ linux,multimedia { ++ compatible = "shared-dma-pool"; ++ reusable; ++ reg = <0x00000000 0x7f000000 0x0 0x01000000>; ++ }; ++ }; ++ ++ mmngr { ++ compatible = "renesas,mmngr"; ++ memory-region = <&lossy_decompress>; ++ }; ++ ++ mmngrbuf { ++ compatible = "renesas,mmngrbuf"; ++ }; ++ ++ vspm_if { ++ compatible = "renesas,vspm_if"; ++ }; ++ ++ 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 { ++ clock-frequency = <133000000>; ++ hactive = <1024>; ++ vactive = <768>; ++ hsync-len = <136>; ++ hfront-porch = <20>; ++ hback-porch = <160>; ++ vfront-porch = <3>; ++ vback-porch = <29>; ++ vsync-len = <6>; ++ }; ++ ++ port { ++ lvds_in: endpoint { ++ remote-endpoint = <&lvds_enc_out>; ++ }; ++ }; ++ }; ++ ++ hdmi-out { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi_con: endpoint { ++ remote-endpoint = <&adv7511_out>; ++ }; ++ }; ++ }; ++ ++ dclkin_p0: clock-out0 { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <148500000>; ++ }; ++ ++ msiof_ref_clk: msiof-ref-clock { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <66666666>; ++ }; ++}; ++ ++&du { ++ pinctrl-0 = <&du_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ endpoint { ++ remote-endpoint = <&adv7511_in>; ++ }; ++ }; ++ }; ++}; ++ ++&extal_clk { ++ clock-frequency = <16666666>; ++}; ++ ++&extalr_clk { ++ clock-frequency = <32768>; ++}; ++ ++&pfc { ++ pinctrl-0 = <&scif_clk_pins>; ++ pinctrl-names = "default"; ++ ++ scif0_pins: scif0 { ++ groups = "scif0_data"; ++ function = "scif0"; ++ }; ++ ++ scif_clk_pins: scif_clk { ++ groups = "scif_clk_b"; ++ function = "scif_clk"; ++ }; ++ ++ i2c0_pins: i2c0 { ++ groups = "i2c0"; ++ function = "i2c0"; ++ }; ++ ++ i2c3_pins: i2c3 { ++ groups = "i2c3"; ++ function = "i2c3"; ++ }; ++ ++ avb_pins: avb { ++ groups = "avb0_mdc"; ++ function = "avb0"; ++ }; ++ ++ du_pins: du { ++ groups = "du_rgb666", "du_sync", "du_clk_out_0", "du_disp"; ++ function = "du"; ++ }; ++}; ++ ++&scif0 { ++ pinctrl-0 = <&scif0_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&scif_clk { ++ clock-frequency = <14745600>; ++ status = "okay"; ++}; ++ ++&i2c0 { ++ pinctrl-0 = <&i2c0_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++ clock-frequency = <400000>; ++ ++ hdmi@39{ ++ compatible = "adi,adv7511w"; ++ #sound-dai-cells = <0>; ++ reg = <0x39>; ++ interrupt-parent = <&gpio1>; ++ interrupts = <20 IRQ_TYPE_LEVEL_LOW>; ++ ++ adi,input-depth = <8>; ++ adi,input-colorspace = "rgb"; ++ adi,input-clock = "1x"; ++ adi,input-style = <1>; ++ adi,input-justification = "evenly"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ adv7511_in: endpoint { ++ remote-endpoint = <&lvds_enc_out>; ++ }; ++ }; ++ port@1 { ++ reg = <1>; ++ adv7511_out: endpoint { ++ remote-endpoint = <&hdmi_con>; ++ }; ++ }; ++ }; ++ }; ++ ++ gpio_ext: pca9654@20 { ++ compatible = "onsemi,pca9654"; ++ reg = <0x20>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ }; ++}; ++ ++&i2c3 { ++ pinctrl-0 = <&i2c3_pins>; ++ pinctrl-names = "default"; ++ ++ 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 = <&gpio_ext 0 GPIO_ACTIVE_LOW>; /* CSI0 DE_PDn */ ++ maxim,gpio0 = <0>; ++ maxim,sensor_delay = <100>; ++ 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>; ++ }; ++ }; ++ }; ++}; ++ ++&wdt0 { ++ status = "okay"; ++}; ++ ++&avb { ++ pinctrl-0 = <&avb_pins>; ++ pinctrl-names = "default"; ++ renesas,no-ether-link; ++ phy-handle = <&phy0>; ++ status = "okay"; ++ phy-int-gpio = <&gpio1 17 GPIO_ACTIVE_LOW>; ++ ++ phy0: ethernet-phy@0 { ++ rxc-skew-ps = <1500>; ++ rxdv-skew-ps = <420>; /* default */ ++ rxd0-skew-ps = <420>; /* default */ ++ rxd1-skew-ps = <420>; /* default */ ++ rxd2-skew-ps = <420>; /* default */ ++ rxd3-skew-ps = <420>; /* default */ ++ txc-skew-ps = <900>; /* default */ ++ txen-skew-ps = <420>; /* default */ ++ txd0-skew-ps = <420>; /* default */ ++ txd1-skew-ps = <420>; /* default */ ++ txd2-skew-ps = <420>; /* default */ ++ txd3-skew-ps = <420>; /* default */ ++ reg = <0>; ++ interrupt-parent = <&gpio1>; ++ interrupts = <17 IRQ_TYPE_LEVEL_LOW>; ++ max-speed = <1000>; ++ }; ++}; ++ ++&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>; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts +new file mode 100644 +index 0000000..979cebe +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts +@@ -0,0 +1,578 @@ ++/* ++ * Device Tree Source for the V3MSK Kingfisher board on r8a7797 ++ * ++ * 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 "r8a7797-v3msk.dts" ++ ++/ { ++ model = "Renesas V3MSK Kingfisher board based on r8a7797"; ++}; ++ ++&canfd { ++ pinctrl-0 = <&canfd0_pins &canfd1_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ channel0 { ++ status = "okay"; ++ }; ++ ++ channel1 { ++ status = "okay"; ++ }; ++}; ++ ++&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>; ++ }; ++ }; ++}; ++ ++&i2c0 { ++ /* i2c0 might conflict with pc9548 reset pin on Kingfisher (uncomment if h/w not patched) */ ++// status = "disabled"; ++}; ++ ++&i2c3 { ++ pinctrl-0 = <&i2c3_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ clock-frequency = <400000>; ++ ++ i2cswitch4: pca9548@71 { ++ compatible = "nxp,pca9548"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x71>; ++// reset-gpios= <&gpio3 15 GPIO_ACTIVE_LOW>; ++ ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ /* Slot B (CN11) */ ++ ++ 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 = <800>; ++ 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 = <800>; ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ }; ++ ++ /* MAX9286 @ 0x2c */ ++ max9286-max9271@0 { ++ compatible = "maxim,max9286-max9271"; ++ reg = <0x2c>; ++ 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@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ /* Slot B (CN11) */ ++ ++ video_a_ext0: pca9535@27 { ++ compatible = "nxp,pca9535"; ++ reg = <0x27>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ video_a_des_cfg1 { ++ gpio-hog; ++ gpios = <5 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-A cfg1"; ++ }; ++ video_a_des_cfg0 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ 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>; ++ input; ++ line-name = "Video-A cfg2"; ++ }; ++ video_a_des_cfg1 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-A cfg1"; ++ }; ++ video_a_des_cfg0 { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ input; ++ 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"; ++ }; ++ video_a_cam_pwr2 { ++ gpio-hog; ++ gpios = <10 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR2"; ++ }; ++ video_a_cam_pwr3 { ++ gpio-hog; ++ gpios = <11 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR3"; ++ }; ++ video_a_des_shdn { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A DES_SHDN"; ++ }; ++ video_a_led { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-A LED"; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&pfc { ++ canfd0_pins: canfd0 { ++ groups = "canfd0_data_a"; ++ function = "canfd0"; ++ }; ++ ++ canfd1_pins: canfd1 { ++ groups = "canfd1_data"; ++ function = "canfd1"; ++ }; ++ ++ i2c3_pins: i2c3 { ++ groups = "i2c3"; ++ function = "i2c3"; ++ }; ++}; ++ ++&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>; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts +new file mode 100644 +index 0000000..4292b7b +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts +@@ -0,0 +1,518 @@ ++/* ++ * Device Tree Source for the V3MSK Videobox Mini board on r8a7797 ++ * ++ * 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 "r8a7797-v3msk.dts" ++ ++/ { ++ model = "Renesas V3MSK Videobox Mini board based on r8a7797"; ++ ++ aliases { ++ serial1 = &scif3; ++ }; ++ ++ pwr0: regulator-pwr0 { ++ compatible = "regulator-fixed"; ++ regulator-name = "PWR0"; ++ regulator-min-microvolt = <9000000>; ++ regulator-max-microvolt = <9000000>; ++ gpio = <&gpio_exp_6c 8 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ pwr1: regulator-pwr1 { ++ compatible = "regulator-fixed"; ++ regulator-name = "PWR1"; ++ regulator-min-microvolt = <9000000>; ++ regulator-max-microvolt = <9000000>; ++ gpio = <&gpio_exp_6c 9 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ pwr2: regulator-pwr2 { ++ compatible = "regulator-fixed"; ++ regulator-name = "PWR2"; ++ regulator-min-microvolt = <9000000>; ++ regulator-max-microvolt = <9000000>; ++ gpio = <&gpio_exp_6c 10 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ pwr3: regulator-pwr3 { ++ compatible = "regulator-fixed"; ++ regulator-name = "PWR3"; ++ regulator-min-microvolt = <9000000>; ++ regulator-max-microvolt = <9000000>; ++ gpio = <&gpio_exp_6c 11 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++}; ++ ++&canfd { ++ pinctrl-0 = <&canfd0_pins &canfd1_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ channel0 { ++ status = "okay"; ++ }; ++ ++ channel1 { ++ status = "okay"; ++ }; ++}; ++ ++&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>; ++ }; ++ }; ++}; ++ ++&i2c1 { ++ pinctrl-0 = <&i2c1_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ clock-frequency = <400000>; ++ ++ i2cswitch1: i2c-switch@74 { ++ compatible = "nxp,pca9548"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x74>; ++ reset-gpios = <&gpio0 9 GPIO_ACTIVE_LOW>; ++ ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ ++ 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@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@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>; ++ }; ++ }; ++ }; ++ ++ max9286-max9271@0 { ++ compatible = "maxim,max9286-max9271"; ++ reg = <0x2c>; ++ maxim,sensor_delay = <350>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ POC0-supply = <&pwr0>; ++ POC1-supply = <&pwr1>; ++ POC2-supply = <&pwr2>; ++ POC3-supply = <&pwr3>; ++ ++ 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>; ++ }; ++ }; ++ }; ++ ++ 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"; ++ POC0-supply = <&pwr0>; ++ POC1-supply = <&pwr1>; ++ POC2-supply = <&pwr2>; ++ POC3-supply = <&pwr3>; ++ ++ 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>; ++ }; ++ }; ++ }; ++ }; ++ ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ ++ gpio_exp_6c: gpio@6c { ++ compatible = "maxim,max7325"; ++ reg = <0x6c>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ virq { ++ gpio-hog; ++ gpios = <5 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "VIRQ"; ++ }; ++ des_cfg { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "CNFG0"; ++ }; ++ pwr_shdn { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "PWR_SHDN"; ++ }; ++ des_shdn { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Des_SHDN"; ++ }; ++ fpdl_shdn { ++ gpio-hog; ++ gpios = <15 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "FPDL_SHDN"; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&gpio0 { ++ can0stby { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "CAN0STBY"; ++ }; ++ ++ can1_load { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "can1_120R_load"; ++ }; ++}; ++ ++&gpio2 { ++ can0_load { ++ gpio-hog; ++ gpios = <16 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "can0_120R_load"; ++ }; ++}; ++ ++&pfc { ++ canfd0_pins: canfd0 { ++ groups = "canfd0_data_a"; ++ function = "canfd0"; ++ }; ++ ++ canfd1_pins: canfd1 { ++ groups = "canfd1_data"; ++ function = "canfd1"; ++ }; ++ ++ i2c1_pins: i2c1 { ++ groups = "i2c1"; ++ function = "i2c1"; ++ }; ++ ++ scif3_pins: scif3 { ++ groups = "scif3_data"; ++ function = "scif3"; ++ }; ++}; ++ ++&scif3 { ++ pinctrl-0 = <&scif3_pins>; ++ pinctrl-names = "default"; ++ ++ 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>; ++ }; ++ }; ++ }; ++}; ++ ++&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>; ++ }; ++ }; ++ }; ++}; ++ ++&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>; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7797-v3msk-view.dts b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-view.dts +new file mode 100644 +index 0000000..573e2bc +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-view.dts +@@ -0,0 +1,298 @@ ++/* ++ * Device Tree Source for the V3MSK View board on r8a7797 ++ * ++ * 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 "r8a7797-v3msk.dts" ++ ++/ { ++ model = "Renesas V3MSK View board based on r8a7797"; ++}; ++ ++&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>; ++ }; ++ }; ++}; ++ ++&i2c3 { ++ pinctrl-0 = <&i2c3_pins>; ++ pinctrl-names = "default"; ++ 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_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ }; ++ }; ++ ++ max9286-max9271@0 { ++ compatible = "maxim,max9286-max9271"; ++ reg = <0x6c>; ++ gpios = <&gpio0 9 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>; ++ }; ++ }; ++ }; ++}; ++ ++&gpio2 { ++ gpio_pwdn1 { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "GPIO_PWDN1#"; ++ }; ++}; ++ ++&pfc { ++ i2c3_pins: i2c3 { ++ groups = "i2c3"; ++ function = "i2c3"; ++ }; ++}; ++ ++&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>; ++ }; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7797-v3msk.dts b/arch/arm64/boot/dts/renesas/r8a7797-v3msk.dts +new file mode 100644 +index 0000000..91d10c5 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7797-v3msk.dts +@@ -0,0 +1,314 @@ ++/* ++ * Device Tree Source for the V3M Starter Kit board on r8a7797 ++ * ++ * 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. ++ */ ++ ++/dts-v1/; ++#include "r8a7797.dtsi" ++#include <dt-bindings/gpio/gpio.h> ++ ++/ { ++ model = "Renesas V3M Starter Kit board based on r8a7797"; ++ compatible = "renesas,v3msk", "renesas,r8a7797"; ++ ++ aliases { ++ serial0 = &scif0; ++ 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 0x38000000>; ++ }; ++ ++ reserved-memory { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ /* device specific region for Lossy Decompression */ ++ lossy_decompress: linux,lossy_decompress { ++ no-map; ++ reg = <0x00000000 0x6c000000 0x0 0x03000000>; ++ }; ++ ++ /* global autoconfigured region for contiguous allocations */ ++ linux,cma { ++ compatible = "shared-dma-pool"; ++ reusable; ++ reg = <0x00000000 0x6f000000 0x0 0x10000000>; ++ linux,cma-default; ++ }; ++ ++ /* device specific region for contiguous allocations */ ++ linux,multimedia { ++ compatible = "shared-dma-pool"; ++ reusable; ++ reg = <0x00000000 0x7f000000 0x0 0x01000000>; ++ }; ++ }; ++ ++ mmngr { ++ compatible = "renesas,mmngr"; ++ memory-region = <&lossy_decompress>; ++ }; ++ ++ mmngrbuf { ++ compatible = "renesas,mmngrbuf"; ++ }; ++ ++ vspm_if { ++ compatible = "renesas,vspm_if"; ++ }; ++ ++ 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>; ++ }; ++ }; ++ }; ++ ++ hdmi-out { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi_con: endpoint { ++ remote-endpoint = <&adv7511_out>; ++ }; ++ }; ++ }; ++ ++ dclkin_p0: clock-out0 { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <148500000>; ++ }; ++ ++ msiof_ref_clk: msiof-ref-clock { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <66666666>; ++ }; ++ ++ vcc_3v3: regulator0 { ++ compatible = "regulator-fixed"; ++ regulator-name = "fixed-VCC3V3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ vcc_vddq_vin0: regulator1 { ++ compatible = "regulator-fixed"; ++ regulator-name = "VCC-VDDQ-VIN0"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++}; ++ ++&du { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ endpoint { ++ remote-endpoint = <&adv7511_in>; ++// remote-endpoint = <&lvds_in>; ++ }; ++ }; ++ }; ++}; ++ ++&extal_clk { ++ clock-frequency = <16666666>; ++}; ++ ++&extalr_clk { ++ clock-frequency = <32768>; ++}; ++ ++&pfc { ++ pinctrl-0 = <&scif_clk_pins>; ++ pinctrl-names = "default"; ++ ++ scif0_pins: scif0 { ++ groups = "scif0_data"; ++ function = "scif0"; ++ }; ++ ++ scif_clk_pins: scif_clk { ++ groups = "scif_clk_b"; ++ function = "scif_clk"; ++ }; ++ ++ i2c0_pins: i2c0 { ++ groups = "i2c0"; ++ function = "i2c0"; ++ }; ++ ++ avb_pins: avb { ++ groups = "avb0_mdc"; ++ function = "avb0"; ++ }; ++ ++ sdhi2_pins_3v3: sdhi2_3v3 { ++ groups = "mmc_data8", "mmc_ctrl"; ++ function = "mmc"; ++ power-source = <3300>; ++ }; ++}; ++ ++&scif0 { ++ pinctrl-0 = <&scif0_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&scif_clk { ++ clock-frequency = <14745600>; ++ status = "okay"; ++}; ++ ++&i2c0 { ++ pinctrl-0 = <&i2c0_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++ clock-frequency = <400000>; ++ ++ hdmi@39{ ++ compatible = "adi,adv7511w"; ++ #sound-dai-cells = <0>; ++ reg = <0x39>; ++ interrupt-parent = <&gpio1>; ++ interrupts = <20 IRQ_TYPE_LEVEL_LOW>; ++ ++ adi,input-depth = <8>; ++ adi,input-colorspace = "rgb"; ++ adi,input-clock = "1x"; ++ adi,input-style = <1>; ++ adi,input-justification = "evenly"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ adv7511_in: endpoint { ++ remote-endpoint = <&lvds_enc_out>; ++ }; ++ }; ++ port@1 { ++ reg = <1>; ++ adv7511_out: endpoint { ++ remote-endpoint = <&hdmi_con>; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&wdt0 { ++ status = "okay"; ++}; ++ ++&avb { ++ pinctrl-0 = <&avb_pins>; ++ pinctrl-names = "default"; ++ renesas,no-ether-link; ++ phy-handle = <&phy0>; ++ status = "okay"; ++ phy-int-gpio = <&gpio1 17 GPIO_ACTIVE_LOW>; ++ ++ phy0: ethernet-phy@0 { ++ rxc-skew-ps = <1500>; ++ rxdv-skew-ps = <420>; /* default */ ++ rxd0-skew-ps = <420>; /* default */ ++ rxd1-skew-ps = <420>; /* default */ ++ rxd2-skew-ps = <420>; /* default */ ++ rxd3-skew-ps = <420>; /* default */ ++ txc-skew-ps = <900>; /* default */ ++ txen-skew-ps = <420>; /* default */ ++ txd0-skew-ps = <420>; /* default */ ++ txd1-skew-ps = <420>; /* default */ ++ txd2-skew-ps = <420>; /* default */ ++ txd3-skew-ps = <420>; /* default */ ++ reg = <0>; ++ interrupt-parent = <&gpio1>; ++ interrupts = <17 IRQ_TYPE_LEVEL_LOW>; ++ max-speed = <1000>; ++ }; ++}; ++ ++&sdhi2 { ++ /* used for on-board eMMC */ ++ pinctrl-0 = <&sdhi2_pins_3v3>; ++ pinctrl-names = "default"; ++ ++ vmmc-supply = <&vcc_3v3>; ++ vqmmc-supply = <&vcc_vddq_vin0>; ++ no-1-8-v; ++ cap-mmc-highspeed; ++ bus-width = <8>; ++ non-removable; ++ status = "okay"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf-cn11.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf-cn11.dtsi +new file mode 100644 +index 0000000..589a774 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/ulcb-kf-cn11.dtsi +@@ -0,0 +1,545 @@ ++/* ++ * Device Tree Source for the H3ULCB Kingfisher board: ++ * this adding conflicting resource on VIN4/VIN5/VIN6/VIN7 for CN11 ++ * use CN11 instead default CN29/CN48 ++ * ++ * 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. ++ */ ++ ++/ { ++ pwr0B: regulator-pwr0B { ++ compatible = "regulator-fixed"; ++ regulator-name = "PWR0B"; ++ regulator-min-microvolt = <9000000>; ++ regulator-max-microvolt = <9000000>; ++ gpio = <&gpio_exp_b_5c 8 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ pwr1B: regulator-pwr1B { ++ compatible = "regulator-fixed"; ++ regulator-name = "PWR1B"; ++ regulator-min-microvolt = <9000000>; ++ regulator-max-microvolt = <9000000>; ++ gpio = <&gpio_exp_b_5c 9 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ pwr2B: regulator-pwr2B { ++ compatible = "regulator-fixed"; ++ regulator-name = "PWR2B"; ++ regulator-min-microvolt = <9000000>; ++ regulator-max-microvolt = <9000000>; ++ gpio = <&gpio_exp_b_5c 10 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ pwr3B: regulator-pwr3B { ++ compatible = "regulator-fixed"; ++ regulator-name = "PWR3B"; ++ regulator-min-microvolt = <9000000>; ++ regulator-max-microvolt = <9000000>; ++ gpio = <&gpio_exp_b_5c 11 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++}; ++ ++&i2cswitch4 { ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ /* Slot B (CN11) */ ++ ++ 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"; ++ POC0-supply = <&pwr0B>; ++ POC1-supply = <&pwr1B>; ++ POC2-supply = <&pwr2B>; ++ POC3-supply = <&pwr3B>; ++ ++ 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"; ++ POC0-supply = <&pwr0B>; ++ POC1-supply = <&pwr1B>; ++ POC2-supply = <&pwr2B>; ++ POC3-supply = <&pwr3B>; ++ ++ 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 @ 0x2c */ ++ max9286-max9271@1 { ++ compatible = "maxim,max9286-max9271"; ++ reg = <0x2c>; ++ maxim,sensor_delay = <350>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ POC0-supply = <&pwr0B>; ++ POC1-supply = <&pwr1B>; ++ POC2-supply = <&pwr2B>; ++ POC3-supply = <&pwr3B>; ++ ++ 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@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ /* Slot B (CN11) */ ++ ++ /* PCA9535 is a redundand/deprecated card */ ++ gpio_exp_b_27: gpio@27 { ++ compatible = "nxp,pca9535"; ++ reg = <0x27>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ video_b_des_cfg1 { ++ gpio-hog; ++ gpios = <5 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-B cfg1"; ++ }; ++ video_b_des_cfg0 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ 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"; ++ }; ++ }; ++ ++ gpio_exp_b_5c: gpio@5c { ++ compatible = "maxim,max7325"; ++ reg = <0x5c>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ video_b_des_cfg2 { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-B cfg2"; ++ }; ++ video_b_des_cfg1 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-B cfg1"; ++ }; ++ video_b_des_cfg0 { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ input; ++ 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_des_shdn { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B DES_SHDN"; ++ }; ++ video_b_led { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-B LED"; ++ }; ++ }; ++ }; ++}; ++ ++&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>; ++ }; ++ vin4_ti964_des1ep0: endpoint@1 { ++ remote-endpoint = <&ti964_des1ep0>; ++ }; ++ vin4_ti954_des1ep0: endpoint@2 { ++ remote-endpoint = <&ti954_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>; ++ }; ++ 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_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>; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf-most.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf-most.dtsi +new file mode 100644 +index 0000000..4af5ca0 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/ulcb-kf-most.dtsi +@@ -0,0 +1,30 @@ ++/* ++ * Device Tree Source for the H3/M3ULCB Kingfisher board: ++ * this overrides GPS in favour MOST on GP5_24/GP5_25 R-CAR pins ++ * ++ * 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. ++ */ ++ ++&pfc { ++ mlp_pins: mlp { ++ groups = "mlb_3pin"; ++ function = "mlb_3pin"; ++ }; ++}; ++ ++&scif1 { ++ status = "disabled"; ++}; ++ ++&mlp { ++ pinctrl-0 = <&mlp_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ clock-speed = "1024fs"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf-sd3.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf-sd3.dtsi +new file mode 100644 +index 0000000..b854216 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/ulcb-kf-sd3.dtsi +@@ -0,0 +1,46 @@ ++/* ++ * Device Tree Source for the H3/M3ULCB Kingfisher board: ++ * this overrides WIFI in favour SD on SDHI3 ++ * ++ * 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. ++ */ ++ ++&sdio_switch { ++ regulator-name = "sd_on"; ++ enable-active-high; ++}; ++ ++&vccq_sdhi3 { ++ compatible = "regulator-gpio"; ++ ++ regulator-min-microvolt = <1800000>; ++ ++ gpios = <&gpio3 14 GPIO_ACTIVE_HIGH>; ++ gpios-states = <1>; ++ states = <3300000 1 ++ 1800000 0>; ++}; ++ ++&sdhi3 { ++ /delete-property/non-removable; ++ /delete-property/cap-power-off-card; ++ /delete-property/keep-power-in-suspend; ++ /delete-property/enable-sdio-wakeup; ++ /delete-property/max-frequency; ++ /delete-property/no-1-8-v; ++ ++ vmmc-supply = <&vcc_sdhi3>; ++ cd-gpios = <&gpio4 15 GPIO_ACTIVE_LOW>; ++ wp-gpios = <&gpio4 16 GPIO_ACTIVE_HIGH>; ++// sd-uhs-sdr50; ++// sd-uhs-sdr104; ++}; ++ ++&wlcore { ++ status = "disabled"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi +new file mode 100644 +index 0000000..5958450 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi +@@ -0,0 +1,1541 @@ ++/* ++ * Device Tree Source for the ULCB Kingfisher board ++ * ++ * 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. ++ */ ++ ++/ { ++ aliases { ++ serial1 = &hscif0; ++ serial2 = &hscif1; ++ serial3 = &scif1; ++ }; ++ ++ 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_74 4 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ vcc_sdhi3: regulator@41 { ++ compatible = "regulator-fixed"; ++ ++ regulator-name = "SDHI3 Vcc"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ gpio = <&gpio4 17 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ vccq_sdhi3: regulator@5 { ++ compatible = "regulator-fixed"; ++ ++ regulator-name = "SDHI3 VccQ"; ++ 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_74 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_74 0 0>; ++ ++ startup-delay-us = <0>; ++ enable-active-high; ++ }; ++ ++ sdio_switch: regulator@9 { ++ compatible = "regulator-fixed"; ++ regulator-name = "wifi_on"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&gpio_ext_74 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_74 13 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ regulator-always-on; ++ }; ++ ++ mpcie_3v3: regulator@12 { ++ compatible = "regulator-fixed"; ++ regulator-name = "mPCIe 3v3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&gpio_ext_77 14 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ mpcie_1v8: regulator@13 { ++ compatible = "regulator-fixed"; ++ regulator-name = "mPCIe 1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ gpio = <&gpio_ext_77 15 GPIO_ACTIVE_HIGH>; ++ startup-delay-us = <200000>; ++ enable-active-high; ++ }; ++ ++ pwr0A: regulator-pwr0A { ++ compatible = "regulator-fixed"; ++ regulator-name = "PWR0A"; ++ regulator-min-microvolt = <9000000>; ++ regulator-max-microvolt = <9000000>; ++ gpio = <&gpio_exp_a_5c 8 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ pwr1A: regulator-pwr1A { ++ compatible = "regulator-fixed"; ++ regulator-name = "PWR1A"; ++ regulator-min-microvolt = <9000000>; ++ regulator-max-microvolt = <9000000>; ++ gpio = <&gpio_exp_a_5c 9 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ pwr2A: regulator-pwr2A { ++ compatible = "regulator-fixed"; ++ regulator-name = "PWR2A"; ++ regulator-min-microvolt = <9000000>; ++ regulator-max-microvolt = <9000000>; ++ gpio = <&gpio_exp_a_5c 10 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ pwr3A: regulator-pwr3A { ++ compatible = "regulator-fixed"; ++ regulator-name = "PWR3A"; ++ regulator-min-microvolt = <9000000>; ++ regulator-max-microvolt = <9000000>; ++ gpio = <&gpio_exp_a_5c 11 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ kim { ++ compatible = "kim"; ++ shutdown-gpios = <&gpio_ext_74 3 GPIO_ACTIVE_HIGH>; ++ /* 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_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_wl18xx: sound@3 { ++ pinctrl-0 = <&sound_3_pins>; ++ pinctrl-names = "default"; ++ compatible = "simple-audio-card"; ++ ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,name = "wl18xx"; ++ ++ simple-audio-card,bitclock-master = <&sound_wl18xx_master>; ++ simple-audio-card,frame-master = <&sound_wl18xx_master>; ++ sound_wl18xx_master: simple-audio-card,cpu@3 { ++ sound-dai = <&rcar_sound 3>; ++ }; ++ ++ simple-audio-card,codec@3 { ++ sound-dai = <&wl18xx_pcm>; ++ }; ++ }; ++ ++ 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>; ++ }; ++ }; ++ }; ++ ++ hdmi-out { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi_con: endpoint { ++ remote-endpoint = <&adv7513_out>; ++ }; ++ }; ++ }; ++ ++ radio: si468x@0 { ++ compatible = "si,si468x-pcm"; ++ status = "okay"; ++ ++ #sound-dai-cells = <0>; ++ }; ++ ++ wl18xx_pcm: wl18xx_pcm@0 { ++ compatible = "ti,wl18xx-pcm"; ++ status = "okay"; ++ ++ #sound-dai-cells = <0>; ++ }; ++ ++ camera_clk: camera_clk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <24000000>; ++ clock-output-names = "mclk"; ++ }; ++}; ++ ++&pfc { ++ scif1_pins: scif1 { ++ groups = "scif1_data_b"; ++ function = "scif1"; ++ }; ++ ++ hscif0_pins: hscif0 { ++ groups = "hscif0_data", "hscif0_ctrl"; ++ function = "hscif0"; ++ }; ++ ++ hscif1_pins: hscif1 { ++ groups = "hscif1_data_a", "hscif1_ctrl_a"; ++ function = "hscif1"; ++ }; ++ ++ du_pins: du { ++ groups = "du_rgb888", "du_sync", "du_clk_out_0", "du_disp"; ++ function = "du"; ++ }; ++ ++ sdhi3_pins_3v3: sd3_3v3 { ++ groups = "sdhi3_data4", "sdhi3_ctrl"; ++ function = "sdhi3"; ++ power-source = <3300>; ++ }; ++ ++ sdhi3_pins_1v8: sd3_1v8 { ++ groups = "sdhi3_data4", "sdhi3_ctrl"; ++ function = "sdhi3"; ++ power-source = <1800>; ++ }; ++ ++ sound_0_pins: sound0 { ++ groups = "ssi349_ctrl", "ssi3_data", "ssi4_data"; ++ function = "ssi"; ++ }; ++ ++ /* sound_pins defined in H3 or M3 ulsb file */ ++ ++ sound_2_pins: sound2 { ++ groups = "ssi6_ctrl", "ssi6_data"; ++ function = "ssi"; ++ }; ++ ++ sound_3_pins: sound3 { ++ groups = "ssi78_ctrl", "ssi7_data", "ssi8_data"; ++ function = "ssi"; ++ }; ++ ++ usb0_pins: usb0 { ++ groups = "usb0"; ++ function = "usb0"; ++ }; ++ ++ can0_pins: can0 { ++ groups = "can0_data_a"; ++ function = "can0"; ++ }; ++ ++ can1_pins: can1 { ++ groups = "can1_data"; ++ function = "can1"; ++ }; ++ ++ canfd0_pins: canfd0 { ++ groups = "canfd0_data_a"; ++ function = "canfd0"; ++ }; ++ ++ canfd1_pins: canfd1 { ++ groups = "canfd1_data"; ++ function = "canfd1"; ++ }; ++ ++ vin5_pins: vin5 { ++ groups = "vin5_data8", "vin5_sync", "vin5_clk"; ++ function = "vin5"; ++ }; ++}; ++ ++&du { ++ pinctrl-0 = <&du_pins>; ++ pinctrl-names = "default"; ++}; ++ ++&gpio2 { ++ bl_pwm { ++ gpio-hog; ++ gpios = <3 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "BL PWM 100%"; ++ }; ++}; ++ ++&gpio4 { ++ most_rst { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "MOST RST"; ++ }; ++}; ++ ++&gpio6 { ++ audio_sw { ++ gpio-hog; ++ gpios = <21 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Onboard MCh Audio"; ++ }; ++}; ++ ++&scif1 { ++ pinctrl-0 = <&scif1_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&hscif0 { ++ pinctrl-0 = <&hscif0_pins>; ++ pinctrl-names = "default"; ++ uart-has-rtscts; ++ ++ status = "okay"; ++}; ++ ++&hscif1 { ++ pinctrl-0 = <&hscif1_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&i2c2 { ++ clock-frequency = <400000>; ++ ++ gpio_ext_74: pca9539@74 { ++ compatible = "nxp,pca9539"; ++ reg = <0x74>; ++ gpio-controller; ++ #gpio-cells = <2>; ++/* ++ interrupt-controller; ++ interrupt-parent = <&gpio6>; ++ interrupts = <8 IRQ_TYPE_EDGE_FALLING>; ++*/ ++ hub_pwen { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "HUB pwen"; ++ }; ++ hub_rst { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "HUB rst"; ++ }; ++ otg_offvbus { ++ gpio-hog; ++ gpios = <8 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "OTG off VBUSn"; ++ }; ++ otg_extlpn { ++ gpio-hog; ++ gpios = <9 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "OTG EXTLPn"; ++ }; ++ }; ++ ++ gpio_ext_75: pca9539@75 { ++ compatible = "nxp,pca9539"; ++ reg = <0x75>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ interrupt-parent = <&gpio6>; ++ interrupts = <4 IRQ_TYPE_EDGE_FALLING>; ++ ++ gps_rst { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "GPS rst"; ++ }; ++ fpdl_shdn { ++ gpio-hog; ++ gpios = <9 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "FPDLink shdn"; ++ }; ++ }; ++ ++ i2cswitch2: pca9548@71 { ++ compatible = "nxp,pca9548"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x71>; ++ reset-gpios = <&gpio5 3 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) */ ++ }; ++ ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ /* Radio node(s) */ ++ }; ++ ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ ++ hdmi@3d { ++ compatible = "adi,adv7511w"; ++ reg = <0x3d>; ++// interrupt-parent = <&gpio2>; ++// interrupts = <0 IRQ_TYPE_EDGE_BOTH>; ++ pd-gpios = <&gpio_ext_75 5 GPIO_ACTIVE_LOW>; ++ ++ adi,input-depth = <8>; ++ adi,input-colorspace = "rgb"; ++ adi,input-clock = "1x"; ++ adi,input-style = <1>; ++ adi,input-justification = "evenly"; ++ adi,clock-delay = <1200>; ++ adi,clock-max-rate = <100000>; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ adv7513_in: endpoint { ++ remote-endpoint = <&du_out_rgb>; ++ }; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ adv7513_out: endpoint { ++ remote-endpoint = <&hdmi_con>; ++ }; ++ }; ++ }; ++ }; ++ }; ++ ++ 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 = <&_en_reg>; ++ VCCDA2-supply = <&_en_reg>; ++ }; ++ ++ lsm9ds0_acc_mag@1d { ++ compatible = "st,lsm9ds0_accel_magn"; ++ reg = <0x1d>; ++ }; ++ ++ lsm9ds0_gyr@6b { ++ compatible = "st,lsm9ds0_gyro"; ++ reg = <0x6b>; ++ }; ++ ++ /* GPS@ 0x42 */ ++ }; ++ }; ++}; ++ ++&i2c4 { ++ gpio_ext_76: pca9539@76 { ++ compatible = "nxp,pca9539"; ++ reg = <0x76>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ interrupt-parent = <&gpio7>; ++ interrupts = <3 IRQ_TYPE_EDGE_FALLING>; ++ ++ port_b_a0 { ++ gpio-hog; ++ gpios = <0 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-B A0"; ++ }; ++ port_b_a1 { ++ gpio-hog; ++ gpios = <1 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B A1"; ++ }; ++ port_a_a0 { ++ gpio-hog; ++ gpios = <2 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-A A0"; ++ }; ++ port_a_a1 { ++ gpio-hog; ++ gpios = <3 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A A1"; ++ }; ++ cmos_pwdn { ++ gpio-hog; ++ gpios = <8 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "CMOS PWDN"; ++ }; ++ cmos_rst { ++ gpio-hog; ++ gpios = <9 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "CMOS RST"; ++ }; ++ /* pin 12 - CAM_CLK */ ++ rpi_cam_io_1 { ++ gpio-hog; ++ gpios = <10 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "RaspB_IO1"; ++ }; ++ /* pin 11 - CAM_GPIO - assume pwdn */ ++ rpi_cam_io_0 { ++ gpio-hog; ++ gpios = <11 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "RaspB_IO0"; ++ }; ++ sam_rst { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "SAM RST"; ++ }; ++ sam_pwr { ++ gpio-hog; ++ gpios = <5 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "SAM PWR"; ++ }; ++ /* 0 - FPDLink output, 1 - LVDS output */ ++ lvds_vs_fpdl { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "LVDS switch"; ++ }; ++ }; ++ ++ gpio_ext_77: pca9539@77 { ++ compatible = "nxp,pca9539"; ++ reg = <0x77>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ interrupt-parent = <&gpio5>; ++ interrupts = <9 IRQ_TYPE_EDGE_FALLING>; ++ ++ mpcie_wake { ++ gpio-hog; ++ gpios = <0 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "mPCIe WAKE#"; ++ }; ++ mpcie_wdisable { ++ gpio-hog; ++ gpios = <1 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "mPCIe W_DISABLE"; ++ }; ++ mpcie_clreq { ++ gpio-hog; ++ gpios = <2 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "mPCIe CLKREQ#"; ++ }; ++ mpcie_ovc { ++ gpio-hog; ++ gpios = <3 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "mPCIe OVC"; ++ }; ++ }; ++ ++ i2cswitch4: pca9548@71 { ++ compatible = "nxp,pca9548"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x71>; ++ reset-gpios= <&gpio3 15 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>; ++ /* Slot A (CN10) */ ++ ++ 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"; ++ POC0-supply = <&pwr0A>; ++ POC1-supply = <&pwr1A>; ++ POC2-supply = <&pwr2A>; ++ POC3-supply = <&pwr3A>; ++ ++ 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"; ++ POC0-supply = <&pwr0A>; ++ POC1-supply = <&pwr1A>; ++ POC2-supply = <&pwr2A>; ++ POC3-supply = <&pwr3A>; ++ ++ 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 @ 0x2c */ ++ max9286-max9271@0 { ++ compatible = "maxim,max9286-max9271"; ++ reg = <0x2c>; ++ maxim,sensor_delay = <350>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ POC0-supply = <&pwr0A>; ++ POC1-supply = <&pwr1A>; ++ POC2-supply = <&pwr2A>; ++ POC3-supply = <&pwr3A>; ++ ++ 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>; ++ ++ rpi_camera: ov5647@36 { ++ compatible = "ovti,ov5647"; ++ reg = <0x36>; ++ ++ port@0 { ++ rpi_camera_in: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ remote-endpoint = <&vin4ep0>; ++ }; ++ }; ++ }; ++ }; ++ ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ ++ cmos_camera: ov5642@3c { ++ compatible = "ovti,ov5642"; ++ reg = <0x3c>; ++ clocks = <&camera_clk>; ++ clock-names = "mclk"; ++ ++ port@0 { ++ cmos_camera_in: endpoint { ++ remote-endpoint = <&vin5ep0>; ++ }; ++ }; ++ }; ++ }; ++ ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ /* Slot A (CN10) */ ++ ++ /* PCA9535 is a redundant/deprecated card */ ++ gpio_exp_a_26: gpio@26 { ++ compatible = "nxp,pca9535"; ++ reg = <0x26>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ video_a_des_cfg1 { ++ gpio-hog; ++ gpios = <5 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-A cfg1"; ++ }; ++ video_a_des_cfg0 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ 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"; ++ }; ++ }; ++ ++ gpio_exp_a_5c: gpio@5c { ++ compatible = "maxim,max7325"; ++ reg = <0x5c>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ video_a_des_cfg2 { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-A cfg2"; ++ }; ++ video_a_des_cfg1 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-A cfg1"; ++ }; ++ video_a_des_cfg0 { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ input; ++ 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_des_shdn { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A DES_SHDN"; ++ }; ++ video_a_led { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-A LED"; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&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 = "csi20"; ++ virtual,channel = <0>; ++ remote-endpoint = <&rpi_camera_in>; ++ data-lanes = <1 2>; ++ }; ++ }; ++ port@1 { ++ csi2ep0: endpoint { ++ remote-endpoint = <&csi2_20_ep>; ++ }; ++ }; ++ }; ++}; ++ ++&vin5 { ++ pinctrl-0 = <&vin5_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin5ep0: endpoint@0 { ++ bus-width = <8>; ++ /* #HSYNC, #VSYNC */ ++ vsync-active = <1>; ++ hsync-active = <0>; ++ remote-endpoint = <&cmos_camera_in>; ++ }; ++ }; ++ }; ++}; ++ ++&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_20 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "raw8"; ++ receive,vc = <0>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi2_20_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ csi-rate = <280>; ++ }; ++ }; ++}; ++ ++ ++&rcar_sound { ++ pinctrl-0 = <&sound_clk_pins>; ++ pinctrl-names = "default"; ++ ++ /* Multi DAI */ ++ #sound-dai-cells = <1>; ++ ++ rcar_sound,dai { ++ dai0 { ++ playback = <&ssi3>; ++ capture = <&ssi4>; ++ }; ++ ++ dai1 { ++ playback = <&ssi0 &src0 &dvc0>; ++ capture = <&ssi1 &src1 &dvc1>; ++ }; ++ ++ dai2 { ++ capture = <&ssi6>; ++ }; ++ ++ dai3 { ++ playback = <&ssi7>; ++ capture = <&ssi8>; ++ }; ++ }; ++}; ++ ++&sdhi3 { ++ pinctrl-0 = <&sdhi3_pins_3v3>; ++ pinctrl-1 = <&sdhi3_pins_1v8>; ++ pinctrl-names = "default", "state_uhs"; ++ ++ 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_FALLING>; ++ }; ++}; ++ ++&usb2_phy0 { ++ pinctrl-0 = <&usb0_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&ehci0 { ++ status = "okay"; ++}; ++ ++&ohci0 { ++ status = "okay"; ++}; ++ ++&xhci0 { ++ status = "okay"; ++}; ++ ++&msiof1 { ++ status = "disabled"; ++}; ++ ++&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"; ++ ++ channel0 { ++ status = "okay"; ++ }; ++ ++ channel1 { ++ status = "okay"; ++ }; ++}; ++ ++&ssi4 { ++ shared-pin; ++}; ++ ++&ssi8 { ++ shared-pin; ++}; ++ ++&pciec1 { ++ pcie3v3-supply = <&mpcie_3v3>; ++ pcie1v8-supply = <&mpcie_1v8>; ++}; ++ +diff --git a/arch/arm64/boot/dts/renesas/ulcb-vb-cn12.dtsi b/arch/arm64/boot/dts/renesas/ulcb-vb-cn12.dtsi +new file mode 100644 +index 0000000..92ed4a4 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/ulcb-vb-cn12.dtsi +@@ -0,0 +1,515 @@ ++/* ++ * Device Tree Source for the H3ULCB Videobox board: ++ * this adding conflicting resource on VIN4/VIN5/VIN6/VIN7 for CN12 ++ * ++ * 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. ++ */ ++ ++&i2cswitch2 { ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ /* Slot C (CN12) */ ++ ++ ov106xx@8 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x68>; ++ ++ port@0 { ++ ov106xx_in8: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ remote-endpoint = <&vin4ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des2ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des2ep0>; ++ }; ++ ov106xx_ti964_des2ep0: endpoint@1 { ++ remote-endpoint = <&ti964_des2ep0>; ++ }; ++ ov106xx_ti954_des2ep0: endpoint@2 { ++ remote-endpoint = <&ti954_des2ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@9 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x69>; ++ ++ port@0 { ++ ov106xx_in9: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ remote-endpoint = <&vin5ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des2ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des2ep1>; ++ }; ++ ov106xx_ti964_des2ep1: endpoint@1 { ++ remote-endpoint = <&ti964_des2ep1>; ++ }; ++ ov106xx_ti954_des2ep1: endpoint@2 { ++ remote-endpoint = <&ti954_des2ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@10 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x6a>; ++ ++ port@0 { ++ ov106xx_in10: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ remote-endpoint = <&vin6ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des2ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des2ep2>; ++ }; ++ ov106xx_ti964_des2ep2: endpoint@1 { ++ remote-endpoint = <&ti964_des2ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@11 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x6b>; ++ ++ port@0 { ++ ov106xx_in11: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ remote-endpoint = <&vin7ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des2ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des2ep3>; ++ }; ++ ov106xx_ti964_des2ep3: endpoint@1 { ++ remote-endpoint = <&ti964_des2ep3>; ++ }; ++ }; ++ }; ++ ++ /* DS90UB964 @ 0x3a */ ++ ti964-ti9x3@2 { ++ compatible = "ti,ti964-ti9x3"; ++ reg = <0x3a>; ++ ti,sensor_delay = <350>; ++ ti,links = <4>; ++ ti,lanes = <2>; ++ ti,forwarding-mode = "round-robin"; ++ ti,cable-mode = "coax"; ++ ++ port@0 { ++ ti964_des2ep0: endpoint@0 { ++ ti9x3-addr = <0x0c>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in8>; ++ }; ++ ti964_des2ep1: endpoint@1 { ++ ti9x3-addr = <0x0d>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in9>; ++ }; ++ ti964_des2ep2: endpoint@2 { ++ ti9x3-addr = <0x0e>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in10>; ++ }; ++ ti964_des2ep3: endpoint@3 { ++ ti9x3-addr = <0x0f>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in11>; ++ }; ++ }; ++ port@1 { ++ ti964_csi1ep0: endpoint { ++ csi-rate = <1450>; ++ remote-endpoint = <&csi2_20_ep>; ++ }; ++ }; ++ }; ++ ++ /* DS90UB954 @ 0x38 */ ++ ti954-ti9x3@2 { ++ compatible = "ti,ti954-ti9x3"; ++ reg = <0x38>; ++ /* gpios = <&video_c_ext1 10 GPIO_ACTIVE_HIGH>; */ ++ ti,sensor_delay = <350>; ++ ti,links = <2>; ++ ti,lanes = <2>; ++ ti,forwarding-mode = "round-robin"; ++ ti,cable-mode = "coax"; ++ ++ port@0 { ++ ti954_des2ep0: endpoint@0 { ++ ti9x3-addr = <0x0c>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in8>; ++ }; ++ ti954_des2ep1: endpoint@1 { ++ ti9x3-addr = <0x0d>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in9>; ++ }; ++ }; ++ port@1 { ++ ti954_csi1ep0: endpoint { ++ csi-rate = <1450>; ++ remote-endpoint = <&csi2_20_ep>; ++ }; ++ }; ++ }; ++ ++ /* MAX9286 @ 0x2c */ ++ max9286-max9271@2 { ++ compatible = "maxim,max9286-max9271"; ++ reg = <0x2c>; ++ maxim,sensor_delay = <350>; ++ maxim,links = <4>; ++ maxim,lanes = <2>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ ++ port@0 { ++ max9286_des2ep0: endpoint@0 { ++ max9271-addr = <0x50>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in8>; ++ }; ++ max9286_des2ep1: endpoint@1 { ++ max9271-addr = <0x51>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in9>; ++ }; ++ max9286_des2ep2: endpoint@2 { ++ max9271-addr = <0x52>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in10>; ++ }; ++ max9286_des2ep3: endpoint@3 { ++ max9271-addr = <0x53>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in11>; ++ }; ++ }; ++ port@1 { ++ max9286_csi1ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi2_20_ep>; ++ }; ++ }; ++ }; ++ }; ++ ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ /* Slot C (CN12) */ ++ ++ video_c_ext0: pca9535@26 { ++ compatible = "nxp,pca9535"; ++ reg = <0x26>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ video_c_des_cfg1 { ++ gpio-hog; ++ gpios = <5 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-C cfg1"; ++ }; ++ video_c_des_cfg0 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-C cfg0"; ++ }; ++ video_c_pwr_shdn { ++ gpio-hog; ++ gpios = <3 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-C PWR_SHDN"; ++ }; ++ video_c_cam_pwr0 { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-C PWR0"; ++ }; ++ video_c_cam_pwr1 { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-C PWR1"; ++ }; ++ video_c_cam_pwr2 { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-C PWR2"; ++ }; ++ video_c_cam_pwr3 { ++ gpio-hog; ++ gpios = <15 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-C PWR3"; ++ }; ++ video_c_des_shdn { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-C DES_SHDN"; ++ }; ++ video_c_des_led { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-C led"; ++ }; ++ }; ++ ++ video_c_ext1: max7325@5c { ++ compatible = "maxim,max7325"; ++ reg = <0x5c>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ video_c_des_cfg2 { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-C cfg2"; ++ }; ++ video_c_des_cfg1 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-C cfg1"; ++ }; ++ video_c_des_cfg0 { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-C cfg0"; ++ }; ++ video_c_pwr_shdn { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-C PWR_SHDN"; ++ }; ++ video_c_cam_pwr0 { ++ gpio-hog; ++ gpios = <8 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-C PWR0"; ++ }; ++ video_c_cam_pwr1 { ++ gpio-hog; ++ gpios = <9 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-C PWR1"; ++ }; ++ video_c_cam_pwr2 { ++ gpio-hog; ++ gpios = <10 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-C PWR2"; ++ }; ++ video_c_cam_pwr3 { ++ gpio-hog; ++ gpios = <11 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-C PWR3"; ++ }; ++ video_c_des_shdn { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-C DES_SHDN"; ++ }; ++ video_c_led { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-C LED"; ++ }; ++ }; ++ }; ++}; ++ ++&vin4 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin4ep0: endpoint { ++ csi,select = "csi20"; ++ virtual,channel = <0>; ++ remote-endpoint = <&ov106xx_in8>; ++ data-lanes = <1 2>; ++ }; ++ }; ++ port@1 { ++ csi2ep0: endpoint { ++ remote-endpoint = <&csi2_20_ep>; ++ }; ++ }; ++ port@2 { ++ vin4_max9286_des2ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des2ep0>; ++ }; ++ vin4_ti964_des2ep0: endpoint@1 { ++ remote-endpoint = <&ti964_des2ep0>; ++ }; ++ vin4_ti954_des2ep0: endpoint@2 { ++ remote-endpoint = <&ti954_des2ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin5 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin5ep0: endpoint@0 { ++ csi,select = "csi20"; ++ virtual,channel = <1>; ++ remote-endpoint = <&ov106xx_in9>; ++ data-lanes = <1 2>; ++ }; ++ }; ++ port@1 { ++ csi2ep1: endpoint { ++ remote-endpoint = <&csi2_20_ep>; ++ }; ++ }; ++ port@2 { ++ vin5_max9286_des2ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des2ep1>; ++ }; ++ vin5_ti964_des2ep1: endpoint@1 { ++ remote-endpoint = <&ti964_des2ep1>; ++ }; ++ vin5_ti954_des2ep1: endpoint@2 { ++ remote-endpoint = <&ti954_des2ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin6 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin6ep0: endpoint@0 { ++ csi,select = "csi20"; ++ virtual,channel = <2>; ++ remote-endpoint = <&ov106xx_in10>; ++ data-lanes = <1 2>; ++ }; ++ }; ++ port@1 { ++ csi2ep2: endpoint { ++ remote-endpoint = <&csi2_20_ep>; ++ }; ++ }; ++ port@2 { ++ vin6_max9286_des2ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des2ep2>; ++ }; ++ vin6_ti964_des2ep2: endpoint@1 { ++ remote-endpoint = <&ti964_des2ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin7 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin7ep0: endpoint@0 { ++ csi,select = "csi20"; ++ virtual,channel = <3>; ++ remote-endpoint = <&ov106xx_in11>; ++ data-lanes = <1 2>; ++ }; ++ }; ++ port@1 { ++ csi2ep3: endpoint { ++ remote-endpoint = <&csi2_20_ep>; ++ }; ++ }; ++ port@2 { ++ vin7_max9286_des2ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des2ep3>; ++ }; ++ vin7_ti964_des2ep3: endpoint@1 { ++ remote-endpoint = <&ti964_des2ep3>; ++ }; ++ }; ++ }; ++}; ++ ++&csi2_20 { ++ 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_20_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ csi-rate = <300>; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/renesas/ulcb-vb.dtsi b/arch/arm64/boot/dts/renesas/ulcb-vb.dtsi +new file mode 100644 +index 0000000..193153e +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/ulcb-vb.dtsi +@@ -0,0 +1,1726 @@ ++/* ++ * Device Tree Source for the ULCB Videobox board ++ * ++ * 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. ++ */ ++ ++/ { ++ leds { ++ compatible = "gpio-leds"; ++ ++ led5 { ++ gpios = <&gpio6 12 GPIO_ACTIVE_HIGH>; ++ }; ++ led6 { ++ gpios = <&gpio6 13 GPIO_ACTIVE_HIGH>; ++ }; ++ /* D13 - status 0 */ ++ led_ext00 { ++ gpios = <&gpio_ext_led 0 GPIO_ACTIVE_LOW>; ++ /* linux,default-trigger = "heartbeat"; */ ++ }; ++ /* D14 - status 1 */ ++ led_ext01 { ++ gpios = <&gpio_ext_led 1 GPIO_ACTIVE_LOW>; ++ /* linux,default-trigger = "mmc1"; */ ++ }; ++ /* D16 - HDMI1 */ ++ led_ext02 { ++ gpios = <&gpio_ext_led 2 GPIO_ACTIVE_LOW>; ++ }; ++ /* D18 - HDMI0 */ ++ led_ext03 { ++ gpios = <&gpio_ext_led 3 GPIO_ACTIVE_LOW>; ++ }; ++ /* D20 - USB3.0 - 0.1 */ ++ led_ext04 { ++ gpios = <&gpio_ext_led 4 GPIO_ACTIVE_LOW>; ++ }; ++ /* D21 - USB3.0 - 0.2 */ ++ led_ext05 { ++ gpios = <&gpio_ext_led 5 GPIO_ACTIVE_LOW>; ++ }; ++ /* D24 - USB3.0 - 1.1 */ ++ led6_ext06 { ++ gpios = <&gpio_ext_led 6 GPIO_ACTIVE_LOW>; ++ }; ++ /* D25 - USB3.0 - 1.2 */ ++ led_ext07 { ++ gpios = <&gpio_ext_led 7 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++ ++ snd_clk: snd_clk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <24576000>; ++ clock-output-names = "scki"; ++ }; ++ ++ 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>; ++ }; ++ ++ fpdlink_switch: regulator@8 { ++ compatible = "regulator-fixed"; ++ regulator-name = "fpdlink_on"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&gpio1 20 0>; ++ enable-active-high; ++ regulator-always-on; ++ }; ++ ++ hub_reset: regulator@9 { ++ compatible = "regulator-fixed"; ++ regulator-name = "hub_reset"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&gpio5 5 0>; ++ enable-active-high; ++ regulator-always-on; ++ }; ++ ++ hub_power: regulator@10 { ++ compatible = "regulator-fixed"; ++ regulator-name = "hub_power"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ gpio = <&gpio6 28 0>; ++ enable-active-high; ++ regulator-always-on; ++ }; ++ ++ /delete-node/sound; ++ ++ rsnd_ak4613: sound@0 { ++ pinctrl-0 = <&sound_0_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>; ++ }; ++ ++ sndcodec: simple-audio-card,codec@1 { ++ sound-dai = <&ak4613>; ++ }; ++ }; ++ ++ 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>; ++ }; ++ }; ++ }; ++ ++ excan_ref_clk: excan-ref-clock { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <16000000>; ++ }; ++ ++ radio: si468x@0 { ++ compatible = "si,si468x-pcm"; ++ status = "okay"; ++ ++ #sound-dai-cells = <0>; ++ }; ++ ++ spi_gpio_sw { ++ compatible = "spi-gpio"; ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ gpio-sck = <&gpio0 8 GPIO_ACTIVE_HIGH>; ++ gpio-miso = <&gpio0 10 GPIO_ACTIVE_HIGH>; ++ gpio-mosi = <&gpio0 11 GPIO_ACTIVE_HIGH>; ++ cs-gpios = <&gpio0 9 GPIO_ACTIVE_HIGH>; ++ num-chipselects = <1>; ++ ++ spidev: spidev@0 { ++ compatible = "spidev", "spi-gpio"; ++ reg = <0>; ++ spi-max-frequency = <25000000>; ++ spi-cpha; ++ spi-cpol; ++ }; ++ }; ++ ++ spi_gpio_can { ++ compatible = "spi-gpio"; ++ #address-cells = <0x1>; ++ #size-cells = <0x0>; ++ gpio-sck = <&gpio1 2 GPIO_ACTIVE_HIGH>; ++ gpio-miso = <&gpio1 3 GPIO_ACTIVE_HIGH>; ++ gpio-mosi = <&gpio1 1 GPIO_ACTIVE_HIGH>; ++ cs-gpios = <&gpio1 0 GPIO_ACTIVE_HIGH ++ &gpio1 4 GPIO_ACTIVE_HIGH>; ++ num-chipselects = <2>; ++ ++ spican0: spidev@0 { ++ compatible = "microchip,mcp2515"; ++ reg = <0>; ++ clocks = <&excan_ref_clk>; ++ interrupt-parent = <&gpio0>; ++ interrupts = <15 GPIO_ACTIVE_LOW>; ++ spi-max-frequency = <10000000>; ++ }; ++ spican1: spidev@1 { ++ compatible = "microchip,mcp2515"; ++ reg = <1>; ++ clocks = <&excan_ref_clk>; ++ interrupt-parent = <&gpio1>; ++ interrupts = <5 GPIO_ACTIVE_LOW>; ++ spi-max-frequency = <10000000>; ++ }; ++ }; ++}; ++ ++&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>; ++ }; ++ ++ /delete-node/sound; ++ ++ sound_0_pins: sound1 { ++ groups = "ssi01239_ctrl", "ssi0_data", "ssi1_data_a"; ++ function = "ssi"; ++ }; ++ ++ usb0_pins: usb0 { ++ groups = "usb0"; ++ function = "usb0"; ++ }; ++ ++ can0_pins: can0 { ++ groups = "can0_data_a"; ++ function = "can0"; ++ }; ++ ++ can1_pins: can1 { ++ groups = "can1_data"; ++ function = "can1"; ++ }; ++ ++ canfd0_pins: canfd0 { ++ groups = "canfd0_data_a"; ++ function = "canfd0"; ++ }; ++ ++ canfd1_pins: canfd1 { ++ groups = "canfd1_data"; ++ function = "canfd1"; ++ }; ++}; ++ ++&gpio0 { ++ video_a_irq { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-A irq"; ++ }; ++ ++ video_b_irq { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-B irq"; ++ }; ++ ++ video_c_irq { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-C irq"; ++ }; ++}; ++ ++&gpio1 { ++ gpioext_4_22_irq { ++ gpio-hog; ++ gpios = <25 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "0x22@i2c4 irq"; ++ }; ++ pcie_disable { ++ gpio-hog; ++ gpios = <11 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "mPCIe W_DISABLE"; ++ }; ++ m2_sleep { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "M.2 SLEEP#"; ++ }; ++ m2_pres { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "M.2 Present"; ++ }; ++ m2_pcie_det { ++ gpio-hog; ++ gpios = <18 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "M.2 PCIe detected"; ++ }; ++ m2_usb_det { ++ gpio-hog; ++ gpios = <19 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "M.2 USB30 detected"; ++ }; ++ m2_usb_det { ++ gpio-hog; ++ gpios = <27 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "M.2 SSD detected"; ++ }; ++ eth_phy_reset { ++ gpio-hog; ++ gpios = <16 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "BR phy reset"; ++ }; ++ eth_sw_reset { ++ gpio-hog; ++ gpios = <17 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "BR switch reset"; ++ }; ++}; ++ ++&gpio2 { ++ m2_wake { ++ gpio-hog; ++ gpios = <1 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "M.2 WAKE#"; ++ }; ++ m2_pcie_en { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "M.2 PCIe enable"; ++ }; ++}; ++ ++&gpio3 { ++ m2_power_off { ++ gpio-hog; ++ gpios = <15 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "M.2 FULL_CARD_POWER_OFF#"; ++ }; ++}; ++ ++&gpio6 { ++ pcie_wake { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "mPCIe WAKE#"; ++ }; ++ pcie_clkreq { ++ gpio-hog; ++ gpios = <10 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "mPCIe CLKREQ#"; ++ }; ++ m2_rst { ++ gpio-hog; ++ gpios = <21 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "M.2 RESET#"; ++ }; ++}; ++ ++&hscif4 { ++ pinctrl-0 = <&hscif4_pins>; ++ pinctrl-names = "default"; ++ uart-has-rtscts; ++ ++ status = "okay"; ++}; ++ ++&i2c2 { ++ clock-frequency = <400000>; ++ ++ i2cswitch2: pca9548@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>; ++ /* USB3.0 HUB node(s) */ ++ }; ++ ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ /* PCIe node(s) */ ++ }; ++ ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ /* Slot A (CN10) */ ++ ++ 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 = "stp"; ++ ++ 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 = "stp"; ++ ++ 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 @ 0x2c */ ++ max9286-max9271@0 { ++ compatible = "maxim,max9286-max9271"; ++ reg = <0x2c>; ++ 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>; ++ /* Slot B (CN11) */ ++ ++ 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 = "stp"; ++ ++ 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 = "stp"; ++ ++ 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 @ 0x2c */ ++ max9286-max9271@1 { ++ compatible = "maxim,max9286-max9271"; ++ reg = <0x2c>; ++ 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>; ++ /* Slot C (CN12) */ ++ }; ++ ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ /* Slot A (CN10) */ ++ ++ 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>; ++ input; ++ line-name = "Video-A cfg1"; ++ }; ++ video_a_des_cfg0 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ 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>; ++ input; ++ line-name = "Video-A cfg2"; ++ }; ++ video_a_des_cfg1 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-A cfg1"; ++ }; ++ video_a_des_cfg0 { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ input; ++ 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"; ++ }; ++ video_a_cam_pwr2 { ++ gpio-hog; ++ gpios = <10 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR2"; ++ }; ++ video_a_cam_pwr3 { ++ gpio-hog; ++ gpios = <11 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR3"; ++ }; ++ video_a_des_shdn { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A DES_SHDN"; ++ }; ++ video_a_led { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-A LED"; ++ }; ++ }; ++ }; ++ ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ /* Slot B (CN11) */ ++ ++ video_b_ext0: pca9535@26 { ++ compatible = "nxp,pca9535"; ++ reg = <0x26>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ video_b_des_cfg1 { ++ gpio-hog; ++ gpios = <5 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-B cfg1"; ++ }; ++ video_b_des_cfg0 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ 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>; ++ input; ++ line-name = "Video-B cfg2"; ++ }; ++ video_b_des_cfg1 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-B cfg1"; ++ }; ++ video_b_des_cfg0 { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ input; ++ 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"; ++ }; ++ video_b_cam_pwr2 { ++ gpio-hog; ++ gpios = <10 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR2"; ++ }; ++ video_b_cam_pwr3 { ++ gpio-hog; ++ gpios = <11 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR3"; ++ }; ++ video_b_des_shdn { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B DES_SHDN"; ++ }; ++ video_b_led { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-B LED"; ++ }; ++ }; ++ }; ++ ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ /* Slot C (CN12) */ ++ }; ++ }; ++}; ++ ++&i2c4 { ++ i2cswitch4: pca9548@74 { ++ compatible = "nxp,pca9548"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x74>; ++ reset-gpios= <&gpio5 15 GPIO_ACTIVE_LOW>; ++ ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ /* FAN node - EMC2103 */ ++ fan_ctrl:ecm2103@2e { ++ compatible = "emc2103"; ++ reg = <0x2e>; ++ }; ++ }; ++ ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ /* Power nodes - 2 x TPS544x20 */ ++ }; ++ ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ /* CAN and power board nodes */ ++ ++ gpio_ext_pwr: pca9535@22 { ++ compatible = "nxp,pca9535"; ++ reg = <0x22>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ interrupt-parent = <&gpio1>; ++ interrupts = <25 IRQ_TYPE_EDGE_FALLING>; ++ ++ /* enable input DCDC after wake-up signal released */ ++ pwr_hold { ++ gpio-hog; ++ gpios = <11 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "pwr_hold"; ++ }; ++ ++ /* CAN0 */ ++ can0_stby { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "can0_stby"; ++ }; ++ can0_load { ++ gpio-hog; ++ gpios = <0 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "can0_120R_load"; ++ }; ++ /* CAN1 */ ++ can1_stby { ++ gpio-hog; ++ gpios = <5 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "can1_stby"; ++ }; ++ can1_load { ++ gpio-hog; ++ gpios = <1 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "can1_120R_load"; ++ }; ++ /* CAN2 */ ++ can2_stby { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "can2_stby"; ++ }; ++ can2_load { ++ gpio-hog; ++ gpios = <2 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "can2_120R_load"; ++ }; ++ can2_rst { ++ gpio-hog; ++ gpios = <8 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "can2_rst"; ++ }; ++ /* CAN3 */ ++ can3_stby { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "can3_stby"; ++ }; ++ can3_load { ++ gpio-hog; ++ gpios = <3 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "can3_120R_load"; ++ }; ++ can3_rst { ++ gpio-hog; ++ gpios = <9 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "can3_rst"; ++ }; ++ }; ++ }; ++ ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ /* FPDLink output node - DS90UH947 */ ++ }; ++ ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ /* BCM switch node */ ++ }; ++ ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ /* LED board node(s) */ ++ ++ gpio_ext_led: pca9535@22 { ++ compatible = "nxp,pca9535"; ++ reg = <0x22>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ /* gpios 0..7 are used for indication LEDs, low-active */ ++ }; ++ }; ++ ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ /* M2 connector i2c node(s) */ ++ }; ++ ++ /* port 7 is not used */ ++ }; ++}; ++ ++&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>; ++}; ++ ++&sata { ++ status = "okay"; ++}; ++ ++&ssi1 { ++ /delete-property/shared-pin; ++}; ++ ++&avb { ++ /delete-property/phy-handle; ++ /delete-property/phy-gpios; ++ phy-mode = "rgmii"; ++ ++ /delete-node/ethernet-phy@0; ++ ++ fixed-link { ++ speed = <100>; ++ full-duplex; ++ }; ++}; ++ ++&msiof1 { ++ status = "disabled"; ++}; ++ ++&usb2_phy0 { ++ pinctrl-0 = <&usb0_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&xhci0 { ++ status = "okay"; ++}; ++ ++&ehci0 { ++ status = "okay"; ++}; ++ ++&ohci0 { ++ status = "okay"; ++}; ++ ++&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"; ++ }; ++}; ++ ++/* uncomment to enable CN12 on VIN4-7 */ ++//#include "ulcb-vb-cn12.dtsi" +diff --git a/arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi b/arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi +new file mode 100644 +index 0000000..beb52e9 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi +@@ -0,0 +1,578 @@ ++/* ++ * Device Tree Source for the ULCB Videobox Mini board ++ * ++ * 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. ++ */ ++ ++/ { ++ aliases { ++ serial1 = &scif1; ++ }; ++ ++ pwr0: regulator-pwr0 { ++ compatible = "regulator-fixed"; ++ regulator-name = "PWR0"; ++ regulator-min-microvolt = <9000000>; ++ regulator-max-microvolt = <9000000>; ++ gpio = <&gpio_exp_6c 8 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ pwr1: regulator-pwr1 { ++ compatible = "regulator-fixed"; ++ regulator-name = "PWR1"; ++ regulator-min-microvolt = <9000000>; ++ regulator-max-microvolt = <9000000>; ++ gpio = <&gpio_exp_6c 9 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ pwr2: regulator-pwr2 { ++ compatible = "regulator-fixed"; ++ regulator-name = "PWR2"; ++ regulator-min-microvolt = <9000000>; ++ regulator-max-microvolt = <9000000>; ++ gpio = <&gpio_exp_6c 10 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ pwr3: regulator-pwr3 { ++ compatible = "regulator-fixed"; ++ regulator-name = "PWR3"; ++ regulator-min-microvolt = <9000000>; ++ regulator-max-microvolt = <9000000>; ++ gpio = <&gpio_exp_6c 11 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ 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>; ++ }; ++ }; ++ }; ++}; ++ ++&can0 { ++ pinctrl-0 = <&can0_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++}; ++ ++&can1 { ++ pinctrl-0 = <&can1_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++}; ++ ++&canfd { ++ pinctrl-0 = <&canfd0_pins &canfd1_pins>; ++ pinctrl-names = "default"; ++ status = "disabled"; ++ ++ channel0 { ++ status = "okay"; ++ }; ++ ++ channel1 { ++ status = "okay"; ++ }; ++}; ++ ++&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>; ++ }; ++ }; ++}; ++ ++&i2c1 { ++ pinctrl-0 = <&i2c1_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ clock-frequency = <400000>; ++ ++ i2cswitch1: i2c-switch@74 { ++ compatible = "nxp,pca9548"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x74>; ++ reset-gpios = <&gpio5 25 GPIO_ACTIVE_LOW>; ++ ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ ++ ov106xx@0 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x60>; ++ ++ port@0 { ++ ov106xx_in0: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin4ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ ov106xx_ti964_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti964_des0ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@1 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x61>; ++ ++ port@0 { ++ ov106xx_in1: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin5ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ ov106xx_ti964_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti964_des0ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@2 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x62>; ++ ++ port@0 { ++ ov106xx_in2: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin6ep0>; ++ }; ++ }; ++ 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 = <&vin7ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ ov106xx_ti964_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti964_des0ep3>; ++ }; ++ }; ++ }; ++ ++ max9286-max9271@0 { ++ compatible = "maxim,max9286-max9271"; ++ reg = <0x2c>; ++ maxim,sensor_delay = <350>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ POC0-supply = <&pwr0>; ++ POC1-supply = <&pwr1>; ++ POC2-supply = <&pwr2>; ++ POC3-supply = <&pwr3>; ++ ++ 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_41_ep>; ++ }; ++ }; ++ }; ++ ++ 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"; ++ POC0-supply = <&pwr0>; ++ POC1-supply = <&pwr1>; ++ POC2-supply = <&pwr2>; ++ POC3-supply = <&pwr3>; ++ ++ 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_41_ep>; ++ }; ++ }; ++ }; ++ }; ++ ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ ++ gpio_exp_6c: gpio@6c { ++ compatible = "maxim,max7325"; ++ reg = <0x6c>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ virq { ++ gpio-hog; ++ gpios = <5 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "VIRQ"; ++ }; ++ des_cfg { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "CNFG0"; ++ }; ++ pwr_shdn { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "PWR_SHDN"; ++ }; ++ des_shdn { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Des_SHDN"; ++ }; ++ fpdl_shdn { ++ gpio-hog; ++ gpios = <15 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "FPDL_SHDN"; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&gpio1 { ++ can0stby { ++ gpio-hog; ++ gpios = <8 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "CAN0STBY"; ++ }; ++}; ++ ++&gpio2 { ++ can0_load { ++ gpio-hog; ++ gpios = <3 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "CAN0Loff"; ++ }; ++}; ++ ++&pfc { ++ can0_pins: can0 { ++ groups = "can0_data_a"; ++ function = "can0"; ++ }; ++ ++ can1_pins: can1 { ++ groups = "can1_data"; ++ function = "can1"; ++ }; ++ ++ canfd0_pins: canfd0 { ++ groups = "canfd0_data_a"; ++ function = "canfd0"; ++ }; ++ ++ canfd1_pins: canfd1 { ++ groups = "canfd1_data"; ++ function = "canfd1"; ++ }; ++ ++ i2c1_pins: i2c1 { ++ groups = "i2c1_b"; ++ function = "i2c1"; ++ }; ++ ++ scif1_pins: scif1 { ++ groups = "scif1_data_a"; ++ function = "scif1"; ++ }; ++}; ++ ++&scif1 { ++ pinctrl-0 = <&scif1_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&vin4 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin4ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ }; ++ port@1 { ++ csi0ep0: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ vin4_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ vin4_ti964_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti964_des0ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin5 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin5ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <1>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ }; ++ port@1 { ++ csi0ep1: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ vin5_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ vin5_ti964_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti964_des0ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin6 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin6ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <2>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ }; ++ port@1 { ++ csi0ep2: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ vin6_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ vin6_ti964_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti964_des0ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin7 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin7ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <3>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ csi0ep3: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ vin7_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ vin7_ti964_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti964_des0ep3>; ++ }; ++ }; ++ }; ++}; ++ +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0041-arm64-dts-renesas-ulcb-enlarge-cma-region.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0041-arm64-dts-renesas-ulcb-enlarge-cma-region.patch new file mode 100644 index 0000000..755317b --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0041-arm64-dts-renesas-ulcb-enlarge-cma-region.patch @@ -0,0 +1,56 @@ +From 0636358bc75e9d5187515ee99d7c8d490c56bd52 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Sat, 15 Jul 2017 00:41:49 +0300 +Subject: [PATCH] arm64: dts: renesas: ulcb: enlarge cma region + +Enlarge cma region since ADSP is not used on ulcb + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb.dts | 2 +- + arch/arm64/boot/dts/renesas/r8a7795-h3ulcb.dts | 2 +- + arch/arm64/boot/dts/renesas/r8a7796-m3ulcb.dts | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb.dts +index 1ba7a22..9d83c6c 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb.dts +@@ -63,7 +63,7 @@ + linux,cma { + compatible = "shared-dma-pool"; + reusable; +- reg = <0x00000000 0x58000000 0x0 0x18000000>; ++ reg = <0x00000000 0x57000000 0x0 0x19000000>; + linux,cma-default; + }; + +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb.dts +index c237888..7406534 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb.dts +@@ -63,7 +63,7 @@ + linux,cma { + compatible = "shared-dma-pool"; + reusable; +- reg = <0x00000000 0x58000000 0x0 0x18000000>; ++ reg = <0x00000000 0x57000000 0x0 0x19000000>; + linux,cma-default; + }; + +diff --git a/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb.dts b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb.dts +index b3ecbd3..9aa4292 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb.dts +@@ -53,7 +53,7 @@ + linux,cma { + compatible = "shared-dma-pool"; + reusable; +- reg = <0x00000000 0x58000000 0x0 0x18000000>; ++ reg = <0x00000000 0x57000000 0x0 0x19000000>; + linux,cma-default; + }; + +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0042-arm64-dts-renesas-r8a7795-es1-h3ulcb-disable-eMMC.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0042-arm64-dts-renesas-r8a7795-es1-h3ulcb-disable-eMMC.patch new file mode 100644 index 0000000..1146a09 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0042-arm64-dts-renesas-r8a7795-es1-h3ulcb-disable-eMMC.patch @@ -0,0 +1,28 @@ +From 7440eb1bd8d9fdd197664086d67c540495832620 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Sat, 15 Jul 2017 00:44:12 +0300 +Subject: [PATCH] arm64: dts: renesas: r8a7795-es1-h3ulcb: disable eMMC + +Disable eMMC due to ES1.x silicon bug + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb.dts | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb.dts +index 9d83c6c..677bf88 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb.dts +@@ -458,7 +458,7 @@ + mmc-hs200-1_8v; + bus-width = <8>; + non-removable; +- status = "okay"; ++ status = "disabled"; + }; + + &ssi1 { +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0043-arm64-dts-renesas-ulcb-use-versaclock-for-du-rgb-and-lvds.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0043-arm64-dts-renesas-ulcb-use-versaclock-for-du-rgb-and-lvds.patch new file mode 100644 index 0000000..1298ba8 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0043-arm64-dts-renesas-ulcb-use-versaclock-for-du-rgb-and-lvds.patch @@ -0,0 +1,143 @@ +From 29bcecbb93b009e650dfdf9e6a1ff6efadc871bc Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Thu, 10 Aug 2017 08:41:53 +0300 +Subject: [PATCH] arm64: dts: renesas: ulcb: use versaclock for DU RGB and LVDS + +This allows to chgange preprogrammed clock in Versa5 clock +generator. +DU has PLL that is not too accurate, hence use prescaled value by VC5. + +[200~Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb.dts | 24 ++++++++++++++++++++++ + arch/arm64/boot/dts/renesas/r8a7795-h3ulcb.dts | 24 ++++++++++++++++++++++ + arch/arm64/boot/dts/renesas/r8a7796-m3ulcb.dts | 22 ++++++++++++++++++++ + 3 files changed, 70 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb.dts +index 677bf88..6fe4416 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb.dts +@@ -229,6 +229,15 @@ + &du { + status = "okay"; + ++ /* update <du_dotclkin0/3> to <programable_clk0/1> */ ++ clocks = <&cpg CPG_MOD 724>, ++ <&cpg CPG_MOD 723>, ++ <&cpg CPG_MOD 722>, ++ <&cpg CPG_MOD 721>, ++ <&cpg CPG_MOD 727>, ++ <&programmable_clk0>, <&du_dotclkin1>, <&du_dotclkin2>, ++ <&programmable_clk1>; ++ + ports { + port@1 { + endpoint { +@@ -390,6 +399,21 @@ + status = "okay"; + + clock-frequency = <400000>; ++ ++ clk_5p49v5925: programmable_clk@6a { ++ compatible = "idt,5p49v5925"; ++ reg = <0x6a>; ++ ++ programmable_clk0: 5p49x_clk1@6a { ++ #clock-cells = <0>; ++ clocks = <&du_dotclkin0>; ++ }; ++ ++ programmable_clk1: 5p49x_clk2@6a { ++ #clock-cells = <0>; ++ clocks = <&du_dotclkin3>; ++ }; ++ }; + }; + + &rcar_sound { +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb.dts +index 7406534..e018f21 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb.dts +@@ -229,6 +229,15 @@ + &du { + status = "okay"; + ++ /* update <du_dotclkin0/3> to <programable_clk0/1> */ ++ clocks = <&cpg CPG_MOD 724>, ++ <&cpg CPG_MOD 723>, ++ <&cpg CPG_MOD 722>, ++ <&cpg CPG_MOD 721>, ++ <&cpg CPG_MOD 727>, ++ <&programmable_clk0>, <&du_dotclkin1>, <&du_dotclkin2>, ++ <&programmable_clk1>; ++ + ports { + port@1 { + endpoint { +@@ -390,6 +399,21 @@ + status = "okay"; + + clock-frequency = <400000>; ++ ++ clk_5p49v5925: programmable_clk@6a { ++ compatible = "idt,5p49v5925"; ++ reg = <0x6a>; ++ ++ programmable_clk0: 5p49x_clk1@6a { ++ #clock-cells = <0>; ++ clocks = <&du_dotclkin0>; ++ }; ++ ++ programmable_clk1: 5p49x_clk2@6a { ++ #clock-cells = <0>; ++ clocks = <&du_dotclkin3>; ++ }; ++ }; + }; + + &rcar_sound { +diff --git a/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb.dts b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb.dts +index 9aa4292..130c068 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb.dts +@@ -312,6 +312,13 @@ + &du { + status = "okay"; + ++ /* update <du_dotclkin0/2> to <programable_clk0/1> */ ++ clocks = <&cpg CPG_MOD 724>, ++ <&cpg CPG_MOD 723>, ++ <&cpg CPG_MOD 722>, ++ <&cpg CPG_MOD 727>, ++ <&programmable_clk0>, <&du_dotclkin1>, <&programmable_clk1>; ++ + ports { + port@1 { + endpoint { +@@ -422,6 +429,21 @@ + &i2c4 { + status = "okay"; + clock-frequency = <400000>; ++ ++ clk_5p49v5925: programmable_clk@6a { ++ compatible = "idt,5p49v5925"; ++ reg = <0x6a>; ++ ++ programmable_clk0: 5p49x_clk1@6a { ++ #clock-cells = <0>; ++ clocks = <&du_dotclkin0>; ++ }; ++ ++ programmable_clk1: 5p49x_clk2@6a { ++ #clock-cells = <0>; ++ clocks = <&du_dotclkin2>; ++ }; ++ }; + }; + + &rcar_sound { +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0044-pinctrl-r8a779x-add-mlb-pinmux.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0044-pinctrl-r8a779x-add-mlb-pinmux.patch new file mode 100644 index 0000000..8541e19 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0044-pinctrl-r8a779x-add-mlb-pinmux.patch @@ -0,0 +1,154 @@ +From 7f797fef45307ed6c5960cc116ce8de65d192269 Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +Date: Fri, 7 Jul 2017 16:22:40 +0300 +Subject: [PATCH] pinctrl: r8a779x: add mlb pinmux + +Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + drivers/pinctrl/sh-pfc/pfc-r8a7795-es1.c | 14 ++++++++++++++ + drivers/pinctrl/sh-pfc/pfc-r8a7795.c | 14 ++++++++++++++ + drivers/pinctrl/sh-pfc/pfc-r8a7796.c | 14 ++++++++++++++ + 3 files changed, 42 insertions(+) + +diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7795-es1.c b/drivers/pinctrl/sh-pfc/pfc-r8a7795-es1.c +index 378065d..f544546 100644 +--- a/drivers/pinctrl/sh-pfc/pfc-r8a7795-es1.c ++++ b/drivers/pinctrl/sh-pfc/pfc-r8a7795-es1.c +@@ -2403,6 +2403,14 @@ enum { + IRQ5_MARK, + }; + ++/* - MLB+ ------------------------------------------------------------------- */ ++static const unsigned int mlb_3pin_pins[] = { ++ RCAR_GP_PIN(5, 23), RCAR_GP_PIN(5, 24), RCAR_GP_PIN(5, 25), ++}; ++static const unsigned int mlb_3pin_mux[] = { ++ MLB_CLK_MARK, MLB_SIG_MARK, MLB_DAT_MARK, ++}; ++ + /* - MSIOF0 ----------------------------------------------------------------- */ + static const unsigned int msiof0_clk_pins[] = { + /* SCK */ +@@ -4266,6 +4274,7 @@ enum { + 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(mlb_3pin), + SH_PFC_PIN_GROUP(msiof0_clk), + SH_PFC_PIN_GROUP(msiof0_sync), + SH_PFC_PIN_GROUP(msiof0_ss1), +@@ -4682,6 +4691,10 @@ enum { + "intc_ex_irq5", + }; + ++static const char * const mlb_3pin_groups[] = { ++ "mlb_3pin", ++}; ++ + static const char * const msiof0_groups[] = { + "msiof0_clk", + "msiof0_sync", +@@ -5032,6 +5045,7 @@ enum { + SH_PFC_FUNCTION(i2c5), + SH_PFC_FUNCTION(i2c6), + SH_PFC_FUNCTION(intc_ex), ++ SH_PFC_FUNCTION(mlb_3pin), + SH_PFC_FUNCTION(msiof0), + SH_PFC_FUNCTION(msiof1), + SH_PFC_FUNCTION(msiof2), +diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7795.c b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c +index 1198998..928bbbc 100644 +--- a/drivers/pinctrl/sh-pfc/pfc-r8a7795.c ++++ b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c +@@ -2466,6 +2466,14 @@ enum { + IRQ5_MARK, + }; + ++/* - MLB+ ------------------------------------------------------------------- */ ++static const unsigned int mlb_3pin_pins[] = { ++ RCAR_GP_PIN(5, 23), RCAR_GP_PIN(5, 24), RCAR_GP_PIN(5, 25), ++}; ++static const unsigned int mlb_3pin_mux[] = { ++ MLB_CLK_MARK, MLB_SIG_MARK, MLB_DAT_MARK, ++}; ++ + /* - MSIOF0 ----------------------------------------------------------------- */ + static const unsigned int msiof0_clk_pins[] = { + /* SCK */ +@@ -4387,6 +4395,7 @@ enum { + 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(mlb_3pin), + SH_PFC_PIN_GROUP(msiof0_clk), + SH_PFC_PIN_GROUP(msiof0_sync), + SH_PFC_PIN_GROUP(msiof0_ss1), +@@ -4811,6 +4820,10 @@ enum { + "intc_ex_irq5", + }; + ++static const char * const mlb_3pin_groups[] = { ++ "mlb_3pin", ++}; ++ + static const char * const msiof0_groups[] = { + "msiof0_clk", + "msiof0_sync", +@@ -5169,6 +5182,7 @@ enum { + SH_PFC_FUNCTION(i2c5), + SH_PFC_FUNCTION(i2c6), + SH_PFC_FUNCTION(intc_ex), ++ SH_PFC_FUNCTION(mlb_3pin), + SH_PFC_FUNCTION(msiof0), + SH_PFC_FUNCTION(msiof1), + SH_PFC_FUNCTION(msiof2), +diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c +index 1cef61b..26a69dc 100644 +--- a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c ++++ b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c +@@ -2468,6 +2468,14 @@ enum { + IRQ5_MARK, + }; + ++/* - MLB+ ------------------------------------------------------------------- */ ++static const unsigned int mlb_3pin_pins[] = { ++ RCAR_GP_PIN(5, 23), RCAR_GP_PIN(5, 24), RCAR_GP_PIN(5, 25), ++}; ++static const unsigned int mlb_3pin_mux[] = { ++ MLB_CLK_MARK, MLB_SIG_MARK, MLB_DAT_MARK, ++}; ++ + /* - MSIOF0 ----------------------------------------------------------------- */ + static const unsigned int msiof0_clk_pins[] = { + /* SCK */ +@@ -4310,6 +4318,7 @@ enum { + 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(mlb_3pin), + SH_PFC_PIN_GROUP(msiof0_clk), + SH_PFC_PIN_GROUP(msiof0_sync), + SH_PFC_PIN_GROUP(msiof0_ss1), +@@ -4722,6 +4731,10 @@ enum { + "intc_ex_irq5", + }; + ++static const char * const mlb_3pin_groups[] = { ++ "mlb_3pin", ++}; ++ + static const char * const msiof0_groups[] = { + "msiof0_clk", + "msiof0_sync", +@@ -5054,6 +5067,7 @@ enum { + SH_PFC_FUNCTION(i2c5), + SH_PFC_FUNCTION(i2c6), + SH_PFC_FUNCTION(intc_ex), ++ SH_PFC_FUNCTION(mlb_3pin), + SH_PFC_FUNCTION(msiof0), + SH_PFC_FUNCTION(msiof1), + SH_PFC_FUNCTION(msiof2), +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0045-clk-r8a779x-add-mlp-clock.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0045-clk-r8a779x-add-mlp-clock.patch new file mode 100644 index 0000000..ca473a1 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0045-clk-r8a779x-add-mlp-clock.patch @@ -0,0 +1,38 @@ +From 741e7fcf44527632a06538419f000843b24d9293 Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +Date: Fri, 7 Jul 2017 16:23:44 +0300 +Subject: [PATCH] clk: r8a779x: add mlp clock + +Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +--- + drivers/clk/renesas/r8a7795-cpg-mssr.c | 1 + + drivers/clk/renesas/r8a7796-cpg-mssr.c | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/drivers/clk/renesas/r8a7795-cpg-mssr.c b/drivers/clk/renesas/r8a7795-cpg-mssr.c +index f833031..38d1f41 100644 +--- a/drivers/clk/renesas/r8a7795-cpg-mssr.c ++++ b/drivers/clk/renesas/r8a7795-cpg-mssr.c +@@ -219,6 +219,7 @@ enum clk_ids { + DEF_MOD("lvds", 727, R8A7795_CLK_S0D4), + DEF_MOD("hdmi1", 728, R8A7795_CLK_HDMI), + DEF_MOD("hdmi0", 729, R8A7795_CLK_HDMI), ++ DEF_MOD("mlp", 802, R8A7795_CLK_S2D1), + DEF_MOD("vin7", 804, R8A7795_CLK_S0D2), + DEF_MOD("vin6", 805, R8A7795_CLK_S0D2), + DEF_MOD("vin5", 806, R8A7795_CLK_S0D2), +diff --git a/drivers/clk/renesas/r8a7796-cpg-mssr.c b/drivers/clk/renesas/r8a7796-cpg-mssr.c +index b938750..6a5936e 100644 +--- a/drivers/clk/renesas/r8a7796-cpg-mssr.c ++++ b/drivers/clk/renesas/r8a7796-cpg-mssr.c +@@ -194,6 +194,7 @@ enum clk_ids { + DEF_MOD("du0", 724, R8A7796_CLK_S2D1), + DEF_MOD("lvds", 727, R8A7796_CLK_S2D1), + DEF_MOD("hdmi0", 729, R8A7796_CLK_HDMI), ++ DEF_MOD("mlp", 802, R8A7796_CLK_S2D1), + DEF_MOD("vin7", 804, R8A7796_CLK_S0D2), + DEF_MOD("vin6", 805, R8A7796_CLK_S0D2), + DEF_MOD("vin5", 806, R8A7796_CLK_S0D2), +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0046-arm64-dts-renesas-r8a779x-add-mlp-nodes.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0046-arm64-dts-renesas-r8a779x-add-mlp-nodes.patch new file mode 100644 index 0000000..1f17f0e --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0046-arm64-dts-renesas-r8a779x-add-mlp-nodes.patch @@ -0,0 +1,87 @@ +From 8d5de721b2e037ce77f886a4307ea5668df9417f Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +Date: Fri, 7 Jul 2017 16:25:06 +0300 +Subject: [PATCH] arm64: dts: renesas: r8a779x: add mlp nodes + +Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +--- + arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi | 13 +++++++++++++ + arch/arm64/boot/dts/renesas/r8a7795.dtsi | 13 +++++++++++++ + arch/arm64/boot/dts/renesas/r8a7796.dtsi | 13 +++++++++++++ + 3 files changed, 39 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi b/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi +index 89c70bb7738b..44a290b32899 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi +@@ -2072,6 +2072,19 @@ + status = "disabled"; + }; + ++ mlp: mlp@ec520000 { ++ compatible = "rcar,medialb-dim2"; ++ reg = <0 0xec520000 0 0x800>; ++ interrupts = <GIC_SPI 385 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 386 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 384 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 387 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 388 IRQ_TYPE_LEVEL_HIGH>; ++ clocks = <&cpg CPG_MOD 802>; ++ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ + msiof0: spi@e6e90000 { + #address-cells = <1>; + #size-cells = <0>; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795.dtsi b/arch/arm64/boot/dts/renesas/r8a7795.dtsi +index 89c70bb7738b..44a290b32899 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi +@@ -2072,6 +2072,19 @@ + status = "disabled"; + }; + ++ mlp: mlp@ec520000 { ++ compatible = "rcar,medialb-dim2"; ++ reg = <0 0xec520000 0 0x800>; ++ interrupts = <GIC_SPI 385 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 386 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 384 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 387 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 388 IRQ_TYPE_LEVEL_HIGH>; ++ clocks = <&cpg CPG_MOD 802>; ++ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ + msiof0: spi@e6e90000 { + #address-cells = <1>; + #size-cells = <0>; +diff --git a/arch/arm64/boot/dts/renesas/r8a7796.dtsi b/arch/arm64/boot/dts/renesas/r8a7796.dtsi +index f430df9df961..565d6e7de4cc 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7796.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a7796.dtsi +@@ -1955,6 +1955,19 @@ + status = "disabled"; + }; + ++ mlp: mlp@ec520000 { ++ compatible = "rcar,medialb-dim2"; ++ reg = <0 0xec520000 0 0x800>; ++ interrupts = <GIC_SPI 385 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 386 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 384 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 387 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 388 IRQ_TYPE_LEVEL_HIGH>; ++ clocks = <&cpg CPG_MOD 802>; ++ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ + msiof1: spi@e6ea0000 { + compatible = "renesas,msiof-r8a7796"; + reg = <0 0xe6ea0000 0 0x0064>; +-- +2.13.0 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0047-arm64-dts-renesas-ulcb-kf-enable-sd3.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0047-arm64-dts-renesas-ulcb-kf-enable-sd3.patch new file mode 100644 index 0000000..81b3dc9 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0047-arm64-dts-renesas-ulcb-kf-enable-sd3.patch @@ -0,0 +1,28 @@ +From a5eed343caa82837c72a2c0e3d53f4db0c5944e4 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Fri, 27 Oct 2017 20:54:47 +0300 +Subject: [PATCH] arm64: dts: renesas: ulcb-kf: enable sd3 + +This enables SD3 on CN47 instead wifi + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + arch/arm64/boot/dts/renesas/ulcb-kf.dtsi | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi +index 8ffafb2..ea6cb1b 100644 +--- a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi ++++ b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi +@@ -1527,3 +1527,8 @@ + + + ++/* enable CN47: SD on SDHI3 */ ++#include "ulcb-kf-sd3.dtsi" ++ ++ ++ +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0048-arm64-dts-renesas-ulcb-kf-enable-most.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0048-arm64-dts-renesas-ulcb-kf-enable-most.patch new file mode 100644 index 0000000..37ad738 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0048-arm64-dts-renesas-ulcb-kf-enable-most.patch @@ -0,0 +1,28 @@ +From ab803d3c36d8444948c7eec238c19926fd036fcc Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Fri, 27 Oct 2017 20:58:21 +0300 +Subject: [PATCH] arm64: dts: renesas: ulcb-kf: enable most + +This enables MOST on CN22 instead GPS + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + arch/arm64/boot/dts/renesas/ulcb-kf.dtsi | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi +index ea6cb1b..ddd5450 100644 +--- a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi ++++ b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi +@@ -1532,3 +1532,8 @@ + + + ++/* enable CN22: enable MOST and disable GPS (move R661->R660, R663->R662) */ ++#include "ulcb-kf-most.dtsi" ++ ++ ++ +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0049-clk-r8a779x-add-IMP-clock.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0049-clk-r8a779x-add-IMP-clock.patch new file mode 100644 index 0000000..a7cf942 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0049-clk-r8a779x-add-IMP-clock.patch @@ -0,0 +1,59 @@ +From 9075957822c829026acfb5e8982a77f895a7a640 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Mon, 27 Nov 2017 16:53:06 +0300 +Subject: [PATCH] clk: r8a779x: add IMP clock + +This adds IMP clock sources for Gen3 SoCs + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + drivers/clk/renesas/r8a7795-cpg-mssr.c | 1 + + drivers/clk/renesas/r8a7796-cpg-mssr.c | 1 + + drivers/clk/renesas/r8a7797-cpg-mssr.c | 7 +++++++ + 3 files changed, 9 insertions(+) + +diff --git a/drivers/clk/renesas/r8a7795-cpg-mssr.c b/drivers/clk/renesas/r8a7795-cpg-mssr.c +index bc10df3..9061f7f 100644 +--- a/drivers/clk/renesas/r8a7795-cpg-mssr.c ++++ b/drivers/clk/renesas/r8a7795-cpg-mssr.c +@@ -234,6 +234,7 @@ enum clk_ids { + DEF_MOD("imr2", 821, R8A7795_CLK_S2D1), + DEF_MOD("imr1", 822, R8A7795_CLK_S2D1), + DEF_MOD("imr0", 823, R8A7795_CLK_S2D1), ++ DEF_MOD("imp", 824, R8A7795_CLK_S1D1), + DEF_MOD("gpio7", 905, R8A7795_CLK_S3D4), + DEF_MOD("gpio6", 906, R8A7795_CLK_S3D4), + DEF_MOD("gpio5", 907, R8A7795_CLK_S3D4), +diff --git a/drivers/clk/renesas/r8a7796-cpg-mssr.c b/drivers/clk/renesas/r8a7796-cpg-mssr.c +index 819d3c6..e886d8a 100644 +--- a/drivers/clk/renesas/r8a7796-cpg-mssr.c ++++ b/drivers/clk/renesas/r8a7796-cpg-mssr.c +@@ -204,6 +204,7 @@ enum clk_ids { + DEF_MOD("vin1", 810, R8A7796_CLK_S0D2), + DEF_MOD("vin0", 811, R8A7796_CLK_S0D2), + DEF_MOD("etheravb", 812, R8A7796_CLK_S0D6), ++ DEF_MOD("imp", 824, R8A7796_CLK_S1D1), + DEF_MOD("gpio7", 905, R8A7796_CLK_S3D4), + DEF_MOD("gpio6", 906, R8A7796_CLK_S3D4), + DEF_MOD("gpio5", 907, R8A7796_CLK_S3D4), +diff --git a/drivers/clk/renesas/r8a7797-cpg-mssr.c b/drivers/clk/renesas/r8a7797-cpg-mssr.c +index 29dfe4a..6655592 100644 +--- a/drivers/clk/renesas/r8a7797-cpg-mssr.c ++++ b/drivers/clk/renesas/r8a7797-cpg-mssr.c +@@ -129,6 +129,13 @@ enum clk_ids { + DEF_MOD("imr2", 821, R8A7797_CLK_S2D1), + DEF_MOD("imr1", 822, R8A7797_CLK_S2D1), + DEF_MOD("imr0", 823, R8A7797_CLK_S2D1), ++ DEF_MOD("imp3", 824, R8A7797_CLK_S1D1), ++ DEF_MOD("imp2", 825, R8A7797_CLK_S1D1), ++ DEF_MOD("imp1", 826, R8A7797_CLK_S1D1), ++ DEF_MOD("imp0", 827, R8A7797_CLK_S1D1), ++ DEF_MOD("imp-ocv1", 828, R8A7797_CLK_S1D1), ++ DEF_MOD("imp-ocv0", 829, R8A7797_CLK_S1D1), ++ DEF_MOD("impram", 830, R8A7797_CLK_S1D1), + DEF_MOD("gpio5", 907, R8A7797_CLK_CP), + DEF_MOD("gpio4", 908, R8A7797_CLK_CP), + DEF_MOD("gpio3", 909, R8A7797_CLK_CP), +-- +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/0050-arm64-dts-renesas-r8a779x-add-IMP-nodes.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0050-arm64-dts-renesas-r8a779x-add-IMP-nodes.patch new file mode 100644 index 0000000..b38a623 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0050-arm64-dts-renesas-r8a779x-add-IMP-nodes.patch @@ -0,0 +1,425 @@ +From 9dcc1345c0b04ebab6e5b9f676881716bf985753 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Tue, 28 Nov 2017 14:47:12 +0300 +Subject: [PATCH] arm64: dts: renesas: r8a779x: add IMP nodes + +This adds IMP resource nodes for Gen3 SoCs + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi | 98 +++++++++++++++++++++++++++ + arch/arm64/boot/dts/renesas/r8a7795.dtsi | 98 +++++++++++++++++++++++++++ + arch/arm64/boot/dts/renesas/r8a7796.dtsi | 62 +++++++++++++++++ + arch/arm64/boot/dts/renesas/r8a7797.dtsi | 99 ++++++++++++++++++++++++++++ + 4 files changed, 357 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi b/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi +index b3f3102..e15af8c 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi +@@ -2794,6 +2794,104 @@ + }; + }; + ++ imp_distributer: impdes0 { ++ compatible = "renesas,impx4-distributer"; ++ reg = <0 0xffa00000 0 0x4000>; ++ interrupts = <GIC_SPI 439 IRQ_TYPE_LEVEL_HIGH>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7795_PD_A3IR>; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ }; ++ ++ imp0 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff900000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <0>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7795_PD_A3IR>; ++ }; ++ ++ imp1 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff920000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <1>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7795_PD_A3IR>; ++ }; ++ ++ imp2 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff940000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <2>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7795_PD_A3IR>; ++ }; ++ ++ imp3 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff960000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <3>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7795_PD_A3IR>; ++ }; ++ ++ impsc0 { ++ compatible = "renesas,impx4-shader"; ++ reg = <0 0xff980000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <4>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7795_PD_A3IR>; ++ }; ++ ++ impsc1 { ++ compatible = "renesas,impx4-shader"; ++ reg = <0 0xff990000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <5>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7795_PD_A3IR>; ++ }; ++ ++ impsl0 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff9c0000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <12>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7795_PD_A3IR>; ++ }; ++ ++ impdm0 { ++ compatible = "renesas,impx5-dmac"; ++ reg = <0 0xffa10000 0 0x4000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <16>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7795_PD_A3IR>; ++ }; ++ ++ impc0 { ++ compatible = "renesas,impx4-memory"; ++ reg = <0 0xffa40000 0 0x20000>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7795_PD_A3IR>; ++ }; ++ ++ imprtt { ++ compatible = "renesas,impx5-rtt"; ++ reg = <0 0xff8d0000 0 0x1000>, ++ <0 0xe6150000 0 0x1000>; ++ interrupts = <GIC_SPI 393 IRQ_TYPE_LEVEL_HIGH>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7795_PD_A3IR>; ++ }; ++ + imrlx4_ch0: imr-lx4@fe860000 { + compatible = "renesas,imr-lx4"; + reg = <0 0xfe860000 0 0x2000>; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795.dtsi b/arch/arm64/boot/dts/renesas/r8a7795.dtsi +index 02c5931..8ba4cec 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi +@@ -2790,6 +2790,104 @@ + }; + }; + ++ imp_distributer: impdes0 { ++ compatible = "renesas,impx4-distributer"; ++ reg = <0 0xffa00000 0 0x4000>; ++ interrupts = <GIC_SPI 439 IRQ_TYPE_LEVEL_HIGH>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7795_PD_A3IR>; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ }; ++ ++ imp0 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff900000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <0>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7795_PD_A3IR>; ++ }; ++ ++ imp1 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff920000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <1>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7795_PD_A3IR>; ++ }; ++ ++ imp2 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff940000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <2>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7795_PD_A3IR>; ++ }; ++ ++ imp3 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff960000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <3>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7795_PD_A3IR>; ++ }; ++ ++ impsc0 { ++ compatible = "renesas,impx4-shader"; ++ reg = <0 0xff980000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <4>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7795_PD_A3IR>; ++ }; ++ ++ impsc1 { ++ compatible = "renesas,impx4-shader"; ++ reg = <0 0xff990000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <5>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7795_PD_A3IR>; ++ }; ++ ++ impsl0 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff9c0000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <12>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7795_PD_A3IR>; ++ }; ++ ++ impdm0 { ++ compatible = "renesas,impx5-dmac"; ++ reg = <0 0xffa10000 0 0x4000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <16>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7795_PD_A3IR>; ++ }; ++ ++ impc0 { ++ compatible = "renesas,impx4-memory"; ++ reg = <0 0xffa40000 0 0x20000>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7795_PD_A3IR>; ++ }; ++ ++ imprtt { ++ compatible = "renesas,impx5-rtt"; ++ reg = <0 0xff8d0000 0 0x1000>, ++ <0 0xe6150000 0 0x1000>; ++ interrupts = <GIC_SPI 393 IRQ_TYPE_LEVEL_HIGH>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7795_PD_A3IR>; ++ }; ++ + imrlx4_ch0: imr-lx4@fe860000 { + compatible = "renesas,imr-lx4"; + reg = <0 0xfe860000 0 0x2000>; +diff --git a/arch/arm64/boot/dts/renesas/r8a7796.dtsi b/arch/arm64/boot/dts/renesas/r8a7796.dtsi +index b94d9e0..7c19f35 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7796.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a7796.dtsi +@@ -2531,5 +2531,67 @@ + }; + }; + }; ++ ++ imp_distributer: impdes0 { ++ compatible = "renesas,impx4-distributer"; ++ reg = <0 0xffa00000 0 0x4000>; ++ interrupts = <GIC_SPI 439 IRQ_TYPE_LEVEL_HIGH>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7796_PD_A3IR>; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ }; ++ ++ imp0 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff900000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <0>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7796_PD_A3IR>; ++ }; ++ ++ imp1 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff920000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <1>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7796_PD_A3IR>; ++ }; ++ ++ impsc0 { ++ compatible = "renesas,impx4-shader"; ++ reg = <0 0xff980000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <4>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7796_PD_A3IR>; ++ }; ++ ++ impdm0 { ++ compatible = "renesas,impx5-dmac"; ++ reg = <0 0xffa10000 0 0x4000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <16>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7796_PD_A3IR>; ++ }; ++ ++ impc0 { ++ compatible = "renesas,impx4-memory"; ++ reg = <0 0xffa40000 0 0x20000>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7796_PD_A3IR>; ++ }; ++ ++ imprtt { ++ compatible = "renesas,impx5-rtt"; ++ reg = <0 0xff8d0000 0 0x1000>, ++ <0 0xe6150000 0 0x1000>; ++ interrupts = <GIC_SPI 393 IRQ_TYPE_LEVEL_HIGH>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7796_PD_A3IR>; ++ }; + }; + }; +diff --git a/arch/arm64/boot/dts/renesas/r8a7797.dtsi b/arch/arm64/boot/dts/renesas/r8a7797.dtsi +index 1be93e8..232eb19 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7797.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a7797.dtsi +@@ -970,6 +970,112 @@ + status = "okay"; + }; + ++ imp_distributer: impdes0 { ++ compatible = "renesas,impx4-distributer"; ++ reg = <0 0xffa00000 0 0x4000>; ++ interrupts = <GIC_SPI 281 IRQ_TYPE_LEVEL_HIGH>; ++ clocks = <&cpg CPG_MOD 830>; ++ power-domains = <&sysc R8A7797_PD_A3IR>; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ }; ++ ++ imp0 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff900000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <0>; ++ clocks = <&cpg CPG_MOD 827>; ++ power-domains = <&sysc R8A7797_PD_A2IR0>; ++ }; ++ ++ imp1 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff920000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <1>; ++ clocks = <&cpg CPG_MOD 826>; ++ power-domains = <&sysc R8A7797_PD_A2IR1>; ++ }; ++ ++ imp2 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff940000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <2>; ++ clocks = <&cpg CPG_MOD 825>; ++ power-domains = <&sysc R8A7797_PD_A2IR2>; ++ }; ++ ++ imp3 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff960000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <3>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7797_PD_A2IR3>; ++ }; ++ ++ impsc0 { ++ compatible = "renesas,impx4-shader"; ++ reg = <0 0xff980000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <4>; ++ clocks = <&cpg CPG_MOD 829>; ++ power-domains = <&sysc R8A7797_PD_A2SC0>; ++ }; ++ ++ impsc1 { ++ compatible = "renesas,impx4-shader"; ++ reg = <0 0xff990000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <5>; ++ clocks = <&cpg CPG_MOD 828>; ++ power-domains = <&sysc R8A7797_PD_A2SC1>; ++ }; ++ ++ impdm0 { ++ compatible = "renesas,impx5-dmac"; ++ reg = <0 0xffa10000 0 0x1000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <16>; ++ clocks = <&cpg CPG_MOD 830>; ++ power-domains = <&sysc R8A7797_PD_A3IR>; ++ }; ++ ++ impdm1 { ++ compatible = "renesas,impx5-dmac"; ++ reg = <0 0xffa10000 0 0x1000>, ++ <0 0xffa10800 0 0x0800>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <17>; ++ clocks = <&cpg CPG_MOD 830>; ++ power-domains = <&sysc R8A7797_PD_A3IR>; ++ }; ++ ++ imppsc0 { ++ compatible = "renesas,impx5-dmac"; ++ reg = <0 0xffa20000 0 0x4000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <12>; ++ clocks = <&cpg CPG_MOD 830>; ++ power-domains = <&sysc R8A7797_PD_A3IR>; ++ }; ++ ++ impc0 { ++ compatible = "renesas,impx4-memory"; ++ reg = <0 0xed000000 0 0x100000>; ++ clocks = <&cpg CPG_MOD 830>; ++ power-domains = <&sysc R8A7797_PD_A3IR>; ++ }; ++ ++ impcnn0 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff9e0000 0 0x10000>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7797_PD_A2IR3>; ++ }; ++ + imrlx4_ch0: imr-lx4@fe860000 { + compatible = "renesas,imr-lx4"; + reg = <0 0xfe860000 0 0x2000>; +-- +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/0062-IIO-lsm9ds0-add-IMU-driver.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0062-IIO-lsm9ds0-add-IMU-driver.patch new file mode 100644 index 0000000..d3a329f --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0062-IIO-lsm9ds0-add-IMU-driver.patch @@ -0,0 +1,972 @@ +From 4631208dd9557e0183acba14dec79318f9cabdc3 Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +Date: Wed, 7 Jun 2017 13:35:52 +0300 +Subject: [PATCH] IIO: lsm9ds0: add IMU driver + +Taken from: +https://github.com/mpod/kernel-playground + +Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +--- + drivers/iio/imu/Kconfig | 11 + + drivers/iio/imu/Makefile | 2 + + drivers/iio/imu/lsm9ds0.c | 912 ++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 925 insertions(+) + create mode 100644 drivers/iio/imu/lsm9ds0.c + +diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig +index 1f1ad41ef881..063c09b8fc53 100644 +--- a/drivers/iio/imu/Kconfig ++++ b/drivers/iio/imu/Kconfig +@@ -38,6 +38,17 @@ config KMX61 + To compile this driver as module, choose M here: the module will + be called kmx61. + ++config LSM9DS0 ++ tristate "ST LSM9DS0 9-axis IMU" ++ depends on I2C ++ select IIO_BUFFER ++ select IIO_TRIGGERED_BUFFER ++ help ++ Say Y here if you want to build a driver for ST LSM9DS0 ++ system-in-package featuring a 3D digital linear acceleration ++ sensor, a 3D digital angular rate sensor, and a 3D digital magnetic ++ sensor. ++ + source "drivers/iio/imu/inv_mpu6050/Kconfig" + + endmenu +diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile +index c71bcd30dc38..4de076d0766e 100644 +--- a/drivers/iio/imu/Makefile ++++ b/drivers/iio/imu/Makefile +@@ -13,6 +13,8 @@ adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_trigger.o + adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_buffer.o + obj-$(CONFIG_IIO_ADIS_LIB) += adis_lib.o + ++obj-$(CONFIG_LSM9DS0) += lsm9ds0.o ++ + obj-y += bmi160/ + obj-y += inv_mpu6050/ + +diff --git a/drivers/iio/imu/lsm9ds0.c b/drivers/iio/imu/lsm9ds0.c +new file mode 100644 +index 000000000000..15e2671daef9 +--- /dev/null ++++ b/drivers/iio/imu/lsm9ds0.c +@@ -0,0 +1,912 @@ ++/* ++ * lsm9ds0_gyro.c ++ * ++ * Copyright (C) 2016 Matija Podravec <matija_podravec@fastmail.fm> ++ * ++ * 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 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see <http://www.gnu.org/licenses/>. ++ * ++ * ++ * Driver for ST LSM9DS0 gyroscope, accelerometer, and magnetometer sensor. ++ * ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/slab.h> ++#include <linux/i2c.h> ++#include <linux/bitops.h> ++#include <linux/iio/iio.h> ++#include <linux/iio/sysfs.h> ++#include <linux/iio/trigger_consumer.h> ++#include <linux/iio/kfifo_buf.h> ++ ++#define LSM9DS0_WHO_AM_I_REG (0x0F) ++#define LSM9DS0_CTRL_REG1_G_REG (0x20) ++#define LSM9DS0_CTRL_REG2_G_REG (0x21) ++#define LSM9DS0_CTRL_REG3_G_REG (0x22) ++#define LSM9DS0_CTRL_REG4_G_REG (0x23) ++#define LSM9DS0_CTRL_REG5_G_REG (0x24) ++#define LSM9DS0_REFERENCE_G_REG (0x25) ++#define LSM9DS0_STATUS_REG_G_REG (0x27) ++#define LSM9DS0_OUT_X_L_G_REG (0x28) ++#define LSM9DS0_OUT_X_H_G_REG (0x29) ++#define LSM9DS0_OUT_Y_L_G_REG (0x2A) ++#define LSM9DS0_OUT_Y_H_G_REG (0x2B) ++#define LSM9DS0_OUT_Z_L_G_REG (0x2C) ++#define LSM9DS0_OUT_Z_H_G_REG (0x2D) ++#define LSM9DS0_FIFO_CTRL_REG_G_REG (0x2E) ++#define LSM9DS0_FIFO_SRC_REG_G_REG (0x2F) ++#define LSM9DS0_INT1_CFG_G_REG (0x30) ++#define LSM9DS0_INT1_SRC_G_REG (0x31) ++#define LSM9DS0_INT1_TSH_XH_G_REG (0x32) ++#define LSM9DS0_INT1_TSH_XL_G_REG (0x33) ++#define LSM9DS0_INT1_TSH_YH_G_REG (0x34) ++#define LSM9DS0_INT1_TSH_YL_G_REG (0x35) ++#define LSM9DS0_INT1_TSH_ZH_G_REG (0x36) ++#define LSM9DS0_INT1_TSH_ZL_G_REG (0x37) ++#define LSM9DS0_INT1_DURATION_G_REG (0x38) ++#define LSM9DS0_OUT_TEMP_L_XM_REG (0x05) ++#define LSM9DS0_OUT_TEMP_H_XM_REG (0x06) ++#define LSM9DS0_STATUS_REG_M_REG (0x07) ++#define LSM9DS0_OUT_X_L_M_REG (0x08) ++#define LSM9DS0_OUT_X_H_M_REG (0x09) ++#define LSM9DS0_OUT_Y_L_M_REG (0x0A) ++#define LSM9DS0_OUT_Y_H_M_REG (0x0B) ++#define LSM9DS0_OUT_Z_L_M_REG (0x0C) ++#define LSM9DS0_OUT_Z_H_M_REG (0x0D) ++#define LSM9DS0_INT_CTRL_REG_M_REG (0x12) ++#define LSM9DS0_INT_SRC_REG_M_REG (0x13) ++#define LSM9DS0_INT_THS_L_M_REG (0x14) ++#define LSM9DS0_INT_THS_H_M_REG (0x15) ++#define LSM9DS0_OFFSET_X_L_M_REG (0x16) ++#define LSM9DS0_OFFSET_X_H_M_REG (0x17) ++#define LSM9DS0_OFFSET_Y_L_M_REG (0x18) ++#define LSM9DS0_OFFSET_Y_H_M_REG (0x19) ++#define LSM9DS0_OFFSET_Z_L_M_REG (0x1A) ++#define LSM9DS0_OFFSET_Z_H_M_REG (0x1B) ++#define LSM9DS0_REFERENCE_X_REG (0x1C) ++#define LSM9DS0_REFERENCE_Y_REG (0x1D) ++#define LSM9DS0_REFERENCE_Z_REG (0x1E) ++#define LSM9DS0_CTRL_REG0_XM_REG (0x1F) ++#define LSM9DS0_CTRL_REG1_XM_REG (0x20) ++#define LSM9DS0_CTRL_REG2_XM_REG (0x21) ++#define LSM9DS0_CTRL_REG3_XM_REG (0x22) ++#define LSM9DS0_CTRL_REG4_XM_REG (0x23) ++#define LSM9DS0_CTRL_REG5_XM_REG (0x24) ++#define LSM9DS0_CTRL_REG6_XM_REG (0x25) ++#define LSM9DS0_CTRL_REG7_XM_REG (0x26) ++#define LSM9DS0_STATUS_REG_A_REG (0x27) ++#define LSM9DS0_OUT_X_L_A_REG (0x28) ++#define LSM9DS0_OUT_X_H_A_REG (0x29) ++#define LSM9DS0_OUT_Y_L_A_REG (0x2A) ++#define LSM9DS0_OUT_Y_H_A_REG (0x2B) ++#define LSM9DS0_OUT_Z_L_A_REG (0x2C) ++#define LSM9DS0_OUT_Z_H_A_REG (0x2D) ++#define LSM9DS0_FIFO_CTRL_REG_REG (0x2E) ++#define LSM9DS0_FIFO_SRC_REG_REG (0x2F) ++#define LSM9DS0_INT_GEN_1_REG_REG (0x30) ++#define LSM9DS0_INT_GEN_1_SRC_REG (0x31) ++#define LSM9DS0_INT_GEN_1_THS_REG (0x32) ++#define LSM9DS0_INT_GEN_1_DURATION_REG (0x33) ++#define LSM9DS0_INT_GEN_2_REG_REG (0x34) ++#define LSM9DS0_INT_GEN_2_SRC_REG (0x35) ++#define LSM9DS0_INT_GEN_2_THS_REG (0x36) ++#define LSM9DS0_INT_GEN_2_DURATION_REG (0x37) ++#define LSM9DS0_CLICK_CFG_REG (0x38) ++#define LSM9DS0_CLICK_SRC_REG (0x39) ++#define LSM9DS0_CLICK_THS_REG (0x3A) ++#define LSM9DS0_TIME_LIMIT_REG (0x3B) ++#define LSM9DS0_TIME_LATENCY_REG (0x3C) ++#define LSM9DS0_TIME_WINDOW_REG (0x3D) ++#define LSM9DS0_ACT_THS_REG (0x3E) ++#define LSM9DS0_ACT_DUR_REG (0x3F) ++ ++#define LSM9DS0_GYRO_ODR_95HZ_VAL (0x00 << 6) ++#define LSM9DS0_GYRO_ODR_190HZ_VAL (0x01 << 6) ++#define LSM9DS0_GYRO_ODR_380HZ_VAL (0x02 << 6) ++#define LSM9DS0_GYRO_ODR_760HZ_VAL (0x03 << 6) ++ ++#define LSM9DS0_ACCEL_POWER_DOWN (0x00 << 4) ++#define LSM9DS0_ACCEL_ODR_3_125HZ_VAL (0x01 << 4) ++#define LSM9DS0_ACCEL_ODR_6_25HZ_VAL (0x02 << 4) ++#define LSM9DS0_ACCEL_ODR_12_5HZ_VAL (0x03 << 4) ++#define LSM9DS0_ACCEL_ODR_25HZ_VAL (0x04 << 4) ++#define LSM9DS0_ACCEL_ODR_50HZ_VAL (0x05 << 4) ++#define LSM9DS0_ACCEL_ODR_100HZ_VAL (0x06 << 4) ++#define LSM9DS0_ACCEL_ODR_200HZ_VAL (0x07 << 4) ++#define LSM9DS0_ACCEL_ODR_400HZ_VAL (0x08 << 4) ++#define LSM9DS0_ACCEL_ODR_800HZ_VAL (0x09 << 4) ++#define LSM9DS0_ACCEL_ODR_1600HZ_VAL (0x0A << 4) ++ ++#define LSM9DS0_ACCEL_FS_MASK (0x03 << 3) ++#define LSM9DS0_ACCEL_FS_2G_VAL (0x00 << 3) ++#define LSM9DS0_ACCEL_FS_4G_VAL (0x01 << 3) ++#define LSM9DS0_ACCEL_FS_6G_VAL (0x02 << 3) ++#define LSM9DS0_ACCEL_FS_8G_VAL (0x03 << 3) ++#define LSM9DS0_ACCEL_FS_16G_VAL (0x04 << 3) ++#define LSM9DS0_ACCEL_FS_2G_GAIN 61 /* ug/LSB */ ++#define LSM9DS0_ACCEL_FS_4G_GAIN 122 /* ug/LSB */ ++#define LSM9DS0_ACCEL_FS_6G_GAIN 183 /* ug/LSB */ ++#define LSM9DS0_ACCEL_FS_8G_GAIN 244 /* ug/LSB */ ++#define LSM9DS0_ACCEL_FS_16G_GAIN 732 /* ug/LSB */ ++ ++#define LSM9DS0_MAGN_ODR_3_125HZ_VAL (0x00 << 2) ++#define LSM9DS0_MAGN_ODR_6_25HZ_VAL (0x01 << 2) ++#define LSM9DS0_MAGN_ODR_12_5HZ_VAL (0x02 << 2) ++#define LSM9DS0_MAGN_ODR_25HZ_VAL (0x03 << 2) ++#define LSM9DS0_MAGN_ODR_50HZ_VAL (0x04 << 2) ++#define LSM9DS0_MAGN_ODR_100HZ_VAL (0x05 << 2) ++ ++#define LSM9DS0_MAGN_FS_MASK (0x03 << 5) ++#define LSM9DS0_MAGN_FS_2GAUSS_VAL (0x00 << 5) ++#define LSM9DS0_MAGN_FS_4GAUSS_VAL (0x01 << 5) ++#define LSM9DS0_MAGN_FS_8GAUSS_VAL (0x02 << 5) ++#define LSM9DS0_MAGN_FS_12GAUSS_VAL (0x03 << 5) ++#define LSM9DS0_MAGN_FS_2GAUSS_GAIN 80 /* ugauss/LSB */ ++#define LSM9DS0_MAGN_FS_4GAUSS_GAIN 160 /* ugauss/LSB */ ++#define LSM9DS0_MAGN_FS_8GAUSS_GAIN 320 /* ugauss/LSB */ ++#define LSM9DS0_MAGN_FS_12GAUSS_GAIN 480 /* ugauss/LSB */ ++ ++#define LSM9DS0_GYRO_FS_MASK (0x03 << 4) ++#define LSM9DS0_GYRO_FS_245DPS_VAL (0x00 << 4) ++#define LSM9DS0_GYRO_FS_500DPS_VAL (0x01 << 4) ++#define LSM9DS0_GYRO_FS_2000DPS_VAL (0x02 << 4) ++#define LSM9DS0_GYRO_FS_245DPS_GAIN 8750 /* udps/LSB */ ++#define LSM9DS0_GYRO_FS_500DPS_GAIN 17500 /* udps/LSB */ ++#define LSM9DS0_GYRO_FS_2000DPS_GAIN 70000 /* udps/LSB */ ++ ++#define LSM9DS0_GYRO_X_EN BIT(1) ++#define LSM9DS0_GYRO_Y_EN BIT(0) ++#define LSM9DS0_GYRO_Z_EN BIT(2) ++#define LSM9DS0_GYRO_POWER_DOWN (0x00 << 3) ++#define LSM9DS0_GYRO_NORMAL_MODE BIT(3) ++#define LSM9DS0_ACCEL_X_EN BIT(0) ++#define LSM9DS0_ACCEL_Y_EN BIT(1) ++#define LSM9DS0_ACCEL_Z_EN BIT(2) ++#define LSM9DS0_TEMP_EN BIT(7) ++#define LSM9DS0_MAGN_LOW_RES_VAL (0x00 << 5) ++#define LSM9DS0_MAGN_HIGH_RES_VAL (0x03 << 5) ++#define LSM9DS0_MAGN_POWER_DOWN (0x02) ++#define LSM9DS0_MAGN_CONT_CONV_MODE (0x00) ++#define LSM9DS0_MAGN_SINGLE_CONV_MODE (0x01) ++ ++#define LSM9DS0_GYRO_ID 0xD4 ++#define LSM9DS0_ACCEL_MAGN_ID 0x49 ++ ++enum { SCAN_INDEX_X, SCAN_INDEX_Y, SCAN_INDEX_Z }; ++enum { ++ SCAN_INDEX_ACCEL_X, SCAN_INDEX_ACCEL_Y, SCAN_INDEX_ACCEL_Z, ++ SCAN_INDEX_MAGN_X, SCAN_INDEX_MAGN_Y, SCAN_INDEX_MAGN_Z ++}; ++enum { GYRO, ACCEL_MAGN }; ++ ++struct lsm9ds0_data { ++ struct i2c_client *client; ++ struct mutex lock; ++ int sensor_type; ++ int gyro_scale; ++ int accel_scale; ++ int magn_scale; ++}; ++ ++struct sensor_fs_avl { ++ unsigned int num; ++ u8 value; ++ unsigned int gain; ++}; ++ ++static const struct sensor_fs_avl lsm9ds0_gyro_fs_avl[3] = { ++ {245, LSM9DS0_GYRO_FS_245DPS_VAL, LSM9DS0_GYRO_FS_245DPS_GAIN}, ++ {500, LSM9DS0_GYRO_FS_500DPS_VAL, LSM9DS0_GYRO_FS_500DPS_GAIN}, ++ {2000, LSM9DS0_GYRO_FS_2000DPS_VAL, LSM9DS0_GYRO_FS_2000DPS_GAIN}, ++}; ++ ++static const struct sensor_fs_avl lsm9ds0_accel_fs_avl[5] = { ++ {2, LSM9DS0_ACCEL_FS_2G_VAL, LSM9DS0_ACCEL_FS_2G_GAIN}, ++ {4, LSM9DS0_ACCEL_FS_4G_VAL, LSM9DS0_ACCEL_FS_4G_GAIN}, ++ {6, LSM9DS0_ACCEL_FS_6G_VAL, LSM9DS0_ACCEL_FS_6G_GAIN}, ++ {8, LSM9DS0_ACCEL_FS_8G_VAL, LSM9DS0_ACCEL_FS_8G_GAIN}, ++ {16, LSM9DS0_ACCEL_FS_16G_VAL, LSM9DS0_ACCEL_FS_16G_GAIN}, ++}; ++ ++static const struct sensor_fs_avl lsm9ds0_magn_fs_avl[4] = { ++ {2, LSM9DS0_MAGN_FS_2GAUSS_VAL, LSM9DS0_MAGN_FS_2GAUSS_GAIN}, ++ {4, LSM9DS0_MAGN_FS_4GAUSS_VAL, LSM9DS0_MAGN_FS_4GAUSS_GAIN}, ++ {8, LSM9DS0_MAGN_FS_8GAUSS_VAL, LSM9DS0_MAGN_FS_8GAUSS_GAIN}, ++ {12, LSM9DS0_MAGN_FS_12GAUSS_VAL, LSM9DS0_MAGN_FS_12GAUSS_GAIN}, ++}; ++ ++static ssize_t lsm9ds0_show_scale_avail(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ //struct iio_dev *indio_dev = dev_to_iio_dev(dev); ++ //struct lsm9ds0_data *data = iio_priv(indio_dev); ++ size_t len = 0; ++ int n; ++ const struct sensor_fs_avl (*avl)[]; ++ ++ if (strcmp(attr->attr.name, "in_gyro_scale_available") == 0) { ++ avl = &lsm9ds0_gyro_fs_avl; ++ n = ARRAY_SIZE(lsm9ds0_gyro_fs_avl); ++ } else if (strcmp(attr->attr.name, "in_accel_scale_available") == 0) { ++ avl = &lsm9ds0_accel_fs_avl; ++ n = ARRAY_SIZE(lsm9ds0_accel_fs_avl); ++ } else if (strcmp(attr->attr.name, "in_magn_scale_available") == 0) { ++ avl = &lsm9ds0_magn_fs_avl; ++ n = ARRAY_SIZE(lsm9ds0_magn_fs_avl); ++ } else { ++ return -EINVAL; ++ } ++ ++ while (n-- > 0) ++ len += scnprintf(buf + len, PAGE_SIZE - len, ++ "0.%06u ", (*avl)[n].gain); ++ buf[len - 1] = '\n'; ++ ++ return len; ++} ++ ++static IIO_DEVICE_ATTR(in_accel_scale_available, S_IRUGO, ++ lsm9ds0_show_scale_avail, NULL, 0); ++static IIO_DEVICE_ATTR(in_magn_scale_available, S_IRUGO, ++ lsm9ds0_show_scale_avail, NULL, 0); ++static IIO_DEVICE_ATTR(in_gyro_scale_available, S_IRUGO, ++ lsm9ds0_show_scale_avail, NULL, 0); ++ ++static struct attribute *lsm9ds0_gyro_attributes[] = { ++ &iio_dev_attr_in_gyro_scale_available.dev_attr.attr, ++ NULL ++}; ++ ++static struct attribute *lsm9ds0_accel_magn_attributes[] = { ++ &iio_dev_attr_in_accel_scale_available.dev_attr.attr, ++ &iio_dev_attr_in_magn_scale_available.dev_attr.attr, ++ NULL ++}; ++ ++static const struct attribute_group lsm9ds0_gyro_group = { ++ .attrs = lsm9ds0_gyro_attributes, ++}; ++ ++static const struct attribute_group lsm9ds0_accel_magn_group = { ++ .attrs = lsm9ds0_accel_magn_attributes, ++}; ++ ++static const struct iio_buffer_setup_ops lsm9ds0_buffer_setup_ops = { ++ .postenable = &iio_triggered_buffer_postenable, ++ .predisable = &iio_triggered_buffer_predisable, ++}; ++ ++static const struct iio_chan_spec lsm9ds0_gyro_channels[] = { ++ { ++ .type = IIO_ANGL_VEL, ++ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), ++ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), ++ .modified = 1, ++ .channel2 = IIO_MOD_X, ++ .scan_index = SCAN_INDEX_X, ++ .scan_type = { ++ .sign = 's', ++ .realbits = 16, ++ .storagebits = 16, ++ .shift = 0, ++ .endianness = IIO_LE, ++ }, ++ }, { ++ .type = IIO_ANGL_VEL, ++ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), ++ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), ++ .modified = 1, ++ .channel2 = IIO_MOD_Y, ++ .scan_index = SCAN_INDEX_Y, ++ .scan_type = { ++ .sign = 's', ++ .realbits = 16, ++ .storagebits = 16, ++ .shift = 0, ++ .endianness = IIO_LE, ++ }, ++ }, { ++ .type = IIO_ANGL_VEL, ++ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), ++ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), ++ .modified = 1, ++ .channel2 = IIO_MOD_Z, ++ .scan_index = SCAN_INDEX_Z, ++ .scan_type = { ++ .sign = 's', ++ .realbits = 16, ++ .storagebits = 16, ++ .shift = 0, ++ .endianness = IIO_LE, ++ }, ++ }, ++ IIO_CHAN_SOFT_TIMESTAMP(3), ++}; ++ ++static const struct iio_chan_spec lsm9ds0_accel_magn_channels[] = { ++ { ++ .type = IIO_ACCEL, ++ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), ++ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), ++ .modified = 1, ++ .channel2 = IIO_MOD_X, ++ .scan_index = SCAN_INDEX_ACCEL_X, ++ .scan_type = { ++ .sign = 's', ++ .realbits = 16, ++ .storagebits = 16, ++ .shift = 0, ++ .endianness = IIO_LE, ++ }, ++ }, { ++ .type = IIO_ACCEL, ++ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), ++ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), ++ .modified = 1, ++ .channel2 = IIO_MOD_Y, ++ .scan_index = SCAN_INDEX_ACCEL_Y, ++ .scan_type = { ++ .sign = 's', ++ .realbits = 16, ++ .storagebits = 16, ++ .shift = 0, ++ .endianness = IIO_LE, ++ }, ++ }, { ++ .type = IIO_ACCEL, ++ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), ++ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), ++ .modified = 1, ++ .channel2 = IIO_MOD_Z, ++ .scan_index = SCAN_INDEX_ACCEL_Z, ++ .scan_type = { ++ .sign = 's', ++ .realbits = 16, ++ .storagebits = 16, ++ .shift = 0, ++ .endianness = IIO_LE, ++ }, ++ }, { ++ .type = IIO_MAGN, ++ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), ++ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), ++ .modified = 1, ++ .channel2 = IIO_MOD_X, ++ .scan_index = SCAN_INDEX_MAGN_X, ++ .scan_type = { ++ .sign = 's', ++ .realbits = 16, ++ .storagebits = 16, ++ .shift = 0, ++ .endianness = IIO_LE, ++ }, ++ }, { ++ .type = IIO_MAGN, ++ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), ++ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), ++ .modified = 1, ++ .channel2 = IIO_MOD_Y, ++ .scan_index = SCAN_INDEX_MAGN_Y, ++ .scan_type = { ++ .sign = 's', ++ .realbits = 16, ++ .storagebits = 16, ++ .shift = 0, ++ .endianness = IIO_LE, ++ }, ++ }, { ++ .type = IIO_MAGN, ++ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), ++ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), ++ .modified = 1, ++ .channel2 = IIO_MOD_Z, ++ .scan_index = SCAN_INDEX_MAGN_Z, ++ .scan_type = { ++ .sign = 's', ++ .realbits = 16, ++ .storagebits = 16, ++ .shift = 0, ++ .endianness = IIO_LE, ++ }, ++ }, ++ IIO_CHAN_SOFT_TIMESTAMP(6), ++}; ++ ++static int lsm9ds0_read_measurements(struct i2c_client *client, ++ u8 reg_address, s16 *x, s16 *y, s16 *z) ++{ ++ int ret; ++ u8 buf[6] = {0}; ++ ++ buf[0] = 0x80 | reg_address; ++ ret = i2c_master_send(client, buf, 1); ++ if (ret < 0) ++ return ret; ++ ++ ret = i2c_master_recv(client, buf, 6); ++ if (ret < 0) ++ return ret; ++ ++ *x = (buf[1] << 8) | buf[0]; ++ *y = (buf[3] << 8) | buf[2]; ++ *z = (buf[5] << 8) | buf[4]; ++ return ret; ++} ++ ++static int lsm9ds0_read_raw(struct iio_dev *iio_dev, ++ struct iio_chan_spec const *channel, ++ int *val, int *val2, long mask) ++{ ++ struct lsm9ds0_data *data = iio_priv(iio_dev); ++ int err = 0; ++ s16 x = 0, y = 0, z = 0; ++ int scale = 0; ++ ++ switch (mask) { ++ case IIO_CHAN_INFO_RAW: ++ mutex_lock(&data->lock); ++ switch (channel->type) { ++ case IIO_ANGL_VEL: ++ err = lsm9ds0_read_measurements(data->client, ++ LSM9DS0_OUT_X_L_G_REG, &x, &y, &z); ++ scale = data->gyro_scale; ++ break; ++ case IIO_ACCEL: ++ err = lsm9ds0_read_measurements(data->client, ++ LSM9DS0_OUT_X_L_A_REG, &x, &y, &z); ++ scale = data->accel_scale; ++ break; ++ case IIO_MAGN: ++ err = lsm9ds0_read_measurements(data->client, ++ LSM9DS0_OUT_X_L_M_REG, &x, &y, &z); ++ scale = data->magn_scale; ++ break; ++ default: ++ return -EINVAL; ++ } ++ mutex_unlock(&data->lock); ++ if (err < 0) ++ goto read_error; ++ ++ switch (channel->channel2) { ++ case IIO_MOD_X: ++ *val = x; ++ break; ++ case IIO_MOD_Y: ++ *val = y; ++ break; ++ case IIO_MOD_Z: ++ *val = z; ++ break; ++ } ++ return IIO_VAL_INT; ++ case IIO_CHAN_INFO_SCALE: ++ *val = 0; ++ switch (channel->type) { ++ case IIO_ANGL_VEL: ++ *val2 = data->gyro_scale; ++ break; ++ case IIO_ACCEL: ++ *val2 = data->accel_scale; ++ break; ++ case IIO_MAGN: ++ *val2 = data->magn_scale; ++ break; ++ default: ++ return -EINVAL; ++ } ++ return IIO_VAL_INT_PLUS_MICRO; ++ default: ++ return -EINVAL; ++ } ++ ++read_error: ++ return err; ++} ++ ++static int lsm9ds0_write_config(struct i2c_client *client, ++ u8 reg_address, u8 mask, u8 value) ++{ ++ u8 reg; ++ s32 ret; ++ ret = i2c_smbus_read_byte_data(client, reg_address); ++ if (ret < 0) ++ return -EINVAL; ++ ++ reg = (u8)ret; ++ reg &= ~mask; ++ reg |= value; ++ ++ ret = i2c_smbus_write_byte_data(client, reg_address, reg); ++ ++ return ret; ++} ++ ++static int lsm9ds0_write_raw(struct iio_dev *indio_dev, ++ struct iio_chan_spec const *channel, ++ int val, int val2, long mask) ++{ ++ struct lsm9ds0_data *data = iio_priv(indio_dev); ++ struct i2c_client *client = data->client; ++ const struct sensor_fs_avl (*avl)[]; ++ int n, i, ret; ++ u8 reg_address, reg_mask, new_value; ++ int *scale_in_data; ++ ++ mutex_lock(&data->lock); ++ switch (mask) { ++ case IIO_CHAN_INFO_SCALE: ++ dev_info(&client->dev, "Vals %d %d\n", val, val2); ++ switch (channel->type) { ++ case IIO_ANGL_VEL: ++ avl = &lsm9ds0_gyro_fs_avl; ++ n = ARRAY_SIZE(lsm9ds0_gyro_fs_avl); ++ reg_address = LSM9DS0_CTRL_REG4_G_REG; ++ reg_mask = LSM9DS0_GYRO_FS_MASK; ++ scale_in_data = &(data->gyro_scale); ++ break; ++ case IIO_ACCEL: ++ avl = &lsm9ds0_accel_fs_avl; ++ n = ARRAY_SIZE(lsm9ds0_accel_fs_avl); ++ reg_address = LSM9DS0_CTRL_REG2_XM_REG; ++ reg_mask = LSM9DS0_ACCEL_FS_MASK; ++ scale_in_data = &(data->accel_scale); ++ break; ++ case IIO_MAGN: ++ avl = &lsm9ds0_magn_fs_avl; ++ n = ARRAY_SIZE(lsm9ds0_magn_fs_avl); ++ reg_address = LSM9DS0_CTRL_REG6_XM_REG; ++ reg_mask = LSM9DS0_MAGN_FS_MASK; ++ scale_in_data = &(data->magn_scale); ++ break; ++ default: ++ ret = -EINVAL; ++ goto done; ++ } ++ ret = -EINVAL; ++ for (i = 0; i < n; i++) { ++ if ((*avl)[i].gain == val2) { ++ ret = 0; ++ new_value = (*avl)[i].value; ++ break; ++ } ++ } ++ if (ret < 0) ++ goto done; ++ ++ ret = lsm9ds0_write_config(client, reg_address, reg_mask, new_value); ++ if (ret < 0) ++ goto done; ++ ++ *scale_in_data = (*avl)[i].gain; ++ break; ++ default: ++ ret = -EINVAL; ++ } ++ ++done: ++ mutex_unlock(&data->lock); ++ return ret; ++} ++ ++static irqreturn_t lsm9ds0_trigger_h(int irq, void *p) ++{ ++ struct iio_poll_func *pf = p; ++ struct iio_dev *indio_dev = pf->indio_dev; ++ struct lsm9ds0_data *data = iio_priv(indio_dev); ++ u32 *buf_data; ++ int i, j; ++ s16 x1, y1, z1, x2, y2, z2; ++ int err; ++ ++ buf_data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); ++ if (!buf_data) ++ goto done; ++ ++ mutex_lock(&data->lock); ++ if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)) { ++ ++ if (data->sensor_type == GYRO) { ++ err = lsm9ds0_read_measurements(data->client, ++ LSM9DS0_OUT_X_L_G_REG, &x1, &y1, &z1); ++ if (err < 0) ++ goto free_buf; ++ } else if (data->sensor_type == ACCEL_MAGN) { ++ err = lsm9ds0_read_measurements(data->client, ++ LSM9DS0_OUT_X_L_A_REG, &x1, &y1, &z1); ++ if (err < 0) ++ goto free_buf; ++ err = lsm9ds0_read_measurements(data->client, ++ LSM9DS0_OUT_X_L_M_REG, &x2, &y2, &z2); ++ if (err < 0) ++ goto free_buf; ++ } else ++ goto free_buf; ++ ++ for (i = 0, j = 0; ++ i < bitmap_weight(indio_dev->active_scan_mask, indio_dev->masklength); ++ i++, j++) { ++ j = find_next_bit(indio_dev->active_scan_mask, indio_dev->masklength, j); ++ ++ if (data->sensor_type == GYRO) { ++ switch (j) { ++ case SCAN_INDEX_X: ++ buf_data[i] = x1; ++ break; ++ case SCAN_INDEX_Y: ++ buf_data[i] = y1; ++ break; ++ case SCAN_INDEX_Z: ++ buf_data[i] = z1; ++ break; ++ default: ++ break; ++ } ++ } else { ++ switch (j) { ++ case SCAN_INDEX_ACCEL_X: ++ buf_data[i] = x1; ++ break; ++ case SCAN_INDEX_ACCEL_Y: ++ buf_data[i] = y1; ++ break; ++ case SCAN_INDEX_ACCEL_Z: ++ buf_data[i] = z1; ++ break; ++ case SCAN_INDEX_MAGN_X: ++ buf_data[i] = x2; ++ break; ++ case SCAN_INDEX_MAGN_Y: ++ buf_data[i] = y2; ++ break; ++ case SCAN_INDEX_MAGN_Z: ++ buf_data[i] = z2; ++ break; ++ default: ++ break; ++ } ++ } ++ } ++ } ++ ++ iio_push_to_buffers_with_timestamp(indio_dev, buf_data, iio_get_time_ns(indio_dev)); ++ ++free_buf: ++ kfree(buf_data); ++ mutex_unlock(&data->lock); ++ ++done: ++ iio_trigger_notify_done(indio_dev->trig); ++ ++ return IRQ_HANDLED; ++} ++ ++static const struct iio_info lsm9ds0_gyro_info = { ++ .attrs = &lsm9ds0_gyro_group, ++ .read_raw = lsm9ds0_read_raw, ++ .write_raw = lsm9ds0_write_raw, ++ .driver_module = THIS_MODULE, ++}; ++ ++static const struct iio_info lsm9ds0_accel_magn_info = { ++ .attrs = &lsm9ds0_accel_magn_group, ++ .read_raw = lsm9ds0_read_raw, ++ .write_raw = lsm9ds0_write_raw, ++ .driver_module = THIS_MODULE, ++}; ++ ++static int lsm9ds0_gyro_init(struct i2c_client *client) ++{ ++ int ret; ++ struct iio_dev *indio_dev; ++ struct lsm9ds0_data *data; ++ ++ ret = i2c_smbus_write_byte_data(client, LSM9DS0_CTRL_REG1_G_REG, ++ LSM9DS0_GYRO_NORMAL_MODE | LSM9DS0_GYRO_X_EN | ++ LSM9DS0_GYRO_Y_EN | LSM9DS0_GYRO_Z_EN); ++ if (ret < 0) { ++ dev_err(&client->dev, "Failed to write control register 5.\n"); ++ return ret; ++ } ++ ret = i2c_smbus_write_byte_data(client, LSM9DS0_CTRL_REG4_G_REG, ++ LSM9DS0_GYRO_FS_245DPS_VAL); ++ if (ret < 0) { ++ dev_err(&client->dev, "Failed to write control register 4.\n"); ++ return ret; ++ } ++ ++ indio_dev = i2c_get_clientdata(client); ++ data = iio_priv(indio_dev); ++ ++ data->gyro_scale = LSM9DS0_GYRO_FS_245DPS_GAIN; ++ ++ return 0; ++} ++ ++static int lsm9ds0_accel_magn_init(struct i2c_client *client) ++{ ++ int ret; ++ struct iio_dev *indio_dev; ++ struct lsm9ds0_data *data; ++ ++ ret = i2c_smbus_write_byte_data(client, LSM9DS0_CTRL_REG1_XM_REG, ++ LSM9DS0_ACCEL_ODR_100HZ_VAL | LSM9DS0_ACCEL_X_EN | ++ LSM9DS0_ACCEL_Y_EN | LSM9DS0_ACCEL_Z_EN); ++ if (ret < 0) { ++ dev_err(&client->dev, "Failed to write control register 1.\n"); ++ return ret; ++ } ++ ret = i2c_smbus_write_byte_data(client, LSM9DS0_CTRL_REG5_XM_REG, ++ LSM9DS0_TEMP_EN | LSM9DS0_MAGN_HIGH_RES_VAL | LSM9DS0_MAGN_ODR_50HZ_VAL); ++ if (ret < 0) { ++ dev_err(&client->dev, "Failed to write control register 5.\n"); ++ return ret; ++ } ++ ret = i2c_smbus_write_byte_data(client, LSM9DS0_CTRL_REG7_XM_REG, ++ LSM9DS0_MAGN_CONT_CONV_MODE); ++ if (ret < 0) { ++ dev_err(&client->dev, "Failed to write control register 7.\n"); ++ return ret; ++ } ++ ret = i2c_smbus_write_byte_data(client, LSM9DS0_CTRL_REG2_XM_REG, ++ LSM9DS0_ACCEL_FS_2G_VAL); ++ if (ret < 0) { ++ dev_err(&client->dev, "Failed to write control register 2.\n"); ++ return ret; ++ } ++ ret = i2c_smbus_write_byte_data(client, LSM9DS0_CTRL_REG6_XM_REG, ++ LSM9DS0_MAGN_FS_2GAUSS_VAL); ++ if (ret < 0) { ++ dev_err(&client->dev, "Failed to write control register 6.\n"); ++ return ret; ++ } ++ ++ indio_dev = i2c_get_clientdata(client); ++ data = iio_priv(indio_dev); ++ ++ data->accel_scale = LSM9DS0_ACCEL_FS_2G_GAIN; ++ data->magn_scale = LSM9DS0_MAGN_FS_2GAUSS_GAIN; ++ ++ return 0; ++} ++ ++static int lsm9ds0_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct iio_dev *indio_dev; ++ struct lsm9ds0_data *data; ++ struct iio_buffer *buffer; ++ int sensor_type; ++ int ret; ++ ++ ++ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA)) { ++ ret = -ENODEV; ++ goto error_ret; ++ } ++ ++ ret = i2c_smbus_read_byte_data(client, LSM9DS0_WHO_AM_I_REG); ++ if (ret < 0) { ++ ret = -EINVAL; ++ goto error_ret; ++ } ++ if (ret == LSM9DS0_GYRO_ID) { ++ dev_info(&client->dev, "Gyroscope found.\n"); ++ sensor_type = GYRO; ++ } else if (ret == LSM9DS0_ACCEL_MAGN_ID) { ++ dev_info(&client->dev, "Accelerometer and magnetometer found.\n"); ++ sensor_type = ACCEL_MAGN; ++ } else { ++ dev_err(&client->dev, "No LSM9DS0 sensor found.\n"); ++ ret = -ENODEV; ++ goto error_ret; ++ } ++ ++ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); ++ if (!indio_dev) { ++ ret = -ENOMEM; ++ goto error_ret; ++ } ++ ++ data = iio_priv(indio_dev); ++ mutex_init(&data->lock); ++ i2c_set_clientdata(client, indio_dev); ++ data->client = client; ++ data->sensor_type = sensor_type; ++ ++ indio_dev->dev.parent = &client->dev; ++ indio_dev->name = dev_name(&client->dev); ++ indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_TRIGGERED; ++ ++ ++ if (sensor_type == GYRO) { ++ ret = lsm9ds0_gyro_init(client); ++ indio_dev->info = &lsm9ds0_gyro_info; ++ indio_dev->channels = lsm9ds0_gyro_channels; ++ indio_dev->num_channels = ARRAY_SIZE(lsm9ds0_gyro_channels); ++ } else { ++ ret = lsm9ds0_accel_magn_init(client); ++ indio_dev->info = &lsm9ds0_accel_magn_info; ++ indio_dev->channels = lsm9ds0_accel_magn_channels; ++ indio_dev->num_channels = ARRAY_SIZE(lsm9ds0_accel_magn_channels); ++ } ++ if (ret < 0) ++ goto error_free_device; ++ ++ buffer = iio_kfifo_allocate(); ++ if (!buffer) { ++ ret = -ENOMEM; ++ goto error_free_device; ++ } ++ iio_device_attach_buffer(indio_dev, buffer); ++ buffer->scan_timestamp = true; ++ indio_dev->setup_ops = &lsm9ds0_buffer_setup_ops; ++ indio_dev->pollfunc = iio_alloc_pollfunc(NULL, ++ &lsm9ds0_trigger_h, ++ IRQF_ONESHOT, ++ indio_dev, ++ "lsm9ds0_consumer%d", ++ indio_dev->id); ++ if (!indio_dev->pollfunc) { ++ ret = -ENOMEM; ++ goto error_free_buffer; ++ } ++ ++ ret = iio_device_register(indio_dev); ++ if (ret < 0) ++ goto error_unconfigure_buffer; ++ ++ return 0; ++ ++error_unconfigure_buffer: ++ iio_dealloc_pollfunc(indio_dev->pollfunc); ++error_free_buffer: ++ iio_kfifo_free(indio_dev->buffer); ++error_free_device: ++ iio_device_free(indio_dev); ++error_ret: ++ return ret; ++} ++ ++static int lsm9ds0_remove(struct i2c_client *client) ++{ ++ struct iio_dev *indio_dev = i2c_get_clientdata(client); ++ iio_device_unregister(indio_dev); ++ iio_device_free(indio_dev); ++ dev_info(&client->dev, "Driver removed."); ++ return 0; ++} ++ ++static const struct i2c_device_id lsm9ds0_id[] = { ++ { "lsm9ds0_gyro", 0 }, ++ { "lsm9ds0_accel_magn", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, lsm9ds0_id); ++ ++static struct i2c_driver lsm9ds0_driver = { ++ .driver = { ++ .name = "lsm9ds0", ++ .owner = THIS_MODULE, ++ }, ++ .probe = lsm9ds0_probe, ++ .remove = lsm9ds0_remove, ++ .id_table = lsm9ds0_id, ++}; ++module_i2c_driver(lsm9ds0_driver); ++ ++MODULE_AUTHOR("Matija Podravec <matija_podravec@fastmail.fm>"); ++MODULE_DESCRIPTION("LSM9DS0 gyroscope, accelerometer, and magnetometer sensor"); ++MODULE_LICENSE("GPL"); +-- +2.13.0 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0063-ASoC-PCM3168A-add-TDM-modes-merge-ADC-and-DAC.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0063-ASoC-PCM3168A-add-TDM-modes-merge-ADC-and-DAC.patch new file mode 100644 index 0000000..46d5d84 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0063-ASoC-PCM3168A-add-TDM-modes-merge-ADC-and-DAC.patch @@ -0,0 +1,479 @@ +From 963d9e84748bc43a8dbcd28019bd8ff0942b5934 Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +Date: Wed, 13 Apr 2016 15:32:38 +0300 +Subject: [PATCH] ASoC: PCM3168A: add TDM modes, merge ADC and DAC + +Also disable 16 bit format and enable at start + +Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +--- + sound/soc/codecs/pcm3168a.c | 320 ++++++++++++++++++++++++++++---------------- + sound/soc/codecs/pcm3168a.h | 2 +- + 2 files changed, 205 insertions(+), 117 deletions(-) + +diff --git a/sound/soc/codecs/pcm3168a.c b/sound/soc/codecs/pcm3168a.c +index 992a77edcd5d..8b9e4ff6b354 100644 +--- a/sound/soc/codecs/pcm3168a.c ++++ b/sound/soc/codecs/pcm3168a.c +@@ -22,7 +22,7 @@ + + #include "pcm3168a.h" + +-#define PCM3168A_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ ++#define PCM3168A_FORMATS (/*SNDRV_PCM_FMTBIT_S16_LE | */\ + SNDRV_PCM_FMTBIT_S24_3LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S32_LE) +@@ -33,7 +33,11 @@ + #define PCM3168A_FMT_RIGHT_J_16 0x3 + #define PCM3168A_FMT_DSP_A 0x4 + #define PCM3168A_FMT_DSP_B 0x5 +-#define PCM3168A_FMT_DSP_MASK 0x4 ++#define PCM3168A_FMT_I2S_TDM 0x6 ++#define PCM3168A_FMT_LEFT_J_TDM 0x7 ++/* High speed */ ++#define PCM3168A_FMT_I2S_TDMHS 0x8 ++#define PCM3168A_FMT_LEFT_J_TDMHS 0x9 + + #define PCM3168A_NUM_SUPPLIES 6 + static const char *const pcm3168a_supply_names[PCM3168A_NUM_SUPPLIES] = { +@@ -45,12 +49,18 @@ static const char *const pcm3168a_supply_names[PCM3168A_NUM_SUPPLIES] = { + "VCCDA2" + }; + ++#define TDM_MODE_NONE 0 ++#define TDM_MODE_NORM 1 ++#define TDM_MODE_HS 2 ++ + struct pcm3168a_priv { + struct regulator_bulk_data supplies[PCM3168A_NUM_SUPPLIES]; + struct regmap *regmap; + struct clk *scki; +- bool adc_master_mode; +- bool dac_master_mode; ++ bool master_mode; ++ unsigned int tdm; ++ unsigned int slots; ++ unsigned int slot_width; + unsigned long sysclk; + unsigned int adc_fmt; + unsigned int dac_fmt; +@@ -313,32 +323,43 @@ static int pcm3168a_set_dai_sysclk(struct snd_soc_dai *dai, + return 0; + } + +-static int pcm3168a_set_dai_fmt(struct snd_soc_dai *dai, ++int format_table[3][6] = { ++ [TDM_MODE_NONE] = { ++ [0] = -1, ++ [SND_SOC_DAIFMT_I2S] = PCM3168A_FMT_I2S, ++ [SND_SOC_DAIFMT_LEFT_J] = PCM3168A_FMT_LEFT_J, ++ [SND_SOC_DAIFMT_RIGHT_J] = PCM3168A_FMT_RIGHT_J, ++ [SND_SOC_DAIFMT_DSP_A] = PCM3168A_FMT_DSP_A, ++ [SND_SOC_DAIFMT_DSP_B] = PCM3168A_FMT_DSP_B}, ++ [TDM_MODE_NORM] = { ++ [0] = -1, ++ [SND_SOC_DAIFMT_I2S] = PCM3168A_FMT_I2S_TDM, ++ [SND_SOC_DAIFMT_LEFT_J] = PCM3168A_FMT_LEFT_J_TDM, ++ [SND_SOC_DAIFMT_RIGHT_J] = -1, ++ [SND_SOC_DAIFMT_DSP_A] = -1, ++ [SND_SOC_DAIFMT_DSP_B] = -1}, ++ [TDM_MODE_HS] = { ++ [0] = -1, ++ [SND_SOC_DAIFMT_I2S] = PCM3168A_FMT_I2S_TDMHS, ++ [SND_SOC_DAIFMT_LEFT_J] = PCM3168A_FMT_LEFT_J_TDMHS, ++ [SND_SOC_DAIFMT_RIGHT_J] = -1, ++ [SND_SOC_DAIFMT_DSP_A] = -1, ++ [SND_SOC_DAIFMT_DSP_B] = -1}, ++}; ++ ++static int __pcm3168a_set_dai_fmt(struct snd_soc_dai *dai, + unsigned int format, bool dac) + { + struct snd_soc_codec *codec = dai->codec; + struct pcm3168a_priv *pcm3168a = snd_soc_codec_get_drvdata(codec); +- u32 fmt, reg, mask, shift; ++ u32 reg, mask, shift; ++ int fmt; + bool master_mode; + +- switch (format & SND_SOC_DAIFMT_FORMAT_MASK) { +- case SND_SOC_DAIFMT_LEFT_J: +- fmt = PCM3168A_FMT_LEFT_J; +- break; +- case SND_SOC_DAIFMT_I2S: +- fmt = PCM3168A_FMT_I2S; +- break; +- case SND_SOC_DAIFMT_RIGHT_J: +- fmt = PCM3168A_FMT_RIGHT_J; +- break; +- case SND_SOC_DAIFMT_DSP_A: +- fmt = PCM3168A_FMT_DSP_A; +- break; +- case SND_SOC_DAIFMT_DSP_B: +- fmt = PCM3168A_FMT_DSP_B; +- break; +- default: +- dev_err(codec->dev, "unsupported dai format\n"); ++ fmt = format_table[pcm3168a->tdm][format & SND_SOC_DAIFMT_FORMAT_MASK]; ++ ++ if (fmt < 0) { ++ dev_err(codec->dev, "unsupported dai format of TDM mode\n"); + return -EINVAL; + } + +@@ -354,6 +375,16 @@ static int pcm3168a_set_dai_fmt(struct snd_soc_dai *dai, + return -EINVAL; + } + ++ if ((pcm3168a->tdm == TDM_MODE_HS) && (master_mode)) { ++ dev_err(codec->dev, "TDM high speed supported only in slave mode\n"); ++ return -EINVAL; ++ } ++ ++ if ((pcm3168a->tdm == TDM_MODE_HS) && (!dac)) { ++ dev_err(codec->dev, "TDM high speed not supported for ADC\n"); ++ return -EINVAL; ++ } ++ + switch (format & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; +@@ -365,31 +396,32 @@ static int pcm3168a_set_dai_fmt(struct snd_soc_dai *dai, + reg = PCM3168A_DAC_PWR_MST_FMT; + mask = PCM3168A_DAC_FMT_MASK; + shift = PCM3168A_DAC_FMT_SHIFT; +- pcm3168a->dac_master_mode = master_mode; + pcm3168a->dac_fmt = fmt; + } else { + reg = PCM3168A_ADC_MST_FMT; + mask = PCM3168A_ADC_FMTAD_MASK; + shift = PCM3168A_ADC_FMTAD_SHIFT; +- pcm3168a->adc_master_mode = master_mode; + pcm3168a->adc_fmt = fmt; + } + ++ pcm3168a->master_mode = master_mode; ++ + regmap_update_bits(pcm3168a->regmap, reg, mask, fmt << shift); + + return 0; + } + +-static int pcm3168a_set_dai_fmt_dac(struct snd_soc_dai *dai, ++static int pcm3168a_set_dai_fmt(struct snd_soc_dai *dai, + unsigned int format) + { +- return pcm3168a_set_dai_fmt(dai, format, true); +-} ++ int ret; + +-static int pcm3168a_set_dai_fmt_adc(struct snd_soc_dai *dai, +- unsigned int format) +-{ +- return pcm3168a_set_dai_fmt(dai, format, false); ++ /* dac */ ++ ret = __pcm3168a_set_dai_fmt(dai, format, false); ++ if (ret) ++ return ret; ++ /* adc */ ++ return __pcm3168a_set_dai_fmt(dai, format, true); + } + + static int pcm3168a_hw_params(struct snd_pcm_substream *substream, +@@ -398,127 +430,170 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream, + { + struct snd_soc_codec *codec = dai->codec; + struct pcm3168a_priv *pcm3168a = snd_soc_codec_get_drvdata(codec); +- bool tx, master_mode; ++ int bits; ++ bool tx; + u32 val, mask, shift, reg; +- unsigned int rate, fmt, ratio, max_ratio; ++ u32 sample_rate = 0; /* auto */ ++ unsigned int rate, channels, fmt, ratio, max_ratio; + int i, min_frame_size; + snd_pcm_format_t format; + + rate = params_rate(params); + format = params_format(params); +- +- ratio = pcm3168a->sysclk / rate; ++ channels = params_channels(params); ++ bits = params->msbits; + + tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; ++ + if (tx) { + max_ratio = PCM3168A_NUM_SCKI_RATIOS_DAC; +- reg = PCM3168A_DAC_PWR_MST_FMT; +- mask = PCM3168A_DAC_MSDA_MASK; +- shift = PCM3168A_DAC_MSDA_SHIFT; +- master_mode = pcm3168a->dac_master_mode; + fmt = pcm3168a->dac_fmt; + } else { + max_ratio = PCM3168A_NUM_SCKI_RATIOS_ADC; +- reg = PCM3168A_ADC_MST_FMT; +- mask = PCM3168A_ADC_MSAD_MASK; +- shift = PCM3168A_ADC_MSAD_SHIFT; +- master_mode = pcm3168a->adc_master_mode; + fmt = pcm3168a->adc_fmt; + } + +- for (i = 0; i < max_ratio; i++) { +- if (pcm3168a_scki_ratios[i] == ratio) +- break; +- } +- +- if (i == max_ratio) { +- dev_err(codec->dev, "unsupported sysclk ratio\n"); +- return -EINVAL; +- } ++ if (pcm3168a->master_mode) { ++ ratio = pcm3168a->sysclk / rate; ++ for (i = 0; i < max_ratio; i++) ++ if (pcm3168a_scki_ratios[i] == ratio) ++ break; + +- min_frame_size = params_width(params) * 2; +- switch (min_frame_size) { +- case 32: +- if (master_mode || (fmt != PCM3168A_FMT_RIGHT_J)) { +- dev_err(codec->dev, "32-bit frames are supported only for slave mode using right justified\n"); ++ if (i == max_ratio) { ++ dev_err(codec->dev, "unsupported sysclk ratio: %d\n", ratio); + return -EINVAL; + } +- fmt = PCM3168A_FMT_RIGHT_J_16; +- break; +- case 48: +- if (master_mode || (fmt & PCM3168A_FMT_DSP_MASK)) { +- dev_err(codec->dev, "48-bit frames not supported in master mode, or slave mode using DSP\n"); +- return -EINVAL; +- } +- break; +- case 64: +- break; +- default: +- dev_err(codec->dev, "unsupported frame size: %d\n", min_frame_size); +- return -EINVAL; ++ val = i + 1; ++ } else { ++ /* slave mode */ ++ val = 0; + } + +- if (master_mode) +- val = ((i + 1) << shift); +- else ++ if (pcm3168a->tdm == TDM_MODE_NONE) { ++ /* one stereo frame size */ ++ min_frame_size = bits * 2; ++ switch (min_frame_size) { ++ case 32: ++ if (pcm3168a->master_mode || ++ (fmt != PCM3168A_FMT_RIGHT_J)) { ++ dev_err(codec->dev, "32-bit frames are supported only for slave mode using right justified\n"); ++ return -EINVAL; ++ } ++ fmt = PCM3168A_FMT_RIGHT_J_16; ++ break; ++ case 48: ++ if (pcm3168a->master_mode || ++ (fmt == PCM3168A_FMT_DSP_A) || ++ (fmt == PCM3168A_FMT_DSP_B)) { ++ dev_err(codec->dev, "48-bit frames not supported in master mode, or slave mode using DSP\n"); ++ return -EINVAL; ++ } ++ break; ++ case 64: ++ break; ++ default: ++ dev_err(codec->dev, "unsupported frame size: %d\n", min_frame_size); ++ return -EINVAL; ++ } ++ } ++ if ((pcm3168a->tdm == TDM_MODE_NORM) || ++ (pcm3168a->tdm == TDM_MODE_HS)) { ++ /* all channels over one or two line */ ++ min_frame_size = bits * channels; ++ ++ /* single rate */ ++ sample_rate = 1; ++ ++ /* ++ * 256fs for single line DIN0/DOUT0 ++ * 128fs for two lines DIN01/DOU01 ++ */ ++ if ((min_frame_size != 256) && ++ (min_frame_size != 128)) { ++ dev_err(codec->dev, "256/128-bit frames only supported in TDM formats\n"); ++ return -EINVAL; ++ } ++ } ++ ++ /* Setup ADC in master mode, couse it drives ADC */ ++ if ((pcm3168a->master_mode) || (tx)) { ++ fmt = pcm3168a->dac_fmt; ++ reg = PCM3168A_DAC_PWR_MST_FMT; ++ mask = PCM3168A_DAC_MSDA_MASK | PCM3168A_DAC_FMT_MASK; ++ shift = PCM3168A_DAC_MSDA_SHIFT; ++ /* start DAC */ ++ regmap_update_bits(pcm3168a->regmap, reg, mask, (val << shift) | fmt); ++ } ++ /* Do we need also ADC? */ ++ if (!tx) { ++ fmt = pcm3168a->adc_fmt; ++ reg = PCM3168A_ADC_MST_FMT; ++ mask = PCM3168A_ADC_MSAD_MASK | PCM3168A_ADC_FMTAD_MASK; ++ shift = PCM3168A_ADC_MSAD_SHIFT; ++ /* ADC slave mode only, driven by DAC or CPU DAI */ + val = 0; ++ regmap_update_bits(pcm3168a->regmap, reg, mask, (val << shift) | fmt); ++ } + +- regmap_update_bits(pcm3168a->regmap, reg, mask, val); ++ regmap_update_bits(pcm3168a->regmap, PCM3168A_RST_SMODE, ++ PCM3168A_DAC_SRDA_MASK, ++ sample_rate << PCM3168A_DAC_SRDA_SHIFT); + +- if (tx) { +- mask = PCM3168A_DAC_FMT_MASK; +- shift = PCM3168A_DAC_FMT_SHIFT; +- } else { +- mask = PCM3168A_ADC_FMTAD_MASK; +- shift = PCM3168A_ADC_FMTAD_SHIFT; +- } ++ return 0; ++} + +- regmap_update_bits(pcm3168a->regmap, reg, mask, fmt << shift); ++static int pcm3168a_set_tdm_slot(struct snd_soc_dai *dai, ++ unsigned int tx_mask, ++ unsigned int rx_mask, ++ int slots, ++ int slot_width) ++{ ++ struct snd_soc_codec *codec = dai->codec; ++ struct pcm3168a_priv *pcm3168a = snd_soc_codec_get_drvdata(codec); ++ ++ if ((slots != 8) && (slots != 4)) ++ return -EINVAL; ++ ++ if ((slot_width != 32) && (slot_width != 24)) ++ return -EINVAL; ++ ++ pcm3168a->slots = slots; ++ pcm3168a->slot_width = slot_width; + + return 0; + } + +-static const struct snd_soc_dai_ops pcm3168a_dac_dai_ops = { +- .set_fmt = pcm3168a_set_dai_fmt_dac, ++static const struct snd_soc_dai_ops pcm3168a_dai_ops = { ++ .set_fmt = pcm3168a_set_dai_fmt, + .set_sysclk = pcm3168a_set_dai_sysclk, ++ .set_tdm_slot = pcm3168a_set_tdm_slot, + .hw_params = pcm3168a_hw_params, + .digital_mute = pcm3168a_digital_mute + }; + +-static const struct snd_soc_dai_ops pcm3168a_adc_dai_ops = { +- .set_fmt = pcm3168a_set_dai_fmt_adc, +- .set_sysclk = pcm3168a_set_dai_sysclk, +- .hw_params = pcm3168a_hw_params +-}; +- +-static struct snd_soc_dai_driver pcm3168a_dais[] = { +- { +- .name = "pcm3168a-dac", +- .playback = { +- .stream_name = "Playback", +- .channels_min = 1, +- .channels_max = 8, +- .rates = SNDRV_PCM_RATE_8000_192000, +- .formats = PCM3168A_FORMATS +- }, +- .ops = &pcm3168a_dac_dai_ops ++static struct snd_soc_dai_driver pcm3168a_dai = { ++ .name = "pcm3168a", ++ .playback = { ++ .stream_name = "Playback", ++ .channels_min = 1, ++ .channels_max = 8, ++ .rates = SNDRV_PCM_RATE_8000_192000, ++ .formats = PCM3168A_FORMATS + }, +- { +- .name = "pcm3168a-adc", +- .capture = { +- .stream_name = "Capture", +- .channels_min = 1, +- .channels_max = 6, +- .rates = SNDRV_PCM_RATE_8000_96000, +- .formats = PCM3168A_FORMATS +- }, +- .ops = &pcm3168a_adc_dai_ops ++ .capture = { ++ .stream_name = "Capture", ++ .channels_min = 1, ++ .channels_max = 8, ++ .rates = SNDRV_PCM_RATE_8000_96000, ++ .formats = PCM3168A_FORMATS + }, ++ .ops = &pcm3168a_dai_ops, ++ .symmetric_rates = 1, + }; + + static const struct reg_default pcm3168a_reg_default[] = { + { PCM3168A_RST_SMODE, PCM3168A_MRST_MASK | PCM3168A_SRST_MASK }, +- { PCM3168A_DAC_PWR_MST_FMT, 0x00 }, ++ { PCM3168A_DAC_PWR_MST_FMT, 0x80 }, + { PCM3168A_DAC_OP_FLT, 0x00 }, + { PCM3168A_DAC_INV, 0x00 }, + { PCM3168A_DAC_MUTE, 0x00 }, +@@ -665,12 +740,25 @@ int pcm3168a_probe(struct device *dev, struct regmap *regmap) + goto err_regulator; + } + ++ /* get TDM mode */ ++ if (dev->of_node) { ++ if (of_get_property(dev->of_node, "tdm", NULL)) ++ pcm3168a->tdm = TDM_MODE_NORM; ++ else if (of_get_property(dev->of_node, "tdmhs", NULL)) ++ pcm3168a->tdm = TDM_MODE_HS; ++ } ++ + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + pm_runtime_idle(dev); + +- ret = snd_soc_register_codec(dev, &pcm3168a_driver, pcm3168a_dais, +- ARRAY_SIZE(pcm3168a_dais)); ++ if (pcm3168a->tdm != TDM_MODE_NONE) { ++ pcm3168a_dai.playback.channels_min = 8; ++ pcm3168a_dai.capture.channels_min = 8; ++ } ++ ++ ret = snd_soc_register_codec(dev, &pcm3168a_driver, ++ &pcm3168a_dai, 1); + if (ret) { + dev_err(dev, "failed to register codec: %d\n", ret); + goto err_regulator; +diff --git a/sound/soc/codecs/pcm3168a.h b/sound/soc/codecs/pcm3168a.h +index 56c8332d82fb..658507f86c97 100644 +--- a/sound/soc/codecs/pcm3168a.h ++++ b/sound/soc/codecs/pcm3168a.h +@@ -69,7 +69,7 @@ extern void pcm3168a_remove(struct device *dev); + #define PCM3168A_ADC_MSAD_SHIFT 4 + #define PCM3168A_ADC_MSAD_MASK 0x70 + #define PCM3168A_ADC_FMTAD_SHIFT 0 +-#define PCM3168A_ADC_FMTAD_MASK 0x7 ++#define PCM3168A_ADC_FMTAD_MASK 0xf + + #define PCM3168A_ADC_PWR_HPFB 0x52 + #define PCM3168A_ADC_PSVAD_SHIFT 4 +-- +2.13.0 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0064-ADV7511-limit-maximum-pixelclock.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0064-ADV7511-limit-maximum-pixelclock.patch new file mode 100644 index 0000000..3ca9284 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0064-ADV7511-limit-maximum-pixelclock.patch @@ -0,0 +1,76 @@ +From 1df040dabaec1697f81b71f15739b499f3e4266e Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +Date: Fri, 9 Jun 2017 20:12:26 +0300 +Subject: [PATCH] ADV7511: limit maximum pixelclock + +DU0 (RGB) supports clock freq up to 100MHz only. +Add ability to set max clock via dts. + +Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +--- + drivers/gpu/drm/bridge/adv7511/adv7511.h | 3 +++ + drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 6 +++++- + 2 files changed, 8 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511.h b/drivers/gpu/drm/bridge/adv7511/adv7511.h +index 161c923..12ee238 100644 +--- a/drivers/gpu/drm/bridge/adv7511/adv7511.h ++++ b/drivers/gpu/drm/bridge/adv7511/adv7511.h +@@ -242,6 +242,7 @@ enum adv7511_sync_polarity { + * @input_style: The input component arrangement variant + * @input_justification: Video input format bit justification + * @clock_delay: Clock delay for the input clock (in ps) ++ * @clock_max_rate: Clock maximum rate (in Hz) + * @embedded_sync: Video input uses BT.656-style embedded sync + * @sync_pulse: Select the sync pulse + * @vsync_polarity: vsync input signal configuration +@@ -255,6 +256,7 @@ struct adv7511_link_config { + enum adv7511_input_justification input_justification; + + int clock_delay; ++ int clock_max_rate; + + bool embedded_sync; + enum adv7511_input_sync_pulse sync_pulse; +@@ -307,6 +309,7 @@ struct adv7511 { + bool powered; + + struct drm_display_mode curr_mode; ++ int clock_max_rate; + + unsigned int f_tmds; + +diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +index 41b45de..5dfa619 100644 +--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c ++++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +@@ -323,6 +323,7 @@ static void adv7511_set_link_config(struct adv7511 *adv7511, + adv7511->hsync_polarity = config->hsync_polarity; + adv7511->vsync_polarity = config->vsync_polarity; + adv7511->rgb = config->input_colorspace == HDMI_COLORSPACE_RGB; ++ adv7511->clock_max_rate = config->clock_max_rate; + } + + static void adv7511_power_on(struct adv7511 *adv7511) +@@ -621,7 +622,7 @@ static int adv7511_get_modes(struct adv7511 *adv7511, + static int adv7511_mode_valid(struct adv7511 *adv7511, + struct drm_display_mode *mode) + { +- if (mode->clock > 165000) ++ if (mode->clock > adv7511->clock_max_rate) + return MODE_CLOCK_HIGH; + + return MODE_OK; +@@ -917,6 +918,9 @@ static int adv7511_parse_dt(struct device_node *np, + if (config->clock_delay < -1200 || config->clock_delay > 1600) + return -EINVAL; + ++ if (of_property_read_u32(np, "adi,clock-max-rate", &config->clock_max_rate)) ++ config->clock_max_rate = 166000; ++ + config->embedded_sync = of_property_read_bool(np, "adi,embedded-sync"); + + /* Hardcode the sync pulse configurations for now. */ +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0066-pci-pcie-rcar-add-regulators-support.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0066-pci-pcie-rcar-add-regulators-support.patch new file mode 100644 index 0000000..2a9a2a0 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0066-pci-pcie-rcar-add-regulators-support.patch @@ -0,0 +1,107 @@ +From d5a3dee65f4ee9d320128bbf79df80d51aec7687 Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +Date: Mon, 24 Jul 2017 20:22:03 +0300 +Subject: [PATCH] pci: pcie-rcar: add regulators support + +Add PCIE regulators + +Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +--- + drivers/pci/host/pcie-rcar.c | 54 ++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 54 insertions(+) + +diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c +index 8e24d5f88415..6994ea2ac936 100644 +--- a/drivers/pci/host/pcie-rcar.c ++++ b/drivers/pci/host/pcie-rcar.c +@@ -16,6 +16,7 @@ + + #include <linux/clk.h> + #include <linux/delay.h> ++#include <linux/regulator/consumer.h> + #include <linux/interrupt.h> + #include <linux/irq.h> + #include <linux/irqdomain.h> +@@ -155,6 +156,8 @@ struct rcar_pcie { + int root_bus_nr; + struct clk *clk; + struct clk *bus_clk; ++ struct regulator *pcie3v3; /* 3.3V power supply */ ++ struct regulator *pcie1v8; /* 1.8V power supply */ + struct rcar_msi msi; + }; + +@@ -1193,6 +1196,36 @@ static int rcar_pcie_parse_request_of_pci_ranges(struct rcar_pcie *pci) + return err; + } + ++static int rcar_pcie_set_vpcie(struct rcar_pcie *pcie) ++{ ++ struct device *dev = pcie->dev; ++ int err; ++ ++ if (!IS_ERR(pcie->pcie3v3)) { ++ err = regulator_enable(pcie->pcie3v3); ++ if (err) { ++ dev_err(dev, "fail to enable vpcie3v3 regulator\n"); ++ goto err_out; ++ } ++ } ++ ++ if (!IS_ERR(pcie->pcie1v8)) { ++ err = regulator_enable(pcie->pcie1v8); ++ if (err) { ++ dev_err(dev, "fail to enable vpcie1v8 regulator\n"); ++ goto err_disable_3v3; ++ } ++ } ++ ++ return 0; ++ ++err_disable_3v3: ++ if (!IS_ERR(pcie->pcie3v3)) ++ regulator_disable(pcie->pcie3v3); ++err_out: ++ return err; ++} ++ + static int rcar_pcie_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +@@ -1209,6 +1242,26 @@ static int rcar_pcie_probe(struct platform_device *pdev) + pcie->dev = dev; + platform_set_drvdata(pdev, pcie); + ++ pcie->pcie3v3 = devm_regulator_get_optional(dev, "pcie3v3"); ++ if (IS_ERR(pcie->pcie3v3)) { ++ if (PTR_ERR(pcie->pcie3v3) == -EPROBE_DEFER) ++ return -EPROBE_DEFER; ++ dev_info(dev, "no pcie3v3 regulator found\n"); ++ } ++ ++ pcie->pcie1v8 = devm_regulator_get_optional(dev, "pcie1v8"); ++ if (IS_ERR(pcie->pcie1v8)) { ++ if (PTR_ERR(pcie->pcie1v8) == -EPROBE_DEFER) ++ return -EPROBE_DEFER; ++ dev_info(dev, "no pcie1v8 regulator found\n"); ++ } ++ ++ err = rcar_pcie_set_vpcie(pcie); ++ if (err) { ++ dev_err(dev, "failed to set pcie regulators\n"); ++ goto err_set_pcie; ++ } ++ + INIT_LIST_HEAD(&pcie->resources); + + rcar_pcie_parse_request_of_pci_ranges(pcie); +@@ -1267,6 +1320,7 @@ static int rcar_pcie_probe(struct platform_device *pdev) + + err_pm_disable: + pm_runtime_disable(dev); ++err_set_pcie: + return err; + } + +-- +2.13.0 diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0067-ti-st-use-proper-way-to-get-shutdown-gpio.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0067-ti-st-use-proper-way-to-get-shutdown-gpio.patch new file mode 100644 index 0000000..4d99054 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0067-ti-st-use-proper-way-to-get-shutdown-gpio.patch @@ -0,0 +1,61 @@ +From 36a9b5317c58a1cdcb8a6fa05416efd524480fbe Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +Date: Wed, 2 Aug 2017 17:39:56 +0300 +Subject: [PATCH] ti-st: use proper way to get shutdown gpio + +Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +--- + drivers/misc/ti-st/st_kim.c | 23 ++++++++++++++++++----- + 1 file changed, 18 insertions(+), 5 deletions(-) + +diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c +index cb2734568471..03b21d314b0b 100644 +--- a/drivers/misc/ti-st/st_kim.c ++++ b/drivers/misc/ti-st/st_kim.c +@@ -32,6 +32,8 @@ + #include <linux/sched.h> + #include <linux/sysfs.h> + #include <linux/tty.h> ++#include <linux/of_device.h> ++#include <linux/of_gpio.h> + + #include <linux/skbuff.h> + #include <linux/ti_wilink_st.h> +@@ -749,18 +751,29 @@ static struct ti_st_plat_data *get_platform_data(struct device *dev) + + dt_pdata = kzalloc(sizeof(*dt_pdata), GFP_KERNEL); + +- if (!dt_pdata) ++ if (!dt_pdata) { + pr_err("Can't allocate device_tree platform data\n"); ++ return NULL; ++ } + + 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); ++ if (!dt_property) { ++ dev_err(dev, "failed to get tty name\n"); ++ goto err; ++ } ++ memcpy(&dt_pdata->dev_name, dt_property, len); ++ dt_pdata->nshutdown_gpio = of_get_named_gpio(np, "shutdown-gpios", 0); ++ if (!gpio_is_valid(dt_pdata->nshutdown_gpio)) { ++ dev_err(dev, "failed to get shutdown gpio\n"); ++ goto err; ++ } + 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; ++err: ++ kfree(dt_pdata); ++ return NULL; + } + + static struct dentry *kim_debugfs_dir; +-- +2.13.0 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0068-drm-adv7511-use-smbus-to-retrieve-edid.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0068-drm-adv7511-use-smbus-to-retrieve-edid.patch new file mode 100644 index 0000000..1b4dbd8 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0068-drm-adv7511-use-smbus-to-retrieve-edid.patch @@ -0,0 +1,53 @@ +From 2e2b673a2a47e8358ef92ec4019be87552949304 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Wed, 9 Aug 2017 11:52:22 +0300 +Subject: [PATCH] drm: adv7511: use smbus to retrieve edid + +Get EDID using smbus protocol instead block i2c transfer +This fixes often checksum errors while retriving EDID at 400kHz bus speed + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +index d3ece87..b2e1b58 100644 +--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c ++++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +@@ -500,18 +500,19 @@ static int adv7511_get_edid_block(void *data, u8 *buf, unsigned int block, + * support 64 byte transfers than 256 byte transfers + */ + ++#define CHUNK_SIZE 1 + xfer[0].addr = adv7511->i2c_edid->addr; + xfer[0].flags = 0; + xfer[0].len = 1; + xfer[0].buf = &offset; + xfer[1].addr = adv7511->i2c_edid->addr; + xfer[1].flags = I2C_M_RD; +- xfer[1].len = 64; ++ xfer[1].len = CHUNK_SIZE; + xfer[1].buf = adv7511->edid_buf; + + offset = 0; + +- for (i = 0; i < 4; ++i) { ++ for (i = 0; i < 256/CHUNK_SIZE; ++i) { + ret = i2c_transfer(adv7511->i2c_edid->adapter, xfer, + ARRAY_SIZE(xfer)); + if (ret < 0) +@@ -519,8 +520,8 @@ static int adv7511_get_edid_block(void *data, u8 *buf, unsigned int block, + else if (ret != 2) + return -EIO; + +- xfer[1].buf += 64; +- offset += 64; ++ xfer[1].buf += CHUNK_SIZE; ++ offset += CHUNK_SIZE; + } + + adv7511->current_edid_segment = block / 2; +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0070-clk-clk-5p49x-add-5P49V5925-chip.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0070-clk-clk-5p49x-add-5P49V5925-chip.patch new file mode 100644 index 0000000..0608eca --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0070-clk-clk-5p49x-add-5P49V5925-chip.patch @@ -0,0 +1,49 @@ +From d9e198a198e8892ac7e1e2636f55207757ee505a Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Thu, 10 Aug 2017 08:46:54 +0300 +Subject: [PATCH] clk: clk-5p49x: add 5P49V5925 chip + +Add 5P49V5925 chip + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + drivers/clk/clk-5p49x.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/drivers/clk/clk-5p49x.c b/drivers/clk/clk-5p49x.c +index 928bacb..8070154 100644 +--- a/drivers/clk/clk-5p49x.c ++++ b/drivers/clk/clk-5p49x.c +@@ -60,6 +60,10 @@ struct clk_5p49_priv { + .xtal_fre = 25000000, + }; + ++static const struct clk_5p49_info clk_5p49v5925 = { ++ .xtal_fre = 25000000, ++}; ++ + static const struct clk_5p49_info clk_5p49v6901a = { + .xtal_fre = 50000000, + }; +@@ -70,6 +74,10 @@ struct clk_5p49_priv { + .data = &clk_5p49v5923a, + }, + { ++ .compatible = "idt,5p49v5925", ++ .data = &clk_5p49v5925, ++ }, ++ { + .compatible = "idt,5p49v6901a", + .data = &clk_5p49v6901a, + }, +@@ -79,6 +87,7 @@ struct clk_5p49_priv { + + static const struct i2c_device_id clk_5p49_id[] = { + { "5p49v5923a",}, ++ { "5p49v5925",}, + { "5p49v6901a",}, + {} + }; +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0071-ASoC-add-dummy-device-for-WL18xx-PCM-audio.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0071-ASoC-add-dummy-device-for-WL18xx-PCM-audio.patch new file mode 100644 index 0000000..30aebe0 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0071-ASoC-add-dummy-device-for-WL18xx-PCM-audio.patch @@ -0,0 +1,128 @@ +From 81ddd8a5dbf200938ef70efaa9254742f49d3034 Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +Date: Thu, 10 Aug 2017 16:29:01 +0300 +Subject: [PATCH] ASoC: add dummy device for WL18xx PCM audio + +Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +--- + sound/soc/codecs/Kconfig | 3 ++ + sound/soc/codecs/Makefile | 2 ++ + sound/soc/codecs/wl18xx.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 77 insertions(+) + create mode 100644 sound/soc/codecs/wl18xx.c + +diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig +index 140f1597966a..6658d05f1648 100644 +--- a/sound/soc/codecs/Kconfig ++++ b/sound/soc/codecs/Kconfig +@@ -625,6 +625,9 @@ config SND_SOC_PCM3168A_SPI + config SND_SOC_SI468X + tristate "Dummy sound driver for Si468x radio" + ++config SND_SOC_WL18XX ++ tristate "Dummy sound driver for WL18xx BT" ++ + config SND_SOC_PCM5102A + tristate + +diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile +index 8e02341428d8..17fd313489de 100644 +--- a/sound/soc/codecs/Makefile ++++ b/sound/soc/codecs/Makefile +@@ -126,6 +126,7 @@ 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-wl18xx-objs := wl18xx.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 +@@ -349,6 +350,7 @@ 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_WL18XX) += snd-soc-wl18xx.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/wl18xx.c b/sound/soc/codecs/wl18xx.c +new file mode 100644 +index 000000000000..50ebbd4c0013 +--- /dev/null ++++ b/sound/soc/codecs/wl18xx.c +@@ -0,0 +1,72 @@ ++/* ++ * Dummy sound driver for wl18xx BT modules ++ * 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 wl18xx_dai = { ++ .name = "wl18xx-pcm", ++ .capture = { ++ .channels_min = 2, ++ .channels_max = 2, ++ .rates = SNDRV_PCM_RATE_48000, ++ .formats = SNDRV_PCM_FMTBIT_S16_LE, ++ }, ++ .playback = { ++ .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_wl18xx; ++ ++static int wl18xx_probe(struct platform_device *pdev) ++{ ++ return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wl18xx, ++ &wl18xx_dai, 1); ++} ++ ++static int wl18xx_remove(struct platform_device *pdev) ++{ ++ snd_soc_unregister_codec(&pdev->dev); ++ ++ return 0; ++} ++ ++static const struct of_device_id wl18xx_of_match[] = { ++ { .compatible = "ti,wl18xx-pcm", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, wl18xx_of_match); ++ ++static struct platform_driver wl18xx_driver = { ++ .driver = { ++ .name = "wl18xx-codec", ++ .of_match_table = wl18xx_of_match, ++ .owner = THIS_MODULE, ++ }, ++ .probe = wl18xx_probe, ++ .remove = wl18xx_remove, ++}; ++ ++module_platform_driver(wl18xx_driver); ++ ++MODULE_AUTHOR("Andrey Gusakov <andrey.gusakov@cogentembedded.com>"); ++MODULE_DESCRIPTION("ASoC wl18xx driver"); ++MODULE_LICENSE("GPL"); +-- +2.13.0 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0072-usb-hub-disable-autosuspend-for-SMSC-hubs.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0072-usb-hub-disable-autosuspend-for-SMSC-hubs.patch new file mode 100644 index 0000000..4989e05 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0072-usb-hub-disable-autosuspend-for-SMSC-hubs.patch @@ -0,0 +1,51 @@ +From 8276db72581e4d1e3f89ccce84555c9fea145e16 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Fri, 11 Aug 2017 17:30:40 +0300 +Subject: [PATCH] usb: hub: disable autosuspend for SMSC hubs + +Disable autosuspend for SMSC hubs (USB5534B/USB2134B devices) +This is a workaround for RCar Gen3 XHCI + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + drivers/usb/core/hub.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c +index cbb1467..2c4c006 100644 +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -34,7 +34,9 @@ + #include "otg_whitelist.h" + + #define USB_VENDOR_GENESYS_LOGIC 0x05e3 ++#define USB_VENDOR_SMSC 0x0424 + #define HUB_QUIRK_CHECK_PORT_AUTOSUSPEND 0x01 ++#define HUB_QUIRK_DISABLE_AUTOSUSPEND 0x02 + + /* Protect struct usb_device->state and ->children members + * Note: Both are also protected by ->dev.sem, except that ->state can +@@ -1845,6 +1847,9 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) + if (id->driver_info & HUB_QUIRK_CHECK_PORT_AUTOSUSPEND) + hub->quirk_check_port_auto_suspend = 1; + ++ if (id->driver_info & HUB_QUIRK_DISABLE_AUTOSUSPEND) ++ pm_runtime_set_autosuspend_delay(&hdev->dev, -1); ++ + if (hub_configure(hub, endpoint) >= 0) + return 0; + +@@ -5226,6 +5231,10 @@ static void hub_event(struct work_struct *work) + } + + static const struct usb_device_id hub_id_table[] = { ++ { .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_CLASS, ++ .idVendor = USB_VENDOR_SMSC, ++ .bInterfaceClass = USB_CLASS_HUB, ++ .driver_info = HUB_QUIRK_DISABLE_AUTOSUSPEND}, + { .match_flags = USB_DEVICE_ID_MATCH_VENDOR + | USB_DEVICE_ID_MATCH_INT_CLASS, + .idVendor = USB_VENDOR_GENESYS_LOGIC, +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0073-MOST-dim2-add-device-tree-support.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0073-MOST-dim2-add-device-tree-support.patch new file mode 100644 index 0000000..b3e2e0b --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0073-MOST-dim2-add-device-tree-support.patch @@ -0,0 +1,169 @@ +From cc64770782e6bb01b2d8b76c1731a28d5d06d135 Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +Date: Fri, 7 Jul 2017 20:42:36 +0300 +Subject: [PATCH] MOST: dim2: add device tree support + +Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +--- + drivers/staging/most/hdm-dim2/dim2_hdm.c | 72 ++++++++++++++++++++++---------- + 1 file changed, 50 insertions(+), 22 deletions(-) + +diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.c b/drivers/staging/most/hdm-dim2/dim2_hdm.c +index a36449551513..f28f169180fe 100644 +--- a/drivers/staging/most/hdm-dim2/dim2_hdm.c ++++ b/drivers/staging/most/hdm-dim2/dim2_hdm.c +@@ -14,6 +14,7 @@ + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #include <linux/module.h> ++#include <linux/of_platform.h> + #include <linux/printk.h> + #include <linux/kernel.h> + #include <linux/init.h> +@@ -21,6 +22,7 @@ + #include <linux/interrupt.h> + #include <linux/slab.h> + #include <linux/io.h> ++#include <linux/clk.h> + #include <linux/dma-mapping.h> + #include <linux/sched.h> + #include <linux/kthread.h> +@@ -101,6 +103,7 @@ struct dim2_hdm { + struct most_interface most_iface; + char name[16 + sizeof "dim2-"]; + void __iomem *io_base; ++ struct clk *clk; + int clk_speed; + struct task_struct *netinfo_task; + wait_queue_head_t netinfo_waitq; +@@ -165,6 +168,27 @@ void dimcb_on_error(u8 error_id, const char *error_message) + error_message); + } + ++static int dim_parce_speed(const char *clock_speed) ++{ ++ if (!strcmp(clock_speed, "256fs")) ++ return CLK_256FS; ++ else if (!strcmp(clock_speed, "512fs")) ++ return CLK_512FS; ++ else if (!strcmp(clock_speed, "1024fs")) ++ return CLK_1024FS; ++ else if (!strcmp(clock_speed, "2048fs")) ++ return CLK_2048FS; ++ else if (!strcmp(clock_speed, "3072fs")) ++ return CLK_3072FS; ++ else if (!strcmp(clock_speed, "4096fs")) ++ return CLK_4096FS; ++ else if (!strcmp(clock_speed, "6144fs")) ++ return CLK_6144FS; ++ else if (!strcmp(clock_speed, "8192fs")) ++ return CLK_8192FS; ++ return -1; ++} ++ + /** + * startup_dim - initialize the dim2 interface + * @pdev: platform device +@@ -178,32 +202,12 @@ static int startup_dim(struct platform_device *pdev) + struct dim2_platform_data *pdata = pdev->dev.platform_data; + u8 hal_ret; + +- dev->clk_speed = -1; +- +- if (clock_speed) { +- if (!strcmp(clock_speed, "256fs")) +- dev->clk_speed = CLK_256FS; +- else if (!strcmp(clock_speed, "512fs")) +- dev->clk_speed = CLK_512FS; +- else if (!strcmp(clock_speed, "1024fs")) +- dev->clk_speed = CLK_1024FS; +- else if (!strcmp(clock_speed, "2048fs")) +- dev->clk_speed = CLK_2048FS; +- else if (!strcmp(clock_speed, "3072fs")) +- dev->clk_speed = CLK_3072FS; +- else if (!strcmp(clock_speed, "4096fs")) +- dev->clk_speed = CLK_4096FS; +- else if (!strcmp(clock_speed, "6144fs")) +- dev->clk_speed = CLK_6144FS; +- else if (!strcmp(clock_speed, "8192fs")) +- dev->clk_speed = CLK_8192FS; +- } ++ if (clock_speed) ++ dev->clk_speed = dim_parce_speed(clock_speed); + + if (dev->clk_speed == -1) { + pr_info("Bad or missing clock speed parameter, using default value: 3072fs\n"); + dev->clk_speed = CLK_3072FS; +- } else { +- pr_info("Selected clock speed: %s\n", clock_speed); + } + if (pdata && pdata->init) { + int ret = pdata->init(pdata, dev->io_base, dev->clk_speed); +@@ -735,6 +739,7 @@ static int dim2_probe(struct platform_device *pdev) + int ret, i; + struct kobject *kobj; + int irq; ++ struct device_node *np = pdev->dev.of_node; + + dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); + if (!dev) +@@ -765,6 +770,14 @@ static int dim2_probe(struct platform_device *pdev) + dev_err(&pdev->dev, "failed to request mlb_int irq %d\n", irq); + return ret; + } ++ ++ dev->clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(dev->clk)) { ++ dev_err(&pdev->dev, "cannot get clock\n"); ++ ret = PTR_ERR(dev->clk); ++ return ret; ++ } ++ clk_prepare_enable(dev->clk); + + init_waitqueue_head(&dev->netinfo_waitq); + dev->deliver_netinfo = 0; +@@ -814,6 +827,12 @@ static int dim2_probe(struct platform_device *pdev) + dev->most_iface.poison_channel = poison_channel; + dev->most_iface.request_netinfo = request_netinfo; + ++ if (np) { ++ const char *tmp; ++ if (!of_property_read_string(np, "clock-speed", &tmp)) ++ dev->clk_speed = dim_parce_speed(tmp); ++ } ++ + kobj = most_register_interface(&dev->most_iface); + if (IS_ERR(kobj)) { + ret = PTR_ERR(kobj); +@@ -866,6 +885,8 @@ static int dim2_remove(struct platform_device *pdev) + most_deregister_interface(&dev->most_iface); + kthread_stop(dev->netinfo_task); + ++ clk_disable_unprepare(dev->clk); ++ + /* + * break link to local platform_device_id struct + * to prevent crash by unload platform device module +@@ -882,12 +903,19 @@ static struct platform_device_id dim2_id[] = { + + MODULE_DEVICE_TABLE(platform, dim2_id); + ++static const struct of_device_id dim2_of_match[] = { ++ { .compatible = "rcar,medialb-dim2", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, dim2_of_match); ++ + static struct platform_driver dim2_driver = { + .probe = dim2_probe, + .remove = dim2_remove, + .id_table = dim2_id, + .driver = { + .name = "hdm_dim2", ++ .of_match_table = dim2_of_match, + }, + }; + +-- +2.13.0 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0074-MOST-dim2-add-R-Car3-related-initialization.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0074-MOST-dim2-add-R-Car3-related-initialization.patch new file mode 100644 index 0000000..572da2a --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0074-MOST-dim2-add-R-Car3-related-initialization.patch @@ -0,0 +1,63 @@ +From 41d15fa6003b65080f05d271bf495104013754f9 Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +Date: Fri, 7 Jul 2017 20:43:33 +0300 +Subject: [PATCH 112/114] MOST: dim2: add R-Car3 related initialization + +Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +--- + drivers/staging/most/hdm-dim2/dim2_hdm.c | 28 +++++++++++++++++++++++++++- + 1 file changed, 27 insertions(+), 1 deletion(-) + +diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.c b/drivers/staging/most/hdm-dim2/dim2_hdm.c +index f28f169180fe..c1beabc28fa8 100644 +--- a/drivers/staging/most/hdm-dim2/dim2_hdm.c ++++ b/drivers/staging/most/hdm-dim2/dim2_hdm.c +@@ -26,6 +26,7 @@ + #include <linux/dma-mapping.h> + #include <linux/sched.h> + #include <linux/kthread.h> ++#include <linux/delay.h> + + #include <mostcore.h> + #include <networking.h> +@@ -189,6 +191,26 @@ static int dim_parce_speed(const char *clock_speed) + return -1; + } + ++static int dim_rcar_init(struct dim2_hdm *dev) ++{ ++ /* PLL */ ++ __raw_writel(0x04, dev->io_base + 0x600); ++ ++ /* 512FS Enable Register */ ++ if (dev->clk_speed == CLK_512FS) ++ __raw_writel(0x01, dev->io_base + 0x604); ++ else ++ __raw_writel(0x00, dev->io_base + 0x604); ++ ++ udelay(200); ++ ++ /* BBCR = 0b11 */ ++ __raw_writel(0x03, dev->io_base + 0x500); ++ __raw_writel(0x0002FF02, dev->io_base + 0x508); ++ ++ return 0; ++} ++ + /** + * startup_dim - initialize the dim2 interface + * @pdev: platform device +@@ -216,6 +238,10 @@ static int startup_dim(struct platform_device *pdev) + return ret; + } + ++ if (1 /* renesas */) { ++ dim_rcar_init(dev); ++ } ++ + pr_info("sync: num of frames per sub-buffer: %u\n", fcnt); + hal_ret = dim_startup(dev->io_base, dev->clk_speed, fcnt); + if (hal_ret != DIM_NO_ERROR) { +-- +2.13.0 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0075-MOST-core-fix-memory-allocation-at-arm64.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0075-MOST-core-fix-memory-allocation-at-arm64.patch new file mode 100644 index 0000000..33a7c3a --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0075-MOST-core-fix-memory-allocation-at-arm64.patch @@ -0,0 +1,54 @@ +From 90bfbf16c895aa53e1d017d4ce7f4f8121e0da3c Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +Date: Fri, 7 Jul 2017 20:45:01 +0300 +Subject: [PATCH 113/114] MOST: core: fix memory allocation at arm64 + +Provide valid dev pointer to dma_alloc_coherent + +Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +--- + drivers/staging/most/hdm-dim2/dim2_hdm.c | 1 + + drivers/staging/most/mostcore/core.c | 2 +- + drivers/staging/most/mostcore/mostcore.h | 1 + + 3 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.c b/drivers/staging/most/hdm-dim2/dim2_hdm.c +index c1beabc28fa8..81edf4f4beb3 100644 +--- a/drivers/staging/most/hdm-dim2/dim2_hdm.c ++++ b/drivers/staging/most/hdm-dim2/dim2_hdm.c +@@ -852,6 +852,7 @@ static int dim2_probe(struct platform_device *pdev) + dev->most_iface.enqueue = enqueue; + dev->most_iface.poison_channel = poison_channel; + dev->most_iface.request_netinfo = request_netinfo; ++ dev->most_iface.dev = &pdev->dev; + + if (np) { + const char *tmp; +diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c +index 7c619feb12d3..ce56d5ca582c 100644 +--- a/drivers/staging/most/mostcore/core.c ++++ b/drivers/staging/most/mostcore/core.c +@@ -1265,7 +1265,7 @@ static int arm_mbo_chain(struct most_c_obj *c, int dir, + mbo->context = c; + mbo->ifp = c->iface; + mbo->hdm_channel_id = c->channel_id; +- mbo->virt_address = dma_alloc_coherent(NULL, ++ mbo->virt_address = dma_alloc_coherent(c->iface->dev, + coherent_buf_size, + &mbo->bus_address, + GFP_KERNEL); +diff --git a/drivers/staging/most/mostcore/mostcore.h b/drivers/staging/most/mostcore/mostcore.h +index 60e018e499ef..334908639067 100644 +--- a/drivers/staging/most/mostcore/mostcore.h ++++ b/drivers/staging/most/mostcore/mostcore.h +@@ -247,6 +247,7 @@ struct most_interface { + struct mbo *mbo); + int (*poison_channel)(struct most_interface *iface, int channel_idx); + void (*request_netinfo)(struct most_interface *iface, int channel_idx); ++ struct device *dev; + void *priv; + }; + +-- +2.13.0 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0076-MOST-dim2-Renesas-R-Car3-variant.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0076-MOST-dim2-Renesas-R-Car3-variant.patch new file mode 100644 index 0000000..5ab496b --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0076-MOST-dim2-Renesas-R-Car3-variant.patch @@ -0,0 +1,120 @@ +From d595053486568b5be30fda582becf9240d171c66 Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +Date: Mon, 25 Sep 2017 7:16:25 +0300 +Subject: [PATCH] MOST: dim2: Renesas R-Car3 variant + +- R-Car H3 has 8 FPSB +- remove not existing registers access + +Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + drivers/staging/most/hdm-dim2/dim2_hal.c | 8 ++++---- + drivers/staging/most/hdm-dim2/dim2_hdm.c | 2 +- + drivers/staging/most/hdm-dim2/dim2_reg.h | 18 +++++++++--------- + 3 files changed, 14 insertions(+), 14 deletions(-) + +diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.c b/drivers/staging/most/hdm-dim2/dim2_hal.c +index 0b9816c..231138c 100644 +--- a/drivers/staging/most/hdm-dim2/dim2_hal.c ++++ b/drivers/staging/most/hdm-dim2/dim2_hal.c +@@ -528,11 +528,11 @@ static void dim2_cleanup(void) + + /* clear status for all dma channels */ + dimcb_io_write(&g.dim2->ACSR0, 0xFFFFFFFF); +- dimcb_io_write(&g.dim2->ACSR1, 0xFFFFFFFF); ++// dimcb_io_write(&g.dim2->ACSR1, 0xFFFFFFFF); + + /* mask interrupts for all channels */ + dimcb_io_write(&g.dim2->ACMR0, 0); +- dimcb_io_write(&g.dim2->ACMR1, 0); ++// dimcb_io_write(&g.dim2->ACMR1, 0); + } + + static void dim2_initialize(bool enable_6pin, u8 mlb_clock) +@@ -548,7 +548,7 @@ static void dim2_initialize(bool enable_6pin, u8 mlb_clock) + + /* activate all HBI channels */ + dimcb_io_write(&g.dim2->HCMR0, 0xFFFFFFFF); +- dimcb_io_write(&g.dim2->HCMR1, 0xFFFFFFFF); ++// dimcb_io_write(&g.dim2->HCMR1, 0xFFFFFFFF); + + /* enable HBI */ + dimcb_io_write(&g.dim2->HCTL, bit_mask(HCTL_EN_BIT)); +@@ -778,7 +778,7 @@ static u8 init_ctrl_async(struct dim_channel *ch, u8 type, u8 is_tx, + void dim_service_mlb_int_irq(void) + { + dimcb_io_write(&g.dim2->MS0, 0); +- dimcb_io_write(&g.dim2->MS1, 0); ++// dimcb_io_write(&g.dim2->MS1, 0); + } + + u16 dim_norm_ctrl_async_buffer_size(u16 buf_size) +diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.c b/drivers/staging/most/hdm-dim2/dim2_hdm.c +index 195efff..84f56c9 100644 +--- a/drivers/staging/most/hdm-dim2/dim2_hdm.c ++++ b/drivers/staging/most/hdm-dim2/dim2_hdm.c +@@ -54,7 +54,7 @@ + * The values 0, 1, 2, 3, 4, 5, 6 represent corresponding number of frames per + * sub-buffer 1, 2, 4, 8, 16, 32, 64. + */ +-static u8 fcnt = 4; /* (1 << fcnt) frames per subbuffer */ ++static u8 fcnt = 3; /* (1 << fcnt) frames per subbuffer */ + module_param(fcnt, byte, 0); + MODULE_PARM_DESC(fcnt, "Num of frames per sub-buffer for sync channels as a power of 2"); + +diff --git a/drivers/staging/most/hdm-dim2/dim2_reg.h b/drivers/staging/most/hdm-dim2/dim2_reg.h +index 01fe499..54e9b6e 100644 +--- a/drivers/staging/most/hdm-dim2/dim2_reg.h ++++ b/drivers/staging/most/hdm-dim2/dim2_reg.h +@@ -20,28 +20,28 @@ + struct dim2_regs { + /* 0x00 */ u32 MLBC0; + /* 0x01 */ u32 rsvd0[1]; +- /* 0x02 */ u32 MLBPC0; ++ /* 0x02 */ u32 MLBPC0; /* no at R-Car3 */ + /* 0x03 */ u32 MS0; + /* 0x04 */ u32 rsvd1[1]; +- /* 0x05 */ u32 MS1; ++ /* 0x05 */ u32 MS1; /* no at R-Car3 */ + /* 0x06 */ u32 rsvd2[2]; + /* 0x08 */ u32 MSS; + /* 0x09 */ u32 MSD; + /* 0x0A */ u32 rsvd3[1]; + /* 0x0B */ u32 MIEN; + /* 0x0C */ u32 rsvd4[1]; +- /* 0x0D */ u32 MLBPC2; +- /* 0x0E */ u32 MLBPC1; ++ /* 0x0D */ u32 MLBPC2; /* no at R-Car3 */ ++ /* 0x0E */ u32 MLBPC1; /* no at R-Car3 */ + /* 0x0F */ u32 MLBC1; + /* 0x10 */ u32 rsvd5[0x10]; + /* 0x20 */ u32 HCTL; + /* 0x21 */ u32 rsvd6[1]; + /* 0x22 */ u32 HCMR0; +- /* 0x23 */ u32 HCMR1; ++ /* 0x23 */ u32 HCMR1; /* no at R-Car3 */ + /* 0x24 */ u32 HCER0; +- /* 0x25 */ u32 HCER1; ++ /* 0x25 */ u32 HCER1; /* no at R-Car3 */ + /* 0x26 */ u32 HCBR0; +- /* 0x27 */ u32 HCBR1; ++ /* 0x27 */ u32 HCBR1; /* no at R-Car3 */ + /* 0x28 */ u32 rsvd7[8]; + /* 0x30 */ u32 MDAT0; + /* 0x31 */ u32 MDAT1; +@@ -57,9 +57,9 @@ struct dim2_regs { + /* 0xF0 */ u32 ACTL; + /* 0xF1 */ u32 rsvd9[3]; + /* 0xF4 */ u32 ACSR0; +- /* 0xF5 */ u32 ACSR1; ++ /* 0xF5 */ u32 ACSR1; /* no at R-Car3 */ + /* 0xF6 */ u32 ACMR0; +- /* 0xF7 */ u32 ACMR1; ++ /* 0xF7 */ u32 ACMR1; /* no at R-Car3 */ + }; + + #define DIM2_MASK(n) (~((~(u32)0) << (n))) +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0077-MOST-dim2-add-timeouts.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0077-MOST-dim2-add-timeouts.patch new file mode 100644 index 0000000..d47c5c6 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0077-MOST-dim2-add-timeouts.patch @@ -0,0 +1,46 @@ +From f02aa2831e169a9f17eebb2784db4c95944ba927 Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +Date: Mon, 25 Sep 2017 07:13:29 +0300 +Subject: [PATCH] MOST: dim2: add timeouts + +Get rid from loop hang if device not functional + +Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + drivers/staging/most/hdm-dim2/dim2_hal.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.c b/drivers/staging/most/hdm-dim2/dim2_hal.c +index 231138c..ee0e307 100644 +--- a/drivers/staging/most/hdm-dim2/dim2_hal.c ++++ b/drivers/staging/most/hdm-dim2/dim2_hal.c +@@ -18,6 +18,7 @@ + #include "dim2_errors.h" + #include "dim2_reg.h" + #include <linux/stddef.h> ++#include <linux/delay.h> + + /* + * Size factor for isochronous DBR buffer. +@@ -148,11 +149,16 @@ static void free_dbr(int offs, int size) + + static void dim2_transfer_madr(u32 val) + { ++ int timeout = 1000; + dimcb_io_write(&g.dim2->MADR, val); + + /* wait for transfer completion */ +- while ((dimcb_io_read(&g.dim2->MCTL) & 1) != 1) ++ while ((dimcb_io_read(&g.dim2->MCTL) & 1) != 1) { ++ if (--timeout == 0) ++ break; ++ udelay(1); + continue; ++ } + + dimcb_io_write(&g.dim2->MCTL, 0); /* clear transfer complete */ + } +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0078-MOST-aim-fix-null-pointer-crash.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0078-MOST-aim-fix-null-pointer-crash.patch new file mode 100644 index 0000000..fd66258 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0078-MOST-aim-fix-null-pointer-crash.patch @@ -0,0 +1,29 @@ +From f3c2f6f40c2b3e43a447c89b523de40ce2211e91 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Fri, 27 Oct 2017 17:34:05 +0300 +Subject: [PATCH] MOST: aim: fix null pointer crash + +The snd_card_new now crashes if first argument NULL + +Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + drivers/staging/most/aim-sound/sound.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/staging/most/aim-sound/sound.c b/drivers/staging/most/aim-sound/sound.c +index e4198e5..a2ccc79 100644 +--- a/drivers/staging/most/aim-sound/sound.c ++++ b/drivers/staging/most/aim-sound/sound.c +@@ -595,7 +595,7 @@ static int audio_probe_channel(struct most_interface *iface, int channel_id, + return ret; + } + +- ret = snd_card_new(NULL, -1, card_name, THIS_MODULE, ++ ret = snd_card_new(iface->dev, -1, card_name, THIS_MODULE, + sizeof(*channel), &card); + if (ret < 0) + return ret; +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0079-Revert-dmaengine-rcar-dmac-use-TCRB-instead-of-TCR-f.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0079-Revert-dmaengine-rcar-dmac-use-TCRB-instead-of-TCR-f.patch new file mode 100644 index 0000000..97409fa --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0079-Revert-dmaengine-rcar-dmac-use-TCRB-instead-of-TCR-f.patch @@ -0,0 +1,29 @@ +From b3026b3a8ddcd9801583aa5e653ef432fbe60bf0 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Mon, 4 Dec 2017 17:49:47 +0300 +Subject: [PATCH] Revert "dmaengine: rcar-dmac: use TCRB instead of TCR for + residue" + +The patch breaks SCIF DMA support + +This reverts commit 936abcc1d0b13ff4a112b153e56c0e60bbdc0f5f. +--- + drivers/dma/sh/rcar-dmac.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c +index 9120ff4..0ae7131 100644 +--- a/drivers/dma/sh/rcar-dmac.c ++++ b/drivers/dma/sh/rcar-dmac.c +@@ -1298,7 +1298,7 @@ static unsigned int rcar_dmac_chan_get_residue(struct rcar_dmac_chan *chan, + } + + /* Add the residue for the current chunk. */ +- residue += rcar_dmac_chan_read(chan, RCAR_DMATCRB) << desc->xfer_shift; ++ residue += rcar_dmac_chan_read(chan, RCAR_DMATCR) << desc->xfer_shift; + + return residue; + } +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0080-dmaengine-rcar-dmac-ensure-CHCR-DE-bit-is-actually-0.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0080-dmaengine-rcar-dmac-ensure-CHCR-DE-bit-is-actually-0.patch new file mode 100644 index 0000000..e1597ea --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0080-dmaengine-rcar-dmac-ensure-CHCR-DE-bit-is-actually-0.patch @@ -0,0 +1,87 @@ +From a8d46a7f5d17ca9cbe9e9c7d1d23dc6ea437e141 Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Fri, 17 Nov 2017 11:00:28 +0900 +Subject: [PATCH 1/2] dmaengine: rcar-dmac: ensure CHCR DE bit is actually 0 + after clearing + +DMAC reads data from source device, and buffered it until transferable +size for sink device. Because of this behavior, DMAC is including +buffered data . + +Now, CHCR DE bit is controlling DMA transfer enable/disable. + +If DE bit was cleared during data transferring, or during buffering, +it will flush buffered data if source device was peripheral device +(The buffered data will be removed if source device was memory). +Because of this behavior, driver should ensure that DE bit is actually +0 after clearing. + +This patch adds new rcar_dmac_chcr_de_barrier() and call it after CHCR +register access. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Tested-by: Hiroyuki Yokoyama <hiroyuki.yokoyama.vx@renesas.com> +Tested-by: Ryo Kodama <ryo.kodama.vz@renesas.com> +Tested-by: Geert Uytterhoeven <geert+renesas@glider.be> +Signed-off-by: Vinod Koul <vinod.koul@intel.com> +--- + drivers/dma/sh/rcar-dmac.c | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c +index 2b2c7db..c99fd0f 100644 +--- a/drivers/dma/sh/rcar-dmac.c ++++ b/drivers/dma/sh/rcar-dmac.c +@@ -10,6 +10,7 @@ + * published by the Free Software Foundation. + */ + ++#include <linux/delay.h> + #include <linux/dma-mapping.h> + #include <linux/dmaengine.h> + #include <linux/interrupt.h> +@@ -741,6 +742,24 @@ static int rcar_dmac_fill_hwdesc(struct rcar_dmac_chan *chan, + /* ----------------------------------------------------------------------------- + * Stop and reset + */ ++static void rcar_dmac_chcr_de_barrier(struct rcar_dmac_chan *chan) ++{ ++ u32 chcr; ++ unsigned int i; ++ ++ /* ++ * Ensure that the setting of the DE bit is actually 0 after ++ * clearing it. ++ */ ++ for (i = 0; i < 1024; i++) { ++ chcr = rcar_dmac_chan_read(chan, RCAR_DMACHCR); ++ if (!(chcr & RCAR_DMACHCR_DE)) ++ return; ++ udelay(1); ++ } ++ ++ dev_err(chan->chan.device->dev, "CHCR DE check error\n"); ++} + + static void rcar_dmac_chan_halt(struct rcar_dmac_chan *chan) + { +@@ -749,6 +768,7 @@ static void rcar_dmac_chan_halt(struct rcar_dmac_chan *chan) + chcr &= ~(RCAR_DMACHCR_DSE | RCAR_DMACHCR_DSIE | RCAR_DMACHCR_IE | + RCAR_DMACHCR_TE | RCAR_DMACHCR_DE); + rcar_dmac_chan_write(chan, RCAR_DMACHCR, chcr); ++ rcar_dmac_chcr_de_barrier(chan); + } + + static void rcar_dmac_chan_reinit(struct rcar_dmac_chan *chan) +@@ -1481,6 +1501,8 @@ static irqreturn_t rcar_dmac_isr_channel(int irq, void *dev) + if (chcr & RCAR_DMACHCR_TE) + mask |= RCAR_DMACHCR_DE; + rcar_dmac_chan_write(chan, RCAR_DMACHCR, chcr & ~mask); ++ if (mask & RCAR_DMACHCR_DE) ++ rcar_dmac_chcr_de_barrier(chan); + + if (chcr & RCAR_DMACHCR_DSE) + ret |= rcar_dmac_isr_desc_stage_end(chan); +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0081-dmaengine-rcar-dmac-use-TCRB-instead-of-TCR-for-resi.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0081-dmaengine-rcar-dmac-use-TCRB-instead-of-TCR-for-resi.patch new file mode 100644 index 0000000..c9bfdfb --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0081-dmaengine-rcar-dmac-use-TCRB-instead-of-TCR-for-resi.patch @@ -0,0 +1,108 @@ +From 73a47bd0da668c99f04e9076f2b02101a5b2749b Mon Sep 17 00:00:00 2001 +From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Date: Fri, 17 Nov 2017 02:09:32 +0000 +Subject: [PATCH 2/2] dmaengine: rcar-dmac: use TCRB instead of TCR for residue + +SYS/RT/Audio DMAC includes independent data buffers for reading +and writing. Therefore, the read transfer counter and write transfer +counter have different values. +TCR indicates read counter, and TCRB indicates write counter. +The relationship is like below. + + TCR TCRB + [SOURCE] -> [DMAC] -> [SINK] + +In the MEM_TO_DEV direction, what really matters is how much data has +been written to the device. If the DMA is interrupted between read and +write, then, the data doesn't end up in the destination, so shouldn't +be counted. TCRB is thus the register we should use in this cases. + +In the DEV_TO_MEM direction, the situation is more complex. Both the +read and write side are important. What matters from a data consumer +point of view is how much data has been written to memory. +On the other hand, if the transfer is interrupted between read and +write, we'll end up losing data. It can also be important to report. + +In the MEM_TO_MEM direction, what matters is of course how much data +has been written to memory from data consumer point of view. +Here, because read and write have independent data buffers, it will +take a while for TCR and TCRB to become equal. Thus we should check +TCRB in this case, too. + +Thus, all cases we should check TCRB instead of TCR. + +Without this patch, Sound Capture has noise after PulseAudio support +(= 07b7acb51d2 ("ASoC: rsnd: update pointer more accurate")), because +the recorder will use wrong residue counter which indicates transferred +from sound device, but in reality the data was not yet put to memory +and recorder will record it. + +However, because DMAC is buffering data until it can be transferable +size, TCRB might not be updated. +For example, if consumer doesn't know how much data can be received, +it requests enough size to DMAC. But in reality, it might receive very +few data. In such case, DMAC just buffered it until transferable size, +and no TCRB updated. + +In such case, this buffered data will be transferred if CHCR::DE bit was +cleared, and this is happen if rcar_dmac_chan_halt(). In other word, it +happen when consumer called dmaengine_terminate_all(). + +Because of this behavior, it need to flush buffered data when it returns +"residue" (= dmaengine_tx_status()). +Otherwise, consumer might calculate wrong things if it called +dmaengine_tx_status() and dmaengine_terminate_all() consecutively. + +Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> +Tested-by: Hiroyuki Yokoyama <hiroyuki.yokoyama.vx@renesas.com> +Tested-by: Ryo Kodama <ryo.kodama.vz@renesas.com> +Tested-by: Geert Uytterhoeven <geert+renesas@glider.be> +Signed-off-by: Vinod Koul <vinod.koul@intel.com> +--- + drivers/dma/sh/rcar-dmac.c | 22 +++++++++++++++++++++- + 1 file changed, 21 insertions(+), 1 deletion(-) + +diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c +index c99fd0f..3bbd11d 100644 +--- a/drivers/dma/sh/rcar-dmac.c ++++ b/drivers/dma/sh/rcar-dmac.c +@@ -761,6 +761,23 @@ static void rcar_dmac_chcr_de_barrier(struct rcar_dmac_chan *chan) + dev_err(chan->chan.device->dev, "CHCR DE check error\n"); + } + ++static void rcar_dmac_sync_tcr(struct rcar_dmac_chan *chan) ++{ ++ u32 chcr = rcar_dmac_chan_read(chan, RCAR_DMACHCR); ++ ++ if (!(chcr & RCAR_DMACHCR_DE)) ++ return; ++ ++ /* set DE=0 and flush remaining data */ ++ rcar_dmac_chan_write(chan, RCAR_DMACHCR, (chcr & ~RCAR_DMACHCR_DE)); ++ ++ /* make sure all remaining data was flushed */ ++ rcar_dmac_chcr_de_barrier(chan); ++ ++ /* back DE */ ++ rcar_dmac_chan_write(chan, RCAR_DMACHCR, chcr); ++} ++ + static void rcar_dmac_chan_halt(struct rcar_dmac_chan *chan) + { + u32 chcr = rcar_dmac_chan_read(chan, RCAR_DMACHCR); +@@ -1329,8 +1346,11 @@ static unsigned int rcar_dmac_chan_get_residue(struct rcar_dmac_chan *chan, + residue += chunk->size; + } + ++ if (desc->direction == DMA_DEV_TO_MEM) ++ rcar_dmac_sync_tcr(chan); ++ + /* Add the residue for the current chunk. */ +- residue += rcar_dmac_chan_read(chan, RCAR_DMATCR) << desc->xfer_shift; ++ residue += rcar_dmac_chan_read(chan, RCAR_DMATCRB) << desc->xfer_shift; + + return residue; + } +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0100-LVDS-ar0132-use-raw12.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0100-LVDS-ar0132-use-raw12.patch new file mode 100644 index 0000000..7822b35 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0100-LVDS-ar0132-use-raw12.patch @@ -0,0 +1,152 @@ +From 2869ff3002560ee637f905ed684aaccfac53372e Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Mon, 28 Aug 2017 03:16:21 +0300 +Subject: [PATCH] LVDS: ar0132: use raw12 + +Set CSI2 type raw8 in RCAR CSI2 and set raw12 in ti960 + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts | 8 ++++---- + arch/arm64/boot/dts/renesas/legacy/r8a7795-h3ulcb-kf-v0.dts | 8 ++++---- + arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts | 8 ++++---- + arch/arm64/boot/dts/renesas/ulcb-kf.dtsi | 8 ++++---- + drivers/media/i2c/soc_camera/ti964_ti9x3.c | 5 +++-- + 5 files changed, 19 insertions(+), 18 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts b/arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts +index cd23797..5dc5144 100644 +--- a/arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts ++++ b/arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts +@@ -1571,19 +1571,19 @@ + + virtual,channel { + csi2_vc0 { +- data,type = "ycbcr422"; ++ data,type = "raw8"; + receive,vc = <0>; + }; + csi2_vc1 { +- data,type = "ycbcr422"; ++ data,type = "raw8"; + receive,vc = <1>; + }; + csi2_vc2 { +- data,type = "ycbcr422"; ++ data,type = "raw8"; + receive,vc = <2>; + }; + csi2_vc3 { +- data,type = "ycbcr422"; ++ data,type = "raw8"; + receive,vc = <3>; + }; + }; +diff --git a/arch/arm64/boot/dts/renesas/legacy/r8a7795-h3ulcb-kf-v0.dts b/arch/arm64/boot/dts/renesas/legacy/r8a7795-h3ulcb-kf-v0.dts +index f640350..b26ca3a 100644 +--- a/arch/arm64/boot/dts/renesas/legacy/r8a7795-h3ulcb-kf-v0.dts ++++ b/arch/arm64/boot/dts/renesas/legacy/r8a7795-h3ulcb-kf-v0.dts +@@ -1578,19 +1578,19 @@ + + virtual,channel { + csi2_vc0 { +- data,type = "ycbcr422"; ++ data,type = "raw8"; + receive,vc = <0>; + }; + csi2_vc1 { +- data,type = "ycbcr422"; ++ data,type = "raw8"; + receive,vc = <1>; + }; + csi2_vc2 { +- data,type = "ycbcr422"; ++ data,type = "raw8"; + receive,vc = <2>; + }; + csi2_vc3 { +- data,type = "ycbcr422"; ++ data,type = "raw8"; + receive,vc = <3>; + }; + }; +diff --git a/arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts +index 9837e17..402e894 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts +@@ -511,19 +511,19 @@ + + virtual,channel { + csi2_vc0 { +- data,type = "ycbcr422"; ++ data,type = "raw8"; + receive,vc = <0>; + }; + csi2_vc1 { +- data,type = "ycbcr422"; ++ data,type = "raw8"; + receive,vc = <1>; + }; + csi2_vc2 { +- data,type = "ycbcr422"; ++ data,type = "raw8"; + receive,vc = <2>; + }; + csi2_vc3 { +- data,type = "ycbcr422"; ++ data,type = "raw8"; + receive,vc = <3>; + }; + }; +diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi +index 4ead97a..6dbcf7f 100644 +--- a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi ++++ b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi +@@ -1346,19 +1346,19 @@ + + virtual,channel { + csi2_vc0 { +- data,type = "ycbcr422"; ++ data,type = "raw8"; + receive,vc = <0>; + }; + csi2_vc1 { +- data,type = "ycbcr422"; ++ data,type = "raw8"; + receive,vc = <1>; + }; + csi2_vc2 { +- data,type = "ycbcr422"; ++ data,type = "raw8"; + receive,vc = <2>; + }; + csi2_vc3 { +- data,type = "ycbcr422"; ++ data,type = "raw8"; + receive,vc = <3>; + }; + }; +diff --git a/drivers/media/i2c/soc_camera/ti964_ti9x3.c b/drivers/media/i2c/soc_camera/ti964_ti9x3.c +index 8dd0f99..caa3f74 100644 +--- a/drivers/media/i2c/soc_camera/ti964_ti9x3.c ++++ b/drivers/media/i2c/soc_camera/ti964_ti9x3.c +@@ -122,12 +122,14 @@ static void ti964_ti9x3_fpdlink3_setup(struct i2c_client *client, int idx) + // 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 */ ++ reg8_write(client, 0x6d, 0x7e); /* Coax, RAW12 */ + } 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, 0x71, (idx << 6) | 0x2a); /* CSI data type: RAW8 (for RAW12 and bits reodering), assign VC */ ++ reg8_write(client, 0x7c, 0x00); /* RAW12 mode */ ++ reg8_write(client, 0xbc, 0x00); /* Setup minimal time between FV and LV to 3 PCLKs */ + reg8_write(client, 0x6e, 0x88); /* Sensor reset: backchannel GPIO0/GPIO1 set low */ + } + +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0101-LVDS-ar0132-use-context-swwitch.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0101-LVDS-ar0132-use-context-swwitch.patch new file mode 100644 index 0000000..00b62e8 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0101-LVDS-ar0132-use-context-swwitch.patch @@ -0,0 +1,119 @@ +From d9b811e183d9cae753929cb55e627a29c6a971a8 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Wed, 30 Aug 2017 14:44:29 +0300 +Subject: [PATCH] LVDS: ar0132 use context swwitch + +This enabled context-A-B switch on every frame + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + drivers/media/i2c/soc_camera/ar0132.c | 19 +++++++++++++++++++ + drivers/media/platform/soc_camera/rcar_vin.c | 23 ++++++++++++++++++----- + 2 files changed, 37 insertions(+), 5 deletions(-) + +diff --git a/drivers/media/i2c/soc_camera/ar0132.c b/drivers/media/i2c/soc_camera/ar0132.c +index 284c522..2c21fa9 100644 +--- a/drivers/media/i2c/soc_camera/ar0132.c ++++ b/drivers/media/i2c/soc_camera/ar0132.c +@@ -238,11 +238,30 @@ static int ar0132_s_register(struct v4l2_subdev *sd, + } + #endif + ++static int ar0132_isr(struct v4l2_subdev *sd, u32 status, bool *handled) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++#if 1 ++ u16 frame_count = 0; ++ /* read frame counter from sensor */ ++ reg16_read16(client, 0x303a, &frame_count); ++#else ++ static int frame_count = 0; ++ /* get cached frame counter */ ++ frame_count++; ++#endif ++ /* odd frame -> Mode A, even frame -> Mode B */ ++ reg16_write16(client, 0x30b0, frame_count & 1 ? 0x2 : 0x2002); ++ ++ return 0; ++}; ++ + static struct v4l2_subdev_core_ops ar0132_core_ops = { + #ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = ar0132_g_register, + .s_register = ar0132_s_register, + #endif ++ .interrupt_service_routine = ar0132_isr, + }; + + static int ar0132_s_ctrl(struct v4l2_ctrl *ctrl) +diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c +index c39fe63..9ab6f00 100644 +--- a/drivers/media/platform/soc_camera/rcar_vin.c ++++ b/drivers/media/platform/soc_camera/rcar_vin.c +@@ -1292,13 +1292,24 @@ static void rcar_vin_stop_streaming(struct vb2_queue *vq) + .wait_finish = vb2_ops_wait_finish, + }; + ++static irqreturn_t rcar_vin_threaded_irq(int irq, void *data) ++{ ++ struct rcar_vin_priv *priv = data; ++ struct soc_camera_device *icd = priv->ici.icd; ++ struct v4l2_subdev *sd = soc_camera_to_subdev(icd); ++ ++ v4l2_subdev_call(sd, core, interrupt_service_routine, 0, NULL); ++ ++ return IRQ_HANDLED; ++}; ++ + 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; ++ unsigned int handled = IRQ_NONE; + int vin_ovr_cnt = 0; + + spin_lock(&priv->lock); +@@ -1309,7 +1320,7 @@ static irqreturn_t rcar_vin_irq(int irq, void *data) + + /* ack interrupts */ + iowrite32(int_status, priv->base + VNINTS_REG); +- handled = 1; ++ handled = IRQ_HANDLED; + + /* overflow occurs */ + if (vin_debug && (int_status & VNINTS_FOS)) { +@@ -1342,6 +1353,8 @@ static irqreturn_t rcar_vin_irq(int irq, void *data) + priv->queue_buf[slot] = NULL; + + can_run = rcar_vin_fill_hw_slot(priv); ++ ++ handled = IRQ_WAKE_THREAD; + } + + if (is_continuous_transfer(priv)) { +@@ -1370,7 +1383,7 @@ static irqreturn_t rcar_vin_irq(int irq, void *data) + done: + spin_unlock(&priv->lock); + +- return IRQ_RETVAL(handled); ++ return handled; + } + + static struct v4l2_subdev *find_csi2(struct rcar_vin_priv *pcdev) +@@ -2930,8 +2943,8 @@ static int rcar_vin_probe(struct platform_device *pdev) + 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); ++ ret = devm_request_threaded_irq(&pdev->dev, irq, rcar_vin_irq, rcar_vin_threaded_irq, ++ IRQF_SHARED, dev_name(&pdev->dev), priv); + if (ret) + return ret; + +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0103-gpu-drm-rcar-du-Extend-VSP1-DRM-interface.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0103-gpu-drm-rcar-du-Extend-VSP1-DRM-interface.patch new file mode 100644 index 0000000..e3f24a6 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0103-gpu-drm-rcar-du-Extend-VSP1-DRM-interface.patch @@ -0,0 +1,546 @@ +From b6176e313aea415b83d5762db275b2f364f08820 Mon Sep 17 00:00:00 2001 +From: Konstantin Kozhevnikov <Konstantin.Kozhevnikov@cogentembedded.com> +Date: Tue, 14 Nov 2017 01:38:51 -0800 +Subject: [PATCH] gpu: drm: rcar-du: Extend VSP1-DRM interface + +Extend VSP1-DRM interface + +Signed-off-by: Konstantin Kozhevnikov <Konstantin.Kozhevnikov@cogentembedded.com> +--- + drivers/gpu/drm/drm_framebuffer.c | 1 + + drivers/gpu/drm/rcar-du/rcar_du_drv.h | 5 + + drivers/gpu/drm/rcar-du/rcar_du_kms.c | 42 ++++++- + drivers/gpu/drm/rcar-du/rcar_du_plane.c | 3 +- + drivers/gpu/drm/rcar-du/rcar_du_plane.h | 5 + + drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 209 ++++++++++++++++++++++++++------ + drivers/gpu/drm/rcar-du/rcar_du_vsp.h | 7 +- + 7 files changed, 232 insertions(+), 40 deletions(-) + +diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c +index 398efd6..4a43e15 100644 +--- a/drivers/gpu/drm/drm_framebuffer.c ++++ b/drivers/gpu/drm/drm_framebuffer.c +@@ -192,6 +192,7 @@ static int format_check(const struct drm_mode_fb_cmd2 *r) + case DRM_FORMAT_YVU422: + case DRM_FORMAT_YUV444: + case DRM_FORMAT_YVU444: ++ case DRM_FORMAT_R8: + return 0; + default: + format_name = drm_get_format_name(r->pixel_format); +diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h +index 45d6e7e..bdf2612 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h ++++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h +@@ -104,6 +104,11 @@ struct rcar_du_device { + struct { + struct drm_property *alpha; + struct drm_property *colorkey; ++ struct drm_property *alphaplane; ++ struct drm_property *blend; ++ struct drm_property *ckey; ++ struct drm_property *ckey_set0; ++ struct drm_property *ckey_set1; + } props; + + unsigned int dpad0_source; +diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c +index e955e92..31b48bc 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c ++++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c +@@ -10,7 +10,7 @@ + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +- ++//#define DEBUG + #include <drm/drmP.h> + #include <drm/drm_atomic.h> + #include <drm/drm_atomic_helper.h> +@@ -101,6 +101,12 @@ static const struct rcar_du_format_info rcar_du_format_infos[] = { + .planes = 2, + .pnmr = PnMR_SPIM_TP_OFF | PnMR_DDDF_YC, + .edf = PnDDCR4_EDF_NONE, ++ }, { ++ .fourcc = DRM_FORMAT_R8, ++ .bpp = 8, ++ .planes = 1, ++ .pnmr = PnMR_SPIM_TP_OFF | PnMR_DDDF_8BPP, ++ .edf = PnDDCR4_EDF_NONE, + }, + }; + +@@ -169,6 +175,10 @@ static const struct rcar_du_format_info rcar_vsp_format_infos[] = { + .fourcc = DRM_FORMAT_YVU444, + .bpp = 24, + .planes = 3, ++ }, { ++ .fourcc = DRM_FORMAT_R8, ++ .bpp = 8, ++ .planes = 1, + }, + }; + +@@ -565,6 +575,36 @@ static int rcar_du_properties_init(struct rcar_du_device *rcdu) + if (rcdu->props.colorkey == NULL) + return -ENOMEM; + ++ rcdu->props.alphaplane = ++ drm_property_create(rcdu->ddev, DRM_MODE_PROP_OBJECT, "alphaplane", 1); ++ if (rcdu->props.alphaplane == NULL) ++ return -ENOMEM; ++ rcdu->props.alphaplane->values[0] = DRM_MODE_OBJECT_FB; ++ ++ rcdu->props.blend = ++ drm_property_create_range(rcdu->ddev, 0, "blend", ++ 0, 0xffffffff); ++ if (rcdu->props.blend == NULL) ++ return -ENOMEM; ++ ++ rcdu->props.ckey = ++ drm_property_create_range(rcdu->ddev, 0, "ckey", ++ 0, 0xffffffff); ++ if (rcdu->props.ckey == NULL) ++ return -ENOMEM; ++ ++ rcdu->props.ckey_set0 = ++ drm_property_create_range(rcdu->ddev, 0, "ckey_set0", ++ 0, 0xffffffff); ++ if (rcdu->props.ckey_set0 == NULL) ++ return -ENOMEM; ++ ++ rcdu->props.ckey_set1 = ++ drm_property_create_range(rcdu->ddev, 0, "ckey_set1", ++ 0, 0xffffffff); ++ if (rcdu->props.ckey_set1 == NULL) ++ return -ENOMEM; ++ + return 0; + } + +diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c +index e408aa3..2b57f09 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c ++++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c +@@ -10,7 +10,7 @@ + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +- ++//#define DEBUG + #include <drm/drmP.h> + #include <drm/drm_atomic.h> + #include <drm/drm_atomic_helper.h> +@@ -719,6 +719,7 @@ static const uint32_t formats[] = { + DRM_FORMAT_NV12, + DRM_FORMAT_NV21, + DRM_FORMAT_NV16, ++ DRM_FORMAT_R8, + }; + + int rcar_du_planes_init(struct rcar_du_group *rgrp) +diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.h b/drivers/gpu/drm/rcar-du/rcar_du_plane.h +index c1de338..a6065ef 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.h ++++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.h +@@ -66,6 +66,11 @@ struct rcar_du_plane_state { + + unsigned int alpha; + unsigned int colorkey; ++ struct drm_framebuffer *alphaplane; ++ unsigned int blend; ++ unsigned int ckey; ++ unsigned int ckey_set0; ++ unsigned int ckey_set1; + }; + + static inline struct rcar_du_plane_state * +diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +index 770238a..910e0f0 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c ++++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +@@ -10,7 +10,7 @@ + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +- ++//#define DEBUG + #include <drm/drmP.h> + #include <drm/drm_atomic.h> + #include <drm/drm_atomic_helper.h> +@@ -91,6 +91,16 @@ void rcar_du_vsp_enable(struct rcar_du_crtc *crtc) + + void rcar_du_vsp_disable(struct rcar_du_crtc *crtc) + { ++ struct rcar_du_vsp *vsp = crtc->vsp; ++ struct rcar_du_vsp_plane *primary = &vsp->planes[0]; ++ struct rcar_du_vsp_plane_state *rstate = to_rcar_vsp_plane_state(primary->plane.state); ++ ++ /* ...drop alpha-plane associated with primary plane (why only primary? - tbd) */ ++ if (rstate->alphaplane) { ++ drm_framebuffer_unreference(rstate->alphaplane); ++ rstate->alphaplane = NULL; ++ } ++ + vsp1_du_setup_lif(crtc->vsp->vsp, NULL, crtc->lif_index, + crtc->suspend); + } +@@ -133,6 +143,7 @@ static const u32 formats_kms[] = { + DRM_FORMAT_YVU422, + DRM_FORMAT_YUV444, + DRM_FORMAT_YVU444, ++ DRM_FORMAT_R8, + }; + + static const u32 formats_v4l2[] = { +@@ -162,6 +173,7 @@ static const u32 formats_v4l2[] = { + V4L2_PIX_FMT_YVU422M, + V4L2_PIX_FMT_YUV444M, + V4L2_PIX_FMT_YVU444M, ++ V4L2_PIX_FMT_GREY, + }; + + static const u32 formats_xlate[][2] = { +@@ -184,6 +196,7 @@ static const u32 formats_xlate[][2] = { + { DRM_FORMAT_NV21, V4L2_PIX_FMT_NV21M }, + { DRM_FORMAT_NV16, V4L2_PIX_FMT_NV16M }, + { DRM_FORMAT_NV61, V4L2_PIX_FMT_NV61M }, ++ { DRM_FORMAT_R8, V4L2_PIX_FMT_GREY }, + }; + + static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane) +@@ -226,6 +239,27 @@ static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane) + } + } + ++ /* ...add alpha-plane as needed */ ++ if (state->alphaplane) { ++ i = state->format->planes; ++ cfg.alpha_mem = sg_dma_address(state->sg_tables[i].sgl); ++ cfg.alpha_pitch = state->alphaplane->pitches[0]; ++ pr_debug("alpha-%d: set alpha-mem address: %llx, pitch=%d\n", i, (unsigned long long)cfg.alpha_mem, cfg.alpha_pitch); ++ } ++ ++ /* ...add blending formula as needed */ ++ if (state->blend) { ++ cfg.blend = state->blend; ++ pr_debug("set blending formula: %X\n", cfg.blend); ++ } ++ ++ /* ...add color key property as needed */ ++ if (state->ckey) { ++ cfg.ckey = state->ckey; ++ cfg.ckey_set0 = state->ckey_set0; ++ cfg.ckey_set1 = state->ckey_set1; ++ } ++ + vsp1_du_atomic_update(plane->vsp->vsp, plane->index, &cfg); + } + +@@ -259,6 +293,23 @@ static int rcar_du_vsp_plane_prepare_fb(struct drm_plane *plane, + } + } + ++ /* ...check if we have alpha-plane attached */ ++ if (rstate->alphaplane) { ++ struct drm_gem_cma_object *gem = drm_fb_cma_get_gem_obj(rstate->alphaplane, 0); ++ struct sg_table *sgt = &rstate->sg_tables[i++]; ++ ++ ret = dma_get_sgtable(rcdu->dev, sgt, gem->vaddr, gem->paddr, gem->base.size); ++ if (ret) ++ goto fail; ++ ++ ret = vsp1_du_map_sg(vsp->vsp, sgt); ++ if (!ret) { ++ sg_free_table(sgt); ++ ret = -ENOMEM; ++ goto fail; ++ } ++ } ++ + return 0; + + fail: +@@ -288,6 +339,14 @@ static void rcar_du_vsp_plane_cleanup_fb(struct drm_plane *plane, + vsp1_du_unmap_sg(vsp->vsp, sgt); + sg_free_table(sgt); + } ++ ++ if (rstate->alphaplane) { ++ struct sg_table *sgt = &rstate->sg_tables[i]; ++ ++ vsp1_du_unmap_sg(vsp->vsp, sgt); ++ sg_free_table(sgt); ++ pr_debug("unmap alpha-plane\n"); ++ } + } + + static int rcar_du_vsp_plane_atomic_check(struct drm_plane *plane, +@@ -369,6 +428,11 @@ rcar_du_vsp_plane_atomic_duplicate_state(struct drm_plane *plane) + if (copy == NULL) + return NULL; + ++ if (copy->alphaplane) { ++ drm_framebuffer_reference(copy->alphaplane); ++ pr_debug("duplicate alpha-plane '%p' (refcount=%d)\n", copy->alphaplane, drm_framebuffer_read_refcount(copy->alphaplane)); ++ } ++ + __drm_atomic_helper_plane_duplicate_state(plane, ©->state); + + return ©->state; +@@ -377,8 +441,15 @@ rcar_du_vsp_plane_atomic_duplicate_state(struct drm_plane *plane) + static void rcar_du_vsp_plane_atomic_destroy_state(struct drm_plane *plane, + struct drm_plane_state *state) + { ++ struct rcar_du_vsp_plane_state *rstate = to_rcar_vsp_plane_state(state); ++ ++ if (rstate->alphaplane) { ++ pr_debug("unref alpha-plane '%p' (refcount=%d)\n", rstate->alphaplane, drm_framebuffer_read_refcount(rstate->alphaplane)); ++ drm_framebuffer_unreference(rstate->alphaplane); ++ } ++ + __drm_atomic_helper_plane_destroy_state(state); +- kfree(to_rcar_vsp_plane_state(state)); ++ kfree(rstate); + } + + static void rcar_du_vsp_plane_reset(struct drm_plane *plane) +@@ -386,6 +457,7 @@ static void rcar_du_vsp_plane_reset(struct drm_plane *plane) + struct rcar_du_vsp_plane_state *state; + + if (plane->state) { ++ pr_debug("reset plane '%p'\n", to_rcar_vsp_plane_state(plane->state)->alphaplane); + rcar_du_vsp_plane_atomic_destroy_state(plane, plane->state); + plane->state = NULL; + } +@@ -410,7 +482,30 @@ static int rcar_du_vsp_plane_atomic_set_property(struct drm_plane *plane, + + if (property == rcdu->props.alpha) + rstate->alpha = val; +- else ++ else if (property == rcdu->props.blend) ++ rstate->blend = val; ++ else if (property == rcdu->props.ckey) ++ rstate->ckey = val; ++ else if (property == rcdu->props.ckey_set0) ++ rstate->ckey_set0 = val; ++ else if (property == rcdu->props.ckey_set1) ++ rstate->ckey_set1 = val; ++ else if (property == rcdu->props.alphaplane) { ++ if (rstate->alphaplane) { ++ pr_debug("unref alpha-plane '%p' (refcount=%d)\n", rstate->alphaplane, drm_framebuffer_read_refcount(rstate->alphaplane)); ++ drm_framebuffer_unreference(rstate->alphaplane); ++ } ++ rstate->alphaplane = drm_framebuffer_lookup(plane->dev, val); ++ if (rstate->alphaplane) { ++ pr_debug("use alpha-plane '%p' (refcount=%d)\n", rstate->alphaplane, drm_framebuffer_read_refcount(rstate->alphaplane)); ++ /* ...the way how we handle this leads to a "loss" of plane reference (it is acquired ++ * within "drm_property_change_valid_get" but not returned in symmetric "drm_property_change_valid_put") ++ * Whether it is a bug or was done intentionally, I don't know. For a moment just drop that ++ * extra reference right here ++ */ ++ if (0) drm_framebuffer_unreference(rstate->alphaplane); ++ } ++ } else + return -EINVAL; + + return 0; +@@ -426,6 +521,16 @@ static int rcar_du_vsp_plane_atomic_get_property(struct drm_plane *plane, + + if (property == rcdu->props.alpha) + *val = rstate->alpha; ++ else if (property == rcdu->props.alphaplane) ++ *val = (rstate->alphaplane ? rstate->alphaplane->base.id : 0); ++ else if (property == rcdu->props.blend) ++ *val = rstate->blend; ++ else if (property == rcdu->props.ckey) ++ *val = rstate->ckey; ++ else if (property == rcdu->props.ckey_set0) ++ *val = rstate->ckey_set0; ++ else if (property == rcdu->props.ckey_set1) ++ *val = rstate->ckey_set1; + else + return -EINVAL; + +@@ -442,9 +547,10 @@ int rcar_du_vsp_write_back(struct drm_device *dev, void *data, + struct rcar_du_crtc *rcrtc; + struct rcar_du_device *rcdu; + const struct drm_display_mode *mode; +- u32 pixelformat, bpp; +- unsigned int pitch; ++ struct drm_framebuffer *fb; + dma_addr_t mem[3]; ++ struct sg_table sg_tables[3]; ++ int i = 0; + + obj = drm_mode_object_find(dev, sh->crtc_id, DRM_MODE_OBJECT_CRTC); + if (!obj) +@@ -455,62 +561,79 @@ int rcar_du_vsp_write_back(struct drm_device *dev, void *data, + rcdu = rcrtc->group->dev; + mode = &rcrtc->crtc.state->adjusted_mode; + +- switch (sh->fmt) { +- case DRM_FORMAT_RGB565: +- bpp = 16; +- pixelformat = V4L2_PIX_FMT_RGB565; +- break; +- case DRM_FORMAT_ARGB1555: +- bpp = 16; +- pixelformat = V4L2_PIX_FMT_ARGB555; +- break; +- case DRM_FORMAT_ARGB8888: +- bpp = 32; +- pixelformat = V4L2_PIX_FMT_ABGR32; +- break; +- default: +- dev_err(rcdu->dev, "specified format is not supported.\n"); ++ fb = drm_framebuffer_lookup(dev, sh->buff); ++ if (!fb) { ++ dev_err(dev->dev, "failed to lookup destination framebuffer '%lu'\n", sh->buff); + return -EINVAL; + } + +- pitch = mode->hdisplay * bpp / 8; ++ /* ...check framebuffer is okay */ ++ if ((fb->width != (mode->hdisplay)) || ++ (fb->height != (mode->vdisplay))) { ++ dev_err(dev->dev, "wrong fb mode: %d*%d vs %d*%d\n", fb->width, fb->height, mode->hdisplay, mode->vdisplay); ++ ret = -EINVAL; ++ goto done; ++ } + +- mem[0] = sh->buff; +- mem[1] = 0; +- mem[2] = 0; ++ /* ...need to verify compatibility of output format, I guess - tbd */ + +- if ((sh->width != (mode->hdisplay)) || +- (sh->height != (mode->vdisplay))) +- return -EINVAL; ++ /* ...fill memory planes addresses */ ++ for (i = 0; i < 3; i++) { ++ struct drm_gem_cma_object *gem; ++ struct sg_table *sgt = &sg_tables[i]; ++ gem = drm_fb_cma_get_gem_obj(fb, i); ++ if (!gem) ++ break; ++ ret = dma_get_sgtable(rcdu->dev, sgt, gem->vaddr, gem->paddr, ++ gem->base.size); ++ if (ret) ++ goto done; + +- if ((pitch * mode->vdisplay) > sh->buff_len) +- return -EINVAL; ++ ret = vsp1_du_map_sg(rcrtc->vsp->vsp, sgt); ++ if (!ret) { ++ sg_free_table(sgt); ++ ret = -ENOMEM; ++ goto done; ++ } ++ mem[i] = sg_dma_address(sg_tables[i].sgl) + fb->offsets[i]; ++ } ++ ++ dev_info(dev->dev, "setup write-back (pixfmt=%X, %u*%u, planes: %d)\n", fb->pixel_format, fb->width, fb->height, i); ++ ++ vsp1_du_setup_wb(rcrtc->vsp->vsp, fb->pixel_format, fb->pitches[0], mem, rcrtc->lif_index); + +- vsp1_du_setup_wb(rcrtc->vsp->vsp, pixelformat, pitch, mem, +- rcrtc->lif_index); + ret = vsp1_du_wait_wb(rcrtc->vsp->vsp, WB_STAT_CATP_SET, + rcrtc->lif_index); + if (ret != 0) +- return ret; ++ goto done; + + ret = rcar_du_async_commit(dev, crtc); + if (ret != 0) +- return ret; ++ goto done; + + ret = vsp1_du_wait_wb(rcrtc->vsp->vsp, WB_STAT_CATP_START, + rcrtc->lif_index); + if (ret != 0) +- return ret; ++ goto done; + + ret = rcar_du_async_commit(dev, crtc); + if (ret != 0) +- return ret; ++ goto done; + + ret = vsp1_du_wait_wb(rcrtc->vsp->vsp, WB_STAT_CATP_DONE, + rcrtc->lif_index); + if (ret != 0) +- return ret; ++ goto done; ++ ++done: ++ /* ...unmap all tables */ ++ while (i--) { ++ struct sg_table *sgt = &sg_tables[i]; ++ vsp1_du_unmap_sg(rcrtc->vsp->vsp, sgt); ++ sg_free_table(sgt); ++ } + ++ drm_framebuffer_unreference(fb); + return ret; + } + +@@ -574,6 +697,7 @@ static const uint32_t formats[] = { + DRM_FORMAT_NV21, + DRM_FORMAT_NV16, + DRM_FORMAT_NV61, ++ DRM_FORMAT_R8, + }; + + int rcar_du_vsp_init(struct rcar_du_vsp *vsp) +@@ -653,13 +777,24 @@ int rcar_du_vsp_init(struct rcar_du_vsp *vsp) + drm_plane_helper_add(&plane->plane, + &rcar_du_vsp_plane_helper_funcs); + ++#if 0 // ...use same set of properties for all planes + if (type == DRM_PLANE_TYPE_PRIMARY) + continue; +- ++#endif + drm_object_attach_property(&plane->plane.base, + rcdu->props.alpha, 255); + drm_plane_create_zpos_property(&plane->plane, 1, 1, + vsp->num_planes - 1); ++ drm_object_attach_property(&plane->plane.base, ++ rcdu->props.alphaplane, 0); ++ drm_object_attach_property(&plane->plane.base, ++ rcdu->props.blend, 0); ++ drm_object_attach_property(&plane->plane.base, ++ rcdu->props.ckey, 0); ++ drm_object_attach_property(&plane->plane.base, ++ rcdu->props.ckey_set0, 0); ++ drm_object_attach_property(&plane->plane.base, ++ rcdu->props.ckey_set1, 0); + } + + return 0; +diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.h b/drivers/gpu/drm/rcar-du/rcar_du_vsp.h +index 3fd9cef..2f4aa41 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.h ++++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.h +@@ -52,10 +52,15 @@ struct rcar_du_vsp_plane_state { + struct drm_plane_state state; + + const struct rcar_du_format_info *format; +- struct sg_table sg_tables[3]; ++ struct sg_table sg_tables[4]; + + unsigned int alpha; + unsigned int zpos; ++ struct drm_framebuffer *alphaplane; ++ unsigned int blend; ++ unsigned int ckey; ++ unsigned int ckey_set0; ++ unsigned int ckey_set1; + }; + + static inline struct rcar_du_vsp_plane_state * +-- +2.7.4 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0104-media-vsp1-extend-DRM-VSP1-interface.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0104-media-vsp1-extend-DRM-VSP1-interface.patch new file mode 100644 index 0000000..2f6fa35 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0104-media-vsp1-extend-DRM-VSP1-interface.patch @@ -0,0 +1,367 @@ +From 0cbfce87c1a16b80111cdcecdd703ad5f75cc6e7 Mon Sep 17 00:00:00 2001 +From: Konstantin Kozhevnikov <Konstantin.Kozhevnikov@cogentembedded.com> +Date: Tue, 14 Nov 2017 01:41:06 -0800 +Subject: [PATCH] media: platform: vsp1: extend DRM-VSP1 interface + +- Extend DRM-VSP1 interface +- Add alpha-plane support for VSP1 + +Signed-off-by: Konstantin Kozhevnikov <Konstantin.Kozhevnikov@cogentembedded.com> +--- + drivers/media/platform/vsp1/vsp1_bru.c | 13 ++++++++++++- + drivers/media/platform/vsp1/vsp1_dl.c | 5 +++++ + drivers/media/platform/vsp1/vsp1_drm.c | 34 ++++++++++++++++++++++++++------- + drivers/media/platform/vsp1/vsp1_lif.c | 2 +- + drivers/media/platform/vsp1/vsp1_pipe.c | 4 ++++ + drivers/media/platform/vsp1/vsp1_rpf.c | 24 ++++++++++++++++++++--- + drivers/media/platform/vsp1/vsp1_rwpf.c | 2 +- + drivers/media/platform/vsp1/vsp1_rwpf.h | 6 ++++++ + drivers/media/platform/vsp1/vsp1_wpf.c | 4 +++- + include/media/vsp1.h | 6 ++++++ + 10 files changed, 86 insertions(+), 14 deletions(-) + +diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c +index 8b3164a..2c131be 100644 +--- a/drivers/media/platform/vsp1/vsp1_bru.c ++++ b/drivers/media/platform/vsp1/vsp1_bru.c +@@ -387,6 +387,16 @@ static void bru_configure(struct vsp1_entity *entity, + ctrl |= VI6_BRU_CTRL_SRCSEL_BRUIN(i); + + vsp1_bru_write(bru, dl, VI6_BRU_CTRL(i), ctrl); ++ dev_dbg(entity->vsp1->dev, "bru#%d: ctrl=%X\n", i, ctrl); ++ ++ /* ...set blending formula as defined by the input RPF */ ++ if (bru->inputs[i].rpf) { ++ if (bru->inputs[i].rpf->blend) { ++ vsp1_bru_write(bru, dl, VI6_BRU_BLD(i), bru->inputs[i].rpf->blend); ++ dev_dbg(entity->vsp1->dev, "bru#%d(#%d): setup blending formula: %X\n", i, bru->inputs[i].rpf->entity.index, bru->inputs[i].rpf->blend); ++ continue; ++ } ++ } + + /* Harcode the blending formula to + * +@@ -441,7 +451,8 @@ struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1) + v4l2_ctrl_new_std(&bru->ctrls, &bru_ctrl_ops, V4L2_CID_BG_COLOR, + 0, 0xffffff, 1, 0); + +- bru->bgcolor = 0; ++ /* ...for YUV, set black background */ ++ bru->bgcolor = 0x00800080; + + bru->entity.subdev.ctrl_handler = &bru->ctrls; + +diff --git a/drivers/media/platform/vsp1/vsp1_dl.c b/drivers/media/platform/vsp1/vsp1_dl.c +index 478e093..f9c6d09 100644 +--- a/drivers/media/platform/vsp1/vsp1_dl.c ++++ b/drivers/media/platform/vsp1/vsp1_dl.c +@@ -272,6 +272,7 @@ void vsp1_dl_set_addr_auto_fld(struct vsp1_dl_list *dl, struct vsp1_rwpf *rpf) + u32 y_top_index, y_bot_index; + u32 u_top_index, u_bot_index; + u32 v_top_index, v_bot_index; ++ u32 alpha_index; + dma_addr_t y_top_addr, y_bot_addr; + dma_addr_t u_top_addr, u_bot_addr; + dma_addr_t v_top_addr, v_bot_addr; +@@ -287,6 +288,7 @@ void vsp1_dl_set_addr_auto_fld(struct vsp1_dl_list *dl, struct vsp1_rwpf *rpf) + u_bot_index = rpf->entity.index * 8 + 3; + v_top_index = rpf->entity.index * 8 + 4; + v_bot_index = rpf->entity.index * 8 + 5; ++ alpha_index = rpf->entity.index * 8 + 6; + + switch (rpf->fmtinfo->fourcc) { + case V4L2_PIX_FMT_YUV420M: +@@ -359,6 +361,9 @@ void vsp1_dl_set_addr_auto_fld(struct vsp1_dl_list *dl, struct vsp1_rwpf *rpf) + dl->src_dst_addr[u_bot_index].addr = u_bot_addr; + dl->src_dst_addr[v_top_index].addr = v_top_addr; + dl->src_dst_addr[v_bot_index].addr = v_bot_addr; ++ ++ /* ...set alpha-plane address as needed */ ++ dl->src_dst_addr[alpha_index].addr = rpf->mem.alpha; + } + + static struct vsp1_dl_list *vsp1_dl_list_alloc(struct vsp1_dl_manager *dlm) +diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c +index 2681c8a..542ca5a 100644 +--- a/drivers/media/platform/vsp1/vsp1_drm.c ++++ b/drivers/media/platform/vsp1/vsp1_drm.c +@@ -10,7 +10,7 @@ + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +- ++//#define DEBUG + #include <linux/device.h> + #include <linux/dma-mapping.h> + #include <linux/slab.h> +@@ -201,7 +201,9 @@ int vsp1_du_setup_lif(struct device *dev, const struct vsp1_du_lif_config *cfg, + + format.format.width = cfg->width; + format.format.height = cfg->height; +- format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32; ++ //format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32; ++ /* ...always blend in YUV colorspace; apply conversion as needed */ ++ format.format.code = MEDIA_BUS_FMT_AYUV8_1X32; + format.format.field = V4L2_FIELD_NONE; + + ret = v4l2_subdev_call(&brs->entity.subdev, pad, +@@ -222,7 +224,9 @@ int vsp1_du_setup_lif(struct device *dev, const struct vsp1_du_lif_config *cfg, + + format.format.width = cfg->width; + format.format.height = cfg->height; +- format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32; ++ //format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32; ++ /* ...always blend in YUV colorspace; apply conversion as needed */ ++ format.format.code = MEDIA_BUS_FMT_AYUV8_1X32; + format.format.field = V4L2_FIELD_NONE; + + ret = v4l2_subdev_call(&bru->entity.subdev, pad, +@@ -241,7 +245,8 @@ int vsp1_du_setup_lif(struct device *dev, const struct vsp1_du_lif_config *cfg, + + format.format.width = cfg->width; + format.format.height = cfg->height; +- format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32; ++ //format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32; ++ format.format.code = MEDIA_BUS_FMT_AYUV8_1X32; + format.format.field = V4L2_FIELD_NONE; + + if (lif_index == 1) { +@@ -275,6 +280,13 @@ int vsp1_du_setup_lif(struct device *dev, const struct vsp1_du_lif_config *cfg, + format.format.code, lif_index); + + format.pad = RWPF_PAD_SOURCE; ++ /* ...force conversion back to ARGB at the output */ ++ format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32; ++ ret = v4l2_subdev_call(&vsp1->wpf[0]->entity.subdev, pad, set_fmt, NULL, ++ &format); ++ if (ret < 0) ++ return ret; ++ + ret = v4l2_subdev_call(&vsp1->wpf[lif_index]->entity.subdev, + pad, get_fmt, NULL, &format); + if (ret < 0) +@@ -402,12 +414,12 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int rpf_index, + } + + dev_dbg(vsp1->dev, +- "%s: RPF%u: (%u,%u)/%ux%u -> (%u,%u)/%ux%u (%08x), pitch %u dma { %pad, %pad, %pad } zpos %u\n", ++ "%s: RPF%u: (%u,%u)/%ux%u -> (%u,%u)/%ux%u (%08x), pitch %u dma { %pad, %pad, %pad } zpos %u, alpha %pad, ckey %x/%x/%x\n", + __func__, rpf_index, + cfg->src.left, cfg->src.top, cfg->src.width, cfg->src.height, + cfg->dst.left, cfg->dst.top, cfg->dst.width, cfg->dst.height, + cfg->pixelformat, cfg->pitch, &cfg->mem[0], &cfg->mem[1], +- &cfg->mem[2], cfg->zpos); ++ &cfg->mem[2], cfg->zpos, &cfg->alpha_mem, cfg->ckey, cfg->ckey_set0, cfg->ckey_set1); + + /* + * Store the format, stride, memory buffer address, crop and compose +@@ -432,6 +444,11 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int rpf_index, + rpf->format.plane_fmt[1].bytesperline = cfg->pitch; + rpf->alpha = cfg->alpha; + rpf->interlaced = cfg->interlaced; ++ rpf->alpha_pitch = cfg->alpha_pitch; ++ rpf->ckey = cfg->ckey; ++ rpf->ckey_set0 = cfg->ckey_set0; ++ rpf->ckey_set1 = cfg->ckey_set1; ++ rpf->blend = cfg->blend; + + if ((vsp1->ths_quirks & VSP1_AUTO_FLD_NOT_SUPPORT) && + rpf->interlaced) { +@@ -443,6 +460,7 @@ int vsp1_du_atomic_update(struct device *dev, unsigned int rpf_index, + rpf->mem.addr[0] = cfg->mem[0]; + rpf->mem.addr[1] = cfg->mem[1]; + rpf->mem.addr[2] = cfg->mem[2]; ++ rpf->mem.alpha = cfg->alpha_mem; + + vsp1->drm->inputs[rpf_index].crop = cfg->src; + vsp1->drm->inputs[rpf_index].compose = cfg->dst; +@@ -517,7 +535,9 @@ static int vsp1_du_setup_rpf_pipe(struct vsp1_device *vsp1, + __func__, format.format.width, format.format.height, + format.format.code, rpf->entity.index); + +- format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32; ++ //format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32; ++ /* ...do blending in YUV color-space; apply conversion as needed */ ++ format.format.code = MEDIA_BUS_FMT_AYUV8_1X32; + + ret = v4l2_subdev_call(&rpf->entity.subdev, pad, set_fmt, NULL, + &format); +diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c +index e79f9e6..753763d 100644 +--- a/drivers/media/platform/vsp1/vsp1_lif.c ++++ b/drivers/media/platform/vsp1/vsp1_lif.c +@@ -162,7 +162,7 @@ static void lif_configure(struct vsp1_entity *entity, + + vsp1_lif_write(lif, dl, VI6_LIF_CTRL(lif->entity.index), + (obth << VI6_LIF_CTRL_OBTH_SHIFT) | +- (format->code == 0 ? VI6_LIF_CTRL_CFMT : 0) | ++ (format->code != MEDIA_BUS_FMT_ARGB8888_1X32 ? VI6_LIF_CTRL_CFMT : 0) | + VI6_LIF_CTRL_REQSEL | VI6_LIF_CTRL_LIF_EN); + + if (soc_device_match(r8a7797)) +diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c +index 8379962..86d4a85 100644 +--- a/drivers/media/platform/vsp1/vsp1_pipe.c ++++ b/drivers/media/platform/vsp1/vsp1_pipe.c +@@ -137,6 +137,10 @@ static const struct vsp1_format_info vsp1_video_formats[] = { + VI6_FMT_Y_U_V_444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | + VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, + 3, { 8, 8, 8 }, false, false, 1, 1, false }, ++ { V4L2_PIX_FMT_GREY, MEDIA_BUS_FMT_Y8_1X8, ++ /*VI6_FMT_Y_U_V_444*/0xDEAD, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS | ++ VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS, ++ 1, { 8, 0, 0 }, false, false, 0, 0, false }, + }; + + /** +diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c +index ff25470..2cce294 100644 +--- a/drivers/media/platform/vsp1/vsp1_rpf.c ++++ b/drivers/media/platform/vsp1/vsp1_rpf.c +@@ -10,7 +10,7 @@ + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +- ++//#define DEBUG + #include <linux/device.h> + + #include <media/v4l2-subdev.h> +@@ -253,8 +253,10 @@ static void rpf_configure(struct vsp1_entity *entity, + if (sink_format->code != source_format->code) + infmt |= VI6_RPF_INFMT_CSC; + ++ dev_dbg(vsp1->dev, "rpf#%d: infmt=%x (csc=%d)\n", rpf->entity.index, infmt, !!(infmt & VI6_RPF_INFMT_CSC)); ++ + vsp1_rpf_write(rpf, dl, VI6_RPF_INFMT, infmt); +- vsp1_rpf_write(rpf, dl, VI6_RPF_DSWAP, fmtinfo->swap); ++ vsp1_rpf_write(rpf, dl, VI6_RPF_DSWAP, fmtinfo->swap | 0xF00); + + /* Output location */ + if (pipe->bru) { +@@ -288,6 +290,15 @@ static void rpf_configure(struct vsp1_entity *entity, + (left << VI6_RPF_LOC_HCOORD_SHIFT) | + (top << VI6_RPF_LOC_VCOORD_SHIFT)); + ++ // ...setup alpha-plane as required ++ if (rpf->mem.alpha) { ++ vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_ADDR_AI, rpf->mem.alpha); ++ vsp1_rpf_write(rpf, dl, VI6_RPF_ALPH_SEL, VI6_RPF_ALPH_SEL_ASEL_8B_PLANE); ++ vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_ASTRIDE, rpf->alpha_pitch); ++ dev_dbg(vsp1->dev, "rpf#%d: setup alpha-plane: buffer=%pad, stride=%u\n", rpf->entity.index, &rpf->mem.alpha, rpf->alpha_pitch); ++ goto out; ++ } ++ + /* On Gen2 use the alpha channel (extended to 8 bits) when available or + * a fixed alpha value set through the V4L2_CID_ALPHA_COMPONENT control + * otherwise. +@@ -342,7 +353,9 @@ static void rpf_configure(struct vsp1_entity *entity, + if (entity->vsp1->info->gen == 3) { + u32 mult; + +- if ((fmtinfo->alpha) && ++ dev_dbg(vsp1->dev, "rpf#%d: alpha=%x, fourcc=%x\n", rpf->entity.index, fmtinfo->alpha, fmtinfo->fourcc); ++ ++ if (0 && (fmtinfo->alpha) && + (fmtinfo->fourcc != V4L2_PIX_FMT_ARGB555)) { + /* When the input contains an alpha channel enable the + * alpha multiplier. If the input is premultiplied we +@@ -371,9 +384,14 @@ static void rpf_configure(struct vsp1_entity *entity, + rpf->mult_alpha = mult; + } + ++out: + vsp1_rpf_write(rpf, dl, VI6_RPF_MSK_CTRL, 0); + vsp1_rpf_write(rpf, dl, VI6_RPF_CKEY_CTRL, 0); + ++ /* ...set up color keying */ ++ vsp1_rpf_write(rpf, dl, VI6_RPF_CKEY_CTRL, rpf->ckey); ++ vsp1_rpf_write(rpf, dl, VI6_RPF_CKEY_SET0, rpf->ckey_set0); ++ vsp1_rpf_write(rpf, dl, VI6_RPF_CKEY_SET1, rpf->ckey_set1); + } + + static const struct vsp1_entity_operations rpf_entity_ops = { +diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.c b/drivers/media/platform/vsp1/vsp1_rwpf.c +index 66e4d7e..d7e730f 100644 +--- a/drivers/media/platform/vsp1/vsp1_rwpf.c ++++ b/drivers/media/platform/vsp1/vsp1_rwpf.c +@@ -10,7 +10,7 @@ + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +- ++//#define DEBUG + #include <media/v4l2-subdev.h> + + #include "vsp1.h" +diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h +index fbe6aa6..7553f2b 100644 +--- a/drivers/media/platform/vsp1/vsp1_rwpf.h ++++ b/drivers/media/platform/vsp1/vsp1_rwpf.h +@@ -33,6 +33,7 @@ struct vsp1_video; + + struct vsp1_rwpf_memory { + dma_addr_t addr[3]; ++ dma_addr_t alpha; + }; + + struct vsp1_rwpf { +@@ -72,6 +73,11 @@ struct vsp1_rwpf { + + int write_back; + dma_addr_t buf_addr[3]; ++ unsigned int alpha_pitch; ++ unsigned int ckey; ++ unsigned int ckey_set0; ++ unsigned int ckey_set1; ++ unsigned int blend; + }; + + static inline struct vsp1_rwpf *to_rwpf(struct v4l2_subdev *subdev) +diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c +index e8b3cfb..cb81848 100644 +--- a/drivers/media/platform/vsp1/vsp1_wpf.c ++++ b/drivers/media/platform/vsp1/vsp1_wpf.c +@@ -10,7 +10,7 @@ + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +- ++//#define DEBUG + #include <linux/device.h> + + #include <media/v4l2-subdev.h> +@@ -358,6 +358,8 @@ static void wpf_configure(struct vsp1_entity *entity, + + wpf->outfmt = outfmt; + ++ dev_dbg(vsp1->dev, "wpf#%d: outfmt=%x (csc=%d)\n", wpf->entity.index, outfmt, !!(outfmt & VI6_WPF_OUTFMT_CSC)); ++ + vsp1_dl_list_write(dl, VI6_DPR_WPF_FPORCH(wpf->entity.index), + VI6_DPR_WPF_FPORCH_FP_WPFN); + +diff --git a/include/media/vsp1.h b/include/media/vsp1.h +index d5d93ed..c1c3201 100644 +--- a/include/media/vsp1.h ++++ b/include/media/vsp1.h +@@ -53,11 +53,17 @@ struct vsp1_du_atomic_config { + u32 pixelformat; + unsigned int pitch; + dma_addr_t mem[3]; ++ dma_addr_t alpha_mem; ++ unsigned int alpha_pitch; ++ unsigned int ckey; ++ unsigned int ckey_set0; ++ unsigned int ckey_set1; + struct v4l2_rect src; + struct v4l2_rect dst; + unsigned int alpha; + unsigned int zpos; + bool interlaced; ++ unsigned int blend; + }; + + void vsp1_du_atomic_begin(struct device *dev, unsigned int lif_index); +-- +2.7.4 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0105-media-rcar-imr-IMR-driver-updates-for-raw-DL.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0105-media-rcar-imr-IMR-driver-updates-for-raw-DL.patch new file mode 100644 index 0000000..42d2e32 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0105-media-rcar-imr-IMR-driver-updates-for-raw-DL.patch @@ -0,0 +1,538 @@ +From a687bfb7343b33992f92e86c234718c3e21144a0 Mon Sep 17 00:00:00 2001 +From: Konstantin Kozhevnikov <Konstantin.Kozhevnikov@cogentembedded.com> +Date: Tue, 14 Nov 2017 01:47:11 -0800 +Subject: [PATCH] media: rcar-imr: IMR driver updates for raw DL + +IMR driver updates for raw DL + +Signed-off-by: Konstantin Kozhevnikov <Konstantin.Kozhevnikov@cogentembedded.com> +--- + drivers/media/platform/rcar_imr.c | 209 ++++++++++++++++++++++++++++++-------- + include/uapi/linux/rcar-imr.h | 16 +-- + 2 files changed, 175 insertions(+), 50 deletions(-) + +diff --git a/drivers/media/platform/rcar_imr.c b/drivers/media/platform/rcar_imr.c +index 30c6742..9b601da 100644 +--- a/drivers/media/platform/rcar_imr.c ++++ b/drivers/media/platform/rcar_imr.c +@@ -94,6 +94,7 @@ struct imr_device { + struct v4l2_device v4l2_dev; + struct video_device video_dev; + struct v4l2_m2m_dev *m2m_dev; ++ struct device *alloc_dev; + + /* ...do we need that counter really? framework counts fh structures for us - tbd */ + int refcount; +@@ -117,6 +118,9 @@ struct imr_ctx { + /* ...cropping parameters (in pixels) */ + u16 crop[4]; + ++ /* ...solid color code */ ++ u32 color; ++ + /* ...number of active configurations (debugging) */ + u32 cfg_num; + }; +@@ -192,6 +196,7 @@ struct imr_ctx { + + #define IMR_TRICR 0x6C + #define IMR_TRIC_YCFORM (1 << 31) ++#define IMR_TRICR2 0xA0 + + #define IMR_UVDPOR 0x70 + #define IMR_SUSR 0x74 +@@ -212,6 +217,8 @@ struct imr_ctx { + #define IMR_CPDP_UBDPO_SHIFT 4 + #define IMR_CPDP_VRDPO_SHIFT 0 + ++#define IMR_TPOR 0xF0 ++ + /******************************************************************************* + * Auxiliary helpers + ******************************************************************************/ +@@ -404,11 +411,16 @@ static int imr_queue_setup(struct vb2_queue *vq, + return -EINVAL; + } + ++ /* ...specify default allocator */ ++ alloc_devs[0] = ctx->imr->alloc_dev; ++ + return 0; + } + + static int imr_buf_prepare(struct vb2_buffer *vb) + { ++ struct imr_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); ++ + /* ...unclear yet if we want to prepare a buffer somehow (cache invalidation? - tbd) */ + return 0; + } +@@ -441,9 +453,10 @@ static void imr_buf_finish(struct vb2_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", ++ v4l2_dbg(3, debug, &ctx->imr->v4l2_dev, "%sput buffer <0x%08llx> done (err: %d) (ctx=%p)\n", + q->is_output ? "in" : "out", +- vb2_dma_contig_plane_dma_addr(vb, 0)); ++ vb2_dma_contig_plane_dma_addr(vb, 0), ++ vb->state, ctx); + + /* ...unref configuration pointer as needed */ + if (q->is_output) +@@ -568,6 +581,11 @@ static inline u16 __imr_auto_sg_dg_tcm(u32 type) + (type & IMR_MAP_TCM ? IMR_TRIM_TCM : 0); + } + ++static inline u16 __imr_bfe_tme(u32 type) ++{ ++ return (type & IMR_MAP_TME ? IMR_TRIM_TME : 0) | (type & IMR_MAP_BFE ? IMR_TRIM_BFE : 0); ++} ++ + static inline u16 __imr_uvdp(u32 type) + { + return __IMR_MAP_UVDPOR(type) | (type & IMR_MAP_DDP ? (1 << 8) : 0); +@@ -674,15 +692,14 @@ static inline u32 * imr_tri_set_type_b(u32 *dl, void *map, struct imr_mesh *mesh + ******************************************************************************/ + + /* ...calculate length of a type "c" mapping */ +-static inline u32 imr_tri_type_c_get_length(struct imr_vbo *vbo, int item_size) ++static inline u32 imr_tri_type_c_get_length(int num, int item_size) + { +- return ((4 + 3 * item_size) * vbo->num + 4); ++ return ((4 + 3 * item_size) * 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) ++static inline u32 * imr_tri_set_type_c(u32 *dl, void *map, int num, int item_size) + { +- int num = vbo->num; + int i; + + /* ...prepare list of triangles to draw */ +@@ -732,6 +749,7 @@ static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg + int h = ctx->queue[0].fmt.height; + int W = ctx->queue[1].fmt.width; + int H = ctx->queue[1].fmt.height; ++ u32 tricr = ctx->color & 0xFFFFFF; + + v4l2_dbg(2, debug, &ctx->imr->v4l2_dev, "setup %u*%u -> %u*%u mapping (type=%x)\n", w, h, W, H, type); + +@@ -739,11 +757,17 @@ static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg + *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); ++ *dl++ = IMR_OP_WTS(IMR_TRIMSR, __imr_auto_sg_dg_tcm(type) | __imr_bfe_tme(type)); ++ ++ /* ...that's probably not needed? - tbd */ ++ *dl++ = IMR_OP_SYNCM; + + /* ...set source / destination coordinate precision */ + *dl++ = IMR_OP_WTS(IMR_UVDPOR, __imr_uvdp(type)); + ++ /* ...that's probably not needed? - tbd */ ++ *dl++ = IMR_OP_SYNCM; ++ + /* ...set luminance/chromacity correction parameters precision */ + *dl++ = IMR_OP_WTS(IMR_CPDPOR, __imr_cpdp(type)); + +@@ -776,14 +800,12 @@ static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg + } + } 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; ++ tricr |= (oflags & IMR_F_YUV_SWAP ? IMR_TRIC_YCFORM : 0); + + /* ...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)); +@@ -810,6 +832,10 @@ static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg + *dl++ = ((w - 2) << 16) | (w - 1); + *dl++ = h - 1; + ++ /* ...set triangle single color */ ++ *dl++ = IMR_OP_WTL(IMR_TRICR, 1); ++ *dl++ = tricr; ++ + /* ...invoke subroutine for triangles drawing */ + *dl++ = IMR_OP_GOSUB; + *dl++ = subaddr; +@@ -852,7 +878,7 @@ 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; ++ int vbo_num; + struct imr_cfg *cfg; + void *buf, *map; + u32 type; +@@ -925,13 +951,6 @@ static int imr_ioctl_map(struct imr_ctx *ctx, struct imr_map_desc *desc) + 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); +@@ -939,22 +958,23 @@ static int imr_ioctl_map(struct imr_ctx *ctx, struct imr_map_desc *desc) + goto out; + } + +- vbo = (struct imr_vbo *)buf; +- length -= sizeof(struct imr_vbo); +- map = buf + sizeof(struct imr_vbo); ++ map = buf; + + /* ...vertex is given with absolute coordinates */ + item_size += 8; + ++ /* ...calculate total number of triangles */ ++ vbo_num = length / (3 * item_size); ++ + /* ...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); ++ 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); ++ tri_length = imr_tri_type_c_get_length(vbo_num, item_size); + } + + /* ...DL main program shall start with 8-byte aligned address */ +@@ -975,13 +995,16 @@ static int imr_ioctl_map(struct imr_ctx *ctx, struct imr_map_desc *desc) + imr_cfg_unref(ctx, ctx->cfg); + + /* ...create new configuration */ +- ctx->cfg = cfg = imr_cfg_create(ctx, dl_size, dl_start_offset); ++ cfg = imr_cfg_create(ctx, dl_size, dl_start_offset); + if (IS_ERR(cfg)) { + ret = PTR_ERR(cfg); ++ ctx->cfg = NULL; + v4l2_err(&imr->v4l2_dev, "failed to create configuration: %d\n", ret); + goto out; + } + ++ ctx->cfg = cfg; ++ + /* ...get pointer to the new display list */ + dl_vaddr = cfg->dl_vaddr; + dl_dma_addr = cfg->dl_dma_addr; +@@ -994,7 +1017,7 @@ static int imr_ioctl_map(struct imr_ctx *ctx, struct imr_map_desc *desc) + imr_tri_set_type_a(dl_vaddr, map, mesh, item_size); + } + } else { +- imr_tri_set_type_c(dl_vaddr, map, vbo, item_size); ++ imr_tri_set_type_c(dl_vaddr, map, vbo_num, item_size); + } + + /* ...prepare main DL-program */ +@@ -1020,6 +1043,66 @@ static int imr_ioctl_map(struct imr_ctx *ctx, struct imr_map_desc *desc) + return ret; + } + ++/* ...set mapping data (function called with video device lock held) */ ++static int imr_ioctl_map_raw(struct imr_ctx *ctx, struct imr_map_desc *desc) ++{ ++ struct imr_device *imr = ctx->imr; ++ u32 type = desc->type; ++ u32 length = desc->size; ++ struct imr_cfg *cfg; ++ void *dl_vaddr; ++ u32 dl_size; ++ u32 dl_start_offset; ++ dma_addr_t dl_dma_addr; ++ ++ /* ...calculate main routine length */ ++ dl_size = imr_dl_program_length(ctx); ++ if (!dl_size) { ++ v4l2_err(&imr->v4l2_dev, "format configuration error\n"); ++ return -EINVAL; ++ } ++ ++ /* ...unref current configuration (will not be used by subsequent jobs) */ ++ imr_cfg_unref(ctx, ctx->cfg); ++ ++ /* ...create new configuration (starts with zero offset) */ ++ cfg = imr_cfg_create(ctx, dl_size, 0); ++ if (IS_ERR(cfg)) { ++ ctx->cfg = NULL; ++ v4l2_err(&imr->v4l2_dev, "failed to create configuration: %ld\n", PTR_ERR(cfg)); ++ return PTR_ERR(cfg); ++ } ++ ++ ctx->cfg = cfg; ++ ++ /* ...get pointer to the new display list */ ++ dl_vaddr = cfg->dl_vaddr; ++ ++ /* ...prepare main DL-program */ ++ imr_dl_program_setup(ctx, cfg, type, dl_vaddr, (u32)(uintptr_t)desc->data); ++ ++ /* ...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, 0); ++ ++ if (debug >= 4) ++ print_hex_dump_bytes("DL-", DUMP_PREFIX_OFFSET, dl_vaddr + dl_start_offset, dl_size - dl_start_offset); ++ ++ /* ...success */ ++ return 0; ++} ++ ++/* ...set mapping data (function called with video device lock held) */ ++static int imr_ioctl_color(struct imr_ctx *ctx, u32 color) ++{ ++ ctx->color = color; ++ ++ return 0; ++} ++ + /******************************************************************************* + * V4L2 I/O controls + ******************************************************************************/ +@@ -1183,7 +1266,7 @@ static int imr_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) + WARN_ON(!mutex_is_locked(&ctx->imr->mutex)); + + /* ...verify the configuration is complete */ +- if (!V4L2_TYPE_IS_OUTPUT(buf->type) && !ctx->cfg) { ++ if (!ctx->cfg) { + v4l2_err(&ctx->imr->v4l2_dev, "stream configuration is not complete\n"); + return -EINVAL; + } +@@ -1265,6 +1348,14 @@ static long imr_default(struct file *file, void *fh, bool valid_prio, unsigned i + /* ...set mesh data */ + return imr_ioctl_map(ctx, (struct imr_map_desc *)arg); + ++ case VIDIOC_IMR_MESH_RAW: ++ /* ...set mesh data */ ++ return imr_ioctl_map_raw(ctx, (struct imr_map_desc *)arg); ++ ++ case VIDIOC_IMR_COLOR: ++ /* ...set solid color code */ ++ return imr_ioctl_color(ctx, *(u32 *)arg); ++ + default: + return -ENOIOCTLCMD; + } +@@ -1326,6 +1417,9 @@ static int imr_open(struct file *file) + /* ...set default cropping parameters */ + ctx->crop[1] = ctx->crop[3] = 0x3FF; + ++ /* ...set default color */ ++ ctx->color = 0x808080; ++ + /* ...initialize M2M processing context */ + ctx->m2m_ctx = v4l2_m2m_ctx_init(imr->m2m_dev, ctx, imr_queue_init); + if (IS_ERR(ctx->m2m_ctx)) { +@@ -1418,8 +1512,11 @@ static unsigned int imr_poll(struct file *file, struct poll_table_struct *wait) + return -ERESTARTSYS; + + res = v4l2_m2m_poll(file, ctx->m2m_ctx, wait); ++ + mutex_unlock(&imr->mutex); + ++ v4l2_dbg(3, debug, &imr->v4l2_dev, "poll result: %X (ctx=%p)\n", res, ctx); ++ + return res; + } + +@@ -1453,7 +1550,6 @@ static const struct v4l2_file_operations imr_fops = { + * M2M device interface + ******************************************************************************/ + +-#if 0 + /* ...job cleanup function */ + static void imr_cleanup(struct imr_ctx *ctx) + { +@@ -1473,17 +1569,16 @@ static void imr_cleanup(struct imr_ctx *ctx) + /* ...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; ++ struct imr_ctx *ctx = priv; ++ struct imr_device *imr = ctx->imr; ++ struct imr_cfg *cfg; ++ struct vb2_v4l2_buffer *src_buf, *dst_buf; ++ u32 src_addr, dst_addr; ++ unsigned long flags; + + v4l2_dbg(3, debug, &imr->v4l2_dev, "run next job...\n"); + +@@ -1494,8 +1589,11 @@ static void imr_device_run(void *priv) + src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); + dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); + ++ /* ...put source/destination buffers sequence numbers */ ++ dst_buf->sequence = src_buf->sequence = ctx->sequence++; ++ + /* ...take configuration pointer associated with input buffer */ +- cfg = to_imr_buffer(to_vb2_v4l2_buffer(src_buf))->cfg; ++ cfg = to_imr_buffer(src_buf)->cfg; + + /* ...cancel software reset state as needed */ + iowrite32(0, imr->mmio + IMR_CR); +@@ -1507,8 +1605,8 @@ static void imr_device_run(void *priv) + 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); ++ *cfg->src_pa_ptr[0] = src_addr = (u32)vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0); ++ *cfg->dst_pa_ptr[0] = dst_addr = (u32)vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0); + + /* ...adjust source/destination parameters of the UV-plane as needed */ + if (cfg->src_pa_ptr[1] && cfg->dst_pa_ptr[1]) { +@@ -1529,6 +1627,9 @@ static void imr_device_run(void *priv) + /* ...set display list address */ + iowrite32(cfg->dl_dma_addr + cfg->dl_start_offset, imr->mmio + IMR_DLSAR); + ++ /* ...enable texture prefetching */ ++ iowrite32(0xACCE5501, imr->mmio + IMR_TPOR); ++ + /* ...explicitly flush any pending write operations (don't need that, I guess) */ + wmb(); + +@@ -1536,7 +1637,7 @@ static void imr_device_run(void *priv) + iowrite32(IMR_CR_RS, imr->mmio + IMR_CR); + + /* ...timestamp input buffer */ +- src_buf->timestamp = ktime_get_ns(); ++ src_buf->vb2_buf.timestamp = ktime_get_ns(); + + /* ...unlock device access */ + spin_unlock_irqrestore(&imr->lock, flags); +@@ -1633,13 +1734,14 @@ static irqreturn_t imr_irq_handler(int irq, void *data) + 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++; ++ //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", ++ v4l2_dbg(3, debug, &imr->v4l2_dev, "buffers <0x%08x,0x%08x> done (ctx=%p)\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)); ++ (u32)vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0), ctx); + } else { + /* ...operation completed in error; no way to understand what exactly went wrong */ + v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR); +@@ -1668,6 +1770,8 @@ static irqreturn_t imr_irq_handler(int irq, void *data) + * Device probing / removal interface + ******************************************************************************/ + ++static struct class *imr_alloc_class; ++ + static int imr_probe(struct platform_device *pdev) + { + struct imr_device *imr; +@@ -1727,6 +1831,26 @@ static int imr_probe(struct platform_device *pdev) + goto device_register_rollback; + } + ++ if (!imr_alloc_class) { ++ imr_alloc_class = class_create(THIS_MODULE, "imr-alloc"); ++ if (IS_ERR(imr_alloc_class)) { ++ v4l2_err(&imr->v4l2_dev, "Failed to create alloc-device class\n"); ++ ret = PTR_ERR(imr_alloc_class); ++ goto m2m_init_rollback; ++ } ++ } ++ ++ struct device *adev = device_create(imr_alloc_class, imr->dev, MKDEV(0, 0), NULL, "%s_alloc", dev_name(&pdev->dev)); ++ if (IS_ERR(adev)) { ++ v4l2_err(&imr->v4l2_dev, "Failed to create alloc-device\n"); ++ ret = PTR_ERR(adev); ++ goto m2m_init_rollback; ++ } ++ adev->dma_mask = &adev->coherent_dma_mask; ++ adev->coherent_dma_mask = DMA_BIT_MASK(32); ++ arch_setup_dma_ops(adev, 0, DMA_BIT_MASK(32) + 1, NULL, true); ++ imr->alloc_dev = adev; ++ + 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; +@@ -1765,6 +1889,7 @@ static int imr_remove(struct platform_device *pdev) + + //pm_runtime_disable(imr->v4l2_dev.dev); + video_unregister_device(&imr->video_dev); ++ //device_destroy(imr->alloc_dev, MKDEV(0, 0)); + v4l2_m2m_release(imr->m2m_dev); + v4l2_device_unregister(&imr->v4l2_dev); + +diff --git a/include/uapi/linux/rcar-imr.h b/include/uapi/linux/rcar-imr.h +index d02082f..7b8ed0c 100644 +--- a/include/uapi/linux/rcar-imr.h ++++ b/include/uapi/linux/rcar-imr.h +@@ -48,6 +48,12 @@ struct imr_map_desc { + /* ...vertex clockwise-mode order */ + #define IMR_MAP_TCM (1 << 5) + ++/* ...texture mapping enable flag */ ++#define IMR_MAP_TME (1 << 6) ++ ++/* ...bilinear filtration enable flag */ ++#define IMR_MAP_BFE (1 << 7) ++ + /* ...source coordinate decimal point position bit index */ + #define __IMR_MAP_UVDPOR_SHIFT 8 + #define __IMR_MAP_UVDPOR(v) (((v) >> __IMR_MAP_UVDPOR_SHIFT) & 0x7) +@@ -81,18 +87,12 @@ struct imr_mesh { + + } __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) ++#define VIDIOC_IMR_MESH_RAW _IOW('V', BASE_VIDIOC_PRIVATE + 1, struct imr_map_desc) ++#define VIDIOC_IMR_COLOR _IOW('V', BASE_VIDIOC_PRIVATE + 2, u32) + + #endif /* RCAR_IMR_USER_H */ +-- +2.7.4 + 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..9796ba5 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/eagle.cfg @@ -0,0 +1,29 @@ +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_CAN_RCAR_CANFD=y +CONFIG_DUMMY=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 +CONFIG_SERIAL_SH_SCI_DMA=y +CONFIG_UIO=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/salvator-x.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/salvator-x.cfg new file mode 100644 index 0000000..a42b74c --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/salvator-x.cfg @@ -0,0 +1,32 @@ +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_CAN_RCAR_CANFD=y +CONFIG_DUMMY=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 +CONFIG_SERIAL_SH_SCI_DMA=y +CONFIG_UIO=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/ulcb.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/ulcb.cfg new file mode 100644 index 0000000..5b637e2 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/ulcb.cfg @@ -0,0 +1,82 @@ +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_CAN_RCAR_CANFD=y +CONFIG_DUMMY=y +CONFIG_EXTRA_FIRMWARE="r8a779x_usb3_v2.dlmem r8a779x_usb3_v3.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_MAX732X_IRQ=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_SOC_CAMERA_OV5647=y +CONFIG_SOC_CAMERA_OV5642=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_PLATFORM=y +CONFIG_USB_XHCI_RCAR=y +CONFIG_USB_ACM=y +CONFIG_VIDEO_RENESAS_IMR=y +CONFIG_VIRTIO_RCAR_PCIE=y +CONFIG_BT=y +CONFIG_BT_BNEP=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_HIDP=m +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_SND_SOC_PCM3168A=y +CONFIG_SND_SOC_PCM3168A_I2C=y +CONFIG_SND_SOC_WL18XX=y +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_PROPERTIES=y +CONFIG_HID_MULTITOUCH=y +CONFIG_IIO=y +CONFIG_IIO_BUFFER=y +CONFIG_IIO_BUFFER_CB=y +CONFIG_IIO_KFIFO_BUF=y +CONFIG_IIO_TRIGGERED_BUFFER=y +CONFIG_IIO_TRIGGER=y +CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 +CONFIG_LSM9DS0=y +CONFIG_DRM_I2C_ADV7511=y +CONFIG_TOUCHSCREEN_EDT_FT5X06=y +CONFIG_SERIAL_SH_SCI_DMA=y +CONFIG_STAGING=y +CONFIG_MOST=y +CONFIG_MOSTCORE=y +CONFIG_AIM_CDEV=y +CONFIG_AIM_NETWORK=y +CONFIG_AIM_SOUND=y +CONFIG_AIM_V4L2=y +CONFIG_HDM_DIM2=y +CONFIG_UIO=y +CONFIG_MMC_SDHI_SEQ_WORKAROUND=y diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3msk.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3msk.cfg new file mode 100644 index 0000000..211da49 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3msk.cfg @@ -0,0 +1,33 @@ +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_CAN_RCAR_CANFD=y +CONFIG_DUMMY=y +CONFIG_DRM_I2C_ADV7511=y +CONFIG_GPIO_MAX732X=y +CONFIG_GPIO_MAX732X_IRQ=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_VIDEO_RENESAS_IMR=y +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_PROPERTIES=y +CONFIG_HID_MULTITOUCH=y +CONFIG_SERIAL_SH_SCI_DMA=y +CONFIG_UIO=y |