diff options
author | Vladimir Barinov <vladimir.barinov@cogentembedded.com> | 2017-05-16 23:37:25 +0300 |
---|---|---|
committer | Vladimir Barinov <vladimir.barinov@cogentembedded.com> | 2017-05-17 10:43:29 +0300 |
commit | 6de4102e912132ff6fbe2d88393517c337473d29 (patch) | |
tree | 0c0c7ff0ebaa918f0259b6243aab0b1d63ec79c3 /meta-rcar-gen3-adas |
Initial commit for ADAS boards support in 2.19.0
Diffstat (limited to 'meta-rcar-gen3-adas')
95 files changed, 41151 insertions, 0 deletions
diff --git a/meta-rcar-gen3-adas/conf/layer.conf b/meta-rcar-gen3-adas/conf/layer.conf new file mode 100644 index 0000000..76c4d8d --- /dev/null +++ b/meta-rcar-gen3-adas/conf/layer.conf @@ -0,0 +1,31 @@ +# We have a conf and classes directory, append to BBPATH +BBPATH .= ":${LAYERDIR}" + +# We have a recipes directory, add to BBFILES +BBFILES += " \ + ${LAYERDIR}/recipes-*/*/*.bb \ + ${LAYERDIR}/recipes-*/*/*.bbappend \ +" + +BBFILE_COLLECTIONS += "rcar-gen3-adas" +BBFILE_PATTERN_rcar-gen3-adas := "^${LAYERDIR}/" +BBFILE_PRIORITY_rcar-gen3-adas = "7" + +# Custom packages +IMAGE_INSTALL_append_rcar-gen3 = " \ + can-utils \ + libsocketcan \ + iproute2 \ + spidev-dbg \ + e2fsprogs \ + ethtool \ + pciutils \ + usbutils \ + util-linux \ + mtd-utils \ + capture \ + v4l2-fw \ + iperf \ + bonnie++ \ + lmbench \ +" diff --git a/meta-rcar-gen3-adas/recipes-bsp/arm-trusted-firmware/arm-trusted-firmware_git.bbappend b/meta-rcar-gen3-adas/recipes-bsp/arm-trusted-firmware/arm-trusted-firmware_git.bbappend new file mode 100644 index 0000000..dabc276 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/arm-trusted-firmware/arm-trusted-firmware_git.bbappend @@ -0,0 +1 @@ +ATFW_OPT_append = " ${@base_conditional("CA57CA53BOOT", "1", " PSCI_DISABLE_BIGLITTLE_IN_CA57BOOT=0", "", d)}" diff --git a/meta-rcar-gen3-adas/recipes-bsp/capture/capture_1.0.bb b/meta-rcar-gen3-adas/recipes-bsp/capture/capture_1.0.bb new file mode 100644 index 0000000..dbfc8c4 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/capture/capture_1.0.bb @@ -0,0 +1,39 @@ +SUMMARY = "Camera application test" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://COPYING;md5=9504a7b7666faec5abd046d28a69450e" + +S = "${WORKDIR}/capture" + +SRC_URI = " \ + file://capture.tar.gz \ +" + +do_compile() { + cd ${S} + make all || die +} + +do_install() { + install -d ${D}${bindir} + install -m 755 ${S}/capture ${D}${bindir} + + install -d ${D}/usr/share/tests/ + install -m 755 ${S}/test_lvds_camera_0.sh ${D}/usr/share/tests/ + install -m 755 ${S}/test_lvds_camera_4.sh ${D}/usr/share/tests/ + install -m 755 ${S}/test_lvds_camera_0-3.sh ${D}/usr/share/tests/ + install -m 755 ${S}/test_lvds_camera_4-7.sh ${D}/usr/share/tests/ + install -m 755 ${S}/test_lvds_2cameras_on_display1920x1080.sh ${D}/usr/share/tests/ + install -m 755 ${S}/test_lvds_4cameras_on_display1920x1080.sh ${D}/usr/share/tests/ + install -m 755 ${S}/test_lvds_8cameras_on_display1920x1080.sh ${D}/usr/share/tests/ +} + +FILES_${PN} = " \ + ${bindir}/capture \ + /usr/share/tests/test_lvds_camera_0.sh \ + /usr/share/tests/test_lvds_camera_4.sh \ + /usr/share/tests/test_lvds_camera_0-3.sh \ + /usr/share/tests/test_lvds_camera_4-7.sh \ + /usr/share/tests/test_lvds_2cameras_on_display1920x1080.sh \ + /usr/share/tests/test_lvds_4cameras_on_display1920x1080.sh \ + /usr/share/tests/test_lvds_8cameras_on_display1920x1080.sh \ +" diff --git a/meta-rcar-gen3-adas/recipes-bsp/capture/files/capture.tar.gz b/meta-rcar-gen3-adas/recipes-bsp/capture/files/capture.tar.gz Binary files differnew file mode 100644 index 0000000..11053be --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/capture/files/capture.tar.gz diff --git a/meta-rcar-gen3-adas/recipes-bsp/mpssd/files/mpssd.tar.gz b/meta-rcar-gen3-adas/recipes-bsp/mpssd/files/mpssd.tar.gz Binary files differnew file mode 100644 index 0000000..4439f2a --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/mpssd/files/mpssd.tar.gz diff --git a/meta-rcar-gen3-adas/recipes-bsp/mpssd/mpssd_1.0.bb b/meta-rcar-gen3-adas/recipes-bsp/mpssd/mpssd_1.0.bb new file mode 100644 index 0000000..0d7db01 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/mpssd/mpssd_1.0.bb @@ -0,0 +1,27 @@ +SUMMARY = "MPSSD" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://COPYING;md5=58dd7e3251f8a7d8c3784355098b8d53" + +DEPENDS = "virtual/kernel" + +export KERNELDIR = "${STAGING_KERNEL_DIR}" + +S = "${WORKDIR}/mpssd" + +SRC_URI = " \ + file://mpssd.tar.gz \ +" + +do_compile() { + cd ${S} + make all || die +} + +do_install() { + install -d ${D}${bindir} + install -m 755 ${S}/mpssd ${D}${bindir} +} + +FILES_${PN} = " \ + ${bindir}/mpssd \ +" diff --git a/meta-rcar-gen3-adas/recipes-bsp/spidev-dbg/files/spidev-dbg.tar.gz b/meta-rcar-gen3-adas/recipes-bsp/spidev-dbg/files/spidev-dbg.tar.gz Binary files differnew file mode 100644 index 0000000..49e3192 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/spidev-dbg/files/spidev-dbg.tar.gz diff --git a/meta-rcar-gen3-adas/recipes-bsp/spidev-dbg/spidev-dbg_1.0.bb b/meta-rcar-gen3-adas/recipes-bsp/spidev-dbg/spidev-dbg_1.0.bb new file mode 100644 index 0000000..36aa562 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/spidev-dbg/spidev-dbg_1.0.bb @@ -0,0 +1,21 @@ +SUMMARY = "SPI device debug utility" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://COPYING;md5=26cdfe4d6a85afebc7ccd5623f195fa2" + +S = "${WORKDIR}/spidev-dbg" + +SRC_URI = " \ + file://spidev-dbg.tar.gz \ +" + +do_compile() { + cd ${S} + make all || die +} + +do_install() { + install -d ${D}${bindir} + install -m 755 ${S}/spidev-dbg ${D}${bindir} +} + +FILES_${PN} = "${bindir}/spidev-dbg" diff --git a/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0001-net-phy-support-fixed-PHY.patch b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0001-net-phy-support-fixed-PHY.patch new file mode 100644 index 0000000..e745be7 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0001-net-phy-support-fixed-PHY.patch @@ -0,0 +1,115 @@ +From 1f65b4710c1f51d01032db201543d0a8269a715f Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Fri, 20 May 2016 01:18:44 +0300 +Subject: [PATCH] uboot: net: support fixed-PHY + +Add support for fixed-PHY + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + drivers/net/phy/Makefile | 1 + + drivers/net/phy/fixed.c | 43 +++++++++++++++++++++++++++++++++++++++++++ + drivers/net/phy/phy.c | 5 ++++- + include/phy.h | 1 + + 6 files changed, 57 insertions(+), 1 deletion(-) + create mode 100644 drivers/net/phy/fixed.c + +diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile +index d096db8..497785e 100644 +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -17,6 +17,7 @@ obj-$(CONFIG_PHY_BROADCOM) += broadcom.o + obj-$(CONFIG_PHY_CORTINA) += cortina.o + obj-$(CONFIG_PHY_DAVICOM) += davicom.o + obj-$(CONFIG_PHY_ET1011C) += et1011c.o ++obj-$(CONFIG_PHY_FIXED) += fixed.o + obj-$(CONFIG_PHY_LXT) += lxt.o + obj-$(CONFIG_PHY_MARVELL) += marvell.o + obj-$(CONFIG_PHY_MICREL) += micrel.o +diff --git a/drivers/net/phy/fixed.c b/drivers/net/phy/fixed.c +new file mode 100644 +index 0000000..4d44aad +--- /dev/null ++++ b/drivers/net/phy/fixed.c +@@ -0,0 +1,43 @@ ++/* ++ * Fixed PHY driver ++ * ++ * Copyright (C) 2016 Renesas Electronics Corporation ++ * Copyright (C) 2016 Cogent Embedded, Inc. ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ */ ++ ++#include <config.h> ++#include <common.h> ++#include <phy.h> ++ ++int fixed_config(struct phy_device *phydev) ++{ ++ phydev->speed = CONFIG_PHY_FIXED_SPEED; ++ phydev->duplex = CONFIG_PHY_FIXED_DUPLEX; ++ phydev->link = 1; ++ ++ return 0; ++} ++ ++static int fixed_startup(struct phy_device *phydev) ++{ ++ return 0; ++} ++ ++static struct phy_driver fixed_driver = { ++ .uid = 0x0, ++ .mask = 0x0, ++ .name = "fixed-PHY", ++ .features = PHY_10G_FEATURES, ++ .config = &fixed_config, ++ .startup = &fixed_startup, ++ .shutdown = &genphy_shutdown, ++}; ++ ++int phy_fixed_init(void) ++{ ++ phy_register(&fixed_driver); ++ ++ return 0; ++} +diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c +index df7e945..3ee6402 100644 +--- a/drivers/net/phy/phy.c ++++ b/drivers/net/phy/phy.c +@@ -484,6 +484,9 @@ int phy_init(void) + #ifdef CONFIG_PHY_VITESSE + phy_vitesse_init(); + #endif ++#ifdef CONFIG_PHY_FIXED ++ phy_fixed_init(); ++#endif + + return 0; + } +@@ -764,7 +767,7 @@ void phy_connect_dev(struct phy_device *phydev, struct eth_device *dev) + phydev->dev->name, dev->name); + } + phydev->dev = dev; +- debug("%s connected to %s\n", dev->name, phydev->drv->name); ++ printf("%s connected to %s\n", dev->name, phydev->drv->name); + } + + struct phy_device *phy_connect(struct mii_dev *bus, int addr, +diff --git a/include/phy.h b/include/phy.h +index d117fc1..c2f2cbc 100644 +--- a/include/phy.h ++++ b/include/phy.h +@@ -239,6 +239,7 @@ int phy_realtek_init(void); + int phy_smsc_init(void); + int phy_teranetics_init(void); + int phy_vitesse_init(void); ++int phy_fixed_init(void); + + int board_phy_config(struct phy_device *phydev); + +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0002-net-ravb-remove-APSR-quirk.patch b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0002-net-ravb-remove-APSR-quirk.patch new file mode 100644 index 0000000..60c9e14 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0002-net-ravb-remove-APSR-quirk.patch @@ -0,0 +1,33 @@ +From 1247dea7b49d7e66e1848da71e28ff5fe9acf5e1 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Thu, 16 Jun 2016 11:41:43 +0300 +Subject: [PATCH] uboot: ravb: remove APSR quirk + +Remove 2ns delay interoduces by DMAC APSR. This is +not used in linux kernel, hence it is important to skips this +in uboot. + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + drivers/net/ravb.c | 5 ----- + 1 files changed, 0 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ravb.c b/drivers/net/ravb.c +index c168381..f4d7aed 100644 +--- a/drivers/net/ravb.c ++++ b/drivers/net/ravb.c +@@ -428,11 +428,6 @@ static int ravb_dmac_init(struct ravb_dev *eth) + /* FIFO size set */ + ravb_write(eth, 0x00222210, TGC); + +- if (CONFIG_RAVB_PHY_MODE == PHY_INTERFACE_MODE_RGMII_ID) { +- /* delay CLK: 2ns */ +- ravb_write(eth, 0x1ul << 14, APSR); +- } +- + return ret; + } + +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0003-net-ravb-fix-unsafe-phy-access.patch b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0003-net-ravb-fix-unsafe-phy-access.patch new file mode 100644 index 0000000..584d6d5 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0003-net-ravb-fix-unsafe-phy-access.patch @@ -0,0 +1,30 @@ +From 63534a79e2fb1e4102fe38f339ecb891682a781e Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Fri, 23 Sep 2016 18:26:53 +0300 +Subject: [PATCH] net: ravb: fix unsafe phy access + +This fixes the ravb driver crash for phy/phyless glue +that do not have writeext field + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + drivers/net/ravb.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ravb.c b/drivers/net/ravb.c +index f4d7aed..5d90a3e 100644 +--- a/drivers/net/ravb.c ++++ b/drivers/net/ravb.c +@@ -475,7 +475,8 @@ static int ravb_config(struct ravb_dev *eth, bd_t *bd) + ravb_write(eth, ECMR_CHG_DM | ECMR_RE | ECMR_TE, ECMR); + } + +- phy->drv->writeext(phy, -1, 0x02, 0x08, (0x0f<<5) | 0x19); ++ if (phy->drv->writeext) ++ phy->drv->writeext(phy, -1, 0x02, 0x08, (0x0f<<5) | 0x19); + + err_phy_cfg: + return ret; +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0004-configs-rcar-gen3-add-CMD_GPIO.patch b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0004-configs-rcar-gen3-add-CMD_GPIO.patch new file mode 100644 index 0000000..f95994f --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0004-configs-rcar-gen3-add-CMD_GPIO.patch @@ -0,0 +1,27 @@ +From 3e733c036e8f50cf073b598074ce9fd6796ec89f Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Sun, 31 Jul 2016 03:59:13 +0300 +Subject: [PATCH] configs: rcar-gen3: add CMD_GPIO + +Enable CONFIG_CMD_GPIO + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + include/configs/rcar-gen3-common.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/include/configs/rcar-gen3-common.h b/include/configs/rcar-gen3-common.h +index 63b80a4..50cfa8a 100644 +--- a/include/configs/rcar-gen3-common.h ++++ b/include/configs/rcar-gen3-common.h +@@ -31,6 +31,7 @@ + #define CONFIG_CMD_EXT2 + #define CONFIG_CMD_EXT4 + #define CONFIG_CMD_EXT4_WRITE ++#define CONFIG_CMD_GPIO + + #define CONFIG_SYS_THUMB_BUILD + #define CONFIG_SYS_GENERIC_BOARD +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0005-common-cmd_source.c-Fix-the-source-command-failure-u.patch b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0005-common-cmd_source.c-Fix-the-source-command-failure-u.patch new file mode 100644 index 0000000..81a205f --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0005-common-cmd_source.c-Fix-the-source-command-failure-u.patch @@ -0,0 +1,53 @@ +From 5b189130c95630cf68c50255fb0d1ed0515cb92a Mon Sep 17 00:00:00 2001 +From: Gong Qianyu <Qianyu.Gong@freescale.com> +Date: Thu, 30 Jul 2015 14:00:01 +0800 +Subject: [PATCH] common/cmd_source.c: Fix the source command failure + under 64-bit platform + +Modify the data pointer type from ulong* to u32*. + +For arm64 type "ulong" could be 64-bit. Then in line 88 of common/cmd_source.c: +"while (*data++);" data will point to the next 64 bits each time. As the uImage +file generated by mkimage tool keeps the same data format in either 32-bit or 64-bit +platform, the difference would cause failure in 64-bit platform. + +Signed-off-by: Gong Qianyu <Qianyu.Gong@freescale.com> +Signed-off-by: Valentine Barshak <valentine.barshak@cogentembedded.com> +--- + common/cmd_source.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/common/cmd_source.c b/common/cmd_source.c +index 6881bc9..291e5f4 100644 +--- a/common/cmd_source.c ++++ b/common/cmd_source.c +@@ -32,7 +32,7 @@ source (ulong addr, const char *fit_uname) + #if defined(CONFIG_IMAGE_FORMAT_LEGACY) + const image_header_t *hdr; + #endif +- ulong *data; ++ u32 *data; + int verify; + void *buf; + #if defined(CONFIG_FIT) +@@ -73,7 +73,7 @@ source (ulong addr, const char *fit_uname) + } + + /* get length of script */ +- data = (ulong *)image_get_data (hdr); ++ data = (u32 *)image_get_data (hdr); + + if ((len = uimage_to_cpu (*data)) == 0) { + puts ("Empty Script\n"); +@@ -127,7 +127,7 @@ source (ulong addr, const char *fit_uname) + return 1; + } + +- data = (ulong *)fit_data; ++ data = (u32 *)fit_data; + len = (ulong)fit_len; + break; + #endif +-- +1.9.3 + diff --git a/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0006-configs-rcar-gen3-common-Enable-U-Boot-scripts.patch b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0006-configs-rcar-gen3-common-Enable-U-Boot-scripts.patch new file mode 100644 index 0000000..aa92851 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0006-configs-rcar-gen3-common-Enable-U-Boot-scripts.patch @@ -0,0 +1,30 @@ +From 3defaae29edd09e89ea0d05082a7a8d5d2cb48d0 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak <valentine.barshak@cogentembedded.com> +Date: Sat, 10 Sep 2016 04:26:24 +0300 +Subject: [PATCH] configs: rcar-gen3-common: Enable U-Boot scripts + +This enables "source" command, which can be used +for running U-Boot scripts in order to simplify +flashing procedure. + +Signed-off-by: Valentine Barshak <valentine.barshak@cogentembedded.com> +--- + include/configs/rcar-gen3-common.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/include/configs/rcar-gen3-common.h b/include/configs/rcar-gen3-common.h +index 50cfa8a..bab2c2c 100644 +--- a/include/configs/rcar-gen3-common.h ++++ b/include/configs/rcar-gen3-common.h +@@ -33,6 +33,8 @@ + #define CONFIG_CMD_EXT4_WRITE + #define CONFIG_CMD_GPIO + ++#define CONFIG_CMD_SOURCE ++ + #define CONFIG_SYS_THUMB_BUILD + #define CONFIG_SYS_GENERIC_BOARD + +-- +1.9.3 + diff --git a/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0007-configs-rcar-gen3-common-Enable-echo-command.patch b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0007-configs-rcar-gen3-common-Enable-echo-command.patch new file mode 100644 index 0000000..fe5ab67 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0007-configs-rcar-gen3-common-Enable-echo-command.patch @@ -0,0 +1,28 @@ +From bb2193f5970ca989910df135010f39d0931c79fb Mon Sep 17 00:00:00 2001 +From: Valentine Barshak <valentine.barshak@cogentembedded.com> +Date: Sat, 10 Sep 2016 05:20:07 +0300 +Subject: [PATCH] configs: rcar-gen3-common: Enable echo command + +This enables "echo" command, which can be used +to make U-Boot scripts more verbose. + +Signed-off-by: Valentine Barshak <valentine.barshak@cogentembedded.com> +--- + include/configs/rcar-gen3-common.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/include/configs/rcar-gen3-common.h b/include/configs/rcar-gen3-common.h +index bab2c2c..7b75562 100644 +--- a/include/configs/rcar-gen3-common.h ++++ b/include/configs/rcar-gen3-common.h +@@ -34,6 +34,7 @@ + #define CONFIG_CMD_GPIO + + #define CONFIG_CMD_SOURCE ++#define CONFIG_CMD_ECHO + + #define CONFIG_SYS_THUMB_BUILD + #define CONFIG_SYS_GENERIC_BOARD +-- +1.9.3 + diff --git a/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0008-configs-rcar-gen3-common-Enable-setexpr-command.patch b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0008-configs-rcar-gen3-common-Enable-setexpr-command.patch new file mode 100644 index 0000000..34e0942 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0008-configs-rcar-gen3-common-Enable-setexpr-command.patch @@ -0,0 +1,28 @@ +From d26edbbf50868a39e840c5f775a9e48f063ec638 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak <valentine.barshak@cogentembedded.com> +Date: Tue, 20 Sep 2016 23:20:15 +0300 +Subject: [PATCH] configs: rcar-gen3-common: Enable setexpr command + +This enables "setexpr" command, which can be used +to evaluate expressions. + +Signed-off-by: Valentine Barshak <valentine.barshak@cogentembedded.com> +--- + include/configs/rcar-gen3-common.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/include/configs/rcar-gen3-common.h b/include/configs/rcar-gen3-common.h +index 7b75562..aaeaf57 100644 +--- a/include/configs/rcar-gen3-common.h ++++ b/include/configs/rcar-gen3-common.h +@@ -35,6 +35,7 @@ + + #define CONFIG_CMD_SOURCE + #define CONFIG_CMD_ECHO ++#define CONFIG_CMD_SETEXPR + + #define CONFIG_SYS_THUMB_BUILD + #define CONFIG_SYS_GENERIC_BOARD +-- +1.9.3 + diff --git a/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0009-configs-rcar-gen3-common-Enable-askenv-command.patch b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0009-configs-rcar-gen3-common-Enable-askenv-command.patch new file mode 100644 index 0000000..4cb1b03 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0009-configs-rcar-gen3-common-Enable-askenv-command.patch @@ -0,0 +1,28 @@ +From 5e9a9694daa132d7b4acfd334fe3fe7f3a25b839 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak <valentine.barshak@cogentembedded.com> +Date: Wed, 21 Sep 2016 02:19:13 +0300 +Subject: [PATCH] configs: rcar-gen3-common: Enable askenv command + +This enables "askenv" command, which can be used +in U-Boot scripts for user input. + +Signed-off-by: Valentine Barshak <valentine.barshak@cogentembedded.com> +--- + include/configs/rcar-gen3-common.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/include/configs/rcar-gen3-common.h b/include/configs/rcar-gen3-common.h +index aaeaf57..2c2a5a5 100644 +--- a/include/configs/rcar-gen3-common.h ++++ b/include/configs/rcar-gen3-common.h +@@ -36,6 +36,7 @@ + #define CONFIG_CMD_SOURCE + #define CONFIG_CMD_ECHO + #define CONFIG_CMD_SETEXPR ++#define CONFIG_CMD_ASKENV + + #define CONFIG_SYS_THUMB_BUILD + #define CONFIG_SYS_GENERIC_BOARD +-- +1.9.3 + diff --git a/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0010-configs-rcar-gen3-common-Enable-hush-parser.patch b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0010-configs-rcar-gen3-common-Enable-hush-parser.patch new file mode 100644 index 0000000..b02cd7a --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0010-configs-rcar-gen3-common-Enable-hush-parser.patch @@ -0,0 +1,30 @@ +From d3687cb45f88245068027956b3e42f13f854dbc0 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak <valentine.barshak@cogentembedded.com> +Date: Mon, 12 Sep 2016 21:00:01 +0300 +Subject: [PATCH] configs: rcar-gen3-common: Enable hush parser + +This enables hush parser, which supports +conditionals and can be used to make +U-Boot scripts more flexible. + +Signed-off-by: Valentine Barshak <valentine.barshak@cogentembedded.com> +--- + include/configs/rcar-gen3-common.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/include/configs/rcar-gen3-common.h b/include/configs/rcar-gen3-common.h +index 2c2a5a5..aa692e5 100644 +--- a/include/configs/rcar-gen3-common.h ++++ b/include/configs/rcar-gen3-common.h +@@ -41,6 +41,8 @@ + #define CONFIG_SYS_THUMB_BUILD + #define CONFIG_SYS_GENERIC_BOARD + ++#define CONFIG_SYS_HUSH_PARSER ++ + #define CONFIG_REMAKE_ELF + + /* boot option */ +-- +1.9.3 + diff --git a/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0011-configs-rcar-gen3-common-Enable-GPT-support.patch b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0011-configs-rcar-gen3-common-Enable-GPT-support.patch new file mode 100644 index 0000000..a45cbc7 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0011-configs-rcar-gen3-common-Enable-GPT-support.patch @@ -0,0 +1,32 @@ +From 04c11b42dc2eca5858e393c80e15d72c73440fb9 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak <valentine.barshak@cogentembedded.com> +Date: Fri, 21 Oct 2016 01:21:55 +0300 +Subject: [PATCH] configs: rcar-gen3-common: Enable GPT support + +This enables GPT support in rcar-gen3-common.h. +It can be used for disk partitioning in U-Boot. + +Signed-off-by: Valentine Barshak <valentine.barshak@cogentembedded.com> +--- + include/configs/rcar-gen3-common.h | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/include/configs/rcar-gen3-common.h b/include/configs/rcar-gen3-common.h +index aa692e5..0fc46ab 100644 +--- a/include/configs/rcar-gen3-common.h ++++ b/include/configs/rcar-gen3-common.h +@@ -38,6 +38,11 @@ + #define CONFIG_CMD_SETEXPR + #define CONFIG_CMD_ASKENV + ++#define CONFIG_EFI_PARTITION ++#define CONFIG_PARTITION_UUIDS ++#define CONFIG_RANDOM_UUID ++#define CONFIG_CMD_GPT ++ + #define CONFIG_SYS_THUMB_BUILD + #define CONFIG_SYS_GENERIC_BOARD + +-- +1.9.3 + diff --git a/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0012-board-ulcb-Fix-reset-command-clock-setting.patch b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0012-board-ulcb-Fix-reset-command-clock-setting.patch new file mode 100644 index 0000000..3ddd592 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0012-board-ulcb-Fix-reset-command-clock-setting.patch @@ -0,0 +1,49 @@ +From 238ab2a2f90819ef4a050b8d2a8f1b1359e2a28a Mon Sep 17 00:00:00 2001 +From: Yusuke Goda <yusuke.goda.sx@renesas.com> +Date: Thu, 11 May 2017 19:46:18 +0900 +Subject: [PATCH] board: ulcb: Fix reset command clock setting + +Reset command uses the power control of the PMIC via CPLD. +CPLD is connected by GPIO2 and GPIO6, so GPIO2 and GPIO6 +clock need to be supplied. + +Signed-off-by: Yusuke Goda <yusuke.goda.sx@renesas.com> +--- + board/renesas/ulcb/cpld.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/board/renesas/ulcb/cpld.c b/board/renesas/ulcb/cpld.c +index abc7c84..66922d7 100644 +--- a/board/renesas/ulcb/cpld.c ++++ b/board/renesas/ulcb/cpld.c +@@ -9,6 +9,7 @@ + + #include <common.h> + #include <asm/arch/prr_depend.h> ++#include <asm/arch/rcar-mstp.h> + #include <asm/io.h> + #include <asm/gpio.h> + +@@ -24,6 +25,9 @@ + #define MISO GPIO_GP_6_10 + #endif + ++#define GP2_MSTP910 (1 << 10) ++#define GP6_MSTP906 (1 << 6) ++ + #define CPLD_ADDR_MODE 0x00 /* RW */ + #define CPLD_ADDR_MUX 0x02 /* RW */ + #define CPLD_ADDR_DIPSW6 0x08 /* R */ +@@ -103,6 +107,9 @@ static void cpld_init(void) + val |= PUEN_SSI_SDATA4; + writel(val, PFC_PUEN5); + ++ /* GPIO2, GPIO6 for reset */ ++ mstp_clrbits_le32(MSTPSR9, SMSTPCR9, GP6_MSTP906 | GP2_MSTP910); ++ + gpio_request(SCLK, NULL); + gpio_request(SSTBZ, NULL); + gpio_request(MOSI, NULL); +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0013-mtd-spi-QSPI-flash-support.patch b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0013-mtd-spi-QSPI-flash-support.patch new file mode 100644 index 0000000..beec9c9 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0013-mtd-spi-QSPI-flash-support.patch @@ -0,0 +1,1763 @@ +From 423d01a1b367d82a3855972483530968309cbbd4 Mon Sep 17 00:00:00 2001 +From: Daisuke Matsushita <daisuke.matsushita.ns@hitachi.com> +Date: Tue, 21 Mar 2017 15:05:15 +0900 +Subject: [PATCH] mtd: spi: Add QSPI flash + +This supports QSPI flash + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + arch/arm/include/asm/arch-rcar_gen3/rcar-base.h | 1 + drivers/mtd/spi/sf.c | 15 + drivers/mtd/spi/sf_internal.h | 195 ++++++--- + drivers/mtd/spi/sf_ops.c | 64 +++ + drivers/mtd/spi/sf_params.c | 249 +++++++----- + drivers/mtd/spi/sf_probe.c | 72 +-- + drivers/spi/Makefile | 1 + drivers/spi/rcar_gen3_qspi.c | 484 ++++++++++++++++++++++++ + drivers/spi/rcar_gen3_qspi.h | 301 ++++++++++++++ + include/linux/bitops.h | 1 + include/spi.h | 22 - + 11 files changed, 1191 insertions(+), 214 deletions(-) + create mode 100644 drivers/spi/rcar_gen3_qspi.c + create mode 100644 drivers/spi/rcar_gen3_qspi.h + +diff --git a/arch/arm/include/asm/arch-rcar_gen3/rcar-base.h b/arch/arm/include/asm/arch-rcar_gen3/rcar-base.h +index 59d34b8..b75e4fb 100644 +--- a/arch/arm/include/asm/arch-rcar_gen3/rcar-base.h ++++ b/arch/arm/include/asm/arch-rcar_gen3/rcar-base.h +@@ -18,6 +18,7 @@ + #define LBSC_BASE 0xEE220200 + #define TMU_BASE 0xE61E0000 + #define GPIO5_BASE 0xE6055000 ++#define SH_QSPI_BASE 0xEE200000 + + /* SCIF */ + #define SCIF0_BASE 0xE6E60000 +diff --git a/drivers/mtd/spi/sf.c b/drivers/mtd/spi/sf.c +index 664e860..4e27bab 100644 +--- a/drivers/mtd/spi/sf.c ++++ b/drivers/mtd/spi/sf.c +@@ -8,7 +8,11 @@ + */ + + #include <common.h> ++#if defined(CONFIG_RCAR_GEN3) ++#include "../../spi/rcar_gen3_qspi.h" ++#else + #include <spi.h> ++#endif + + static int spi_flash_read_write(struct spi_slave *spi, + const u8 *cmd, size_t cmd_len, +@@ -25,16 +29,13 @@ static int spi_flash_read_write(struct spi_slave *spi, + if (data_len == 0) + flags |= SPI_XFER_END; + +- ret = spi_xfer(spi, cmd_len * 8, cmd, NULL, flags); ++ ret = spi_xfer_cmd(spi, *cmd); + if (ret) { +- debug("SF: Failed to send command (%zu bytes): %d\n", +- cmd_len, ret); ++ debug("SF: Failed to send command (%zu bytes): %d\n", cmd_len, ret); + } else if (data_len != 0) { +- ret = spi_xfer(spi, data_len * 8, data_out, data_in, +- SPI_XFER_END); ++ ret = spi_xfer(spi, data_len * 8, data_out, data_in, flags|SPI_XFER_END); + if (ret) +- debug("SF: Failed to transfer %zu bytes of data: %d\n", +- data_len, ret); ++ debug("SF: Failed to transfer %zu bytes of data: %d\n", data_len, ret); + } + + return ret; +diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h +index 785f7a9..aacee1a 100644 +--- a/drivers/mtd/spi/sf_internal.h ++++ b/drivers/mtd/spi/sf_internal.h +@@ -12,6 +12,7 @@ + + #include <linux/types.h> + #include <linux/compiler.h> ++#include <spi_flash.h> + + /* Dual SPI flash memories - see SPI_COMM_DUAL_... */ + enum spi_dual_flash { +@@ -20,33 +21,6 @@ enum spi_dual_flash { + SF_DUAL_PARALLEL_FLASH = 1 << 1, + }; + +-/* Enum list - Full read commands */ +-enum spi_read_cmds { +- ARRAY_SLOW = 1 << 0, +- ARRAY_FAST = 1 << 1, +- DUAL_OUTPUT_FAST = 1 << 2, +- DUAL_IO_FAST = 1 << 3, +- QUAD_OUTPUT_FAST = 1 << 4, +- QUAD_IO_FAST = 1 << 5, +-}; +- +-/* Normal - Extended - Full command set */ +-#define RD_NORM (ARRAY_SLOW | ARRAY_FAST) +-#define RD_EXTN (RD_NORM | DUAL_OUTPUT_FAST | DUAL_IO_FAST) +-#define RD_FULL (RD_EXTN | QUAD_OUTPUT_FAST | QUAD_IO_FAST) +- +-/* sf param flags */ +-enum { +- SECT_4K = 1 << 0, +- SECT_32K = 1 << 1, +- E_FSR = 1 << 2, +- SST_BP = 1 << 3, +- SST_WP = 1 << 4, +- WR_QPP = 1 << 5, +-}; +- +-#define SST_WR (SST_BP | SST_WP) +- + #define SPI_FLASH_3B_ADDR_LEN 3 + #define SPI_FLASH_CMD_LEN (1 + SPI_FLASH_3B_ADDR_LEN) + #define SPI_FLASH_16MB_BOUN 0x1000000 +@@ -57,31 +31,101 @@ enum { + #define SPI_FLASH_CFI_MFR_MACRONIX 0xc2 + #define SPI_FLASH_CFI_MFR_WINBOND 0xef + +-/* Erase commands */ +-#define CMD_ERASE_4K 0x20 +-#define CMD_ERASE_32K 0x52 +-#define CMD_ERASE_CHIP 0xc7 +-#define CMD_ERASE_64K 0xd8 ++/* Read Device ID */ ++#define CMD_READ_ID 0x9f ++#define CMD_READ_SFDP 0x5a ++#define CMD_READ_QUAD_ID 0xaf + +-/* Write commands */ ++/* Register Access */ ++#define CMD_READ_STATUS 0x05 ++#define CMD_READ_STATUS2 0x07 ++#define CMD_READ_STATUS1 0x35 ++#define CMD_READ_CONFIG 0x35 ++#define CMD_READ_ANY_REG 0x65 + #define CMD_WRITE_STATUS 0x01 +-#define CMD_PAGE_PROGRAM 0x02 + #define CMD_WRITE_DISABLE 0x04 +-#define CMD_READ_STATUS 0x05 +-#define CMD_QUAD_PAGE_PROGRAM 0x32 +-#define CMD_READ_STATUS1 0x35 + #define CMD_WRITE_ENABLE 0x06 +-#define CMD_READ_CONFIG 0x35 +-#define CMD_FLAG_STATUS 0x70 ++#define CMD_WRITE_ANY_REG 0x71 ++#define CMD_CLSR 0x30 ++#define CMD_CLSR_ALT 0x82 ++#define CMD_4BYTE_ADDR_MODE 0xb7 ++#define CMD_SET_BURST_LEN 0xc0 ++#define CMD_EVALUATE_ERASE_STATUS 0xd0 ++#define CMD_ECC_READ 0x19 ++#define CMD_ECC_READ_ADDR4 0x18 ++#define CMD_DLPRD 0x41 ++#define CMD_PNVDLR 0x43 ++#define CMD_WVDLR 0x4a + + /* Read commands */ + #define CMD_READ_ARRAY_SLOW 0x03 ++#define CMD_READ_ARRAY_SLOW_ADDR4 0x13 + #define CMD_READ_ARRAY_FAST 0x0b ++#define CMD_READ_ARRAY_FAST_ADDR4 0x0c + #define CMD_READ_DUAL_OUTPUT_FAST 0x3b + #define CMD_READ_DUAL_IO_FAST 0xbb ++#define CMD_READ_DUAL_IO_FAST_ADDR4 0xbc + #define CMD_READ_QUAD_OUTPUT_FAST 0x6b + #define CMD_READ_QUAD_IO_FAST 0xeb +-#define CMD_READ_ID 0x9f ++#define CMD_READ_QUAD_IO_FAST_ADDR4 0xec ++#define CMD_READ_QUAD_IO_DDR 0xed ++#define CMD_READ_QUAD_IO_DDR_ADDR4 0xee ++ ++/* Write commands */ ++#define CMD_PAGE_PROGRAM 0x02 ++#define CMD_PAGE_PROGRAM_ADDR4 0x12 ++#define CMD_QUAD_PAGE_PROGRAM 0x32 ++#define CMD_FLAG_STATUS 0x70 ++ ++/* Erase commands */ ++#define CMD_ERASE_4K 0x20 ++#define CMD_ERASE_4K_ADDR4 0x21 ++#define CMD_ERASE_32K 0x52 ++#define CMD_ERASE_CHIP 0xc7 ++#define CMD_ERASE_64K 0xd8 ++#define CMD_ERASE_256K_ADDR4 0xdc ++#define CMD_BULK_ERASE 0x60 ++#define CMD_BULK_ERASE_ALT 0xc7 ++ ++/* Erase Program / Suspend Program */ ++#define CMD_EPS 0x75 ++#define CMD_EPS_ALT 0x85 ++#define CMD_EPS_ALT2 0xb0 ++#define CMD_EPR 0x7a ++#define CMD_EPR_ALT 0x8a ++#define CMD_EPR_ALT2 0x30 ++ ++/* One Time Program Array */ ++#define CMD_OTP_PROGRAM 0x42 ++#define CMD_OTP_READ 0x4b ++ ++/* Advanced Sector Protection */ ++#define CMD_DYB_READ 0xfa ++#define CMD_DYB_READ_ADDR4 0xe0 ++#define CMD_DYB_WRITE 0xfb ++#define CMD_DYB_WRITE_ADDR4 0xe1 ++#define CMD_PPB_READ 0xfc ++#define CMD_PPB_READ_ADDR4 0xe2 ++#define CMD_PPB_PROGRAM 0xfd ++#define CMD_PPB_PROGRAM_ADDR4 0xe3 ++#define CMD_PPB_ERASE 0xe4 ++#define CMD_ASP_READ 0x2b ++#define CMD_ASP_PROGRAM 0x2f ++#define CMD_PPB_LOCKBIT_READ 0xa7 ++#define CMD_PPB_LOCKBIT_WRITE 0xa6 ++#define CMD_PASSWD_READ 0xe7 ++#define CMD_PASSWD_PROGRAM 0xe8 ++#define CMD_PASSWD_UNLOCK 0xe9 ++ ++/* Reset */ ++#define CMD_SOFT_RESET_ENABLE 0x66 ++#define CMD_SOFT_RESET 0x99 ++#define CMD_LEGACY_SOFT_RESET 0xf0 ++#define CMD_MODE_BIT_RESET 0xff ++ ++/* DPD */ ++#define CMD_ENT_DEEP_POWER_DOWN 0xb9 ++#define CMD_REL_DEEP_POWER_DOWN 0xab + + /* Bank addr access commands */ + #ifdef CONFIG_SPI_FLASH_BAR +@@ -94,13 +138,22 @@ enum { + /* Common status */ + #define STATUS_WIP (1 << 0) + #define STATUS_QEB_WINSPAN (1 << 1) +-#define STATUS_QEB_MXIC (1 << 6) ++#define STATUS_QEB_MXIC (1 << 6) + #define STATUS_PEC (1 << 7) + + #ifdef CONFIG_SYS_SPI_ST_ENABLE_WP_PIN + #define STATUS_SRWD (1 << 7) /* SR write protect */ + #endif + ++/* Status Register 1(SR1V) */ ++#define SR1V_WEL (1 << 1) ++#define SR1V_WIP (1 << 0) ++ ++/* Status Register 2(SR2V) */ ++#define SR2V_ESTAT (1 << 2) ++#define SR2V_ES (1 << 1) ++#define SR2V_PS (1 << 0) ++ + /* Flash timeout values */ + #define SPI_FLASH_PROG_TIMEOUT (2 * CONFIG_SYS_HZ) + #define SPI_FLASH_PAGE_ERASE_TIMEOUT (5 * CONFIG_SYS_HZ) +@@ -117,25 +170,43 @@ int sst_write_bp(struct spi_flash *flash, u32 offset, size_t len, + const void *buf); + #endif + +-/** +- * struct spi_flash_params - SPI/QSPI flash device params structure +- * +- * @name: Device name ([MANUFLETTER][DEVTYPE][DENSITY][EXTRAINFO]) +- * @jedec: Device jedec ID (0x[1byte_manuf_id][2byte_dev_id]) +- * @ext_jedec: Device ext_jedec ID +- * @sector_size: Sector size of this device +- * @nr_sectors: No.of sectors on this device +- * @e_rd_cmd: Enum list for read commands +- * @flags: Important param, for flash specific behaviour +- */ ++#define JEDEC_MFR(info) ((info)->id[0]) ++#define JEDEC_ID(info) (((info)->id[1]) << 8 | ((info)->id[2])) ++#define JEDEC_EXT(info) (((info)->id[3]) << 8 | ((info)->id[4])) ++#define JEDEC_FID(info) ((info)->id[5]) ++#define SPI_FLASH_MAX_ID_LEN 6 ++ + struct spi_flash_params { +- const char *name; +- u32 jedec; +- u16 ext_jedec; +- u32 sector_size; +- u32 nr_sectors; +- u8 e_rd_cmd; +- u16 flags; ++ /* Device name ([MANUFLETTER][DEVTYPE][DENSITY][EXTRAINFO]) */ ++ const char *name; ++ ++ /* ++ * This array stores the ID bytes. ++ * The first three bytes are the JEDIC ID. ++ * JEDEC ID zero means "no ID" (mostly older chips). ++ */ ++ u8 id[SPI_FLASH_MAX_ID_LEN]; ++ u8 id_len; ++ ++ /* ++ * The size listed here is what works with SPINOR_OP_SE, which isn't ++ * necessarily called a "sector" by the vendor. ++ */ ++ u32 sector_size; ++ u32 n_sectors; ++ ++ u16 page_size; ++ ++ u16 flags; ++#define SECT_4K BIT(0) /* CMD_ERASE_4K works uniformly */ ++#define E_FSR BIT(1) /* use flag status register for */ ++#define SST_WR BIT(2) /* use SST byte/word programming */ ++#define WR_QPP BIT(3) /* use Quad Page Program */ ++#define RD_QUAD BIT(4) /* use Quad Read */ ++#define RD_DUAL BIT(5) /* use Dual Read */ ++#define RD_QUADIO BIT(6) /* use Quad IO Read */ ++#define RD_DUALIO BIT(7) /* use Dual IO Read */ ++#define RD_FULL (RD_QUAD | RD_DUAL | RD_QUADIO | RD_DUALIO) + }; + + extern const struct spi_flash_params spi_flash_params_table[]; +@@ -164,6 +235,12 @@ int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len); + /* Read the status register */ + int spi_flash_cmd_read_status(struct spi_flash *flash, u8 *rs); + ++/* Read the status register2 */ ++int spi_flash_cmd_read_status2(struct spi_flash *flash, u8 *rs); ++ ++/* Evaluate Erase Status */ ++int spi_flash_cmd_evaluate_erase_status(struct spi_flash *flash, u32 addr); ++ + /* Program the status register */ + int spi_flash_cmd_write_status(struct spi_flash *flash, u8 ws); + +diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c +index 34bc54e..6af38c1 100644 +--- a/drivers/mtd/spi/sf_ops.c ++++ b/drivers/mtd/spi/sf_ops.c +@@ -11,7 +11,11 @@ + #include <common.h> + #include <errno.h> + #include <malloc.h> ++#if defined(CONFIG_RCAR_GEN3) ++#include "../../spi/rcar_gen3_qspi.h" ++#else + #include <spi.h> ++#endif + #include <spi_flash.h> + #include <watchdog.h> + +@@ -40,6 +44,38 @@ int spi_flash_cmd_read_status(struct spi_flash *flash, u8 *rs) + return 0; + } + ++int spi_flash_cmd_read_status2(struct spi_flash *flash, u8 *rs) ++{ ++ int ret; ++ u8 cmd; ++ ++ cmd = CMD_READ_STATUS2; ++ ret = spi_flash_read_common(flash, &cmd, 1, rs, 1); ++ if (ret < 0) { ++ debug("SF: fail to read status register2\n"); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++int spi_flash_cmd_evaluate_erase_status(struct spi_flash *flash, u32 addr) ++{ ++ int ret; ++ u8 cmd; ++ ++ cmd = CMD_EVALUATE_ERASE_STATUS; ++ spi_set_addr(addr & 0x00ffffff); ++ ++ ret = spi_xfer_cmd(flash->spi, (int)cmd); ++ if (ret < 0) { ++ debug("SF: fail to Evaluate Erase Status\n"); ++ return ret; ++ } ++ ++ return 0; ++} ++ + int spi_flash_cmd_write_status(struct spi_flash *flash, u8 ws) + { + u8 cmd; +@@ -158,7 +194,10 @@ int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout) + { + struct spi_slave *spi = flash->spi; + unsigned long timebase; ++#ifdef CONFIG_SF_DUAL_FLASH + unsigned long flags = SPI_XFER_BEGIN; ++#endif ++ + int ret; + u8 status; + u8 check_status = 0x0; +@@ -174,7 +213,7 @@ int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout) + if (spi->flags & SPI_XFER_U_PAGE) + flags |= SPI_XFER_U_PAGE; + #endif +- ret = spi_xfer(spi, 8, &cmd, NULL, flags); ++ ret = spi_xfer_cmd(spi, cmd); + if (ret) { + debug("SF: fail to read %s status register\n", + cmd == CMD_READ_STATUS ? "read" : "flag"); +@@ -250,6 +289,8 @@ int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len) + u32 erase_size, erase_addr; + u8 cmd[SPI_FLASH_CMD_LEN]; + int ret = -1; ++ u8 read_sts; ++ int wait_msec, wait_interval; + + erase_size = flash->erase_size; + if (offset % erase_size || len % erase_size) { +@@ -270,6 +311,7 @@ int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len) + if (ret < 0) + return ret; + #endif ++ spi_set_addr(erase_addr); + spi_flash_addr(erase_addr, cmd); + + debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1], +@@ -285,6 +327,24 @@ int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len) + len -= erase_size; + } + ++ /* Wait for Erase Complete */ ++ wait_msec = 0; ++ wait_interval = 100; ++ while (wait_msec < 3000) { /* Max 3sec */ ++ mdelay(wait_interval); ++ ret = spi_flash_cmd_evaluate_erase_status(flash, offset-erase_size); ++ WaitReadyDevice(flash->spi); ++ ret = spi_flash_cmd_read_status2(flash, &read_sts); ++ if (read_sts & SR2V_ESTAT) { ++ break; ++ } ++ wait_msec += wait_interval; ++ } ++ ++ if ((ret != 0) || (read_sts != SR2V_ESTAT)) { ++ ret = -1; ++ } ++ + return ret; + } + +@@ -319,6 +379,7 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, + chunk_len = min(chunk_len, + (size_t)flash->spi->max_write_size); + ++ spi_set_addr(write_addr); + spi_flash_addr(write_addr, cmd); + + debug("SF: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n", +@@ -409,6 +470,7 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset, + else + read_len = remain_len; + ++ spi_set_addr(read_addr); + spi_flash_addr(read_addr, cmd); + + ret = spi_flash_read_common(flash, cmd, cmdsz, data, read_len); +diff --git a/drivers/mtd/spi/sf_params.c b/drivers/mtd/spi/sf_params.c +index c12e8c6..bd19bfb 100644 +--- a/drivers/mtd/spi/sf_params.c ++++ b/drivers/mtd/spi/sf_params.c +@@ -12,129 +12,172 @@ + + #include "sf_internal.h" + +-/* SPI/QSPI flash device params structure */ ++/* Used when the "_ext_id" is two bytes at most */ ++#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ ++ .id = { \ ++ ((_jedec_id) >> 16) & 0xff, \ ++ ((_jedec_id) >> 8) & 0xff, \ ++ (_jedec_id) & 0xff, \ ++ ((_ext_id) >> 8) & 0xff, \ ++ (_ext_id) & 0xff, \ ++ }, \ ++ .id_len = (!(_jedec_id) ? 0 : (3 + ((_ext_id) ? 2 : 0))), \ ++ .sector_size = (_sector_size), \ ++ .n_sectors = (_n_sectors), \ ++ .page_size = 256, \ ++ .flags = (_flags), ++ ++#define INFO6(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ ++ .id = { \ ++ ((_jedec_id) >> 16) & 0xff, \ ++ ((_jedec_id) >> 8) & 0xff, \ ++ (_jedec_id) & 0xff, \ ++ ((_ext_id) >> 16) & 0xff, \ ++ ((_ext_id) >> 8) & 0xff, \ ++ (_ext_id) & 0xff, \ ++ }, \ ++ .id_len = 6, \ ++ .sector_size = (_sector_size), \ ++ .n_sectors = (_n_sectors), \ ++ .page_size = 256, \ ++ .flags = (_flags), ++ + const struct spi_flash_params spi_flash_params_table[] = { + #ifdef CONFIG_SPI_FLASH_ATMEL /* ATMEL */ +- {"AT45DB011D", 0x1f2200, 0x0, 64 * 1024, 4, RD_NORM, SECT_4K}, +- {"AT45DB021D", 0x1f2300, 0x0, 64 * 1024, 8, RD_NORM, SECT_4K}, +- {"AT45DB041D", 0x1f2400, 0x0, 64 * 1024, 8, RD_NORM, SECT_4K}, +- {"AT45DB081D", 0x1f2500, 0x0, 64 * 1024, 16, RD_NORM, SECT_4K}, +- {"AT45DB161D", 0x1f2600, 0x0, 64 * 1024, 32, RD_NORM, SECT_4K}, +- {"AT45DB321D", 0x1f2700, 0x0, 64 * 1024, 64, RD_NORM, SECT_4K}, +- {"AT45DB641D", 0x1f2800, 0x0, 64 * 1024, 128, RD_NORM, SECT_4K}, +- {"AT25DF321", 0x1f4701, 0x0, 64 * 1024, 64, RD_NORM, SECT_4K}, ++ {"at45db011d", INFO(0x1f2200, 0x0, 64 * 1024, 4, SECT_4K) }, ++ {"at45db021d", INFO(0x1f2300, 0x0, 64 * 1024, 8, SECT_4K) }, ++ {"at45db041d", INFO(0x1f2400, 0x0, 64 * 1024, 8, SECT_4K) }, ++ {"at45db081d", INFO(0x1f2500, 0x0, 64 * 1024, 16, SECT_4K) }, ++ {"at45db161d", INFO(0x1f2600, 0x0, 64 * 1024, 32, SECT_4K) }, ++ {"at45db321d", INFO(0x1f2700, 0x0, 64 * 1024, 64, SECT_4K) }, ++ {"at45db641d", INFO(0x1f2800, 0x0, 64 * 1024, 128, SECT_4K) }, ++ {"at25df321a", INFO(0x1f4701, 0x0, 64 * 1024, 64, SECT_4K) }, ++ {"at25df321", INFO(0x1f4700, 0x0, 64 * 1024, 64, SECT_4K) }, ++ {"at26df081a", INFO(0x1f4501, 0x0, 64 * 1024, 16, SECT_4K) }, + #endif + #ifdef CONFIG_SPI_FLASH_EON /* EON */ +- {"EN25Q32B", 0x1c3016, 0x0, 64 * 1024, 64, RD_NORM, 0}, +- {"EN25Q64", 0x1c3017, 0x0, 64 * 1024, 128, RD_NORM, SECT_4K}, +- {"EN25Q128B", 0x1c3018, 0x0, 64 * 1024, 256, RD_NORM, 0}, +- {"EN25S64", 0x1c3817, 0x0, 64 * 1024, 128, RD_NORM, 0}, ++ {"en25q32b", INFO(0x1c3016, 0x0, 64 * 1024, 64, 0) }, ++ {"en25q64", INFO(0x1c3017, 0x0, 64 * 1024, 128, SECT_4K) }, ++ {"en25q128b", INFO(0x1c3018, 0x0, 64 * 1024, 256, 0) }, ++ {"en25s64", INFO(0x1c3817, 0x0, 64 * 1024, 128, 0) }, + #endif + #ifdef CONFIG_SPI_FLASH_GIGADEVICE /* GIGADEVICE */ +- {"GD25Q64B", 0xc84017, 0x0, 64 * 1024, 128, RD_NORM, SECT_4K}, +- {"GD25LQ32", 0xc86016, 0x0, 64 * 1024, 64, RD_NORM, SECT_4K}, ++ {"gd25q64b", INFO(0xc84017, 0x0, 64 * 1024, 128, SECT_4K) }, ++ {"gd25lq32", INFO(0xc86016, 0x0, 64 * 1024, 64, SECT_4K) }, ++#endif ++#ifdef CONFIG_SPI_FLASH_ISSI /* ISSI */ ++ {"is25lp032", INFO(0x9d6016, 0x0, 64 * 1024, 64, 0) }, ++ {"is25lp064", INFO(0x9d6017, 0x0, 64 * 1024, 128, 0) }, ++ {"is25lp128", INFO(0x9d6018, 0x0, 64 * 1024, 256, 0) }, + #endif + #ifdef CONFIG_SPI_FLASH_MACRONIX /* MACRONIX */ +- {"MX25L2006E", 0xc22012, 0x0, 64 * 1024, 4, RD_NORM, 0}, +- {"MX25L4005", 0xc22013, 0x0, 64 * 1024, 8, RD_NORM, 0}, +- {"MX25L8005", 0xc22014, 0x0, 64 * 1024, 16, RD_NORM, 0}, +- {"MX25L1605D", 0xc22015, 0x0, 64 * 1024, 32, RD_NORM, 0}, +- {"MX25L3205D", 0xc22016, 0x0, 64 * 1024, 64, RD_NORM, 0}, +- {"MX25L6405D", 0xc22017, 0x0, 64 * 1024, 128, RD_NORM, 0}, +- {"MX25L12805", 0xc22018, 0x0, 64 * 1024, 256, RD_FULL, WR_QPP}, +- {"MX25L25635F", 0xc22019, 0x0, 64 * 1024, 512, RD_FULL, WR_QPP}, +- {"MX25L51235F", 0xc2201a, 0x0, 64 * 1024, 1024, RD_FULL, WR_QPP}, +- {"MX25L12855E", 0xc22618, 0x0, 64 * 1024, 256, RD_FULL, WR_QPP}, ++ {"mx25l2006e", INFO(0xc22012, 0x0, 64 * 1024, 4, 0) }, ++ {"mx25l4005", INFO(0xc22013, 0x0, 64 * 1024, 8, 0) }, ++ {"mx25l8005", INFO(0xc22014, 0x0, 64 * 1024, 16, 0) }, ++ {"mx25l1605d", INFO(0xc22015, 0x0, 64 * 1024, 32, 0) }, ++ {"mx25l3205d", INFO(0xc22016, 0x0, 64 * 1024, 64, 0) }, ++ {"mx25l6405d", INFO(0xc22017, 0x0, 64 * 1024, 128, 0) }, ++ {"mx25l12805", INFO(0xc22018, 0x0, 64 * 1024, 256, RD_FULL | WR_QPP) }, ++ {"mx25l25635f", INFO(0xc22019, 0x0, 64 * 1024, 512, RD_FULL | WR_QPP) }, ++ {"mx25l51235f", INFO(0xc2201a, 0x0, 64 * 1024, 1024, RD_FULL | WR_QPP) }, ++ {"mx25l12855e", INFO(0xc22618, 0x0, 64 * 1024, 256, RD_FULL | WR_QPP) }, ++ {"mx66u51235f", INFO(0xc2253a, 0x0, 64 * 1024, 1024, RD_FULL | WR_QPP) }, ++ {"mx66l1g45g", INFO(0xc2201b, 0x0, 64 * 1024, 2048, RD_FULL | WR_QPP) }, + #endif + #ifdef CONFIG_SPI_FLASH_SPANSION /* SPANSION */ +- {"S25FL008A", 0x010213, 0x0, 64 * 1024, 16, RD_NORM, 0}, +- {"S25FL016A", 0x010214, 0x0, 64 * 1024, 32, RD_NORM, 0}, +- {"S25FL032A", 0x010215, 0x0, 64 * 1024, 64, RD_NORM, 0}, +- {"S25FL064A", 0x010216, 0x0, 64 * 1024, 128, RD_NORM, 0}, +- {"S25FL116K", 0x014015, 0x0, 64 * 1024, 128, RD_NORM, 0}, +- {"S25FL164K", 0x014017, 0x0140, 64 * 1024, 128, RD_NORM, 0}, +- {"S25FL128P_256K", 0x012018, 0x0300, 256 * 1024, 64, RD_FULL, WR_QPP}, +- {"S25FL128P_64K", 0x012018, 0x0301, 64 * 1024, 256, RD_FULL, WR_QPP}, +- {"S25FL032P", 0x010215, 0x4d00, 64 * 1024, 64, RD_FULL, WR_QPP}, +- {"S25FL064P", 0x010216, 0x4d00, 64 * 1024, 128, RD_FULL, WR_QPP}, +- {"S25FL128S_256K", 0x012018, 0x4d00, 256 * 1024, 64, RD_FULL, WR_QPP}, +- {"S25FL128S_64K", 0x012018, 0x4d01, 64 * 1024, 256, RD_FULL, WR_QPP}, +- {"S25FL256S_256K", 0x010219, 0x4d00, 256 * 1024, 128, RD_FULL, WR_QPP}, +- {"S25FL256S_64K", 0x010219, 0x4d01, 64 * 1024, 512, RD_FULL, WR_QPP}, +- {"S25FL512S_256K", 0x010220, 0x4d00, 256 * 1024, 256, RD_FULL, WR_QPP}, +- {"S25FL512S_64K", 0x010220, 0x4d01, 64 * 1024, 1024, RD_FULL, WR_QPP}, +- {"S25FL512S_512K", 0x010220, 0x4f00, 256 * 1024, 256, RD_FULL, WR_QPP}, ++ {"s25fl008a", INFO(0x010213, 0x0, 64 * 1024, 16, 0) }, ++ {"s25fl016a", INFO(0x010214, 0x0, 64 * 1024, 32, 0) }, ++ {"s25fl032a", INFO(0x010215, 0x0, 64 * 1024, 64, 0) }, ++ {"s25fl064a", INFO(0x010216, 0x0, 64 * 1024, 128, 0) }, ++ {"s25fl116k", INFO(0x014015, 0x0, 64 * 1024, 128, 0) }, ++ {"s25fl164k", INFO(0x014017, 0x0140, 64 * 1024, 128, 0) }, ++ {"s25fl128p_256k", INFO(0x012018, 0x0300, 256 * 1024, 64, RD_FULL | WR_QPP) }, ++ {"s25fl128p_64k", INFO(0x012018, 0x0301, 64 * 1024, 256, RD_FULL | WR_QPP) }, ++ {"s25fl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, RD_FULL | WR_QPP) }, ++ {"s25fl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128, RD_FULL | WR_QPP) }, ++ {"s25fl128s_256k", INFO(0x012018, 0x4d00, 256 * 1024, 64, RD_FULL | WR_QPP) }, ++ {"s25fl128s_64k", INFO(0x012018, 0x4d01, 64 * 1024, 256, RD_FULL | WR_QPP) }, ++ {"s25fl256s_256k", INFO(0x010219, 0x4d00, 256 * 1024, 128, RD_FULL | WR_QPP) }, ++ {"s25fl256s_64k", INFO(0x010219, 0x4d01, 64 * 1024, 512, RD_FULL | WR_QPP) }, ++ {"s25fs256s_64k", INFO6(0x010219, 0x4d0181, 64 * 1024, 512, RD_FULL | WR_QPP | SECT_4K) }, ++ {"s25fs512s", INFO6(0x010220, 0x4d0081, 256 * 1024, 2048, RD_FULL | WR_QPP | SECT_4K) }, ++ {"s25fl512s_256k", INFO(0x010220, 0x4d00, 256 * 1024, 256, RD_FULL | WR_QPP) }, ++ {"s25fl512s_64k", INFO(0x010220, 0x4d01, 64 * 1024, 1024, RD_FULL | WR_QPP) }, ++ {"s25fl512s_512k", INFO(0x010220, 0x4f00, 256 * 1024, 256, RD_FULL | WR_QPP) }, + #endif + #ifdef CONFIG_SPI_FLASH_STMICRO /* STMICRO */ +- {"M25P10", 0x202011, 0x0, 32 * 1024, 4, RD_NORM, 0}, +- {"M25P20", 0x202012, 0x0, 64 * 1024, 4, RD_NORM, 0}, +- {"M25P40", 0x202013, 0x0, 64 * 1024, 8, RD_NORM, 0}, +- {"M25P80", 0x202014, 0x0, 64 * 1024, 16, RD_NORM, 0}, +- {"M25P16", 0x202015, 0x0, 64 * 1024, 32, RD_NORM, 0}, +- {"M25PE16", 0x208015, 0x1000, 64 * 1024, 32, RD_NORM, 0}, +- {"M25PX16", 0x207115, 0x1000, 64 * 1024, 32, RD_EXTN, 0}, +- {"M25P32", 0x202016, 0x0, 64 * 1024, 64, RD_NORM, 0}, +- {"M25P64", 0x202017, 0x0, 64 * 1024, 128, RD_NORM, 0}, +- {"M25P128", 0x202018, 0x0, 256 * 1024, 64, RD_NORM, 0}, +- {"M25PX64", 0x207117, 0x0, 64 * 1024, 128, RD_NORM, SECT_4K}, +- {"N25Q32", 0x20ba16, 0x0, 64 * 1024, 64, RD_FULL, WR_QPP | SECT_4K}, +- {"N25Q32A", 0x20bb16, 0x0, 64 * 1024, 64, RD_FULL, WR_QPP | SECT_4K}, +- {"N25Q64", 0x20ba17, 0x0, 64 * 1024, 128, RD_FULL, WR_QPP | SECT_4K}, +- {"N25Q64A", 0x20bb17, 0x0, 64 * 1024, 128, RD_FULL, WR_QPP | SECT_4K}, +- {"N25Q128", 0x20ba18, 0x0, 64 * 1024, 256, RD_FULL, WR_QPP}, +- {"N25Q128A", 0x20bb18, 0x0, 64 * 1024, 256, RD_FULL, WR_QPP}, +- {"N25Q256", 0x20ba19, 0x0, 64 * 1024, 512, RD_FULL, WR_QPP | SECT_4K}, +- {"N25Q256A", 0x20bb19, 0x0, 64 * 1024, 512, RD_FULL, WR_QPP | SECT_4K}, +- {"N25Q512", 0x20ba20, 0x0, 64 * 1024, 1024, RD_FULL, WR_QPP | E_FSR | SECT_4K}, +- {"N25Q512A", 0x20bb20, 0x0, 64 * 1024, 1024, RD_FULL, WR_QPP | E_FSR | SECT_4K}, +- {"N25Q1024", 0x20ba21, 0x0, 64 * 1024, 2048, RD_FULL, WR_QPP | E_FSR | SECT_4K}, +- {"N25Q1024A", 0x20bb21, 0x0, 64 * 1024, 2048, RD_FULL, WR_QPP | E_FSR | SECT_4K}, ++ {"m25p10", INFO(0x202011, 0x0, 32 * 1024, 4, 0) }, ++ {"m25p20", INFO(0x202012, 0x0, 64 * 1024, 4, 0) }, ++ {"m25p40", INFO(0x202013, 0x0, 64 * 1024, 8, 0) }, ++ {"m25p80", INFO(0x202014, 0x0, 64 * 1024, 16, 0) }, ++ {"m25p16", INFO(0x202015, 0x0, 64 * 1024, 32, 0) }, ++ {"m25pE16", INFO(0x208015, 0x1000, 64 * 1024, 32, 0) }, ++ {"m25pX16", INFO(0x207115, 0x1000, 64 * 1024, 32, RD_QUAD | RD_DUAL) }, ++ {"m25p32", INFO(0x202016, 0x0, 64 * 1024, 64, 0) }, ++ {"m25p64", INFO(0x202017, 0x0, 64 * 1024, 128, 0) }, ++ {"m25p128", INFO(0x202018, 0x0, 256 * 1024, 64, 0) }, ++ {"m25pX64", INFO(0x207117, 0x0, 64 * 1024, 128, SECT_4K) }, ++ {"n25q016a", INFO(0x20bb15, 0x0, 64 * 1024, 32, SECT_4K) }, ++ {"n25q32", INFO(0x20ba16, 0x0, 64 * 1024, 64, RD_FULL | WR_QPP | SECT_4K) }, ++ {"n25q32a", INFO(0x20bb16, 0x0, 64 * 1024, 64, RD_FULL | WR_QPP | SECT_4K) }, ++ {"n25q64", INFO(0x20ba17, 0x0, 64 * 1024, 128, RD_FULL | WR_QPP | SECT_4K) }, ++ {"n25q64a", INFO(0x20bb17, 0x0, 64 * 1024, 128, RD_FULL | WR_QPP | SECT_4K) }, ++ {"n25q128", INFO(0x20ba18, 0x0, 64 * 1024, 256, RD_FULL | WR_QPP) }, ++ {"n25q128a", INFO(0x20bb18, 0x0, 64 * 1024, 256, RD_FULL | WR_QPP) }, ++ {"n25q256", INFO(0x20ba19, 0x0, 64 * 1024, 512, RD_FULL | WR_QPP | SECT_4K) }, ++ {"n25q256a", INFO(0x20bb19, 0x0, 64 * 1024, 512, RD_FULL | WR_QPP | SECT_4K) }, ++ {"n25q512", INFO(0x20ba20, 0x0, 64 * 1024, 1024, RD_FULL | WR_QPP | E_FSR | SECT_4K) }, ++ {"n25q512a", INFO(0x20bb20, 0x0, 64 * 1024, 1024, RD_FULL | WR_QPP | E_FSR | SECT_4K) }, ++ {"n25q1024", INFO(0x20ba21, 0x0, 64 * 1024, 2048, RD_FULL | WR_QPP | E_FSR | SECT_4K) }, ++ {"n25q1024a", INFO(0x20bb21, 0x0, 64 * 1024, 2048, RD_FULL | WR_QPP | E_FSR | SECT_4K) }, ++ {"mt25qu02g", INFO(0x20bb22, 0x0, 64 * 1024, 4096, RD_FULL | WR_QPP | E_FSR | SECT_4K) }, ++ {"mt25ql02g", INFO(0x20ba22, 0x0, 64 * 1024, 4096, RD_FULL | WR_QPP | E_FSR | SECT_4K) }, + #endif + #ifdef CONFIG_SPI_FLASH_SST /* SST */ +- {"SST25VF040B", 0xbf258d, 0x0, 64 * 1024, 8, RD_NORM, SECT_4K | SST_WR}, +- {"SST25VF080B", 0xbf258e, 0x0, 64 * 1024, 16, RD_NORM, SECT_4K | SST_WR}, +- {"SST25VF016B", 0xbf2541, 0x0, 64 * 1024, 32, RD_NORM, SECT_4K | SST_WR}, +- {"SST25VF032B", 0xbf254a, 0x0, 64 * 1024, 64, RD_NORM, SECT_4K | SST_WR}, +- {"SST25VF064C", 0xbf254b, 0x0, 64 * 1024, 128, RD_NORM, SECT_4K}, +- {"SST25WF512", 0xbf2501, 0x0, 64 * 1024, 1, RD_NORM, SECT_4K | SST_WR}, +- {"SST25WF010", 0xbf2502, 0x0, 64 * 1024, 2, RD_NORM, SECT_4K | SST_WR}, +- {"SST25WF020", 0xbf2503, 0x0, 64 * 1024, 4, RD_NORM, SECT_4K | SST_WR}, +- {"SST25WF040", 0xbf2504, 0x0, 64 * 1024, 8, RD_NORM, SECT_4K | SST_WR}, +- {"SST25WF040B", 0x621613, 0x0, 64 * 1024, 8, RD_NORM, SECT_4K | SST_WR}, +- {"SST25WF080", 0xbf2505, 0x0, 64 * 1024, 16, RD_NORM, SECT_4K | SST_WR}, ++ {"sst25vf040b", INFO(0xbf258d, 0x0, 64 * 1024, 8, SECT_4K | SST_WR) }, ++ {"sst25vf080b", INFO(0xbf258e, 0x0, 64 * 1024, 16, SECT_4K | SST_WR) }, ++ {"sst25vf016b", INFO(0xbf2541, 0x0, 64 * 1024, 32, SECT_4K | SST_WR) }, ++ {"sst25vf032b", INFO(0xbf254a, 0x0, 64 * 1024, 64, SECT_4K | SST_WR) }, ++ {"sst25vf064c", INFO(0xbf254b, 0x0, 64 * 1024, 128, SECT_4K) }, ++ {"sst25wf512", INFO(0xbf2501, 0x0, 64 * 1024, 1, SECT_4K | SST_WR) }, ++ {"sst25wf010", INFO(0xbf2502, 0x0, 64 * 1024, 2, SECT_4K | SST_WR) }, ++ {"sst25wf020", INFO(0xbf2503, 0x0, 64 * 1024, 4, SECT_4K | SST_WR) }, ++ {"sst25wf040", INFO(0xbf2504, 0x0, 64 * 1024, 8, SECT_4K | SST_WR) }, ++ {"sst25wf040b", INFO(0x621613, 0x0, 64 * 1024, 8, SECT_4K) }, ++ {"sst25wf080", INFO(0xbf2505, 0x0, 64 * 1024, 16, SECT_4K | SST_WR) }, + #endif + #ifdef CONFIG_SPI_FLASH_WINBOND /* WINBOND */ +- {"W25P80", 0xef2014, 0x0, 64 * 1024, 16, RD_NORM, 0}, +- {"W25P16", 0xef2015, 0x0, 64 * 1024, 32, RD_NORM, 0}, +- {"W25P32", 0xef2016, 0x0, 64 * 1024, 64, RD_NORM, 0}, +- {"W25X40", 0xef3013, 0x0, 64 * 1024, 8, RD_NORM, SECT_4K}, +- {"W25X16", 0xef3015, 0x0, 64 * 1024, 32, RD_NORM, SECT_4K}, +- {"W25X32", 0xef3016, 0x0, 64 * 1024, 64, RD_NORM, SECT_4K}, +- {"W25X64", 0xef3017, 0x0, 64 * 1024, 128, RD_NORM, SECT_4K}, +- {"W25Q80BL", 0xef4014, 0x0, 64 * 1024, 16, RD_FULL, WR_QPP | SECT_4K}, +- {"W25Q16CL", 0xef4015, 0x0, 64 * 1024, 32, RD_FULL, WR_QPP | SECT_4K}, +- {"W25Q32BV", 0xef4016, 0x0, 64 * 1024, 64, RD_FULL, WR_QPP | SECT_4K}, +- {"W25Q64CV", 0xef4017, 0x0, 64 * 1024, 128, RD_FULL, WR_QPP | SECT_4K}, +- {"W25Q128BV", 0xef4018, 0x0, 64 * 1024, 256, RD_FULL, WR_QPP | SECT_4K}, +- {"W25Q256", 0xef4019, 0x0, 64 * 1024, 512, RD_FULL, WR_QPP | SECT_4K}, +- {"W25Q80BW", 0xef5014, 0x0, 64 * 1024, 16, RD_FULL, WR_QPP | SECT_4K}, +- {"W25Q16DW", 0xef6015, 0x0, 64 * 1024, 32, RD_FULL, WR_QPP | SECT_4K}, +- {"W25Q32DW", 0xef6016, 0x0, 64 * 1024, 64, RD_FULL, WR_QPP | SECT_4K}, +- {"W25Q64DW", 0xef6017, 0x0, 64 * 1024, 128, RD_FULL, WR_QPP | SECT_4K}, +- {"W25Q128FW", 0xef6018, 0x0, 64 * 1024, 256, RD_FULL, WR_QPP | SECT_4K}, ++ {"w25p80", INFO(0xef2014, 0x0, 64 * 1024, 16, 0) }, ++ {"w25p16", INFO(0xef2015, 0x0, 64 * 1024, 32, 0) }, ++ {"w25p32", INFO(0xef2016, 0x0, 64 * 1024, 64, 0) }, ++ {"w25x40", INFO(0xef3013, 0x0, 64 * 1024, 8, SECT_4K) }, ++ {"w25x16", INFO(0xef3015, 0x0, 64 * 1024, 32, SECT_4K) }, ++ {"w25x32", INFO(0xef3016, 0x0, 64 * 1024, 64, SECT_4K) }, ++ {"w25x64", INFO(0xef3017, 0x0, 64 * 1024, 128, SECT_4K) }, ++ {"w25q80bl", INFO(0xef4014, 0x0, 64 * 1024, 16, RD_FULL | WR_QPP | SECT_4K) }, ++ {"w25q16cl", INFO(0xef4015, 0x0, 64 * 1024, 32, RD_FULL | WR_QPP | SECT_4K) }, ++ {"w25q32bv", INFO(0xef4016, 0x0, 64 * 1024, 64, RD_FULL | WR_QPP | SECT_4K) }, ++ {"w25q64cv", INFO(0xef4017, 0x0, 64 * 1024, 128, RD_FULL | WR_QPP | SECT_4K) }, ++ {"w25q128bv", INFO(0xef4018, 0x0, 64 * 1024, 256, RD_FULL | WR_QPP | SECT_4K) }, ++ {"w25q256", INFO(0xef4019, 0x0, 64 * 1024, 512, RD_FULL | WR_QPP | SECT_4K) }, ++ {"w25q80bw", INFO(0xef5014, 0x0, 64 * 1024, 16, RD_FULL | WR_QPP | SECT_4K) }, ++ {"w25q16dw", INFO(0xef6015, 0x0, 64 * 1024, 32, RD_FULL | WR_QPP | SECT_4K) }, ++ {"w25q32dw", INFO(0xef6016, 0x0, 64 * 1024, 64, RD_FULL | WR_QPP | SECT_4K) }, ++ {"w25q64dw", INFO(0xef6017, 0x0, 64 * 1024, 128, RD_FULL | WR_QPP | SECT_4K) }, ++ {"w25q128fw", INFO(0xef6018, 0x0, 64 * 1024, 256, RD_FULL | WR_QPP | SECT_4K) }, + #endif + {}, /* Empty entry to terminate the list */ + /* + * Note: + * Below paired flash devices has similar spi_flash params. +- * (S25FL129P_64K, S25FL128S_64K) +- * (W25Q80BL, W25Q80BV) +- * (W25Q16CL, W25Q16DV) +- * (W25Q32BV, W25Q32FV_SPI) +- * (W25Q64CV, W25Q64FV_SPI) +- * (W25Q128BV, W25Q128FV_SPI) +- * (W25Q32DW, W25Q32FV_QPI) +- * (W25Q64DW, W25Q64FV_QPI) +- * (W25Q128FW, W25Q128FV_QPI) ++ * (s25fl129p_64k, s25fl128s_64k) ++ * (w25q80bl, w25q80bv) ++ * (w25q16cl, w25q16dv) ++ * (w25q32bv, w25q32fv_spi) ++ * (w25q64cv, w25q64fv_spi) ++ * (w25q128bv, w25q128fv_spi) ++ * (w25q32dw, w25q32fv_qpi) ++ * (w25q64dw, w25q64fv_qpi) ++ * (w25q128fw, w25q128fv_qpi) + */ + }; +diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c +index 4103723..28ef787 100644 +--- a/drivers/mtd/spi/sf_probe.c ++++ b/drivers/mtd/spi/sf_probe.c +@@ -21,16 +21,6 @@ + + DECLARE_GLOBAL_DATA_PTR; + +-/* Read commands array */ +-static u8 spi_read_cmds_array[] = { +- CMD_READ_ARRAY_SLOW, +- CMD_READ_ARRAY_FAST, +- CMD_READ_DUAL_OUTPUT_FAST, +- CMD_READ_DUAL_IO_FAST, +- CMD_READ_QUAD_OUTPUT_FAST, +- CMD_READ_QUAD_IO_FAST, +-}; +- + #ifdef CONFIG_SPI_FLASH_MACRONIX + static int spi_flash_set_qeb_mxic(struct spi_flash *flash) + { +@@ -102,19 +92,27 @@ static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode, + struct spi_flash *flash) + { + const struct spi_flash_params *params; +- u8 cmd; ++ u8 manufacture_id = idcode[0]; + u16 jedec = idcode[1] << 8 | idcode[2]; + u16 ext_jedec = idcode[3] << 8 | idcode[4]; ++ u8 family_id = idcode[5]; + + /* Validate params from spi_flash_params table */ + params = spi_flash_params_table; + for (; params->name != NULL; params++) { +- if ((params->jedec >> 16) == idcode[0]) { +- if ((params->jedec & 0xFFFF) == jedec) { +- if (params->ext_jedec == 0) +- break; +- else if (params->ext_jedec == ext_jedec) ++ if (JEDEC_MFR(params) == manufacture_id) { ++ if (JEDEC_ID(params) == jedec) { ++ if (params->id_len - 3 == 0) { + break; ++ } else if (params->id_len - 3 == 2) { ++ if (JEDEC_EXT(params) == ext_jedec) { ++ break; ++ } ++ } else { ++ if ((JEDEC_EXT(params) == (ext_jedec & 0xFF00)) && (JEDEC_FID(params) == family_id)) { ++ break; ++ } ++ } + } + } + } +@@ -149,48 +147,48 @@ static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode, + + /* Compute the flash size */ + flash->shift = (flash->dual_flash & SF_DUAL_PARALLEL_FLASH) ? 1 : 0; ++ flash->page_size = params->page_size; + /* + * The Spansion S25FL032P and S25FL064P have 256b pages, yet use the + * 0x4d00 Extended JEDEC code. The rest of the Spansion flashes with + * the 0x4d00 Extended JEDEC code have 512b pages. All of the others + * have 256b pages. + */ +- if (ext_jedec == 0x4d00) { +- if ((jedec == 0x0215) || (jedec == 0x216)) +- flash->page_size = 256; +- else ++ if ((ext_jedec & 0xFF00) == 0x4d00) { ++ if ((jedec != 0x0215) && (jedec != 0x0216) && (jedec != 0x220)) { + flash->page_size = 512; +- } else { +- flash->page_size = 256; ++ } + } ++ + flash->page_size <<= flash->shift; + flash->sector_size = params->sector_size << flash->shift; +- flash->size = flash->sector_size * params->nr_sectors << flash->shift; ++ flash->size = flash->sector_size * params->n_sectors << flash->shift; + #ifdef CONFIG_SF_DUAL_FLASH + if (flash->dual_flash & SF_DUAL_STACKED_FLASH) + flash->size <<= 1; + #endif + ++#ifdef CONFIG_SPI_FLASH_USE_4K_SECTORS + /* Compute erase sector and command */ + if (params->flags & SECT_4K) { + flash->erase_cmd = CMD_ERASE_4K; + flash->erase_size = 4096 << flash->shift; +- } else if (params->flags & SECT_32K) { +- flash->erase_cmd = CMD_ERASE_32K; +- flash->erase_size = 32768 << flash->shift; +- } else { +- flash->erase_cmd = CMD_ERASE_64K; ++ } else ++#endif ++ { ++ flash->erase_cmd = CMD_ERASE_256K_ADDR4; + flash->erase_size = flash->sector_size; + } + + /* Look for the fastest read cmd */ +- cmd = fls(params->e_rd_cmd & flash->spi->op_mode_rx); +- if (cmd) { +- cmd = spi_read_cmds_array[cmd - 1]; +- flash->read_cmd = cmd; ++ if (flash->spi->op_mode_rx & SPI_RX_SLOW) { ++ flash->read_cmd = CMD_READ_ARRAY_SLOW; ++ } else if ((flash->spi->op_mode_rx & SPI_RX_QUAD) && (params->flags & RD_QUAD)) { ++ flash->read_cmd = CMD_READ_QUAD_OUTPUT_FAST; ++ } else if ((flash->spi->op_mode_rx & SPI_RX_DUAL) && (params->flags & RD_DUAL)) { ++ flash->read_cmd = CMD_READ_DUAL_OUTPUT_FAST; + } else { +- /* Go for default supported read cmd */ +- flash->read_cmd = CMD_READ_ARRAY_FAST; ++ flash->read_cmd = CMD_READ_ARRAY_FAST_ADDR4; + } + + /* Not require to look for fastest only two write cmds yet */ +@@ -198,7 +196,7 @@ static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode, + flash->write_cmd = CMD_QUAD_PAGE_PROGRAM; + else + /* Go for default supported write cmd */ +- flash->write_cmd = CMD_PAGE_PROGRAM; ++ flash->write_cmd = CMD_PAGE_PROGRAM_ADDR4; + + /* Read dummy_byte: dummy byte is determined based on the + * dummy cycles of a particular command. +@@ -324,7 +322,7 @@ static int spi_enable_wp_pin(struct spi_flash *flash) + */ + int spi_flash_probe_slave(struct spi_slave *spi, struct spi_flash *flash) + { +- u8 idcode[5]; ++ u8 idcode[SPI_FLASH_MAX_ID_LEN]; + int ret; + + /* Setup spi_slave */ +@@ -385,6 +383,7 @@ int spi_flash_probe_slave(struct spi_slave *spi, struct spi_flash *flash) + puts("\n"); + #endif + #ifndef CONFIG_SPI_FLASH_BAR ++#ifndef CONFIG_R8A7797 + if (((flash->dual_flash == SF_SINGLE_FLASH) && + (flash->size > SPI_FLASH_16MB_BOUN)) || + ((flash->dual_flash > SF_SINGLE_FLASH) && +@@ -393,6 +392,7 @@ int spi_flash_probe_slave(struct spi_slave *spi, struct spi_flash *flash) + puts(" Full access #define CONFIG_SPI_FLASH_BAR\n"); + } + #endif ++#endif + if (spi_enable_wp_pin(flash)) + puts("Enable WP pin failed\n"); + +diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile +index ce6f1cc..fd1dd7c 100644 +--- a/drivers/spi/Makefile ++++ b/drivers/spi/Makefile +@@ -39,6 +39,7 @@ obj-$(CONFIG_MXC_SPI) += mxc_spi.o + obj-$(CONFIG_MXS_SPI) += mxs_spi.o + obj-$(CONFIG_OC_TINY_SPI) += oc_tiny_spi.o + obj-$(CONFIG_OMAP3_SPI) += omap3_spi.o ++obj-$(CONFIG_RCAR_GEN3_QSPI) += rcar_gen3_qspi.o + obj-$(CONFIG_SANDBOX_SPI) += sandbox_spi.o + obj-$(CONFIG_SH_SPI) += sh_spi.o + obj-$(CONFIG_SH_QSPI) += sh_qspi.o +diff --git a/drivers/spi/rcar_gen3_qspi.c b/drivers/spi/rcar_gen3_qspi.c +new file mode 100644 +index 0000000..5095b07 +--- /dev/null ++++ b/drivers/spi/rcar_gen3_qspi.c +@@ -0,0 +1,485 @@ ++/* ++ * R-CarH3 QSPI (Quad SPI) driver ++ * ++ */ ++ ++#include <common.h> ++#include <malloc.h> ++#include "rcar_gen3_qspi.h" ++#include <asm/arch/rcar_gen3.h> ++#include <asm/arch/rpc-flash.h> ++#include <asm/io.h> ++ ++#include "../mtd/spi/sf_internal.h" ++ ++/* if DEBUG_PRINT defined, Output debug log */ ++//#define DEBUG_PRINT ++#ifdef DEBUG_PRINT ++#define debug_print(format, arg...) printf("[DBG] " format, ## arg) ++#else ++#define debug_print(format, arg...) do {} while(0) ++#endif ++ ++struct rcar_gen3_qspi_regs { ++ unsigned int cmncr; ++ unsigned int ssldr; ++ unsigned int dummy0; ++ unsigned int drcr; ++ unsigned int drcmr; ++ unsigned int drear; ++ unsigned int dropr; ++ unsigned int drenr; ++ unsigned int smcr; ++ unsigned int smcmr; ++ unsigned int smadr; ++ unsigned int smopr; ++ unsigned int smenr; ++ unsigned int dummy1; ++ unsigned int smrdr0; ++ unsigned int smrdr1; ++ unsigned int smwdr0; ++ unsigned int smwdr1; ++ unsigned int cmnsr; ++ unsigned int dummy2[3]; ++ unsigned int drdmcr; ++ unsigned int drdrenr; ++ unsigned int smdmcr; ++ unsigned int smdrenr; ++ unsigned int dummy3[5]; ++ unsigned int phycnt; ++ unsigned int phyoffset1; ++ unsigned int phyoffset2; ++ unsigned int phyint; ++ unsigned int dummy4[7]; ++ unsigned int div_reg; ++}; ++ ++struct sh_qspi_slave { ++ struct spi_slave slave; ++ struct rcar_gen3_qspi_regs *regs; ++}; ++ ++const SPI_COMMAND spi_cmd_tbl[] = { ++ { CMD_READ_ID, SPI_CMD_READ, SPI_DATA_ENABLE, 0, 0, "Read ID (JEDEC Manufacturer ID and JEDEC CFI)" }, ++ { CMD_READ_SFDP, SPI_CMD_READ, SPI_DATA_ENABLE, 3, 8, "Read JEDEC Serial Flash Discoverable Parameters" }, ++ { CMD_READ_QUAD_ID, SPI_CMD_READ, SPI_DATA_ENABLE, 0, 0, "Read Quad ID" }, ++ { CMD_READ_STATUS, SPI_CMD_READ, SPI_DATA_ENABLE, 0, 0, "Read Status Register-1" }, ++ { CMD_READ_STATUS2, SPI_CMD_READ, SPI_DATA_ENABLE, 0, 0, "Read Status Register-2" }, ++ { CMD_READ_CONFIG, SPI_CMD_READ, SPI_DATA_ENABLE, 0, 0, "Read Configuration Register-1" }, ++ { CMD_READ_ANY_REG, SPI_CMD_READ, SPI_DATA_ENABLE, 3, 8, "Read Any Register" }, ++ { CMD_WRITE_STATUS, SPI_CMD_WRITE, SPI_DATA_ENABLE, 0, 0, "Write Register (Status-1, Configuration-1)" }, ++ { CMD_WRITE_DISABLE, SPI_CMD_OTHER, SPI_DATA_DISABLE, 0, 0, "Write Disable" }, ++ { CMD_WRITE_ENABLE, SPI_CMD_OTHER, SPI_DATA_DISABLE, 0, 0, "Write Enable" }, ++ { CMD_WRITE_ANY_REG, SPI_CMD_WRITE, SPI_DATA_ENABLE, 3, 0, "Write Any Register" }, ++ { CMD_CLSR, SPI_CMD_OTHER, SPI_DATA_DISABLE, 0, 0, "Clear Status Register-1 - Erase/Prog. Fail Reset" }, ++ { CMD_CLSR_ALT, SPI_CMD_OTHER, SPI_DATA_DISABLE, 0, 0, "Clear Status Register-1 - Erase/Prog. Fail Reset" }, ++ { CMD_4BYTE_ADDR_MODE, SPI_CMD_OTHER, SPI_DATA_DISABLE, 0, 0, "Enter 4-byte Address Mode" }, ++ { CMD_SET_BURST_LEN, SPI_CMD_WRITE, SPI_DATA_ENABLE, 0, 0, "Set Burst Length" }, ++ { CMD_EVALUATE_ERASE_STATUS, SPI_CMD_OTHER, SPI_DATA_DISABLE, 3, 0, "Evaluate Erase Status" }, ++ { CMD_ECC_READ, SPI_CMD_READ, SPI_DATA_ENABLE, 3, 8, "ECC Read (3- or 4-byte address)" }, ++ { CMD_ECC_READ_ADDR4, SPI_CMD_READ, SPI_DATA_ENABLE, 4, 8, "ECC Read (4-byte address)" }, ++ { CMD_DLPRD, SPI_CMD_READ, SPI_DATA_ENABLE, 0, 0, "Data Learning Pattern Read" }, ++ { CMD_PNVDLR, SPI_CMD_WRITE, SPI_DATA_ENABLE, 0, 0, "Program NV Data Learning Register" }, ++ { CMD_WVDLR, SPI_CMD_WRITE, SPI_DATA_ENABLE, 0, 0, "Write Volatile Data Learning Register" }, ++ { CMD_READ_ARRAY_SLOW, SPI_CMD_READ, SPI_DATA_ENABLE, 3, 0, "Read (3- or 4-byte address)" }, ++ { CMD_READ_ARRAY_SLOW_ADDR4, SPI_CMD_READ, SPI_DATA_ENABLE, 4, 0, "Read (4-byte address)" }, ++ { CMD_READ_ARRAY_FAST, SPI_CMD_READ, SPI_DATA_ENABLE, 3, 8, "Fast Read (3- or 4-byte address)" }, ++ { CMD_READ_ARRAY_FAST_ADDR4, SPI_CMD_READ, SPI_DATA_ENABLE, 4, 8, "Fast Read (4-byte address)" }, ++ { CMD_READ_DUAL_IO_FAST, SPI_CMD_READ, SPI_DATA_ENABLE, 3, 8, "Dual I/O Read (3- or 4-byte address)" }, ++ { CMD_READ_DUAL_IO_FAST_ADDR4, SPI_CMD_READ, SPI_DATA_ENABLE, 4, 8, "Dual I/O Read (4-byte address)" }, ++ { CMD_READ_QUAD_IO_FAST, SPI_CMD_READ, SPI_DATA_ENABLE, 3, 8, "Quad I/O Read (3- or 4-byte address)" }, ++ { CMD_READ_QUAD_IO_FAST_ADDR4, SPI_CMD_READ, SPI_DATA_ENABLE, 4, 8, "Quad I/O Read (4-byte address)" }, ++ { CMD_READ_QUAD_IO_DDR, SPI_CMD_READ, SPI_DATA_ENABLE, 3, 8, "DDR Quad I/O Read (3- or 4-byte address)" }, ++ { CMD_READ_QUAD_IO_DDR_ADDR4, SPI_CMD_READ, SPI_DATA_ENABLE, 4, 8, "DDR Quad I/O Read (4-byte address)" }, ++ { CMD_PAGE_PROGRAM, SPI_CMD_WRITE, SPI_DATA_ENABLE, 3, 0, "Page Program (3- or 4-byte address)" }, ++ { CMD_PAGE_PROGRAM_ADDR4, SPI_CMD_WRITE, SPI_DATA_ENABLE, 4, 0, "Page Program (4-byte address)" }, ++ { CMD_ERASE_4K, SPI_CMD_ERASE, SPI_DATA_DISABLE, 3, 0, "Parameter 4 kB-sector Erase (3- or 4-byte address)" }, ++ { CMD_ERASE_4K_ADDR4, SPI_CMD_ERASE, SPI_DATA_DISABLE, 4, 0, "Parameter 4 kB-sector Erase (4-byte address)" }, ++ { CMD_ERASE_64K, SPI_CMD_ERASE, SPI_DATA_DISABLE, 3, 0, "Erase 256 kB (3- or 4-byte address)" }, ++ { CMD_ERASE_256K_ADDR4, SPI_CMD_ERASE, SPI_DATA_DISABLE, 4, 0, "Erase 256 kB (4-byte address)" }, ++ { CMD_BULK_ERASE, SPI_CMD_ERASE, SPI_DATA_DISABLE, 0, 0, "Bulk Erase" }, ++ { CMD_BULK_ERASE_ALT, SPI_CMD_ERASE, SPI_DATA_DISABLE, 0, 0, "Bulk Erase (alternate command)" }, ++ { CMD_EPS, SPI_CMD_ERASE, SPI_DATA_DISABLE, 0, 0, "Erase / Program Suspend" }, ++ { CMD_EPS_ALT, SPI_CMD_ERASE, SPI_DATA_DISABLE, 0, 0, "Erase / Program Suspend" }, ++ { CMD_EPS_ALT2, SPI_CMD_ERASE, SPI_DATA_DISABLE, 0, 0, "Erase / Program Suspend" }, ++ { CMD_EPR, SPI_CMD_ERASE, SPI_DATA_DISABLE, 0, 0, "Erase / Program Resume" }, ++ { CMD_EPR_ALT, SPI_CMD_ERASE, SPI_DATA_DISABLE, 0, 0, "Erase / Program Resume" }, ++ { CMD_EPR_ALT2, SPI_CMD_ERASE, SPI_DATA_DISABLE, 0, 0, "Erase / Program Resume" }, ++ { CMD_OTP_PROGRAM, SPI_CMD_WRITE, SPI_DATA_ENABLE, 3, 0, "OTP Program" }, ++ { CMD_OTP_READ, SPI_CMD_WRITE, SPI_DATA_ENABLE, 3, 0, "OTP Read" }, ++ { CMD_DYB_READ, SPI_CMD_READ, SPI_DATA_ENABLE, 3, 0, "DYB Read" }, ++ { CMD_DYB_READ_ADDR4, SPI_CMD_READ, SPI_DATA_ENABLE, 4, 0, "DYB Read" }, ++ { CMD_DYB_WRITE, SPI_CMD_WRITE, SPI_DATA_ENABLE, 3, 0, "DYB Write" }, ++ { CMD_DYB_WRITE_ADDR4, SPI_CMD_WRITE, SPI_DATA_ENABLE, 4, 0, "DYB Write" }, ++ { CMD_PPB_READ, SPI_CMD_READ, SPI_DATA_ENABLE, 3, 0, "PPB Read" }, ++ { CMD_PPB_READ_ADDR4, SPI_CMD_READ, SPI_DATA_ENABLE, 3, 0, "PPB Read" }, ++ { CMD_PPB_PROGRAM, SPI_CMD_WRITE, SPI_DATA_DISABLE, 3, 0, "PPB Program" }, ++ { CMD_PPB_PROGRAM_ADDR4, SPI_CMD_WRITE, SPI_DATA_DISABLE, 3, 0, "PPB Program" }, ++ { CMD_PPB_ERASE, SPI_CMD_OTHER, SPI_DATA_DISABLE, 0, 0, "PPB Erase" }, ++ { CMD_ASP_READ, SPI_CMD_READ, SPI_DATA_ENABLE, 0, 0, "ASP Read" }, ++ { CMD_ASP_PROGRAM, SPI_CMD_WRITE, SPI_DATA_ENABLE, 0, 0, "ASP Program" }, ++ { CMD_PPB_LOCKBIT_READ, SPI_CMD_READ, SPI_DATA_ENABLE, 0, 0, "PPB Lock Bit Read" }, ++ { CMD_PPB_LOCKBIT_WRITE, SPI_CMD_WRITE, SPI_DATA_DISABLE, 0, 0, "PPB Lock Bit Write" }, ++ { CMD_PASSWD_READ, SPI_CMD_READ, SPI_DATA_ENABLE, 0, 0, "Password Read" }, ++ { CMD_PASSWD_PROGRAM, SPI_CMD_WRITE, SPI_DATA_ENABLE, 0, 0, "Password Program" }, ++ { CMD_PASSWD_UNLOCK, SPI_CMD_OTHER, SPI_DATA_ENABLE, 0, 0, "Password Unlock" }, ++ { CMD_SOFT_RESET_ENABLE, SPI_CMD_OTHER, SPI_DATA_DISABLE, 0, 0, "Software Reset Enable" }, ++ { CMD_SOFT_RESET, SPI_CMD_OTHER, SPI_DATA_DISABLE, 0, 0, "Software Reset" }, ++ { CMD_LEGACY_SOFT_RESET, SPI_CMD_OTHER, SPI_DATA_DISABLE, 0, 0, "Legacy Software Reset" }, ++ { CMD_MODE_BIT_RESET, SPI_CMD_OTHER, SPI_DATA_DISABLE, 0, 0, "Mode Bit Reset" }, ++ { CMD_ENT_DEEP_POWER_DOWN, SPI_CMD_OTHER, SPI_DATA_DISABLE, 0, 0, "Enter Deep Power-Down Mode" }, ++ { CMD_REL_DEEP_POWER_DOWN, SPI_CMD_OTHER, SPI_DATA_DISABLE, 0, 0, "Release from Deep Power-Down Mode" }, ++ { SPI_COMMAND_LAST, SPI_CMD_OTHER, SPI_DATA_DISABLE, 0, 0, "Last Command" }, ++}; ++ ++static inline struct sh_qspi_slave *to_sh_qspi(struct spi_slave *slave) ++{ ++ return container_of(slave, struct sh_qspi_slave, slave); ++} ++ ++void spi_set_addr(uint32_t addr) ++{ ++ debug_print("Set Addr: %08X\n", addr); ++ out_le32(RPC_SMADR, addr); ++ return; ++} ++ ++static void rcar_gen3_qspi_init(void) ++{ ++ out_le32(RPC_PHYCNT, 0x80000260); ++ out_le32(RPC_CMNCR, 0x81FFF300); ++ ++ return; ++} ++ ++int spi_cs_is_valid(unsigned int bus, unsigned int cs) ++{ ++ return 1; ++} ++ ++void spi_cs_activate(struct spi_slave *slave) ++{ ++ out_le32(RPC_PHYCNT, 0x80000260); ++ ++ return; ++} ++ ++void spi_cs_deactivate(struct spi_slave *slave) ++{ ++ out_le32(RPC_SMCR, SPI_SMCR_SPIE); ++ WaitRpcTxEnd(); ++ out_le32(RPC_PHYCNT, 0x00000274); ++ out_le32(RPC_DRCR, 0x01FF0301); ++ ++ return; ++} ++ ++void spi_init(void) ++{ ++ /* nothing to do */ ++} ++ ++struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, ++ unsigned int max_hz, unsigned int mode) ++{ ++ struct sh_qspi_slave *ss; ++ ++ if (!spi_cs_is_valid(bus, cs)) ++ return NULL; ++ ++ ss = spi_alloc_slave(struct sh_qspi_slave, bus, cs); ++ if (!ss) { ++ printf("SPI_error: Fail to allocate sh_qspi_slave\n"); ++ return NULL; ++ } ++ ++ ss->regs = (struct rcar_gen3_qspi_regs *)SH_QSPI_BASE; ++ ++ /* Init R-Car-Gen3 QSPI */ ++ rcar_gen3_qspi_init(); ++ ++ return &ss->slave; ++} ++ ++void spi_free_slave(struct spi_slave *slave) ++{ ++ struct sh_qspi_slave *spi = to_sh_qspi(slave); ++ ++ free(spi); ++} ++ ++int spi_claim_bus(struct spi_slave *slave) ++{ ++ return 0; ++} ++ ++void spi_release_bus(struct spi_slave *slave) ++{ ++} ++ ++#define BUFFER_SIZE (128) ++int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, ++ void *din, unsigned long flags) ++{ ++ unsigned long nbyte, rnbyte, wnbyte; ++ int i, ret = 0; ++ uint32_t *tdata_l = (uint32_t *)dout; ++ uint32_t *rdata_l = (uint32_t *)din; ++ uint8_t *ptr_b; ++ uint32_t readVal, writeVal; ++ ++ if (dout == NULL && din == NULL) { ++ if (flags & SPI_XFER_END) ++ spi_cs_deactivate(slave); ++ return 0; ++ } ++ ++ if (bitlen % 8) { ++ printf("%s: bitlen is not 8bit alined %d", __func__, bitlen); ++ return 1; ++ } ++ ++ if (flags & SPI_XFER_BEGIN) { ++ spi_cs_activate(slave); ++ } ++ ++ /* Set Data Enable 32bit */ ++ readVal = in_le32(RPC_SMENR); ++ writeVal = (readVal & 0xffff0000); ++ writeVal |= SPI_SMENR_SPIDE_32BIT; ++ out_le32(RPC_SMENR, writeVal); ++ ++ nbyte = bitlen / 8; ++ if (tdata_l != NULL) ++ wnbyte = nbyte; ++ else ++ wnbyte = 0; ++ ++ if (rdata_l != NULL) ++ rnbyte = nbyte; ++ else ++ rnbyte = 0; ++ ++ while (wnbyte > 0) { ++ if (wnbyte < BYTE_32BIT) { ++ out_8(RPC_SMWDR0, *(uint8_t*)tdata_l); ++ /* Set Data Enable 8bit */ ++ readVal = in_le32(RPC_SMENR); ++ writeVal = (readVal & 0xffff0000); ++ writeVal |= SPI_SMENR_SPIDE_8BIT; ++ out_le32(RPC_SMENR, writeVal); ++ }else{ ++ out_le32(RPC_SMWDR0, *tdata_l); ++ } ++ ++ if (wnbyte >= BYTE_32BIT) { ++ tdata_l++; ++ wnbyte -= BYTE_32BIT; ++ }else{ ++ ptr_b = (uint8_t*) tdata_l; ++ ptr_b++; ++ tdata_l = (uint32_t*) ptr_b; ++ wnbyte -= BYTE_8BIT; ++ } ++ ++ if (wnbyte > 0) { ++ out_le32(RPC_SMCR, SPI_SMCR_SSLKP | SPI_SMCR_SPIWE | SPI_SMCR_SPIE); ++ }else{ ++ out_le32(RPC_SMCR, SPI_SMCR_SPIWE | SPI_SMCR_SPIE); ++ } ++ ++ WaitRpcTxEnd(); ++ ++ if (wnbyte == 0) { ++ WaitReadyDevice(slave); ++ } ++ } ++ ++ while (rnbyte > 0) { ++ if (rnbyte < BYTE_32BIT) { ++ readVal = in_le32(RPC_SMRDR0); ++ ptr_b = (uint8_t*) rdata_l; ++ for(i=0; i<rnbyte; i++) { ++ *ptr_b = (readVal >> (8*i)) & 0x000000ff; ++ ptr_b++; ++ } ++ }else{ ++ *rdata_l = in_le32(RPC_SMRDR0); ++ } ++ ++ rdata_l++; ++ ++ if(slave->spi_cmd->cmd_code == CMD_READ_ARRAY_FAST_ADDR4) { ++ readVal = in_le32(RPC_SMENR); ++ writeVal = readVal | 0x0000CF00; ++ out_le32(RPC_SMENR, writeVal); ++ readVal = in_le32(RPC_SMADR); ++ readVal += BYTE_32BIT; ++ spi_set_addr(readVal); ++ out_le32(RPC_SMCR, SPI_SMCR_SPIRE | SPI_SMCR_SPIE); ++ }else{ ++ if (rnbyte > BYTE_32BIT) { ++ out_le32(RPC_SMCR, SPI_SMCR_SSLKP | SPI_SMCR_SPIRE | SPI_SMCR_SPIE); ++ }else{ ++ out_le32(RPC_SMCR, SPI_SMCR_SPIRE | SPI_SMCR_SPIE); ++ } ++ } ++ ++ WaitRpcTxEnd(); ++ ++ if (rnbyte >= BYTE_32BIT) { ++ rnbyte -= BYTE_32BIT; ++ }else{ ++ rnbyte = 0; ++ } ++ } ++ ++ if (flags & SPI_XFER_END){ ++ spi_cs_deactivate(slave); ++ } ++ ++ return ret; ++} ++ ++int spi_xfer_cmd(struct spi_slave *slave, int cmd_no) ++{ ++ uint32_t readVal, writeVal, dummy_cyc; ++ const SPI_COMMAND *cur_cmd_tbl; ++ cur_cmd_tbl = spi_cmd_tbl; ++ ++ while(cur_cmd_tbl->cmd_code != SPI_COMMAND_LAST) { ++ if(cur_cmd_tbl->cmd_code != cmd_no) { ++ cur_cmd_tbl++; ++ continue; ++ } ++ ++ slave->spi_cmd = cur_cmd_tbl; ++ ++ spi_cs_activate(slave); ++ out_le32(RPC_SMCMR, cmd_no << SPI_SMCMR_CMD_BIT); ++ debug_print("SPI CODE:0x%02X [ %s ]\n", cur_cmd_tbl->cmd_code, cur_cmd_tbl->cmd_desc); ++ ++ readVal = in_le32(RPC_SMENR); ++ writeVal = readVal & 0xFFFF0000; ++ writeVal |= SPI_SMENR_CDE; ++ ++ /* Setting Address */ ++ switch (cur_cmd_tbl->addr_len) { ++ case 3: ++ writeVal |= SPI_SMENR_ADE_3BYTE; ++ break; ++ case 4: ++ writeVal |= SPI_SMENR_ADE_4BYTE; ++ break; ++ default: ++ writeVal |= SPI_SMENR_ADE_DISABLE; ++ break; ++ } ++ ++ /* Setting dummy cycle */ ++ if (cur_cmd_tbl->dummy_len != 0) { ++ writeVal |= SPI_SMENR_DME; ++ dummy_cyc = cur_cmd_tbl->dummy_len - 1; ++ out_le32(RPC_SMDMCR, dummy_cyc); ++ } ++ out_le32(RPC_SMENR, writeVal); ++ ++ switch(cur_cmd_tbl->rw_type) { ++ case SPI_CMD_READ: ++ readVal = in_le32(RPC_SMENR); ++ writeVal = readVal & 0xFFFFFFF0; ++ writeVal |= SPI_SMENR_SPIDE_32BIT; ++ out_le32(RPC_SMENR, writeVal); ++ ++ if(cur_cmd_tbl->data_enable == SPI_DATA_ENABLE) { ++ if(cur_cmd_tbl->cmd_code == CMD_READ_ARRAY_FAST_ADDR4) { ++ out_le32(RPC_SMCR, SPI_SMCR_SPIRE | SPI_SMCR_SPIE); ++ }else{ ++ out_le32(RPC_SMCR, SPI_SMCR_SSLKP | SPI_SMCR_SPIRE | SPI_SMCR_SPIE); ++ } ++ }else{ ++ out_le32(RPC_SMCR, SPI_SMCR_SPIRE | SPI_SMCR_SPIE); ++ } ++ break; ++ case SPI_CMD_WRITE: ++ if(cur_cmd_tbl->data_enable == SPI_DATA_ENABLE) { ++ out_le32(RPC_SMCR, SPI_SMCR_SSLKP | SPI_SMCR_SPIWE | SPI_SMCR_SPIE); ++ }else{ ++ out_le32(RPC_SMCR, SPI_SMCR_SPIWE | SPI_SMCR_SPIE); ++ } ++ break; ++ default: ++ if(cur_cmd_tbl->data_enable == SPI_DATA_ENABLE) { ++ out_le32(RPC_SMCR, SPI_SMCR_SSLKP | SPI_SMCR_SPIE); ++ }else{ ++ out_le32(RPC_SMCR, SPI_SMCR_SPIE); ++ } ++ break; ++ } ++ ++ WaitRpcTxEnd(); ++ ++ if (cur_cmd_tbl->data_enable != SPI_DATA_ENABLE) { ++ spi_cs_deactivate(slave); ++ } ++ break; ++ } ++ ++ if(cur_cmd_tbl->cmd_code == SPI_COMMAND_LAST) { ++ printf("Unknown SPI Command : %02x\n", cmd_no); ++ return -1; ++ } ++ return 0; ++} ++ ++void WaitRpcTxEnd(void) ++{ ++ uint32_t dataL=0; ++ ++ while(1) { ++ dataL = in_le32(RPC_CMNSR); ++ if(dataL & 0x00000001) { ++ break; ++ } ++ // Wait for TEND = 1 ++ if(ctrlc()) { ++ puts("abort\n"); ++ return; ++ } ++ udelay(1); ++ } ++ return; ++} ++ ++void WaitReadyDevice(struct spi_slave *slave) ++{ ++ int ret; ++ u8 status; ++ while(1) { ++ ret = spi_get_read_status(slave, &status); ++ if (ret < 0) { ++ printf("SF: fail to get read status\n"); ++ return; ++ } ++ if ((status & SR1V_WIP) == 0) { ++ break; ++ } ++ udelay(1); ++ } ++ return; ++} ++ ++int spi_get_read_status(struct spi_slave *slave, u8 *rs) ++{ ++ int ret; ++ u8 cmd; ++ ++ cmd = CMD_READ_STATUS; ++ ret = spi_flash_cmd_read(slave, &cmd, 1, rs, 1); ++ if (ret < 0) { ++ debug("SF: fail to get read status register\n"); ++ return ret; ++ } ++ ++ return 0; ++} +diff --git a/drivers/spi/rcar_gen3_qspi.h b/drivers/spi/rcar_gen3_qspi.h +new file mode 100644 +index 0000000..deb18d3 +--- /dev/null ++++ b/drivers/spi/rcar_gen3_qspi.h +@@ -0,0 +1,301 @@ ++/* ++ * Common R-Car-Gen3 QSPI Interface: Controller-specific definitions ++ * ++ */ ++ ++#ifndef _R_CAR_GEN3_QSPI_H_ ++#define _R_CAR_GEN3_QSPI_H_ ++ ++/* SPI transfer flags */ ++#define SPI_XFER_BEGIN 0x01 /* Assert CS before transfer */ ++#define SPI_XFER_END 0x02 /* Deassert CS after transfer */ ++#define SPI_XFER_MMAP 0x08 /* Memory Mapped start */ ++#define SPI_XFER_MMAP_END 0x10 /* Memory Mapped End */ ++#define SPI_XFER_ONCE (SPI_XFER_BEGIN | SPI_XFER_END) ++#define SPI_XFER_U_PAGE (1 << 5) ++ ++#define SPI_COMMAND_LAST 0xffffffff ++#define SPI_SMCMR_CMD_BIT 16 ++ ++#define SPI_CMD_OTHER 0 ++#define SPI_CMD_READ 1 ++#define SPI_CMD_WRITE 2 ++#define SPI_CMD_ERASE 3 ++ ++#define SPI_DATA_DISABLE 0 ++#define SPI_DATA_ENABLE 1 ++ ++#define SPI_SMCR_SPIE 0x00000001 ++#define SPI_SMCR_SPIWE 0x00000002 ++#define SPI_SMCR_SPIRE 0x00000004 ++#define SPI_SMCR_SSLKP 0x00000100 ++ ++#define SPI_SMENR_DME (1 << 15) ++#define SPI_SMENR_CDE (1 << 14) ++#define SPI_SMENR_ADE_DISABLE (0x0 << 8) ++#define SPI_SMENR_ADE_3BYTE (0x7 << 8) ++#define SPI_SMENR_ADE_4BYTE (0xF << 8) ++#define SPI_SMENR_SPIDE_DISABLE (0x0) ++#define SPI_SMENR_SPIDE_8BIT (0x8) ++#define SPI_SMENR_SPIDE_16BIT (0xC) ++#define SPI_SMENR_SPIDE_32BIT (0xF) ++ ++#define BYTE_32BIT (4) ++#define BYTE_8BIT (1) ++ ++typedef struct { ++ uint32_t cmd_code; ++ uint8_t rw_type; ++ uint32_t data_enable; ++ uint32_t addr_len; ++ uint32_t dummy_len; ++ char* cmd_desc; ++} SPI_COMMAND; ++ ++/** ++ * struct spi_slave - Representation of a SPI slave ++ * ++ * For driver model this is the per-child data used by the SPI bus. It can ++ * be accessed using dev_get_parentdata() on the slave device. The SPI uclass ++ * sets uip per_child_auto_alloc_size to sizeof(struct spi_slave), and the ++ * driver should not override it. Two platform data fields (max_hz and mode) ++ * are copied into this structure to provide an initial value. This allows ++ * them to be changed, since we should never change platform data in drivers. ++ * ++ * If not using driver model, drivers are expected to extend this with ++ * controller-specific data. ++ * ++ * @dev: SPI slave device ++ * @max_hz: Maximum speed for this slave ++ * @mode: SPI mode to use for this slave (see SPI mode flags) ++ * @bus: ID of the bus that the slave is attached to. For ++ * driver model this is the sequence number of the SPI ++ * bus (bus->seq) so does not need to be stored ++ * @cs: ID of the chip select connected to the slave. ++ * @op_mode_rx: SPI RX operation mode. ++ * @op_mode_tx: SPI TX operation mode. ++ * @wordlen: Size of SPI word in number of bits ++ * @max_write_size: If non-zero, the maximum number of bytes which can ++ * be written at once, excluding command bytes. ++ * @memory_map: Address of read-only SPI flash access. ++ * @option: Varies SPI bus options - separate, shared bus. ++ * @flags: Indication of SPI flags. ++ */ ++struct spi_slave { ++#ifdef CONFIG_DM_SPI ++ struct udevice *dev; /* struct spi_slave is dev->parentdata */ ++ uint max_hz; ++ uint mode; ++#else ++ unsigned int bus; ++ unsigned int cs; ++#endif ++ u8 op_mode_rx; ++ u8 op_mode_tx; ++ unsigned int wordlen; ++ unsigned int max_write_size; ++ void *memory_map; ++ u8 option; ++ u8 flags; ++ const SPI_COMMAND *spi_cmd; ++}; ++ ++/** ++ * Initialization, must be called once on start up. ++ * ++ * TODO: I don't think we really need this. ++ */ ++void spi_init(void); ++ ++/** ++ * spi_do_alloc_slave - Allocate a new SPI slave (internal) ++ * ++ * Allocate and zero all fields in the spi slave, and set the bus/chip ++ * select. Use the helper macro spi_alloc_slave() to call this. ++ * ++ * @offset: Offset of struct spi_slave within slave structure. ++ * @size: Size of slave structure. ++ * @bus: Bus ID of the slave chip. ++ * @cs: Chip select ID of the slave chip on the specified bus. ++ */ ++void *spi_do_alloc_slave(int offset, int size, unsigned int bus, ++ unsigned int cs); ++ ++/** ++ * spi_alloc_slave - Allocate a new SPI slave ++ * ++ * Allocate and zero all fields in the spi slave, and set the bus/chip ++ * select. ++ * ++ * @_struct: Name of structure to allocate (e.g. struct tegra_spi). ++ * This structure must contain a member 'struct spi_slave *slave'. ++ * @bus: Bus ID of the slave chip. ++ * @cs: Chip select ID of the slave chip on the specified bus. ++ */ ++#define spi_alloc_slave(_struct, bus, cs) \ ++ spi_do_alloc_slave(offsetof(_struct, slave), \ ++ sizeof(_struct), bus, cs) ++ ++/** ++ * spi_alloc_slave_base - Allocate a new SPI slave with no private data ++ * ++ * Allocate and zero all fields in the spi slave, and set the bus/chip ++ * select. ++ * ++ * @bus: Bus ID of the slave chip. ++ * @cs: Chip select ID of the slave chip on the specified bus. ++ */ ++#define spi_alloc_slave_base(bus, cs) \ ++ spi_do_alloc_slave(0, sizeof(struct spi_slave), bus, cs) ++ ++/** ++ * Set up communications parameters for a SPI slave. ++ * ++ * This must be called once for each slave. Note that this function ++ * usually doesn't touch any actual hardware, it only initializes the ++ * contents of spi_slave so that the hardware can be easily ++ * initialized later. ++ * ++ * @bus: Bus ID of the slave chip. ++ * @cs: Chip select ID of the slave chip on the specified bus. ++ * @max_hz: Maximum SCK rate in Hz. ++ * @mode: Clock polarity, clock phase and other parameters. ++ * ++ * Returns: A spi_slave reference that can be used in subsequent SPI ++ * calls, or NULL if one or more of the parameters are not supported. ++ */ ++struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, ++ unsigned int max_hz, unsigned int mode); ++ ++/** ++ * Free any memory associated with a SPI slave. ++ * ++ * @slave: The SPI slave ++ */ ++void spi_free_slave(struct spi_slave *slave); ++ ++/** ++ * Claim the bus and prepare it for communication with a given slave. ++ * ++ * This must be called before doing any transfers with a SPI slave. It ++ * will enable and initialize any SPI hardware as necessary, and make ++ * sure that the SCK line is in the correct idle state. It is not ++ * allowed to claim the same bus for several slaves without releasing ++ * the bus in between. ++ * ++ * @slave: The SPI slave ++ * ++ * Returns: 0 if the bus was claimed successfully, or a negative value ++ * if it wasn't. ++ */ ++int spi_claim_bus(struct spi_slave *slave); ++ ++/** ++ * Release the SPI bus ++ * ++ * This must be called once for every call to spi_claim_bus() after ++ * all transfers have finished. It may disable any SPI hardware as ++ * appropriate. ++ * ++ * @slave: The SPI slave ++ */ ++void spi_release_bus(struct spi_slave *slave); ++ ++/** ++ * Set the word length for SPI transactions ++ * ++ * Set the word length (number of bits per word) for SPI transactions. ++ * ++ * @slave: The SPI slave ++ * @wordlen: The number of bits in a word ++ * ++ * Returns: 0 on success, -1 on failure. ++ */ ++int spi_set_wordlen(struct spi_slave *slave, unsigned int wordlen); ++ ++/** ++ * SPI transfer ++ * ++ * This writes "bitlen" bits out the SPI MOSI port and simultaneously clocks ++ * "bitlen" bits in the SPI MISO port. That's just the way SPI works. ++ * ++ * The source of the outgoing bits is the "dout" parameter and the ++ * destination of the input bits is the "din" parameter. Note that "dout" ++ * and "din" can point to the same memory location, in which case the ++ * input data overwrites the output data (since both are buffered by ++ * temporary variables, this is OK). ++ * ++ * spi_xfer() interface: ++ * @slave: The SPI slave which will be sending/receiving the data. ++ * @bitlen: How many bits to write and read. ++ * @dout: Pointer to a string of bits to send out. The bits are ++ * held in a byte array and are sent MSB first. ++ * @din: Pointer to a string of bits that will be filled in. ++ * @flags: A bitwise combination of SPI_XFER_* flags. ++ * ++ * Returns: 0 on success, not 0 on failure ++ */ ++int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, ++ void *din, unsigned long flags); ++ ++/** ++ * Determine if a SPI chipselect is valid. ++ * This function is provided by the board if the low-level SPI driver ++ * needs it to determine if a given chipselect is actually valid. ++ * ++ * Returns: 1 if bus:cs identifies a valid chip on this board, 0 ++ * otherwise. ++ */ ++int spi_cs_is_valid(unsigned int bus, unsigned int cs); ++ ++#ifndef CONFIG_DM_SPI ++/** ++ * Activate a SPI chipselect. ++ * This function is provided by the board code when using a driver ++ * that can't control its chipselects automatically (e.g. ++ * common/soft_spi.c). When called, it should activate the chip select ++ * to the device identified by "slave". ++ */ ++void spi_cs_activate(struct spi_slave *slave); ++ ++/** ++ * Deactivate a SPI chipselect. ++ * This function is provided by the board code when using a driver ++ * that can't control its chipselects automatically (e.g. ++ * common/soft_spi.c). When called, it should deactivate the chip ++ * select to the device identified by "slave". ++ */ ++void spi_cs_deactivate(struct spi_slave *slave); ++ ++/** ++ * Set transfer speed. ++ * This sets a new speed to be applied for next spi_xfer(). ++ * @slave: The SPI slave ++ * @hz: The transfer speed ++ */ ++void spi_set_speed(struct spi_slave *slave, uint hz); ++#endif ++ ++ ++/** ++ * Set up a SPI slave for a particular device tree node ++ * ++ * This calls spi_setup_slave() with the correct bus number. Call ++ * spi_free_slave() to free it later. ++ * ++ * @param blob: Device tree blob ++ * @param slave_node: Slave node to use ++ * @param spi_node: SPI peripheral node to use ++ * @return pointer to new spi_slave structure ++ */ ++struct spi_slave *spi_setup_slave_fdt(const void *blob, int slave_node, ++ int spi_node); ++ ++/* QSPI Flash Read/Write function */ ++void spi_set_addr(uint32_t addr); ++int spi_xfer_cmd(struct spi_slave *slave, int cmd_no); ++void WaitRpcTxEnd(void); ++void WaitReadyDevice(struct spi_slave *slave); ++int spi_get_read_status(struct spi_slave *slave, u8 *rs); ++ ++#endif /* _R_CAR_GEN3_QSPI_H_ */ +diff --git a/include/linux/bitops.h b/include/linux/bitops.h +index e724310..3bf04d2 100644 +--- a/include/linux/bitops.h ++++ b/include/linux/bitops.h +@@ -104,6 +104,7 @@ static inline unsigned int generic_hweight8(unsigned int w) + return (res & 0x0F) + ((res >> 4) & 0x0F); + } + ++#define BIT(nr) (1UL << (nr)) + #define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) + #define BIT_WORD(nr) ((nr) / BITS_PER_LONG) + +diff --git a/include/spi.h b/include/spi.h +index c58e453..d6978c7 100644 +--- a/include/spi.h ++++ b/include/spi.h +@@ -11,18 +11,24 @@ + #define _SPI_H_ + + /* SPI mode flags */ +-#define SPI_CPHA 0x01 /* clock phase */ +-#define SPI_CPOL 0x02 /* clock polarity */ ++#define SPI_CPHA BIT(0) /* clock phase */ ++#define SPI_CPOL BIT(1) /* clock polarity */ + #define SPI_MODE_0 (0|0) /* (original MicroWire) */ + #define SPI_MODE_1 (0|SPI_CPHA) + #define SPI_MODE_2 (SPI_CPOL|0) + #define SPI_MODE_3 (SPI_CPOL|SPI_CPHA) +-#define SPI_CS_HIGH 0x04 /* CS active high */ +-#define SPI_LSB_FIRST 0x08 /* per-word bits-on-wire */ +-#define SPI_3WIRE 0x10 /* SI/SO signals shared */ +-#define SPI_LOOP 0x20 /* loopback mode */ +-#define SPI_SLAVE 0x40 /* slave mode */ +-#define SPI_PREAMBLE 0x80 /* Skip preamble bytes */ ++#define SPI_CS_HIGH BIT(2) /* CS active high */ ++#define SPI_LSB_FIRST BIT(3) /* per-word bits-on-wire */ ++#define SPI_3WIRE BIT(4) /* SI/SO signals shared */ ++#define SPI_LOOP BIT(5) /* loopback mode */ ++#define SPI_SLAVE BIT(6) /* slave mode */ ++#define SPI_PREAMBLE BIT(7) /* Skip preamble bytes */ ++#define SPI_TX_BYTE BIT(8) /* transmit with 1 wire byte */ ++#define SPI_TX_DUAL BIT(9) /* transmit with 2 wires */ ++#define SPI_TX_QUAD BIT(10) /* transmit with 4 wires */ ++#define SPI_RX_SLOW BIT(11) /* receive with 1 wire slow */ ++#define SPI_RX_DUAL BIT(12) /* receive with 2 wires */ ++#define SPI_RX_QUAD BIT(13) /* receive with 4 wires */ + + /* SPI transfer flags */ + #define SPI_XFER_BEGIN 0x01 /* Assert CS before transfer */ +-- +1.9.1 diff --git a/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0014-arm-renesas-Add-Renesas-R8A7797-SoC-support.patch b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0014-arm-renesas-Add-Renesas-R8A7797-SoC-support.patch new file mode 100644 index 0000000..672ec39 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0014-arm-renesas-Add-Renesas-R8A7797-SoC-support.patch @@ -0,0 +1,3543 @@ +From 02cc2edc21e6c6895cf0304beecae4d990225ea2 Mon Sep 17 00:00:00 2001 +From: Daisuke Matsushita <daisuke.matsushita.ns@hitachi.com> +Date: Tue, 21 Mar 2017 15:05:15 +0900 +Subject: [PATCH] arm: renesas: Add Renesas R8A7797 SoC support + +This adds Renesas R8A7797 SoC support + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + arch/arm/cpu/armv8/Kconfig | 3 + + arch/arm/cpu/armv8/rcar_gen3/Makefile | 2 + + arch/arm/cpu/armv8/rcar_gen3/cpu_info-r8a7797.c | 39 + + arch/arm/cpu/armv8/rcar_gen3/cpu_info.c | 8 + + arch/arm/cpu/armv8/rcar_gen3/pfc-r8a7797.c | 2764 ++++++++++++++++++++ + arch/arm/cpu/armv8/rcar_gen3/prr_depend.c | 29 + + arch/arm/include/asm/arch-rcar_gen3/gpio.h | 4 + + arch/arm/include/asm/arch-rcar_gen3/r8a7797-gpio.h | 456 ++++ + arch/arm/include/asm/arch-rcar_gen3/r8a7797.h | 33 + + arch/arm/include/asm/arch-rcar_gen3/rcar-base.h | 5 + + arch/arm/include/asm/arch-rcar_gen3/rcar_gen3.h | 2 + + drivers/serial/serial_sh.h | 3 +- + include/configs/rcar-gen3-common.h | 12 + + 13 files changed, 3359 insertions(+), 1 deletion(-) + create mode 100644 arch/arm/cpu/armv8/rcar_gen3/cpu_info-r8a7797.c + create mode 100644 arch/arm/cpu/armv8/rcar_gen3/pfc-r8a7797.c + create mode 100644 arch/arm/include/asm/arch-rcar_gen3/r8a7797-gpio.h + create mode 100644 arch/arm/include/asm/arch-rcar_gen3/r8a7797.h + +diff --git a/arch/arm/cpu/armv8/Kconfig b/arch/arm/cpu/armv8/Kconfig +index 415a9ee..36b7983 100644 +--- a/arch/arm/cpu/armv8/Kconfig ++++ b/arch/arm/cpu/armv8/Kconfig +@@ -27,6 +27,9 @@ config R8A7795 + config R8A7796 + bool "Renesas SoC R8A7796" + ++config R8A7797 ++ bool "Renesas SoC R8A7797" ++ + endchoice + + config SYS_SOC +diff --git a/arch/arm/cpu/armv8/rcar_gen3/Makefile b/arch/arm/cpu/armv8/rcar_gen3/Makefile +index 2bf2416..e85ca94 100644 +--- a/arch/arm/cpu/armv8/rcar_gen3/Makefile ++++ b/arch/arm/cpu/armv8/rcar_gen3/Makefile +@@ -13,3 +13,5 @@ obj-$(CONFIG_R8A7795) += lowlevel_init.o cpu_info-r8a7795.o \ + pfc.o pfc-r8a7795.o pfc-r8a7795_es.o prr_depend.o + obj-$(CONFIG_R8A7796) += lowlevel_init.o cpu_info-r8a7796.o \ + pfc.o pfc-r8a7796.o prr_depend.o ++obj-$(CONFIG_R8A7797) += lowlevel_init.o cpu_info-r8a7797.o \ ++ pfc.o pfc-r8a7797.o prr_depend.o +diff --git a/arch/arm/cpu/armv8/rcar_gen3/cpu_info-r8a7797.c b/arch/arm/cpu/armv8/rcar_gen3/cpu_info-r8a7797.c +new file mode 100644 +index 0000000..cc8e1e6 +--- /dev/null ++++ b/arch/arm/cpu/armv8/rcar_gen3/cpu_info-r8a7797.c +@@ -0,0 +1,39 @@ ++/* ++ * arch/arm/cpu/armv8/rcar_gen3/cpu_info-r8a7797.c ++ * This file defines cpu information funstions. ++ * ++ * Copyright (C) 2016 Renesas Electronics Corporation ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ */ ++#include <common.h> ++#include <asm/io.h> ++ ++#define PRR 0xFFF00044 ++ ++u32 rcar_get_cpu_type(void) ++{ ++ u32 product; ++ ++ product = readl(PRR); ++ ++ return (product & 0x00007F00) >> 8; ++} ++ ++u32 rcar_get_cpu_rev_integer(void) ++{ ++ u32 product; ++ ++ product = readl(PRR); ++ ++ return (u32)(((product & 0x000000F0) >> 4) + 1); ++} ++ ++u32 rcar_get_cpu_rev_fraction(void) ++{ ++ u32 product; ++ ++ product = readl(PRR); ++ ++ return (u32)(product & 0x0000000F); ++} +diff --git a/arch/arm/cpu/armv8/rcar_gen3/cpu_info.c b/arch/arm/cpu/armv8/rcar_gen3/cpu_info.c +index c3fd92b..1d5127d 100644 +--- a/arch/arm/cpu/armv8/rcar_gen3/cpu_info.c ++++ b/arch/arm/cpu/armv8/rcar_gen3/cpu_info.c +@@ -73,6 +73,14 @@ int print_cpuinfo(void) + CONFIG_RCAR_TARGET_STRING); + } + break; ++ case 0x54: ++ printf("CPU: Renesas Electronics R8A7797 rev %d.%d\n", ++ rev_integer, rev_fraction); ++ if (strcmp(CONFIG_RCAR_TARGET_STRING, "r8a7797")) { ++ printf("Warning: this code supports only %s\n", ++ CONFIG_RCAR_TARGET_STRING); ++ } ++ break; + } + return 0; + } +diff --git a/arch/arm/cpu/armv8/rcar_gen3/pfc-r8a7797.c b/arch/arm/cpu/armv8/rcar_gen3/pfc-r8a7797.c +new file mode 100644 +index 0000000..3b2f75e +--- /dev/null ++++ b/arch/arm/cpu/armv8/rcar_gen3/pfc-r8a7797.c +@@ -0,0 +1,2764 @@ ++/* ++ * arch/arm/cpu/armv8/rcar_gen3/pfc-r8a7797.c ++ * This file is r8a7797 processor support - PFC hardware block. ++ * ++ * Copyright (C) 2016 Renesas Electronics Corporation ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ */ ++ ++#include <common.h> ++#include <sh_pfc.h> ++#include <asm/gpio.h> ++ ++#define CPU_32_PORT(fn, pfx, sfx) \ ++ PORT_10(fn, pfx, sfx), PORT_10(fn, pfx##1, sfx), \ ++ PORT_10(fn, pfx##2, sfx), PORT_1(fn, pfx##30, sfx), \ ++ PORT_1(fn, pfx##31, sfx) ++ ++#define CPU_32_PORT1(fn, pfx, sfx) \ ++ PORT_10(fn, pfx, sfx), PORT_10(fn, pfx##1, sfx), \ ++ PORT_10(fn, pfx##2, sfx) ++ ++#define CPU_32_PORT2(fn, pfx, sfx) \ ++ PORT_10(fn, pfx, sfx), PORT_10(fn, pfx##1, sfx), \ ++ PORT_10(fn, pfx##2, sfx) ++ ++#define CPU_32_PORT_28(fn, pfx, sfx) \ ++ PORT_10(fn, pfx, sfx), \ ++ PORT_10(fn, pfx##1, sfx), \ ++ PORT_1(fn, pfx##20, sfx), \ ++ PORT_1(fn, pfx##21, sfx), \ ++ PORT_1(fn, pfx##22, sfx), \ ++ PORT_1(fn, pfx##23, sfx), \ ++ PORT_1(fn, pfx##24, sfx), \ ++ PORT_1(fn, pfx##25, sfx), \ ++ PORT_1(fn, pfx##26, sfx), \ ++ PORT_1(fn, pfx##27, sfx) ++ ++#define CPU_32_PORT_22(fn, pfx, sfx) \ ++ PORT_10(fn, pfx, sfx), \ ++ PORT_10(fn, pfx##1, sfx), \ ++ PORT_1(fn, pfx##20, sfx), \ ++ PORT_1(fn, pfx##21, sfx) ++ ++#define CPU_32_PORT_17(fn, pfx, sfx) \ ++ PORT_10(fn, pfx, sfx), \ ++ PORT_1(fn, pfx##10, sfx), \ ++ PORT_1(fn, pfx##11, sfx), \ ++ PORT_1(fn, pfx##12, sfx), \ ++ PORT_1(fn, pfx##13, sfx), \ ++ PORT_1(fn, pfx##14, sfx), \ ++ PORT_1(fn, pfx##15, sfx), \ ++ PORT_1(fn, pfx##16, sfx) ++ ++#define CPU_32_PORT_15(fn, pfx, sfx) \ ++ PORT_10(fn, pfx, sfx), \ ++ PORT_1(fn, pfx##10, sfx), \ ++ PORT_1(fn, pfx##11, sfx), \ ++ PORT_1(fn, pfx##12, sfx), \ ++ PORT_1(fn, pfx##13, sfx), \ ++ PORT_1(fn, pfx##14, sfx) ++ ++#define CPU_32_PORT_6(fn, pfx, sfx) \ ++ PORT_1(fn, pfx##0, sfx), \ ++ PORT_1(fn, pfx##1, sfx), \ ++ PORT_1(fn, pfx##2, sfx), \ ++ PORT_1(fn, pfx##3, sfx), \ ++ PORT_1(fn, pfx##4, sfx), \ ++ PORT_1(fn, pfx##5, sfx) ++ ++ ++/* --gen3-- */ ++/* GP_0_0_DATA -> GP_5_14_DATA */ ++/* except for GP0[22] - [31], ++ GP1[28] - [31], ++ GP2[17] - [31], ++ GP3[17] - [31], ++ GP4[6] - [31], ++ GP5[15] - [31], */ ++ ++#define CPU_ALL_PORT(fn, pfx, sfx) \ ++ CPU_32_PORT_22(fn, pfx##_0_, sfx), \ ++ CPU_32_PORT_28(fn, pfx##_1_, sfx), \ ++ CPU_32_PORT_17(fn, pfx##_2_, sfx), \ ++ CPU_32_PORT_17(fn, pfx##_3_, sfx), \ ++ CPU_32_PORT_6(fn, pfx##_4_, sfx), \ ++ CPU_32_PORT_15(fn, pfx##_5_, sfx) ++ ++#define _GP_GPIO(pfx, sfx) PINMUX_GPIO(GPIO_GP##pfx, GP##pfx##_DATA) ++#define _GP_DATA(pfx, sfx) PINMUX_DATA(GP##pfx##_DATA, GP##pfx##_FN, \ ++ GP##pfx##_IN, GP##pfx##_OUT) ++ ++#define _GP_INOUTSEL(pfx, sfx) GP##pfx##_IN, GP##pfx##_OUT ++#define _GP_INDT(pfx, sfx) GP##pfx##_DATA ++ ++#define GP_ALL(str) CPU_ALL_PORT(_PORT_ALL, GP, str) ++#define PINMUX_GPIO_GP_ALL() CPU_ALL_PORT(_GP_GPIO, , unused) ++#define PINMUX_DATA_GP_ALL() CPU_ALL_PORT(_GP_DATA, , unused) ++ ++ ++#define PORT_10_REV(fn, pfx, sfx) \ ++ PORT_1(fn, pfx##9, sfx), PORT_1(fn, pfx##8, sfx), \ ++ PORT_1(fn, pfx##7, sfx), PORT_1(fn, pfx##6, sfx), \ ++ PORT_1(fn, pfx##5, sfx), PORT_1(fn, pfx##4, sfx), \ ++ PORT_1(fn, pfx##3, sfx), PORT_1(fn, pfx##2, sfx), \ ++ PORT_1(fn, pfx##1, sfx), PORT_1(fn, pfx##0, sfx) ++ ++#define CPU_32_PORT_REV(fn, pfx, sfx) \ ++ PORT_1(fn, pfx##31, sfx), PORT_1(fn, pfx##30, sfx), \ ++ PORT_10_REV(fn, pfx##2, sfx), PORT_10_REV(fn, pfx##1, sfx), \ ++ PORT_10_REV(fn, pfx, sfx) ++ ++#define GP_INOUTSEL(bank) CPU_32_PORT_REV(_GP_INOUTSEL, _##bank##_, unused) ++#define GP_INDT(bank) CPU_32_PORT_REV(_GP_INDT, _##bank##_, unused) ++ ++#define PINMUX_IPSR_IDATA(fn) PINMUX_DATA(fn##_IMARK, GFN_##fn, IFN_##fn) ++#define PINMUX_IPSR_DATA(ipsr, fn) PINMUX_DATA(fn##_MARK, GFN_##ipsr, FN_##fn) ++#define PINMUX_IPSR_MODSEL_DATA(ipsr, fn, ms) PINMUX_DATA(fn##_MARK, FN_##ms, \ ++ FN_##ipsr, FN_##fn) ++ ++enum { ++ PINMUX_RESERVED = 0, ++ ++ PINMUX_DATA_BEGIN, ++ GP_ALL(DATA), ++ PINMUX_DATA_END, ++ ++ PINMUX_INPUT_BEGIN, ++ GP_ALL(IN), ++ PINMUX_INPUT_END, ++ ++ PINMUX_OUTPUT_BEGIN, ++ GP_ALL(OUT), ++ PINMUX_OUTPUT_END, ++ ++ PINMUX_FUNCTION_BEGIN, ++ GP_ALL(FN), ++ ++ /* GPSR0 */ ++ GFN_DU_EXODDF_DU_ODDF_DISP_CDE, ++ GFN_DU_EXVSYNC_DU_VSYNC, ++ GFN_DU_EXHSYNC_DU_HSYNC, ++ GFN_DU_DOTCLKOUT, ++ GFN_DU_DB7, ++ GFN_DU_DB6, ++ GFN_DU_DB5, ++ GFN_DU_DB4, ++ GFN_DU_DB3, ++ GFN_DU_DB2, ++ GFN_DU_DG7, ++ GFN_DU_DG6, ++ GFN_DU_DG5, ++ GFN_DU_DG4, ++ GFN_DU_DG3, ++ GFN_DU_DG2, ++ GFN_DU_DR7, ++ GFN_DU_DR6, ++ GFN_DU_DR5, ++ GFN_DU_DR4, ++ GFN_DU_DR3, ++ GFN_DU_DR2, ++ ++ /* GPSR1 */ ++ GFN_DIGRF_CLKOUT, ++ GFN_DIGRF_CLKIN, ++ GFN_CANFD_CLK_A, ++ GFN_CANFD1_RX, ++ GFN_CANFD1_TX, ++ GFN_CANFD0_RX_A, ++ GFN_CANFD0_TX_A, ++ GFN_AVB0_AVTP_CAPTURE, ++ FN_AVB0_AVTP_MATCH, ++ FN_AVB0_LINK, ++ FN_AVB0_PHY_INT, ++ FN_AVB0_MAGIC, ++ FN_AVB0_MDC, ++ FN_AVB0_MDIO, ++ FN_AVB0_TXCREFCLK, ++ FN_AVB0_TD3, ++ FN_AVB0_TD2, ++ FN_AVB0_TD1, ++ FN_AVB0_TD0, ++ FN_AVB0_TXC, ++ FN_AVB0_TX_CTL, ++ FN_AVB0_RD3, ++ FN_AVB0_RD2, ++ FN_AVB0_RD1, ++ FN_AVB0_RD0, ++ FN_AVB0_RXC, ++ FN_AVB0_RX_CTL, ++ GFN_IRQ0, ++ ++ /* GPSR2 */ ++ GFN_VI0_FIELD, ++ GFN_VI0_DATA11, ++ GFN_VI0_DATA10, ++ GFN_VI0_DATA9, ++ GFN_VI0_DATA8, ++ GFN_VI0_DATA7, ++ GFN_VI0_DATA6, ++ GFN_VI0_DATA5, ++ GFN_VI0_DATA4, ++ GFN_VI0_DATA3, ++ GFN_VI0_DATA2, ++ GFN_VI0_DATA1, ++ GFN_VI0_DATA0, ++ GFN_VI0_VSYNC_N, ++ GFN_VI0_HSYNC_N, ++ GFN_VI0_CLKENB, ++ GFN_VI0_CLK, ++ ++ /* GPSR3 */ ++ GFN_VI1_FIELD, ++ GFN_VI1_DATA11, ++ GFN_VI1_DATA10, ++ GFN_VI1_DATA9, ++ GFN_VI1_DATA8, ++ GFN_VI1_DATA7, ++ GFN_VI1_DATA6, ++ GFN_VI1_DATA5, ++ GFN_VI1_DATA4, ++ GFN_VI1_DATA3, ++ GFN_VI1_DATA2, ++ GFN_VI1_DATA1, ++ GFN_VI1_DATA0, ++ GFN_VI1_VSYNC_N, ++ GFN_VI1_HSYNC_N, ++ GFN_VI1_CLKENB, ++ GFN_VI1_CLK, ++ ++ /* GPSR4 */ ++ GFN_SDA2, ++ GFN_SCL2, ++ GFN_SDA1, ++ GFN_SCL1, ++ GFN_SDA0, ++ GFN_SCL0, ++ ++ /* GPSR5 */ ++ FN_RPC_INT_N, ++ FN_RPC_WP_N, ++ FN_RPC_RESET_N, ++ FN_QSPI1_SSL, ++ FN_QSPI1_IO3, ++ FN_QSPI1_IO2, ++ FN_QSPI1_MISO_IO1, ++ FN_QSPI1_MOSI_IO0, ++ FN_QSPI1_SPCLK, ++ FN_QSPI0_SSL, ++ FN_QSPI0_IO3, ++ FN_QSPI0_IO2, ++ FN_QSPI0_MISO_IO1, ++ FN_QSPI0_MOSI_IO0, ++ FN_QSPI0_SPCLK, ++ ++ /* IPSR0 */ ++ IFN_DU_DR2, ++ FN_HSCK0, ++ FN_A0, ++ IFN_DU_DR3, ++ FN_HRTS0_N, ++ FN_A1, ++ IFN_DU_DR4, ++ FN_HCTS0_N, ++ FN_A2, ++ IFN_DU_DR5, ++ FN_HTX0, ++ FN_A3, ++ IFN_DU_DR6, ++ FN_MSIOF3_RXD, ++ FN_A4, ++ IFN_DU_DR7, ++ FN_MSIOF3_TXD, ++ FN_A5, ++ IFN_DU_DG2, ++ FN_MSIOF3_SS1, ++ FN_A6, ++ IFN_DU_DG3, ++ FN_MSIOF3_SS2, ++ FN_A7, ++ FN_PWMFSW0, ++ ++ /* IPSR1 */ ++ IFN_DU_DG4, ++ FN_A8, ++ FN_FSO_CFE_0_N_A, ++ IFN_DU_DG5, ++ FN_A9, ++ FN_FSO_CFE_1_N_A, ++ IFN_DU_DG6, ++ FN_A10, ++ FN_FSO_TOE_N_A, ++ IFN_DU_DG7, ++ FN_A11, ++ FN_IRQ1, ++ IFN_DU_DB2, ++ FN_A12, ++ FN_IRQ2, ++ IFN_DU_DB3, ++ FN_A13, ++ FN_FXR_CLKOUT1, ++ IFN_DU_DB4, ++ FN_A14, ++ FN_FXR_CLKOUT2, ++ IFN_DU_DB5, ++ FN_A15, ++ FN_FXR_TXENA_N, ++ ++ /* IPSR2 */ ++ IFN_DU_DB6, ++ FN_A16, ++ FN_FXR_TXENB_N, ++ IFN_DU_DB7, ++ FN_A17, ++ FN_STPWT_EXTFXR, ++ IFN_DU_DOTCLKOUT, ++ FN_SCIF_CLK_A, ++ FN_A18, ++ IFN_DU_EXHSYNC_DU_HSYNC, ++ FN_HRX0, ++ FN_A19, ++ FN_IRQ3, ++ IFN_DU_EXVSYNC_DU_VSYNC, ++ FN_MSIOF3_SCK, ++ FN_A20, ++ IFN_DU_EXODDF_DU_ODDF_DISP_CDE, ++ FN_MSIOF3_SYNC, ++ FN_A21, ++ IFN_IRQ0, ++ FN_CC5_OSCOUT, ++ IFN_VI0_CLK, ++ FN_MSIOF2_SCK, ++ FN_SCK3, ++ FN_HSCK3, ++ ++ /* IPSR3 */ ++ IFN_VI0_CLKENB, ++ FN_MSIOF2_RXD, ++ FN_RX3, ++ FN_RD_WR_N, ++ FN_HCTS3_N, ++ IFN_VI0_HSYNC_N, ++ FN_MSIOF2_TXD, ++ FN_TX3, ++ FN_HRTS3_N, ++ IFN_VI0_VSYNC_N, ++ FN_MSIOF2_SYNC, ++ FN_CTS3_N, ++ FN_HTX3, ++ IFN_VI0_DATA0, ++ FN_MSIOF2_SS1, ++ FN_RTS3_N_TANS, ++ FN_HRX3, ++ IFN_VI0_DATA1, ++ FN_MSIOF2_SS2, ++ FN_SCK1, ++ FN_SPEEDIN_A, ++ IFN_VI0_DATA2, ++ FN_AVB0_AVTP_PPS, ++ FN_SDA3_A, ++ IFN_VI0_DATA3, ++ FN_HSCK1, ++ FN_SCL3_A, ++ IFN_VI0_DATA4, ++ FN_HRTS1_N, ++ FN_RX1_A, ++ ++ /* IPSR4 */ ++ IFN_VI0_DATA5, ++ FN_HCTS1_N, ++ FN_TX1_A, ++ IFN_VI0_DATA6, ++ FN_HTX1, ++ FN_CTS1_N, ++ IFN_VI0_DATA7, ++ FN_HRX1, ++ FN_RTS1_N_TANS, ++ IFN_VI0_DATA8, ++ FN_HSCK2, ++ FN_PWM0_A, ++ FN_A22, ++ IFN_VI0_DATA9, ++ FN_HCTS2_N, ++ FN_PWM1_A, ++ FN_A23, ++ FN_FSO_CFE_0_N_B, ++ IFN_VI0_DATA10, ++ FN_HRTS2_N, ++ FN_PWM2_A, ++ FN_A24, ++ FN_FSO_CFE_1_N_B, ++ IFN_VI0_DATA11, ++ FN_HTX2, ++ FN_PWM3_A, ++ FN_A25, ++ FN_FSO_TOE_N_B, ++ IFN_VI0_FIELD, ++ FN_HRX2, ++ FN_PWM4_A, ++ FN_CS1_N_A26, ++ FN_FSCLKST2_N_A, ++ ++ /* IPSR5 */ ++ IFN_VI1_CLK, ++ FN_MSIOF1_RXD, ++ FN_CS0_N, ++ IFN_VI1_CLKENB, ++ FN_MSIOF1_TXD, ++ FN_D0, ++ IFN_VI1_HSYNC_N, ++ FN_MSIOF1_SCK, ++ FN_D1, ++ IFN_VI1_VSYNC_N, ++ FN_MSIOF1_SYNC, ++ FN_D2, ++ IFN_VI1_DATA0, ++ FN_MSIOF1_SS1, ++ FN_D3, ++ IFN_VI1_DATA1, ++ FN_MSIOF1_SS2, ++ FN_D4, ++ FN_MMC_CMD, ++ IFN_VI1_DATA2, ++ FN_CANFD0_TX_B, ++ FN_D5, ++ FN_MMC_D0, ++ IFN_VI1_DATA3, ++ FN_CANFD0_RX_B, ++ FN_D6, ++ FN_MMC_D1, ++ ++ /* IPSR6 */ ++ IFN_VI1_DATA4, ++ FN_CANFD_CLK_B, ++ FN_D7, ++ FN_MMC_D2, ++ IFN_VI1_DATA5, ++ FN_SCK4, ++ FN_D8, ++ FN_MMC_D3, ++ IFN_VI1_DATA6, ++ FN_RX4, ++ FN_D9, ++ FN_MMC_CLK, ++ IFN_VI1_DATA7, ++ FN_TX4, ++ FN_D10, ++ FN_MMC_D4, ++ IFN_VI1_DATA8, ++ FN_CTS4_N, ++ FN_D11, ++ FN_MMC_D5, ++ IFN_VI1_DATA9, ++ FN_RTS4_N_TANS, ++ FN_D12, ++ FN_MMC_D6, ++ FN_SCL3_B, ++ IFN_VI1_DATA10, ++ FN_D13, ++ FN_MMC_D7, ++ FN_SDA3_B, ++ IFN_VI1_DATA11, ++ FN_SCL4, ++ FN_IRQ4, ++ FN_D14, ++ FN_MMC_WP, ++ ++ /* IPSR7 */ ++ IFN_VI1_FIELD, ++ FN_SDA4, ++ FN_IRQ5, ++ FN_D15, ++ FN_MMC_CD, ++ IFN_SCL0, ++ FN_DU_DR0, ++ FN_TPU0TO0, ++ FN_CLKOUT, ++ FN_MSIOF0_RXD, ++ IFN_SDA0, ++ FN_DU_DR1, ++ FN_TPU0TO1, ++ FN_BS_N, ++ FN_SCK0, ++ FN_MSIOF0_TXD, ++ IFN_SCL1, ++ FN_DU_DG0, ++ FN_TPU0TO2, ++ FN_RD_N, ++ FN_CTS0_N, ++ FN_MSIOF0_SCK, ++ IFN_SDA1, ++ FN_DU_DG1, ++ FN_TPU0TO3, ++ FN_WE0_N, ++ FN_RTS0_N_TANS, ++ FN_MSIOF0_SYNC, ++ IFN_SCL2, ++ FN_DU_DB0, ++ FN_TCLK1_A, ++ FN_WE1_N, ++ FN_RX0, ++ FN_MSIOF0_SS1, ++ IFN_SDA2, ++ FN_DU_DB1, ++ FN_TCLK2_A, ++ FN_EX_WAIT0, ++ FN_TX0, ++ FN_MSIOF0_SS2, ++ IFN_AVB0_AVTP_CAPTURE, ++ FN_FSCLKST2_N_B, ++ ++ /* IPSR8 */ ++ IFN_CANFD0_TX_A, ++ FN_FXR_TXDA, ++ FN_PWM0_B, ++ FN_DU_DISP, ++ FN_FSCLKST2_N_C, ++ IFN_CANFD0_RX_A, ++ FN_RXDA_EXTFXR, ++ FN_PWM1_B, ++ FN_DU_CDE, ++ IFN_CANFD1_TX, ++ FN_FXR_TXDB, ++ FN_PWM2_B, ++ FN_TCLK1_B, ++ FN_TX1_B, ++ IFN_CANFD1_RX, ++ FN_RXDB_EXTFXR, ++ FN_PWM3_B, ++ FN_TCLK2_B, ++ FN_RX1_B, ++ IFN_CANFD_CLK_A, ++ FN_CLK_EXTFXR, ++ FN_PWM4_B, ++ FN_SPEEDIN_B, ++ FN_SCIF_CLK_B, ++ IFN_DIGRF_CLKIN, ++ FN_DIGRF_CLKEN_IN, ++ IFN_DIGRF_CLKOUT, ++ FN_DIGRF_CLKEN_OUT, ++ ++ /* MOD_SEL0 */ ++ FN_SEL_HSCIF0_0, FN_SEL_HSCIF0_1, ++ FN_SEL_SCIF1_0, FN_SEL_SCIF1_1, ++ FN_SEL_CANFD0_0, FN_SEL_CANFD0_1, ++ FN_SEL_PWM4_0, FN_SEL_PWM4_1, ++ FN_SEL_PWM3_0, FN_SEL_PWM3_1, ++ FN_SEL_PWM2_0, FN_SEL_PWM2_1, ++ FN_SEL_PWM1_0, FN_SEL_PWM1_1, ++ FN_SEL_PWM0_0, FN_SEL_PWM0_1, ++ FN_SEL_RFSO_0, FN_SEL_RFSO_1, ++ FN_SEL_RSP_0, FN_SEL_RSP_1, ++ FN_SEL_TMU_0, FN_SEL_TMU_1, ++ ++ PINMUX_FUNCTION_END, ++ ++ PINMUX_MARK_BEGIN, ++ ++ /* GPSR0 */ ++ DU_EXODDF_DU_ODDF_DISP_CDE_GMARK, ++ DU_EXVSYNC_DU_VSYNC_GMARK, ++ DU_EXHSYNC_DU_HSYNC_GMARK, ++ DU_DOTCLKOUT_GMARK, ++ DU_DB7_GMARK, ++ DU_DB6_GMARK, ++ DU_DB5_GMARK, ++ DU_DB4_GMARK, ++ DU_DB3_GMARK, ++ DU_DB2_GMARK, ++ DU_DG7_GMARK, ++ DU_DG6_GMARK, ++ DU_DG5_GMARK, ++ DU_DG4_GMARK, ++ DU_DG3_GMARK, ++ DU_DG2_GMARK, ++ DU_DR7_GMARK, ++ DU_DR6_GMARK, ++ DU_DR5_GMARK, ++ DU_DR4_GMARK, ++ DU_DR3_GMARK, ++ DU_DR2_GMARK, ++ ++ /* GPSR1 */ ++ DIGRF_CLKOUT_GMARK, ++ DIGRF_CLKIN_GMARK, ++ CANFD_CLK_A_GMARK, ++ CANFD1_RX_GMARK, ++ CANFD1_TX_GMARK, ++ CANFD0_RX_A_GMARK, ++ CANFD0_TX_A_GMARK, ++ AVB0_AVTP_CAPTURE_GMARK, ++ AVB0_AVTP_MATCH_MARK, ++ AVB0_LINK_MARK, ++ AVB0_PHY_INT_MARK, ++ AVB0_MAGIC_MARK, ++ AVB0_MDC_MARK, ++ AVB0_MDIO_MARK, ++ AVB0_TXCREFCLK_MARK, ++ AVB0_TD3_MARK, ++ AVB0_TD2_MARK, ++ AVB0_TD1_MARK, ++ AVB0_TD0_MARK, ++ AVB0_TXC_MARK, ++ AVB0_TX_CTL_MARK, ++ AVB0_RD3_MARK, ++ AVB0_RD2_MARK, ++ AVB0_RD1_MARK, ++ AVB0_RD0_MARK, ++ AVB0_RXC_MARK, ++ AVB0_RX_CTL_MARK, ++ IRQ0_GMARK, ++ ++ /* GPSR2 */ ++ VI0_FIELD_GMARK, ++ VI0_DATA11_GMARK, ++ VI0_DATA10_GMARK, ++ VI0_DATA9_GMARK, ++ VI0_DATA8_GMARK, ++ VI0_DATA7_GMARK, ++ VI0_DATA6_GMARK, ++ VI0_DATA5_GMARK, ++ VI0_DATA4_GMARK, ++ VI0_DATA3_GMARK, ++ VI0_DATA2_GMARK, ++ VI0_DATA1_GMARK, ++ VI0_DATA0_GMARK, ++ VI0_VSYNC_N_GMARK, ++ VI0_HSYNC_N_GMARK, ++ VI0_CLKENB_GMARK, ++ VI0_CLK_GMARK, ++ ++ /* GPSR3 */ ++ VI1_FIELD_GMARK, ++ VI1_DATA11_GMARK, ++ VI1_DATA10_GMARK, ++ VI1_DATA9_GMARK, ++ VI1_DATA8_GMARK, ++ VI1_DATA7_GMARK, ++ VI1_DATA6_GMARK, ++ VI1_DATA5_GMARK, ++ VI1_DATA4_GMARK, ++ VI1_DATA3_GMARK, ++ VI1_DATA2_GMARK, ++ VI1_DATA1_GMARK, ++ VI1_DATA0_GMARK, ++ VI1_VSYNC_N_GMARK, ++ VI1_HSYNC_N_GMARK, ++ VI1_CLKENB_GMARK, ++ VI1_CLK_GMARK, ++ ++ /* GPSR4 */ ++ SDA2_GMARK, ++ SCL2_GMARK, ++ SDA1_GMARK, ++ SCL1_GMARK, ++ SDA0_GMARK, ++ SCL0_GMARK, ++ ++ /* GPSR5 */ ++ RPC_INT_N_MARK, ++ RPC_WP_N_MARK, ++ RPC_RESET_N_MARK, ++ QSPI1_SSL_MARK, ++ QSPI1_IO3_MARK, ++ QSPI1_IO2_MARK, ++ QSPI1_MISO_IO1_MARK, ++ QSPI1_MOSI_IO0_MARK, ++ QSPI1_SPCLK_MARK, ++ QSPI0_SSL_MARK, ++ QSPI0_IO3_MARK, ++ QSPI0_IO2_MARK, ++ QSPI0_MISO_IO1_MARK, ++ QSPI0_MOSI_IO0_MARK, ++ QSPI0_SPCLK_MARK, ++ ++ /* IPSR0 */ ++ DU_DR2_IMARK, ++ HSCK0_MARK, ++ A0_MARK, ++ DU_DR3_IMARK, ++ HRTS0_N_MARK, ++ A1_MARK, ++ DU_DR4_IMARK, ++ HCTS0_N_MARK, ++ A2_MARK, ++ DU_DR5_IMARK, ++ HTX0_MARK, ++ A3_MARK, ++ DU_DR6_IMARK, ++ MSIOF3_RXD_MARK, ++ A4_MARK, ++ DU_DR7_IMARK, ++ MSIOF3_TXD_MARK, ++ A5_MARK, ++ DU_DG2_IMARK, ++ MSIOF3_SS1_MARK, ++ A6_MARK, ++ DU_DG3_IMARK, ++ MSIOF3_SS2_MARK, ++ A7_MARK, ++ PWMFSW0_MARK, ++ ++ /* IPSR1 */ ++ DU_DG4_IMARK, ++ A8_MARK, ++ FSO_CFE_0_N_A_MARK, ++ DU_DG5_IMARK, ++ A9_MARK, ++ FSO_CFE_1_N_A_MARK, ++ DU_DG6_IMARK, ++ A10_MARK, ++ FSO_TOE_N_A_MARK, ++ DU_DG7_IMARK, ++ A11_MARK, ++ IRQ1_MARK, ++ DU_DB2_IMARK, ++ A12_MARK, ++ IRQ2_MARK, ++ DU_DB3_IMARK, ++ A13_MARK, ++ FXR_CLKOUT1_MARK, ++ DU_DB4_IMARK, ++ A14_MARK, ++ FXR_CLKOUT2_MARK, ++ DU_DB5_IMARK, ++ A15_MARK, ++ FXR_TXENA_N_MARK, ++ ++ /* IPSR2 */ ++ DU_DB6_IMARK, ++ A16_MARK, ++ FXR_TXENB_N_MARK, ++ DU_DB7_IMARK, ++ A17_MARK, ++ STPWT_EXTFXR_MARK, ++ DU_DOTCLKOUT_IMARK, ++ SCIF_CLK_A_MARK, ++ A18_MARK, ++ DU_EXHSYNC_DU_HSYNC_IMARK, ++ HRX0_MARK, ++ A19_MARK, ++ IRQ3_MARK, ++ DU_EXVSYNC_DU_VSYNC_IMARK, ++ MSIOF3_SCK_MARK, ++ A20_MARK, ++ DU_EXODDF_DU_ODDF_DISP_CDE_IMARK, ++ MSIOF3_SYNC_MARK, ++ A21_MARK, ++ IRQ0_IMARK, ++ CC5_OSCOUT_MARK, ++ VI0_CLK_IMARK, ++ MSIOF2_SCK_MARK, ++ SCK3_MARK, ++ HSCK3_MARK, ++ ++ /* IPSR3 */ ++ VI0_CLKENB_IMARK, ++ MSIOF2_RXD_MARK, ++ RX3_MARK, ++ RD_WR_N_MARK, ++ HCTS3_N_MARK, ++ VI0_HSYNC_N_IMARK, ++ MSIOF2_TXD_MARK, ++ TX3_MARK, ++ HRTS3_N_MARK, ++ VI0_VSYNC_N_IMARK, ++ MSIOF2_SYNC_MARK, ++ CTS3_N_MARK, ++ HTX3_MARK, ++ VI0_DATA0_IMARK, ++ MSIOF2_SS1_MARK, ++ RTS3_N_TANS_MARK, ++ HRX3_MARK, ++ VI0_DATA1_IMARK, ++ MSIOF2_SS2_MARK, ++ SCK1_MARK, ++ SPEEDIN_A_MARK, ++ VI0_DATA2_IMARK, ++ AVB0_AVTP_PPS_MARK, ++ SDA3_A_MARK, ++ VI0_DATA3_IMARK, ++ HSCK1_MARK, ++ SCL3_A_MARK, ++ VI0_DATA4_IMARK, ++ HRTS1_N_MARK, ++ RX1_A_MARK, ++ ++ /* IPSR4 */ ++ VI0_DATA5_IMARK, ++ HCTS1_N_MARK, ++ TX1_A_MARK, ++ VI0_DATA6_IMARK, ++ HTX1_MARK, ++ CTS1_N_MARK, ++ VI0_DATA7_IMARK, ++ HRX1_MARK, ++ RTS1_N_TANS_MARK, ++ VI0_DATA8_IMARK, ++ HSCK2_MARK, ++ PWM0_A_MARK, ++ A22_MARK, ++ VI0_DATA9_IMARK, ++ HCTS2_N_MARK, ++ PWM1_A_MARK, ++ A23_MARK, ++ FSO_CFE_0_N_B_MARK, ++ VI0_DATA10_IMARK, ++ HRTS2_N_MARK, ++ PWM2_A_MARK, ++ A24_MARK, ++ FSO_CFE_1_N_B_MARK, ++ VI0_DATA11_IMARK, ++ HTX2_MARK, ++ PWM3_A_MARK, ++ A25_MARK, ++ FSO_TOE_N_B_MARK, ++ VI0_FIELD_IMARK, ++ HRX2_MARK, ++ PWM4_A_MARK, ++ CS1_N_A26_MARK, ++ FSCLKST2_N_A_MARK, ++ ++ /* IPSR5 */ ++ VI1_CLK_IMARK, ++ MSIOF1_RXD_MARK, ++ CS0_N_MARK, ++ VI1_CLKENB_IMARK, ++ MSIOF1_TXD_MARK, ++ D0_MARK, ++ VI1_HSYNC_N_IMARK, ++ MSIOF1_SCK_MARK, ++ D1_MARK, ++ VI1_VSYNC_N_IMARK, ++ MSIOF1_SYNC_MARK, ++ D2_MARK, ++ VI1_DATA0_IMARK, ++ MSIOF1_SS1_MARK, ++ D3_MARK, ++ VI1_DATA1_IMARK, ++ MSIOF1_SS2_MARK, ++ D4_MARK, ++ MMC_CMD_MARK, ++ VI1_DATA2_IMARK, ++ CANFD0_TX_B_MARK, ++ D5_MARK, ++ MMC_D0_MARK, ++ VI1_DATA3_IMARK, ++ CANFD0_RX_B_MARK, ++ D6_MARK, ++ MMC_D1_MARK, ++ ++ /* IPSR6 */ ++ VI1_DATA4_IMARK, ++ CANFD_CLK_B_MARK, ++ D7_MARK, ++ MMC_D2_MARK, ++ VI1_DATA5_IMARK, ++ SCK4_MARK, ++ D8_MARK, ++ MMC_D3_MARK, ++ VI1_DATA6_IMARK, ++ RX4_MARK, ++ D9_MARK, ++ MMC_CLK_MARK, ++ VI1_DATA7_IMARK, ++ TX4_MARK, ++ D10_MARK, ++ MMC_D4_MARK, ++ VI1_DATA8_IMARK, ++ CTS4_N_MARK, ++ D11_MARK, ++ MMC_D5_MARK, ++ VI1_DATA9_IMARK, ++ RTS4_N_TANS_MARK, ++ D12_MARK, ++ MMC_D6_MARK, ++ SCL3_B_MARK, ++ VI1_DATA10_IMARK, ++ D13_MARK, ++ MMC_D7_MARK, ++ SDA3_B_MARK, ++ VI1_DATA11_IMARK, ++ SCL4_MARK, ++ IRQ4_MARK, ++ D14_MARK, ++ MMC_WP_MARK, ++ ++ /* IPSR7 */ ++ VI1_FIELD_IMARK, ++ SDA4_MARK, ++ IRQ5_MARK, ++ D15_MARK, ++ MMC_CD_MARK, ++ SCL0_IMARK, ++ DU_DR0_MARK, ++ TPU0TO0_MARK, ++ CLKOUT_MARK, ++ MSIOF0_RXD_MARK, ++ SDA0_IMARK, ++ DU_DR1_MARK, ++ TPU0TO1_MARK, ++ BS_N_MARK, ++ SCK0_MARK, ++ MSIOF0_TXD_MARK, ++ SCL1_IMARK, ++ DU_DG0_MARK, ++ TPU0TO2_MARK, ++ RD_N_MARK, ++ CTS0_N_MARK, ++ MSIOF0_SCK_MARK, ++ SDA1_IMARK, ++ DU_DG1_MARK, ++ TPU0TO3_MARK, ++ WE0_N_MARK, ++ RTS0_N_TANS_MARK, ++ MSIOF0_SYNC_MARK, ++ SCL2_IMARK, ++ DU_DB0_MARK, ++ TCLK1_A_MARK, ++ WE1_N_MARK, ++ RX0_MARK, ++ MSIOF0_SS1_MARK, ++ SDA2_IMARK, ++ DU_DB1_MARK, ++ TCLK2_A_MARK, ++ EX_WAIT0_MARK, ++ TX0_MARK, ++ MSIOF0_SS2_MARK, ++ AVB0_AVTP_CAPTURE_IMARK, ++ FSCLKST2_N_B_MARK, ++ ++ /* IPSR8 */ ++ CANFD0_TX_A_IMARK, ++ FXR_TXDA_MARK, ++ PWM0_B_MARK, ++ DU_DISP_MARK, ++ FSCLKST2_N_C_MARK, ++ CANFD0_RX_A_IMARK, ++ RXDA_EXTFXR_MARK, ++ PWM1_B_MARK, ++ DU_CDE_MARK, ++ CANFD1_TX_IMARK, ++ FXR_TXDB_MARK, ++ PWM2_B_MARK, ++ TCLK1_B_MARK, ++ TX1_B_MARK, ++ CANFD1_RX_IMARK, ++ RXDB_EXTFXR_MARK, ++ PWM3_B_MARK, ++ TCLK2_B_MARK, ++ RX1_B_MARK, ++ CANFD_CLK_A_IMARK, ++ CLK_EXTFXR_MARK, ++ PWM4_B_MARK, ++ SPEEDIN_B_MARK, ++ SCIF_CLK_B_MARK, ++ DIGRF_CLKIN_IMARK, ++ DIGRF_CLKEN_IN_MARK, ++ DIGRF_CLKOUT_IMARK, ++ DIGRF_CLKEN_OUT_MARK, ++ ++ PINMUX_MARK_END, ++}; ++ ++static pinmux_enum_t pinmux_data[] = { ++ PINMUX_DATA_GP_ALL(), /* PINMUX_DATA(GP_M_N_DATA, GP_M_N_FN...), */ ++ ++ /* GPSR0 */ ++ PINMUX_DATA(DU_EXODDF_DU_ODDF_DISP_CDE_GMARK, GFN_DU_EXODDF_DU_ODDF_DISP_CDE), ++ PINMUX_DATA(DU_EXVSYNC_DU_VSYNC_GMARK, GFN_DU_EXVSYNC_DU_VSYNC), ++ PINMUX_DATA(DU_EXHSYNC_DU_HSYNC_GMARK, GFN_DU_EXHSYNC_DU_HSYNC), ++ PINMUX_DATA(DU_DOTCLKOUT_GMARK, GFN_DU_DOTCLKOUT), ++ PINMUX_DATA(DU_DB7_GMARK, GFN_DU_DB7), ++ PINMUX_DATA(DU_DB6_GMARK, GFN_DU_DB6), ++ PINMUX_DATA(DU_DB5_GMARK, GFN_DU_DB5), ++ PINMUX_DATA(DU_DB4_GMARK, GFN_DU_DB4), ++ PINMUX_DATA(DU_DB3_GMARK, GFN_DU_DB3), ++ PINMUX_DATA(DU_DB2_GMARK, GFN_DU_DB2), ++ PINMUX_DATA(DU_DG7_GMARK, GFN_DU_DG7), ++ PINMUX_DATA(DU_DG6_GMARK, GFN_DU_DG6), ++ PINMUX_DATA(DU_DG5_GMARK, GFN_DU_DG5), ++ PINMUX_DATA(DU_DG4_GMARK, GFN_DU_DG4), ++ PINMUX_DATA(DU_DG3_GMARK, GFN_DU_DG3), ++ PINMUX_DATA(DU_DG2_GMARK, GFN_DU_DG2), ++ PINMUX_DATA(DU_DR7_GMARK, GFN_DU_DR7), ++ PINMUX_DATA(DU_DR6_GMARK, GFN_DU_DR6), ++ PINMUX_DATA(DU_DR5_GMARK, GFN_DU_DR5), ++ PINMUX_DATA(DU_DR4_GMARK, GFN_DU_DR4), ++ PINMUX_DATA(DU_DR3_GMARK, GFN_DU_DR3), ++ PINMUX_DATA(DU_DR2_GMARK, GFN_DU_DR2), ++ ++ /* GPSR1 */ ++ PINMUX_DATA(DIGRF_CLKOUT_GMARK, GFN_DIGRF_CLKOUT), ++ PINMUX_DATA(DIGRF_CLKIN_GMARK, GFN_DIGRF_CLKIN), ++ PINMUX_DATA(CANFD_CLK_A_GMARK, GFN_CANFD_CLK_A), ++ PINMUX_DATA(CANFD1_RX_GMARK, GFN_CANFD1_RX), ++ PINMUX_DATA(CANFD1_TX_GMARK, GFN_CANFD1_TX), ++ PINMUX_DATA(CANFD0_RX_A_GMARK, GFN_CANFD0_RX_A), ++ PINMUX_DATA(CANFD0_TX_A_GMARK, GFN_CANFD0_TX_A), ++ PINMUX_DATA(AVB0_AVTP_CAPTURE_GMARK, GFN_AVB0_AVTP_CAPTURE), ++ PINMUX_DATA(AVB0_AVTP_MATCH_MARK, FN_AVB0_AVTP_MATCH), ++ PINMUX_DATA(AVB0_LINK_MARK, FN_AVB0_LINK), ++ PINMUX_DATA(AVB0_PHY_INT_MARK, FN_AVB0_PHY_INT), ++ PINMUX_DATA(AVB0_MAGIC_MARK, FN_AVB0_MAGIC), ++ PINMUX_DATA(AVB0_MDC_MARK, FN_AVB0_MDC), ++ PINMUX_DATA(AVB0_MDIO_MARK, FN_AVB0_MDIO), ++ PINMUX_DATA(AVB0_TXCREFCLK_MARK, FN_AVB0_TXCREFCLK), ++ PINMUX_DATA(AVB0_TD3_MARK, FN_AVB0_TD3), ++ PINMUX_DATA(AVB0_TD2_MARK, FN_AVB0_TD2), ++ PINMUX_DATA(AVB0_TD1_MARK, FN_AVB0_TD1), ++ PINMUX_DATA(AVB0_TD0_MARK, FN_AVB0_TD0), ++ PINMUX_DATA(AVB0_TXC_MARK, FN_AVB0_TXC), ++ PINMUX_DATA(AVB0_TX_CTL_MARK, FN_AVB0_TX_CTL), ++ PINMUX_DATA(AVB0_RD3_MARK, FN_AVB0_RD3), ++ PINMUX_DATA(AVB0_RD2_MARK, FN_AVB0_RD2), ++ PINMUX_DATA(AVB0_RD1_MARK, FN_AVB0_RD1), ++ PINMUX_DATA(AVB0_RD0_MARK, FN_AVB0_RD0), ++ PINMUX_DATA(AVB0_RXC_MARK, FN_AVB0_RXC), ++ PINMUX_DATA(AVB0_RX_CTL_MARK, FN_AVB0_RX_CTL), ++ PINMUX_DATA(IRQ0_GMARK, GFN_IRQ0), ++ ++ /* GPSR2 */ ++ PINMUX_DATA(VI0_FIELD_GMARK, GFN_VI0_FIELD), ++ PINMUX_DATA(VI0_DATA11_GMARK, GFN_VI0_DATA11), ++ PINMUX_DATA(VI0_DATA10_GMARK, GFN_VI0_DATA10), ++ PINMUX_DATA(VI0_DATA9_GMARK, GFN_VI0_DATA9), ++ PINMUX_DATA(VI0_DATA8_GMARK, GFN_VI0_DATA8), ++ PINMUX_DATA(VI0_DATA7_GMARK, GFN_VI0_DATA7), ++ PINMUX_DATA(VI0_DATA6_GMARK, GFN_VI0_DATA6), ++ PINMUX_DATA(VI0_DATA5_GMARK, GFN_VI0_DATA5), ++ PINMUX_DATA(VI0_DATA4_GMARK, GFN_VI0_DATA4), ++ PINMUX_DATA(VI0_DATA3_GMARK, GFN_VI0_DATA3), ++ PINMUX_DATA(VI0_DATA2_GMARK, GFN_VI0_DATA2), ++ PINMUX_DATA(VI0_DATA1_GMARK, GFN_VI0_DATA1), ++ PINMUX_DATA(VI0_DATA0_GMARK, GFN_VI0_DATA0), ++ PINMUX_DATA(VI0_VSYNC_N_GMARK, GFN_VI0_VSYNC_N), ++ PINMUX_DATA(VI0_HSYNC_N_GMARK, GFN_VI0_HSYNC_N), ++ PINMUX_DATA(VI0_CLKENB_GMARK, GFN_VI0_CLKENB), ++ PINMUX_DATA(VI0_CLK_GMARK, GFN_VI0_CLK), ++ ++ /* GPSR3 */ ++ PINMUX_DATA(VI1_FIELD_GMARK, GFN_VI1_FIELD), ++ PINMUX_DATA(VI1_DATA11_GMARK, GFN_VI1_DATA11), ++ PINMUX_DATA(VI1_DATA10_GMARK, GFN_VI1_DATA10), ++ PINMUX_DATA(VI1_DATA9_GMARK, GFN_VI1_DATA9), ++ PINMUX_DATA(VI1_DATA8_GMARK, GFN_VI1_DATA8), ++ PINMUX_DATA(VI1_DATA7_GMARK, GFN_VI1_DATA7), ++ PINMUX_DATA(VI1_DATA6_GMARK, GFN_VI1_DATA6), ++ PINMUX_DATA(VI1_DATA5_GMARK, GFN_VI1_DATA5), ++ PINMUX_DATA(VI1_DATA4_GMARK, GFN_VI1_DATA4), ++ PINMUX_DATA(VI1_DATA3_GMARK, GFN_VI1_DATA3), ++ PINMUX_DATA(VI1_DATA2_GMARK, GFN_VI1_DATA2), ++ PINMUX_DATA(VI1_DATA1_GMARK, GFN_VI1_DATA1), ++ PINMUX_DATA(VI1_DATA0_GMARK, GFN_VI1_DATA0), ++ PINMUX_DATA(VI1_VSYNC_N_GMARK, GFN_VI1_VSYNC_N), ++ PINMUX_DATA(VI1_HSYNC_N_GMARK, GFN_VI1_HSYNC_N), ++ PINMUX_DATA(VI1_CLKENB_GMARK, GFN_VI1_CLKENB), ++ PINMUX_DATA(VI1_CLK_GMARK, GFN_VI1_CLK), ++ ++ /* GPSR4 */ ++ PINMUX_DATA(SDA2_GMARK, GFN_SDA2), ++ PINMUX_DATA(SCL2_GMARK, GFN_SCL2), ++ PINMUX_DATA(SDA1_GMARK, GFN_SDA1), ++ PINMUX_DATA(SCL1_GMARK, GFN_SCL1), ++ PINMUX_DATA(SDA0_GMARK, GFN_SDA0), ++ PINMUX_DATA(SCL0_GMARK, GFN_SCL0), ++ ++ /* GPSR5 */ ++ PINMUX_DATA(RPC_INT_N_MARK, FN_RPC_INT_N), ++ PINMUX_DATA(RPC_WP_N_MARK, FN_RPC_WP_N), ++ PINMUX_DATA(RPC_RESET_N_MARK, FN_RPC_RESET_N), ++ PINMUX_DATA(QSPI1_SSL_MARK, FN_QSPI1_SSL), ++ PINMUX_DATA(QSPI1_IO3_MARK, FN_QSPI1_IO3), ++ PINMUX_DATA(QSPI1_IO2_MARK, FN_QSPI1_IO2), ++ PINMUX_DATA(QSPI1_MISO_IO1_MARK, FN_QSPI1_MISO_IO1), ++ PINMUX_DATA(QSPI1_MOSI_IO0_MARK, FN_QSPI1_MOSI_IO0), ++ PINMUX_DATA(QSPI1_SPCLK_MARK, FN_QSPI1_SPCLK), ++ PINMUX_DATA(QSPI0_SSL_MARK, FN_QSPI0_SSL), ++ PINMUX_DATA(QSPI0_IO3_MARK, FN_QSPI0_IO3), ++ PINMUX_DATA(QSPI0_IO2_MARK, FN_QSPI0_IO2), ++ PINMUX_DATA(QSPI0_MISO_IO1_MARK, FN_QSPI0_MISO_IO1), ++ PINMUX_DATA(QSPI0_MOSI_IO0_MARK, FN_QSPI0_MOSI_IO0), ++ PINMUX_DATA(QSPI0_SPCLK_MARK, FN_QSPI0_SPCLK), ++ ++ ++ /* IPSR0 */ ++ PINMUX_IPSR_IDATA(DU_DR2), ++ PINMUX_IPSR_DATA(DU_DR2, HSCK0), ++ PINMUX_IPSR_DATA(DU_DR2, A0), ++ PINMUX_IPSR_IDATA(DU_DR3), ++ PINMUX_IPSR_DATA(DU_DR3, HRTS0_N), ++ PINMUX_IPSR_DATA(DU_DR3, A1), ++ PINMUX_IPSR_IDATA(DU_DR4), ++ PINMUX_IPSR_DATA(DU_DR4, HCTS0_N), ++ PINMUX_IPSR_DATA(DU_DR4, A2), ++ PINMUX_IPSR_IDATA(DU_DR5), ++ PINMUX_IPSR_DATA(DU_DR5, HTX0), ++ PINMUX_IPSR_DATA(DU_DR5, A3), ++ PINMUX_IPSR_IDATA(DU_DR6), ++ PINMUX_IPSR_DATA(DU_DR6, MSIOF3_RXD), ++ PINMUX_IPSR_DATA(DU_DR6, A4), ++ PINMUX_IPSR_IDATA(DU_DR7), ++ PINMUX_IPSR_DATA(DU_DR7, MSIOF3_TXD), ++ PINMUX_IPSR_DATA(DU_DR7, A5), ++ PINMUX_IPSR_IDATA(DU_DG2), ++ PINMUX_IPSR_DATA(DU_DG2, MSIOF3_SS1), ++ PINMUX_IPSR_DATA(DU_DG2, A6), ++ PINMUX_IPSR_IDATA(DU_DG3), ++ PINMUX_IPSR_DATA(DU_DG3, MSIOF3_SS2), ++ PINMUX_IPSR_DATA(DU_DG3, A7), ++ PINMUX_IPSR_DATA(DU_DG3, PWMFSW0), ++ ++ /* IPSR1 */ ++ PINMUX_IPSR_IDATA(DU_DG4), ++ PINMUX_IPSR_DATA(DU_DG4, A8), ++ PINMUX_IPSR_DATA(DU_DG4, FSO_CFE_0_N_A), ++ PINMUX_IPSR_IDATA(DU_DG5), ++ PINMUX_IPSR_DATA(DU_DG5, A9), ++ PINMUX_IPSR_DATA(DU_DG5, FSO_CFE_1_N_A), ++ PINMUX_IPSR_IDATA(DU_DG6), ++ PINMUX_IPSR_DATA(DU_DG6, A10), ++ PINMUX_IPSR_DATA(DU_DG6, FSO_TOE_N_A), ++ PINMUX_IPSR_IDATA(DU_DG7), ++ PINMUX_IPSR_DATA(DU_DG7, A11), ++ PINMUX_IPSR_DATA(DU_DG7, IRQ1), ++ PINMUX_IPSR_IDATA(DU_DB2), ++ PINMUX_IPSR_DATA(DU_DB2, A12), ++ PINMUX_IPSR_DATA(DU_DB2, IRQ2), ++ PINMUX_IPSR_IDATA(DU_DB3), ++ PINMUX_IPSR_DATA(DU_DB3, A13), ++ PINMUX_IPSR_DATA(DU_DB3, FXR_CLKOUT1), ++ PINMUX_IPSR_IDATA(DU_DB4), ++ PINMUX_IPSR_DATA(DU_DB4, A14), ++ PINMUX_IPSR_DATA(DU_DB4, FXR_CLKOUT2), ++ PINMUX_IPSR_IDATA(DU_DB5), ++ PINMUX_IPSR_DATA(DU_DB5, A15), ++ PINMUX_IPSR_DATA(DU_DB5, FXR_TXENA_N), ++ ++ /* IPSR2 */ ++ PINMUX_IPSR_IDATA(DU_DB6), ++ PINMUX_IPSR_DATA(DU_DB6, A16), ++ PINMUX_IPSR_DATA(DU_DB6, FXR_TXENB_N), ++ PINMUX_IPSR_IDATA(DU_DB7), ++ PINMUX_IPSR_DATA(DU_DB7, A17), ++ PINMUX_IPSR_DATA(DU_DB7, STPWT_EXTFXR), ++ PINMUX_IPSR_IDATA(DU_DOTCLKOUT), ++ PINMUX_IPSR_DATA(DU_DOTCLKOUT, SCIF_CLK_A), ++ PINMUX_IPSR_DATA(DU_DOTCLKOUT, A18), ++ PINMUX_IPSR_IDATA(DU_EXHSYNC_DU_HSYNC), ++ PINMUX_IPSR_DATA(DU_EXHSYNC_DU_HSYNC, HRX0), ++ PINMUX_IPSR_DATA(DU_EXHSYNC_DU_HSYNC, A19), ++ PINMUX_IPSR_DATA(DU_EXHSYNC_DU_HSYNC, IRQ3), ++ PINMUX_IPSR_IDATA(DU_EXVSYNC_DU_VSYNC), ++ PINMUX_IPSR_DATA(DU_EXVSYNC_DU_VSYNC, MSIOF3_SCK), ++ PINMUX_IPSR_DATA(DU_EXVSYNC_DU_VSYNC, A20), ++ PINMUX_IPSR_IDATA(DU_EXODDF_DU_ODDF_DISP_CDE), ++ PINMUX_IPSR_DATA(DU_EXODDF_DU_ODDF_DISP_CDE, MSIOF3_SYNC), ++ PINMUX_IPSR_DATA(DU_EXODDF_DU_ODDF_DISP_CDE, A21), ++ PINMUX_IPSR_IDATA(IRQ0), ++ PINMUX_IPSR_DATA(IRQ0, CC5_OSCOUT), ++ PINMUX_IPSR_IDATA(VI0_CLK), ++ PINMUX_IPSR_DATA(VI0_CLK, MSIOF2_SCK), ++ PINMUX_IPSR_DATA(VI0_CLK, SCK3), ++ PINMUX_IPSR_DATA(VI0_CLK, HSCK3), ++ ++ /* IPSR3 */ ++ PINMUX_IPSR_IDATA(VI0_CLKENB), ++ PINMUX_IPSR_DATA(VI0_CLKENB, MSIOF2_RXD), ++ PINMUX_IPSR_DATA(VI0_CLKENB, RX3), ++ PINMUX_IPSR_DATA(VI0_CLKENB, RD_WR_N), ++ PINMUX_IPSR_DATA(VI0_CLKENB, HCTS3_N), ++ PINMUX_IPSR_IDATA(VI0_HSYNC_N), ++ PINMUX_IPSR_DATA(VI0_HSYNC_N, MSIOF2_TXD), ++ PINMUX_IPSR_DATA(VI0_HSYNC_N, TX3), ++ PINMUX_IPSR_DATA(VI0_HSYNC_N, HRTS3_N), ++ PINMUX_IPSR_IDATA(VI0_VSYNC_N), ++ PINMUX_IPSR_DATA(VI0_VSYNC_N, MSIOF2_SYNC), ++ PINMUX_IPSR_DATA(VI0_VSYNC_N, CTS3_N), ++ PINMUX_IPSR_DATA(VI0_VSYNC_N, HTX3), ++ PINMUX_IPSR_IDATA(VI0_DATA0), ++ PINMUX_IPSR_DATA(VI0_DATA0, MSIOF2_SS1), ++ PINMUX_IPSR_DATA(VI0_DATA0, RTS3_N_TANS), ++ PINMUX_IPSR_DATA(VI0_DATA0, HRX3), ++ PINMUX_IPSR_IDATA(VI0_DATA1), ++ PINMUX_IPSR_DATA(VI0_DATA1, MSIOF2_SS2), ++ PINMUX_IPSR_DATA(VI0_DATA3, SCK1), ++ PINMUX_IPSR_DATA(VI0_DATA1, SPEEDIN_A), ++ PINMUX_IPSR_IDATA(VI0_DATA2), ++ PINMUX_IPSR_DATA(VI0_DATA2, AVB0_AVTP_PPS), ++ PINMUX_IPSR_DATA(VI0_DATA2, SDA3_A), ++ PINMUX_IPSR_IDATA(VI0_DATA3), ++ PINMUX_IPSR_DATA(VI0_DATA3, HSCK1), ++ PINMUX_IPSR_DATA(VI0_DATA1, SCL3_A), ++ PINMUX_IPSR_IDATA(VI0_DATA4), ++ PINMUX_IPSR_DATA(VI0_DATA4, HRTS1_N), ++ PINMUX_IPSR_DATA(VI0_DATA4, RX1_A), ++ ++ /* IPSR4 */ ++ PINMUX_IPSR_IDATA(VI0_DATA5), ++ PINMUX_IPSR_DATA(VI0_DATA5, HCTS1_N), ++ PINMUX_IPSR_DATA(VI0_DATA5, TX1_A), ++ PINMUX_IPSR_IDATA(VI0_DATA6), ++ PINMUX_IPSR_DATA(VI0_DATA6, HTX1), ++ PINMUX_IPSR_DATA(VI0_DATA6, CTS1_N), ++ PINMUX_IPSR_IDATA(VI0_DATA7), ++ PINMUX_IPSR_DATA(VI0_DATA7, HRX1), ++ PINMUX_IPSR_DATA(VI0_DATA7, RTS1_N_TANS), ++ PINMUX_IPSR_IDATA(VI0_DATA8), ++ PINMUX_IPSR_DATA(VI0_DATA8, HSCK2), ++ PINMUX_IPSR_DATA(VI0_DATA8, PWM0_A), ++ PINMUX_IPSR_DATA(VI0_DATA8, A22), ++ PINMUX_IPSR_IDATA(VI0_DATA9), ++ PINMUX_IPSR_DATA(VI0_DATA9, HCTS2_N), ++ PINMUX_IPSR_DATA(VI0_DATA9, PWM1_A), ++ PINMUX_IPSR_DATA(VI0_DATA9, A23), ++ PINMUX_IPSR_DATA(VI0_DATA9, FSO_CFE_0_N_B), ++ PINMUX_IPSR_IDATA(VI0_DATA10), ++ PINMUX_IPSR_DATA(VI0_DATA10, HRTS2_N), ++ PINMUX_IPSR_DATA(VI0_DATA10, PWM2_A), ++ PINMUX_IPSR_DATA(VI0_DATA10, A24), ++ PINMUX_IPSR_DATA(VI0_DATA10, FSO_CFE_1_N_B), ++ PINMUX_IPSR_IDATA(VI0_DATA11), ++ PINMUX_IPSR_DATA(VI0_DATA11, HTX2), ++ PINMUX_IPSR_DATA(VI0_DATA11, PWM3_A), ++ PINMUX_IPSR_DATA(VI0_DATA11, A25), ++ PINMUX_IPSR_DATA(VI0_DATA11, FSO_TOE_N_B), ++ PINMUX_IPSR_IDATA(VI0_FIELD), ++ PINMUX_IPSR_DATA(VI0_FIELD, HRX2), ++ PINMUX_IPSR_DATA(VI0_FIELD, PWM4_A), ++ PINMUX_IPSR_DATA(VI0_FIELD, CS1_N_A26), ++ PINMUX_IPSR_DATA(VI0_FIELD, FSCLKST2_N_A), ++ ++ /* IPSR5 */ ++ PINMUX_IPSR_IDATA(VI1_CLK), ++ PINMUX_IPSR_DATA(VI1_CLK, MSIOF1_RXD), ++ PINMUX_IPSR_DATA(VI1_CLK, CS0_N), ++ PINMUX_IPSR_IDATA(VI1_CLKENB), ++ PINMUX_IPSR_DATA(VI1_CLKENB, MSIOF1_TXD), ++ PINMUX_IPSR_DATA(VI1_CLKENB, D0), ++ PINMUX_IPSR_IDATA(VI1_HSYNC_N), ++ PINMUX_IPSR_DATA(VI1_HSYNC_N, MSIOF1_SCK), ++ PINMUX_IPSR_DATA(VI1_HSYNC_N, D1), ++ PINMUX_IPSR_IDATA(VI1_VSYNC_N), ++ PINMUX_IPSR_DATA(VI1_VSYNC_N, MSIOF1_SYNC), ++ PINMUX_IPSR_DATA(VI1_VSYNC_N, D2), ++ PINMUX_IPSR_IDATA(VI1_DATA0), ++ PINMUX_IPSR_DATA(VI1_DATA0, MSIOF1_SS1), ++ PINMUX_IPSR_DATA(VI1_DATA0, D3), ++ PINMUX_IPSR_IDATA(VI1_DATA1), ++ PINMUX_IPSR_DATA(VI1_DATA1, MSIOF1_SS2), ++ PINMUX_IPSR_DATA(VI1_DATA1, D4), ++ PINMUX_IPSR_DATA(VI1_DATA1, MMC_CMD), ++ PINMUX_IPSR_IDATA(VI1_DATA2), ++ PINMUX_IPSR_DATA(VI1_DATA2, CANFD0_TX_B), ++ PINMUX_IPSR_DATA(VI1_DATA2, D5), ++ PINMUX_IPSR_DATA(VI1_DATA2, MMC_D0), ++ PINMUX_IPSR_IDATA(VI1_DATA3), ++ PINMUX_IPSR_DATA(VI1_DATA3, CANFD0_RX_B), ++ PINMUX_IPSR_DATA(VI1_DATA3, D6), ++ PINMUX_IPSR_DATA(VI1_DATA3, MMC_D1), ++ ++ /* IPSR6 */ ++ PINMUX_IPSR_IDATA(VI1_DATA4), ++ PINMUX_IPSR_DATA(VI1_DATA4, CANFD_CLK_B), ++ PINMUX_IPSR_DATA(VI1_DATA4, D7), ++ PINMUX_IPSR_DATA(VI1_DATA4, MMC_D2), ++ PINMUX_IPSR_IDATA(VI1_DATA5), ++ PINMUX_IPSR_DATA(VI1_DATA5, SCK4), ++ PINMUX_IPSR_DATA(VI1_DATA5, D8), ++ PINMUX_IPSR_DATA(VI1_DATA5, MMC_D3), ++ PINMUX_IPSR_IDATA(VI1_DATA6), ++ PINMUX_IPSR_DATA(VI1_DATA6, RX4), ++ PINMUX_IPSR_DATA(VI1_DATA6, D9), ++ PINMUX_IPSR_DATA(VI1_DATA6, MMC_CLK), ++ PINMUX_IPSR_IDATA(VI1_DATA7), ++ PINMUX_IPSR_DATA(VI1_DATA7, TX4), ++ PINMUX_IPSR_DATA(VI1_DATA7, D10), ++ PINMUX_IPSR_DATA(VI1_DATA7, MMC_D4), ++ PINMUX_IPSR_IDATA(VI1_DATA8), ++ PINMUX_IPSR_DATA(VI1_DATA8, CTS4_N), ++ PINMUX_IPSR_DATA(VI1_DATA8, D11), ++ PINMUX_IPSR_DATA(VI1_DATA8, MMC_D5), ++ PINMUX_IPSR_IDATA(VI1_DATA9), ++ PINMUX_IPSR_DATA(VI1_DATA9, RTS4_N_TANS), ++ PINMUX_IPSR_DATA(VI1_DATA9, D12), ++ PINMUX_IPSR_DATA(VI1_DATA9, MMC_D6), ++ PINMUX_IPSR_DATA(VI1_DATA9, SCL3_B), ++ PINMUX_IPSR_IDATA(VI1_DATA10), ++ PINMUX_IPSR_DATA(VI1_DATA10, D13), ++ PINMUX_IPSR_DATA(VI1_DATA10, MMC_D7), ++ PINMUX_IPSR_DATA(VI1_DATA10, SDA3_B), ++ PINMUX_IPSR_IDATA(VI1_DATA11), ++ PINMUX_IPSR_DATA(VI1_DATA11, SCL4), ++ PINMUX_IPSR_DATA(VI1_DATA11, IRQ4), ++ PINMUX_IPSR_DATA(VI1_DATA11, D14), ++ PINMUX_IPSR_DATA(VI1_DATA11, MMC_WP), ++ ++ /* IPSR7 */ ++ PINMUX_IPSR_IDATA(VI1_FIELD), ++ PINMUX_IPSR_DATA(VI1_FIELD, SDA4), ++ PINMUX_IPSR_DATA(VI1_FIELD, IRQ5), ++ PINMUX_IPSR_DATA(VI1_FIELD, D15), ++ PINMUX_IPSR_DATA(VI1_FIELD, MMC_CD), ++ PINMUX_IPSR_IDATA(SCL0), ++ PINMUX_IPSR_DATA(SCL0, DU_DR0), ++ PINMUX_IPSR_DATA(SCL0, TPU0TO0), ++ PINMUX_IPSR_DATA(SCL0, CLKOUT), ++ PINMUX_IPSR_DATA(SCL0, MSIOF0_RXD), ++ PINMUX_IPSR_IDATA(SDA0), ++ PINMUX_IPSR_DATA(SDA0, DU_DR1), ++ PINMUX_IPSR_DATA(SDA0, TPU0TO1), ++ PINMUX_IPSR_DATA(SDA0, BS_N), ++ PINMUX_IPSR_DATA(SDA0, SCK0), ++ PINMUX_IPSR_DATA(SDA0, MSIOF0_TXD), ++ PINMUX_IPSR_IDATA(SCL1), ++ PINMUX_IPSR_DATA(SCL1, DU_DG0), ++ PINMUX_IPSR_DATA(SCL1, TPU0TO2), ++ PINMUX_IPSR_DATA(SCL1, RD_N), ++ PINMUX_IPSR_DATA(SCL1, CTS0_N), ++ PINMUX_IPSR_DATA(SCL1, MSIOF0_SCK), ++ PINMUX_IPSR_IDATA(SDA1), ++ PINMUX_IPSR_DATA(SDA1, DU_DG1), ++ PINMUX_IPSR_DATA(SDA1, TPU0TO3), ++ PINMUX_IPSR_DATA(SDA1, WE0_N), ++ PINMUX_IPSR_DATA(SDA1, RTS0_N_TANS), ++ PINMUX_IPSR_DATA(SDA1, MSIOF0_SYNC), ++ PINMUX_IPSR_IDATA(SCL2), ++ PINMUX_IPSR_DATA(SCL2, DU_DB0), ++ PINMUX_IPSR_DATA(SCL2, TCLK1_A), ++ PINMUX_IPSR_DATA(SCL2, WE1_N), ++ PINMUX_IPSR_DATA(SCL2, RX0), ++ PINMUX_IPSR_DATA(SCL2, MSIOF0_SS1), ++ PINMUX_IPSR_IDATA(SDA2), ++ PINMUX_IPSR_DATA(SDA2, DU_DB1), ++ PINMUX_IPSR_DATA(SDA2, TCLK2_A), ++ PINMUX_IPSR_DATA(SDA2, EX_WAIT0), ++ PINMUX_IPSR_DATA(SDA2, TX0), ++ PINMUX_IPSR_DATA(SDA2, MSIOF0_SS2), ++ PINMUX_IPSR_IDATA(AVB0_AVTP_CAPTURE), ++ PINMUX_IPSR_DATA(AVB0_AVTP_CAPTURE, FSCLKST2_N_B), ++ ++ /* IPSR8 */ ++ PINMUX_IPSR_IDATA(CANFD0_TX_A), ++ PINMUX_IPSR_DATA(CANFD0_TX_A, FXR_TXDA), ++ PINMUX_IPSR_DATA(CANFD0_TX_A, PWM0_B), ++ PINMUX_IPSR_DATA(CANFD0_TX_A, DU_DISP), ++ PINMUX_IPSR_DATA(CANFD0_TX_A, FSCLKST2_N_C), ++ PINMUX_IPSR_IDATA(CANFD0_RX_A), ++ PINMUX_IPSR_DATA(CANFD0_RX_A, RXDA_EXTFXR), ++ PINMUX_IPSR_DATA(CANFD0_RX_A, PWM1_B), ++ PINMUX_IPSR_DATA(CANFD0_RX_A, DU_CDE), ++ PINMUX_IPSR_IDATA(CANFD1_TX), ++ PINMUX_IPSR_DATA(CANFD1_TX, FXR_TXDB), ++ PINMUX_IPSR_DATA(CANFD1_TX, PWM2_B), ++ PINMUX_IPSR_DATA(CANFD1_TX, TCLK1_B), ++ PINMUX_IPSR_DATA(CANFD1_TX, TX1_B), ++ PINMUX_IPSR_IDATA(CANFD1_RX), ++ PINMUX_IPSR_DATA(CANFD1_RX, RXDB_EXTFXR), ++ PINMUX_IPSR_DATA(CANFD1_RX, PWM3_B), ++ PINMUX_IPSR_DATA(CANFD1_RX, TCLK2_B), ++ PINMUX_IPSR_DATA(CANFD1_RX, RX1_B), ++ PINMUX_IPSR_IDATA(CANFD_CLK_A), ++ PINMUX_IPSR_DATA(CANFD_CLK_A, CLK_EXTFXR), ++ PINMUX_IPSR_DATA(CANFD_CLK_A, PWM4_B), ++ PINMUX_IPSR_DATA(CANFD_CLK_A, SPEEDIN_B), ++ PINMUX_IPSR_DATA(CANFD_CLK_A, SCIF_CLK_B), ++ PINMUX_IPSR_IDATA(DIGRF_CLKIN), ++ PINMUX_IPSR_DATA(DIGRF_CLKIN, DIGRF_CLKEN_IN), ++ PINMUX_IPSR_IDATA(DIGRF_CLKOUT), ++ PINMUX_IPSR_DATA(DIGRF_CLKOUT, DIGRF_CLKEN_OUT), ++}; ++ ++static struct pinmux_gpio pinmux_gpios[] = { ++ PINMUX_GPIO_GP_ALL(), ++ ++ /* GPSR0 */ ++ GPIO_GFN(DU_EXODDF_DU_ODDF_DISP_CDE), ++ GPIO_GFN(DU_EXVSYNC_DU_VSYNC), ++ GPIO_GFN(DU_EXHSYNC_DU_HSYNC), ++ GPIO_GFN(DU_DOTCLKOUT), ++ GPIO_GFN(DU_DB7), ++ GPIO_GFN(DU_DB6), ++ GPIO_GFN(DU_DB5), ++ GPIO_GFN(DU_DB4), ++ GPIO_GFN(DU_DB3), ++ GPIO_GFN(DU_DB2), ++ GPIO_GFN(DU_DG7), ++ GPIO_GFN(DU_DG6), ++ GPIO_GFN(DU_DG5), ++ GPIO_GFN(DU_DG4), ++ GPIO_GFN(DU_DG3), ++ GPIO_GFN(DU_DG2), ++ GPIO_GFN(DU_DR7), ++ GPIO_GFN(DU_DR6), ++ GPIO_GFN(DU_DR5), ++ GPIO_GFN(DU_DR4), ++ GPIO_GFN(DU_DR3), ++ GPIO_GFN(DU_DR2), ++ ++ /* GPSR1 */ ++ GPIO_GFN(DIGRF_CLKOUT), ++ GPIO_GFN(DIGRF_CLKIN), ++ GPIO_GFN(CANFD_CLK_A), ++ GPIO_GFN(CANFD1_RX), ++ GPIO_GFN(CANFD1_TX), ++ GPIO_GFN(CANFD0_RX_A), ++ GPIO_GFN(CANFD0_TX_A), ++ GPIO_GFN(AVB0_AVTP_CAPTURE), ++ GPIO_FN(AVB0_AVTP_MATCH), ++ GPIO_FN(AVB0_LINK), ++ GPIO_FN(AVB0_PHY_INT), ++ GPIO_FN(AVB0_MAGIC), ++ GPIO_FN(AVB0_MDC), ++ GPIO_FN(AVB0_MDIO), ++ GPIO_FN(AVB0_TXCREFCLK), ++ GPIO_FN(AVB0_TD3), ++ GPIO_FN(AVB0_TD2), ++ GPIO_FN(AVB0_TD1), ++ GPIO_FN(AVB0_TD0), ++ GPIO_FN(AVB0_TXC), ++ GPIO_FN(AVB0_TX_CTL), ++ GPIO_FN(AVB0_RD3), ++ GPIO_FN(AVB0_RD2), ++ GPIO_FN(AVB0_RD1), ++ GPIO_FN(AVB0_RD0), ++ GPIO_FN(AVB0_RXC), ++ GPIO_FN(AVB0_RX_CTL), ++ GPIO_GFN(IRQ0), ++ ++ /* GPSR2 */ ++ GPIO_GFN(VI0_FIELD), ++ GPIO_GFN(VI0_DATA11), ++ GPIO_GFN(VI0_DATA10), ++ GPIO_GFN(VI0_DATA9), ++ GPIO_GFN(VI0_DATA8), ++ GPIO_GFN(VI0_DATA7), ++ GPIO_GFN(VI0_DATA6), ++ GPIO_GFN(VI0_DATA5), ++ GPIO_GFN(VI0_DATA4), ++ GPIO_GFN(VI0_DATA3), ++ GPIO_GFN(VI0_DATA2), ++ GPIO_GFN(VI0_DATA1), ++ GPIO_GFN(VI0_DATA0), ++ GPIO_GFN(VI0_VSYNC_N), ++ GPIO_GFN(VI0_HSYNC_N), ++ GPIO_GFN(VI0_CLKENB), ++ GPIO_GFN(VI0_CLK), ++ ++ /* GPSR3 */ ++ GPIO_GFN(VI1_FIELD), ++ GPIO_GFN(VI1_DATA11), ++ GPIO_GFN(VI1_DATA10), ++ GPIO_GFN(VI1_DATA9), ++ GPIO_GFN(VI1_DATA8), ++ GPIO_GFN(VI1_DATA7), ++ GPIO_GFN(VI1_DATA6), ++ GPIO_GFN(VI1_DATA5), ++ GPIO_GFN(VI1_DATA4), ++ GPIO_GFN(VI1_DATA3), ++ GPIO_GFN(VI1_DATA2), ++ GPIO_GFN(VI1_DATA1), ++ GPIO_GFN(VI1_DATA0), ++ GPIO_GFN(VI1_VSYNC_N), ++ GPIO_GFN(VI1_HSYNC_N), ++ GPIO_GFN(VI1_CLKENB), ++ GPIO_GFN(VI1_CLK), ++ ++ /* GPSR4 */ ++ GPIO_GFN(SDA2), ++ GPIO_GFN(SCL2), ++ GPIO_GFN(SDA1), ++ GPIO_GFN(SCL1), ++ GPIO_GFN(SDA0), ++ GPIO_GFN(SCL0), ++ ++ /* GPSR5 */ ++ GPIO_FN(RPC_INT_N), ++ GPIO_FN(RPC_WP_N), ++ GPIO_FN(RPC_RESET_N), ++ GPIO_FN(QSPI1_SSL), ++ GPIO_FN(QSPI1_IO3), ++ GPIO_FN(QSPI1_IO2), ++ GPIO_FN(QSPI1_MISO_IO1), ++ GPIO_FN(QSPI1_MOSI_IO0), ++ GPIO_FN(QSPI1_SPCLK), ++ GPIO_FN(QSPI0_SSL), ++ GPIO_FN(QSPI0_IO3), ++ GPIO_FN(QSPI0_IO2), ++ GPIO_FN(QSPI0_MISO_IO1), ++ GPIO_FN(QSPI0_MOSI_IO0), ++ GPIO_FN(QSPI0_SPCLK), ++ ++ /* IPSR0 */ ++ GPIO_IFN(DU_DR2), ++ GPIO_FN(HSCK0), ++ GPIO_FN(A0), ++ GPIO_IFN(DU_DR3), ++ GPIO_FN(HRTS0_N), ++ GPIO_FN(A1), ++ GPIO_IFN(DU_DR4), ++ GPIO_FN(HCTS0_N), ++ GPIO_FN(A2), ++ GPIO_IFN(DU_DR5), ++ GPIO_FN(HTX0), ++ GPIO_FN(A3), ++ GPIO_IFN(DU_DR6), ++ GPIO_FN(MSIOF3_RXD), ++ GPIO_FN(A4), ++ GPIO_IFN(DU_DR7), ++ GPIO_FN(MSIOF3_TXD), ++ GPIO_FN(A5), ++ GPIO_IFN(DU_DG2), ++ GPIO_FN(MSIOF3_SS1), ++ GPIO_FN(A6), ++ GPIO_IFN(DU_DG3), ++ GPIO_FN(MSIOF3_SS2), ++ GPIO_FN(A7), ++ GPIO_FN(PWMFSW0), ++ ++ /* IPSR1 */ ++ GPIO_IFN(DU_DG4), ++ GPIO_FN(A8), ++ GPIO_FN(FSO_CFE_0_N_A), ++ GPIO_IFN(DU_DG5), ++ GPIO_FN(A9), ++ GPIO_FN(FSO_CFE_1_N_A), ++ GPIO_IFN(DU_DG6), ++ GPIO_FN(A10), ++ GPIO_FN(FSO_TOE_N_A), ++ GPIO_IFN(DU_DG7), ++ GPIO_FN(A11), ++ GPIO_FN(IRQ1), ++ GPIO_IFN(DU_DB2), ++ GPIO_FN(A12), ++ GPIO_FN(IRQ2), ++ GPIO_IFN(DU_DB3), ++ GPIO_FN(A13), ++ GPIO_FN(FXR_CLKOUT1), ++ GPIO_IFN(DU_DB4), ++ GPIO_FN(A14), ++ GPIO_FN(FXR_CLKOUT2), ++ GPIO_IFN(DU_DB5), ++ GPIO_FN(A15), ++ GPIO_FN(FXR_TXENA_N), ++ ++ /* IPSR2 */ ++ GPIO_IFN(DU_DB6), ++ GPIO_FN(A16), ++ GPIO_FN(FXR_TXENB_N), ++ GPIO_IFN(DU_DB7), ++ GPIO_FN(A17), ++ GPIO_FN(STPWT_EXTFXR), ++ GPIO_IFN(DU_DOTCLKOUT), ++ GPIO_FN(SCIF_CLK_A), ++ GPIO_FN(A18), ++ GPIO_IFN(DU_EXHSYNC_DU_HSYNC), ++ GPIO_FN(HRX0), ++ GPIO_FN(A19), ++ GPIO_FN(IRQ3), ++ GPIO_IFN(DU_EXVSYNC_DU_VSYNC), ++ GPIO_FN(MSIOF3_SCK), ++ GPIO_FN(A20), ++ GPIO_IFN(DU_EXODDF_DU_ODDF_DISP_CDE), ++ GPIO_FN(MSIOF3_SYNC), ++ GPIO_FN(A21), ++ GPIO_IFN(IRQ0), ++ GPIO_FN(CC5_OSCOUT), ++ GPIO_IFN(VI0_CLK), ++ GPIO_FN(MSIOF2_SCK), ++ GPIO_FN(SCK3), ++ GPIO_FN(HSCK3), ++ ++ /* IPSR3 */ ++ GPIO_IFN(VI0_CLKENB), ++ GPIO_FN(MSIOF2_RXD), ++ GPIO_FN(RX3), ++ GPIO_FN(RD_WR_N), ++ GPIO_FN(HCTS3_N), ++ GPIO_IFN(VI0_HSYNC_N), ++ GPIO_FN(MSIOF2_TXD), ++ GPIO_FN(TX3), ++ GPIO_FN(HRTS3_N), ++ GPIO_IFN(VI0_VSYNC_N), ++ GPIO_FN(MSIOF2_SYNC), ++ GPIO_FN(CTS3_N), ++ GPIO_FN(HTX3), ++ GPIO_IFN(VI0_DATA0), ++ GPIO_FN(MSIOF2_SS1), ++ GPIO_FN(RTS3_N_TANS), ++ GPIO_FN(HRX3), ++ GPIO_IFN(VI0_DATA1), ++ GPIO_FN(MSIOF2_SS2), ++ GPIO_FN(SCK1), ++ GPIO_FN(SPEEDIN_A), ++ GPIO_IFN(VI0_DATA2), ++ GPIO_FN(AVB0_AVTP_PPS), ++ GPIO_FN(SDA3_A), ++ GPIO_IFN(VI0_DATA3), ++ GPIO_FN(HSCK1), ++ GPIO_FN(SCL3_A), ++ GPIO_IFN(VI0_DATA4), ++ GPIO_FN(HRTS1_N), ++ GPIO_FN(RX1_A), ++ ++ /* IPSR4 */ ++ GPIO_IFN(VI0_DATA5), ++ GPIO_FN(HCTS1_N), ++ GPIO_FN(TX1_A), ++ GPIO_IFN(VI0_DATA6), ++ GPIO_FN(HTX1), ++ GPIO_FN(CTS1_N), ++ GPIO_IFN(VI0_DATA7), ++ GPIO_FN(HRX1), ++ GPIO_FN(RTS1_N_TANS), ++ GPIO_IFN(VI0_DATA8), ++ GPIO_FN(HSCK2), ++ GPIO_FN(PWM0_A), ++ GPIO_FN(A22), ++ GPIO_IFN(VI0_DATA9), ++ GPIO_FN(HCTS2_N), ++ GPIO_FN(PWM1_A), ++ GPIO_FN(A23), ++ GPIO_FN(FSO_CFE_0_N_B), ++ GPIO_IFN(VI0_DATA10), ++ GPIO_FN(HRTS2_N), ++ GPIO_FN(PWM2_A), ++ GPIO_FN(A24), ++ GPIO_FN(FSO_CFE_1_N_B), ++ GPIO_IFN(VI0_DATA11), ++ GPIO_FN(HTX2), ++ GPIO_FN(PWM3_A), ++ GPIO_FN(A25), ++ GPIO_FN(FSO_TOE_N_B), ++ GPIO_IFN(VI0_FIELD), ++ GPIO_FN(HRX2), ++ GPIO_FN(PWM4_A), ++ GPIO_FN(CS1_N_A26), ++ GPIO_FN(FSCLKST2_N_A), ++ ++ /* IPSR5 */ ++ GPIO_IFN(VI1_CLK), ++ GPIO_FN(MSIOF1_RXD), ++ GPIO_FN(CS0_N), ++ GPIO_IFN(VI1_CLKENB), ++ GPIO_FN(MSIOF1_TXD), ++ GPIO_FN(D0), ++ GPIO_IFN(VI1_HSYNC_N), ++ GPIO_FN(MSIOF1_SCK), ++ GPIO_FN(D1), ++ GPIO_IFN(VI1_VSYNC_N), ++ GPIO_FN(MSIOF1_SYNC), ++ GPIO_FN(D2), ++ GPIO_IFN(VI1_DATA0), ++ GPIO_FN(MSIOF1_SS1), ++ GPIO_FN(D3), ++ GPIO_IFN(VI1_DATA1), ++ GPIO_FN(MSIOF1_SS2), ++ GPIO_FN(D4), ++ GPIO_FN(MMC_CMD), ++ GPIO_IFN(VI1_DATA2), ++ GPIO_FN(CANFD0_TX_B), ++ GPIO_FN(D5), ++ GPIO_FN(MMC_D0), ++ GPIO_IFN(VI1_DATA3), ++ GPIO_FN(CANFD0_RX_B), ++ GPIO_FN(D6), ++ GPIO_FN(MMC_D1), ++ ++ /* IPSR6 */ ++ GPIO_IFN(VI1_DATA4), ++ GPIO_FN(CANFD_CLK_B), ++ GPIO_FN(D7), ++ GPIO_FN(MMC_D2), ++ GPIO_IFN(VI1_DATA5), ++ GPIO_FN(SCK4), ++ GPIO_FN(D8), ++ GPIO_FN(MMC_D3), ++ GPIO_IFN(VI1_DATA6), ++ GPIO_FN(RX4), ++ GPIO_FN(D9), ++ GPIO_FN(MMC_CLK), ++ GPIO_IFN(VI1_DATA7), ++ GPIO_FN(TX4), ++ GPIO_FN(D10), ++ GPIO_FN(MMC_D4), ++ GPIO_IFN(VI1_DATA8), ++ GPIO_FN(CTS4_N), ++ GPIO_FN(D11), ++ GPIO_FN(MMC_D5), ++ GPIO_IFN(VI1_DATA9), ++ GPIO_FN(RTS4_N_TANS), ++ GPIO_FN(D12), ++ GPIO_FN(MMC_D6), ++ GPIO_FN(SCL3_B), ++ GPIO_IFN(VI1_DATA10), ++ GPIO_FN(D13), ++ GPIO_FN(MMC_D7), ++ GPIO_FN(SDA3_B), ++ GPIO_IFN(VI1_DATA11), ++ GPIO_FN(SCL4), ++ GPIO_FN(IRQ4), ++ GPIO_FN(D14), ++ GPIO_FN(MMC_WP), ++ ++ /* IPSR7 */ ++ GPIO_IFN(VI1_FIELD), ++ GPIO_FN(SDA4), ++ GPIO_FN(IRQ5), ++ GPIO_FN(D15), ++ GPIO_FN(MMC_CD), ++ GPIO_IFN(SCL0), ++ GPIO_FN(DU_DR0), ++ GPIO_FN(TPU0TO0), ++ GPIO_FN(CLKOUT), ++ GPIO_FN(MSIOF0_RXD), ++ GPIO_IFN(SDA0), ++ GPIO_FN(DU_DR1), ++ GPIO_FN(TPU0TO1), ++ GPIO_FN(BS_N), ++ GPIO_FN(SCK0), ++ GPIO_FN(MSIOF0_TXD), ++ GPIO_IFN(SCL1), ++ GPIO_FN(DU_DG0), ++ GPIO_FN(TPU0TO2), ++ GPIO_FN(RD_N), ++ GPIO_FN(CTS0_N), ++ GPIO_FN(MSIOF0_SCK), ++ GPIO_IFN(SDA1), ++ GPIO_FN(DU_DG1), ++ GPIO_FN(TPU0TO3), ++ GPIO_FN(WE0_N), ++ GPIO_FN(RTS0_N_TANS), ++ GPIO_FN(MSIOF0_SYNC), ++ GPIO_IFN(SCL2), ++ GPIO_FN(DU_DB0), ++ GPIO_FN(TCLK1_A), ++ GPIO_FN(WE1_N), ++ GPIO_FN(RX0), ++ GPIO_FN(MSIOF0_SS1), ++ GPIO_IFN(SDA2), ++ GPIO_FN(DU_DB1), ++ GPIO_FN(TCLK2_A), ++ GPIO_FN(EX_WAIT0), ++ GPIO_FN(TX0), ++ GPIO_FN(MSIOF0_SS2), ++ GPIO_IFN(AVB0_AVTP_CAPTURE), ++ GPIO_FN(FSCLKST2_N_B), ++ ++ /* IPSR8 */ ++ GPIO_IFN(CANFD0_TX_A), ++ GPIO_FN(FXR_TXDA), ++ GPIO_FN(PWM0_B), ++ GPIO_FN(DU_DISP), ++ GPIO_FN(FSCLKST2_N_C), ++ GPIO_IFN(CANFD0_RX_A), ++ GPIO_FN(RXDA_EXTFXR), ++ GPIO_FN(PWM1_B), ++ GPIO_FN(DU_CDE), ++ GPIO_IFN(CANFD1_TX), ++ GPIO_FN(FXR_TXDB), ++ GPIO_FN(PWM2_B), ++ GPIO_FN(TCLK1_B), ++ GPIO_FN(TX1_B), ++ GPIO_IFN(CANFD1_RX), ++ GPIO_FN(RXDB_EXTFXR), ++ GPIO_FN(PWM3_B), ++ GPIO_FN(TCLK2_B), ++ GPIO_FN(RX1_B), ++ GPIO_IFN(CANFD_CLK_A), ++ GPIO_FN(CLK_EXTFXR), ++ GPIO_FN(PWM4_B), ++ GPIO_FN(SPEEDIN_B), ++ GPIO_FN(SCIF_CLK_B), ++ GPIO_IFN(DIGRF_CLKIN), ++ GPIO_FN(DIGRF_CLKEN_IN), ++ GPIO_IFN(DIGRF_CLKOUT), ++ GPIO_FN(DIGRF_CLKEN_OUT), ++ ++}; ++ ++static struct pinmux_cfg_reg pinmux_config_regs[] = { ++ /* GPSR0(0xE6060100) md[3:1] controls initial value */ ++ /* md[3:1] .. 0 : 0x0000FFFF */ ++ /* .. other : 0x00000000 */ ++ { 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, GFN_DU_EXODDF_DU_ODDF_DISP_CDE, ++ GP_0_20_FN, GFN_DU_EXVSYNC_DU_VSYNC, ++ GP_0_19_FN, GFN_DU_EXHSYNC_DU_HSYNC, ++ GP_0_18_FN, GFN_DU_DOTCLKOUT, ++ GP_0_17_FN, GFN_DU_DB7, ++ GP_0_16_FN, GFN_DU_DB6, ++ GP_0_15_FN, GFN_DU_DB5, ++ GP_0_14_FN, GFN_DU_DB4, ++ GP_0_13_FN, GFN_DU_DB3, ++ GP_0_12_FN, GFN_DU_DB2, ++ GP_0_11_FN, GFN_DU_DG7, ++ GP_0_10_FN, GFN_DU_DG6, ++ GP_0_9_FN, GFN_DU_DG5, ++ GP_0_8_FN, GFN_DU_DG4, ++ GP_0_7_FN, GFN_DU_DG3, ++ GP_0_6_FN, GFN_DU_DG2, ++ GP_0_5_FN, GFN_DU_DR7, ++ GP_0_4_FN, GFN_DU_DR6, ++ GP_0_3_FN, GFN_DU_DR5, ++ GP_0_2_FN, GFN_DU_DR4, ++ GP_0_1_FN, GFN_DU_DR3, ++ GP_0_0_FN, GFN_DU_DR2 } ++ }, ++ /* GPSR1(0xE6060104) is md[3:1] controls initial value */ ++ /* md[3:1] .. 0 : 0x0EFFFFFF */ ++ /* .. other : 0x00000000 */ ++ { PINMUX_CFG_REG("GPSR1", 0xE6060104, 32, 1) { ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ GP_1_27_FN, GFN_DIGRF_CLKOUT, ++ GP_1_26_FN, GFN_DIGRF_CLKIN, ++ GP_1_25_FN, GFN_CANFD_CLK_A, ++ GP_1_24_FN, GFN_CANFD1_RX, ++ GP_1_23_FN, GFN_CANFD1_TX, ++ GP_1_22_FN, GFN_CANFD0_RX_A, ++ GP_1_21_FN, GFN_CANFD0_TX_A, ++ GP_1_20_FN, GFN_AVB0_AVTP_CAPTURE, ++ GP_1_19_FN, FN_AVB0_AVTP_MATCH, ++ GP_1_18_FN, FN_AVB0_LINK, ++ GP_1_17_FN, FN_AVB0_PHY_INT, ++ GP_1_16_FN, FN_AVB0_MAGIC, ++ GP_1_15_FN, FN_AVB0_MDC, ++ GP_1_14_FN, FN_AVB0_MDIO, ++ GP_1_13_FN, FN_AVB0_TXCREFCLK, ++ GP_1_12_FN, FN_AVB0_TD3, ++ GP_1_11_FN, FN_AVB0_TD2, ++ GP_1_10_FN, FN_AVB0_TD1, ++ GP_1_9_FN, FN_AVB0_TD0, ++ GP_1_8_FN, FN_AVB0_TXC, ++ GP_1_7_FN, FN_AVB0_TX_CTL, ++ GP_1_6_FN, FN_AVB0_RD3, ++ GP_1_5_FN, FN_AVB0_RD2, ++ GP_1_4_FN, FN_AVB0_RD1, ++ GP_1_3_FN, FN_AVB0_RD0, ++ GP_1_2_FN, FN_AVB0_RXC, ++ GP_1_1_FN, FN_AVB0_RX_CTL, ++ GP_1_0_FN, GFN_IRQ0 } ++ }, ++ /* GPSR2(0xE6060108) is md[3:1] controls */ ++ /* md[3:1] .. 0 : 0x000003C0 */ ++ /* .. other : 0x00000200 */ ++ { 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, GFN_VI0_FIELD, ++ GP_2_15_FN, GFN_VI0_DATA11, ++ GP_2_14_FN, GFN_VI0_DATA10, ++ GP_2_13_FN, GFN_VI0_DATA9, ++ GP_2_12_FN, GFN_VI0_DATA8, ++ GP_2_11_FN, GFN_VI0_DATA7, ++ GP_2_10_FN, GFN_VI0_DATA6, ++ GP_2_9_FN, GFN_VI0_DATA5, ++ GP_2_8_FN, GFN_VI0_DATA4, ++ GP_2_7_FN, GFN_VI0_DATA3, ++ GP_2_6_FN, GFN_VI0_DATA2, ++ GP_2_5_FN, GFN_VI0_DATA1, ++ GP_2_4_FN, GFN_VI0_DATA0, ++ GP_2_3_FN, GFN_VI0_VSYNC_N, ++ GP_2_2_FN, GFN_VI0_HSYNC_N, ++ GP_2_1_FN, GFN_VI0_CLKENB, ++ GP_2_0_FN, GFN_VI0_CLK } ++ }, ++ ++ /* GPSR3 */ ++ { 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, GFN_VI1_FIELD, ++ GP_3_15_FN, GFN_VI1_DATA11, ++ GP_3_14_FN, GFN_VI1_DATA10, ++ GP_3_13_FN, GFN_VI1_DATA9, ++ GP_3_12_FN, GFN_VI1_DATA8, ++ GP_3_11_FN, GFN_VI1_DATA7, ++ GP_3_10_FN, GFN_VI1_DATA6, ++ GP_3_9_FN, GFN_VI1_DATA5, ++ GP_3_8_FN, GFN_VI1_DATA4, ++ GP_3_7_FN, GFN_VI1_DATA3, ++ GP_3_6_FN, GFN_VI1_DATA2, ++ GP_3_5_FN, GFN_VI1_DATA1, ++ GP_3_4_FN, GFN_VI1_DATA0, ++ GP_3_3_FN, GFN_VI1_VSYNC_N, ++ GP_3_2_FN, GFN_VI1_HSYNC_N, ++ GP_3_1_FN, GFN_VI1_CLKENB, ++ GP_3_0_FN, GFN_VI1_CLK } ++ }, ++ /* GPSR4 */ ++ { 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, GFN_SDA2, ++ GP_4_4_FN, GFN_SCL2, ++ GP_4_3_FN, GFN_SDA1, ++ GP_4_2_FN, GFN_SCL1, ++ GP_4_1_FN, GFN_SDA0, ++ GP_4_0_FN, GFN_SCL0 } ++ }, ++ /* GPSR5 */ ++ { 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, FN_RPC_INT_N, ++ GP_5_13_FN, FN_RPC_WP_N, ++ GP_5_12_FN, FN_RPC_RESET_N, ++ GP_5_11_FN, FN_QSPI1_SSL, ++ GP_5_10_FN, FN_QSPI1_IO3, ++ GP_5_9_FN, FN_QSPI1_IO2, ++ GP_5_8_FN, FN_QSPI1_MISO_IO1, ++ GP_5_7_FN, FN_QSPI1_MOSI_IO0, ++ GP_5_6_FN, FN_QSPI1_SPCLK, ++ GP_5_5_FN, FN_QSPI0_SSL, ++ GP_5_4_FN, FN_QSPI0_IO3, ++ GP_5_3_FN, FN_QSPI0_IO2, ++ GP_5_2_FN, FN_QSPI0_MISO_IO1, ++ GP_5_1_FN, FN_QSPI0_MOSI_IO0, ++ GP_5_0_FN, FN_QSPI0_SPCLK } ++ }, ++ ++ { PINMUX_CFG_REG_VAR("IPSR0", 0xE6060200, 32, ++ 4, 4, 4, 4, 4, 4, 4, 4) { ++ /* IPSR0_31_28 [4] */ ++ IFN_DU_DG3, FN_MSIOF3_SS2, 0, FN_A7, ++ FN_PWMFSW0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR0_27_24 [4] */ ++ IFN_DU_DG2, FN_MSIOF3_SS1, 0, FN_A6, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR0_23_20 [4] */ ++ IFN_DU_DR7, FN_MSIOF3_TXD, 0, FN_A5, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR0_19_16 [4] */ ++ IFN_DU_DR6, FN_MSIOF3_RXD, 0, FN_A4, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR0_15_12 [4] */ ++ IFN_DU_DR5, FN_HTX0, 0, FN_A3, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR0_11_8 [4] */ ++ IFN_DU_DR4, FN_HCTS0_N, 0, FN_A2, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR0_7_4 [4] */ ++ IFN_DU_DR3, FN_HRTS0_N, 0, FN_A1, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR0_3_0 [4] */ ++ IFN_DU_DR2, FN_HSCK0, 0, FN_A0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ } ++ }, ++ { PINMUX_CFG_REG_VAR("IPSR1", 0xE6060204, 32, ++ 4, 4, 4, 4, 4, 4, 4, 4) { ++ /* IPSR1_31_28 [4] */ ++ IFN_DU_DB5, 0, 0, FN_A15, ++ FN_FXR_TXENA_N, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR1_27_24 [4] */ ++ IFN_DU_DB4, 0, 0, FN_A14, ++ FN_FXR_CLKOUT2, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR1_23_20 [4] */ ++ IFN_DU_DB3, 0, 0, FN_A13, ++ FN_FXR_CLKOUT1, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR1_19_16 [4] */ ++ IFN_DU_DB2, 0, 0, FN_A12, ++ FN_IRQ2, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR1_15_12 [4] */ ++ IFN_DU_DG7, 0, 0, FN_A11, ++ FN_IRQ1, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR1_11_8 [4] */ ++ IFN_DU_DG6, 0, 0, FN_A10, ++ FN_FSO_TOE_N_A, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR1_7_4 [4] */ ++ IFN_DU_DG5, 0, 0, FN_A9, ++ FN_FSO_CFE_1_N_A, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR1_3_0 [4] */ ++ IFN_DU_DG4, 0, 0, FN_A8, ++ FN_FSO_CFE_0_N_A, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0 ++ } ++ }, ++ { PINMUX_CFG_REG_VAR("IPSR2", 0xE6060208, 32, ++ 4, 4, 4, 4, 4, 4, 4, 4) { ++ /* IPSR2_31_28 [4] */ ++ IFN_VI0_CLK, FN_MSIOF2_SCK, FN_SCK3, 0, ++ FN_HSCK3, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR2_27_24 [4] */ ++ IFN_IRQ0, FN_CC5_OSCOUT, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR2_23_20 [4] */ ++ IFN_DU_EXODDF_DU_ODDF_DISP_CDE, FN_MSIOF3_SYNC, 0, FN_A21, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR2_19_16 [4] */ ++ IFN_DU_EXVSYNC_DU_VSYNC, FN_MSIOF3_SCK, 0, FN_A20, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR2_15_12 [4] */ ++ IFN_DU_EXHSYNC_DU_HSYNC, FN_HRX0, 0, FN_A19, ++ FN_IRQ3, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR2_11_8 [4] */ ++ IFN_DU_DOTCLKOUT, FN_SCIF_CLK_A, 0, FN_A18, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR2_7_4 [4] */ ++ IFN_DU_DB7, 0, 0, FN_A17, ++ FN_STPWT_EXTFXR, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR2_3_0 [4] */ ++ IFN_DU_DB6, 0, 0, FN_A16, ++ FN_FXR_TXENB_N, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ } ++ }, ++ { PINMUX_CFG_REG_VAR("IPSR3", 0xE606020C, 32, ++ 4, 4, 4, 4, 4, 4, 4, 4) { ++ /* IPSR3_31_28 [4] */ ++ IFN_VI0_DATA4, FN_HRTS1_N, FN_RX1_A, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR3_27_24 [4] */ ++ IFN_VI0_DATA3, FN_HSCK1, FN_SCL3_A, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR3_23_20 [4] */ ++ IFN_VI0_DATA2, FN_AVB0_AVTP_PPS, FN_SDA3_A, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR3_19_16 [4] */ ++ IFN_VI0_DATA1, FN_MSIOF2_SS2, FN_SCK1, 0, ++ FN_SPEEDIN_A, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR3_15_12 [4] */ ++ IFN_VI0_DATA0, FN_MSIOF2_SS1, FN_RTS3_N_TANS, 0, ++ FN_HRX3, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR3_11_8 [4] */ ++ IFN_VI0_VSYNC_N, FN_MSIOF2_SYNC, FN_CTS3_N, 0, ++ FN_HTX3, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR3_7_4 [4] */ ++ IFN_VI0_HSYNC_N, FN_MSIOF2_TXD, FN_TX3, 0, ++ FN_HRTS3_N, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR3_3_0 [4] */ ++ IFN_VI0_CLKENB, FN_MSIOF2_RXD, FN_RX3, FN_RD_WR_N, ++ FN_HCTS3_N, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ } ++ }, ++ { PINMUX_CFG_REG_VAR("IPSR4", 0xE6060210, 32, ++ 4, 4, 4, 4, 4, 4, 4, 4) { ++ /* IPSR4_31_28 [4] */ ++ IFN_VI0_FIELD, FN_HRX2, FN_PWM4_A, FN_CS1_N_A26, ++ FN_FSCLKST2_N_A, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR4_27_24 [4] */ ++ IFN_VI0_DATA11, FN_HTX2, FN_PWM3_A, FN_A25, ++ FN_FSO_TOE_N_B, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR4_23_20 [4] */ ++ IFN_VI0_DATA10, FN_HRTS2_N, FN_PWM2_A, FN_A24, ++ FN_FSO_CFE_1_N_B, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR4_19_16 [4] */ ++ IFN_VI0_DATA9, FN_HCTS2_N, FN_PWM1_A, FN_A23, ++ FN_FSO_CFE_0_N_B, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR4_15_12 [4] */ ++ IFN_VI0_DATA8, FN_HSCK2, FN_PWM0_A, FN_A22, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR4_11_8 [4] */ ++ IFN_VI0_DATA7, FN_HRX1, FN_RTS1_N_TANS, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR4_7_4 [4] */ ++ IFN_VI0_DATA6, FN_HTX1, FN_CTS1_N, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR4_3_0 [4] */ ++ IFN_VI0_DATA5, FN_HCTS1_N, FN_TX1_A, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ } ++ }, ++ { PINMUX_CFG_REG_VAR("IPSR5", 0xE6060214, 32, ++ 4, 4, 4, 4, 4, 4, 4, 4) { ++ /* IPSR5_31_28 [4] */ ++ IFN_VI1_DATA3, FN_CANFD0_RX_B, 0, FN_D6, ++ FN_MMC_D1, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR5_27_24 [4] */ ++ IFN_VI1_DATA2, FN_CANFD0_TX_B, 0, FN_D5, ++ FN_MMC_D0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR5_23_20 [4] */ ++ IFN_VI1_DATA1, FN_MSIOF1_SS2, 0, FN_D4, ++ FN_MMC_CMD, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR5_19_16 [4] */ ++ IFN_VI1_DATA0, FN_MSIOF1_SS1, 0, FN_D3, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR5_15_12 [4] */ ++ IFN_VI1_VSYNC_N, FN_MSIOF1_SYNC, 0, FN_D2, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR5_11_8 [4] */ ++ IFN_VI1_HSYNC_N, FN_MSIOF1_SCK, 0, FN_D1, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR5_7_4 [4] */ ++ IFN_VI1_CLKENB, FN_MSIOF1_TXD, 0, FN_D0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR5_3_0 [4] */ ++ IFN_VI1_CLK, FN_MSIOF1_RXD, 0, FN_CS0_N, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ } ++ }, ++ { PINMUX_CFG_REG_VAR("IPSR6", 0xE6060218, 32, ++ 4, 4, 4, 4, 4, 4, 4, 4) { ++ /* IPSR6_31_28 [4] */ ++ IFN_VI1_DATA11, FN_SCL4, FN_IRQ4, FN_D14, ++ FN_MMC_WP, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR6_27_24 [4] */ ++ IFN_VI1_DATA10, 0, 0, FN_D13, ++ FN_MMC_D7, FN_SDA3_B, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR6_23_20 [4] */ ++ IFN_VI1_DATA9, 0, FN_RTS4_N_TANS, FN_D12, ++ FN_MMC_D6, FN_SCL3_B, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR6_19_16 [4] */ ++ IFN_VI1_DATA8, 0, FN_CTS4_N, FN_D11, ++ FN_MMC_D5, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR6_15_12 [4] */ ++ IFN_VI1_DATA7, 0, FN_TX4, FN_D10, ++ FN_MMC_D4, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR6_11_8 [4] */ ++ IFN_VI1_DATA6, 0, FN_RX4, FN_D9, ++ FN_MMC_CLK, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR6_7_4 [4] */ ++ IFN_VI1_DATA5, 0, FN_SCK4, FN_D8, ++ FN_MMC_D3, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR6_3_0 [4] */ ++ IFN_VI1_DATA4, FN_CANFD_CLK_B, 0, FN_D7, ++ FN_MMC_D2, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ } ++ }, ++ { PINMUX_CFG_REG_VAR("IPSR7", 0xE606021C, 32, ++ 4, 4, 4, 4, 4, 4, 4, 4) { ++ /* IPSR7_31_28 [4] */ ++ IFN_AVB0_AVTP_CAPTURE, 0, 0, 0, ++ FN_FSCLKST2_N_B, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR7_27_24 [4] */ ++ IFN_SDA2, FN_DU_DB1, FN_TCLK2_A, FN_EX_WAIT0, ++ FN_TX0, FN_MSIOF0_SS2, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR7_23_20 [4] */ ++ IFN_SCL2, FN_DU_DB0, FN_TCLK1_A, FN_WE1_N, ++ FN_RX0, FN_MSIOF0_SS1, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR7_19_16 [4] */ ++ IFN_SDA1, FN_DU_DG1, FN_TPU0TO3, FN_WE0_N, ++ FN_RTS0_N_TANS, FN_MSIOF0_SYNC, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR7_15_12 [4] */ ++ IFN_SCL1, FN_DU_DG0, FN_TPU0TO2, FN_RD_N, ++ FN_CTS0_N, FN_MSIOF0_SCK, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR7_11_8 [4] */ ++ IFN_SDA0, FN_DU_DR1, FN_TPU0TO1, FN_BS_N, ++ FN_SCK0, FN_MSIOF0_TXD, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR7_7_4 [4] */ ++ IFN_SCL0, FN_DU_DR0, FN_TPU0TO0, FN_CLKOUT, ++ 0, FN_MSIOF0_RXD, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR7_3_0 [4] */ ++ IFN_VI1_FIELD, FN_SDA4, FN_IRQ5, FN_D15, ++ FN_MMC_CD, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ } ++ }, ++ { PINMUX_CFG_REG_VAR("IPSR8", 0xE6060220, 32, ++ 4, 4, 4, 4, 4, 4, 4, 4) { ++ /* IPSR8_31_28 [4] */ ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR8_27_24 [4] */ ++ IFN_DIGRF_CLKOUT, FN_DIGRF_CLKEN_OUT, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR8_23_20 [4] */ ++ IFN_DIGRF_CLKIN, FN_DIGRF_CLKEN_IN, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR8_19_16 [4] */ ++ IFN_CANFD_CLK_A, FN_CLK_EXTFXR, FN_PWM4_B, FN_SPEEDIN_B, ++ FN_SCIF_CLK_B, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR8_15_12 [4] */ ++ IFN_CANFD1_RX, FN_RXDB_EXTFXR, FN_PWM3_B, FN_TCLK2_B, ++ FN_RX1_B, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR8_11_8 [4] */ ++ IFN_CANFD1_TX, FN_FXR_TXDB, FN_PWM2_B, FN_TCLK1_B, ++ FN_TX1_B, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR8_7_4 [4] */ ++ IFN_CANFD0_RX_A, FN_RXDA_EXTFXR, FN_PWM1_B, FN_DU_CDE, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR8_3_0 [4] */ ++ IFN_CANFD0_TX_A, FN_FXR_TXDA, FN_PWM0_B, FN_DU_DISP, ++ FN_FSCLKST2_N_C, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ } ++ }, ++ { PINMUX_CFG_REG("MOD_SEL0", 0xE6060500, 32, 1) { ++ /* reserved [31..24] */ ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ /* reserved [23..16] */ ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ /* reserved [15..11] */ ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ /* SEL_HSCIF0 [1] */ ++ FN_SEL_HSCIF0_0, ++ FN_SEL_HSCIF0_1, ++ /* SEL_SCIF1 [1] */ ++ FN_SEL_SCIF1_0, ++ FN_SEL_SCIF1_1, ++ /* SEL_CANFD0 [1] */ ++ FN_SEL_CANFD0_0, ++ FN_SEL_CANFD0_1, ++ /* SEL_PWM4 [1] */ ++ FN_SEL_PWM4_0, ++ FN_SEL_PWM4_1, ++ /* SEL_PWM3 [1] */ ++ FN_SEL_PWM3_0, ++ FN_SEL_PWM3_1, ++ /* SEL_PWM2 [1] */ ++ FN_SEL_PWM2_0, ++ FN_SEL_PWM2_1, ++ /* SEL_PWM1 [1] */ ++ FN_SEL_PWM1_0, ++ FN_SEL_PWM1_1, ++ /* SEL_PWM0 [1] */ ++ FN_SEL_PWM0_0, ++ FN_SEL_PWM0_1, ++ /* SEL_RFSO [1] */ ++ FN_SEL_RFSO_0, ++ FN_SEL_RFSO_1, ++ /* SEL_RSP [1] */ ++ FN_SEL_RSP_0, ++ FN_SEL_RSP_1, ++ /* SEL_TMU [1] */ ++ FN_SEL_TMU_0, ++ FN_SEL_TMU_1, ++ } ++ }, ++ ++ /* under construction */ ++ { PINMUX_CFG_REG("INOUTSEL0", 0xE6050004, 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_IN, GP_0_21_OUT, ++ GP_0_20_IN, GP_0_20_OUT, ++ GP_0_19_IN, GP_0_19_OUT, ++ GP_0_18_IN, GP_0_18_OUT, ++ GP_0_17_IN, GP_0_17_OUT, ++ GP_0_16_IN, GP_0_16_OUT, ++ GP_0_15_IN, GP_0_15_OUT, ++ GP_0_14_IN, GP_0_14_OUT, ++ GP_0_13_IN, GP_0_13_OUT, ++ GP_0_12_IN, GP_0_12_OUT, ++ GP_0_11_IN, GP_0_11_OUT, ++ GP_0_10_IN, GP_0_10_OUT, ++ GP_0_9_IN, GP_0_9_OUT, ++ GP_0_8_IN, GP_0_8_OUT, ++ GP_0_7_IN, GP_0_7_OUT, ++ GP_0_6_IN, GP_0_6_OUT, ++ GP_0_5_IN, GP_0_5_OUT, ++ GP_0_4_IN, GP_0_4_OUT, ++ GP_0_3_IN, GP_0_3_OUT, ++ GP_0_2_IN, GP_0_2_OUT, ++ GP_0_1_IN, GP_0_1_OUT, ++ GP_0_0_IN, GP_0_0_OUT, ++ } ++ }, ++ { PINMUX_CFG_REG("INOUTSEL1", 0xE6051004, 32, 1) { ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ GP_1_27_IN, GP_1_27_OUT, ++ GP_1_26_IN, GP_1_26_OUT, ++ GP_1_25_IN, GP_1_25_OUT, ++ GP_1_24_IN, GP_1_24_OUT, ++ GP_1_23_IN, GP_1_23_OUT, ++ GP_1_22_IN, GP_1_22_OUT, ++ GP_1_21_IN, GP_1_21_OUT, ++ GP_1_20_IN, GP_1_20_OUT, ++ GP_1_19_IN, GP_1_19_OUT, ++ GP_1_18_IN, GP_1_18_OUT, ++ GP_1_17_IN, GP_1_17_OUT, ++ GP_1_16_IN, GP_1_16_OUT, ++ GP_1_15_IN, GP_1_15_OUT, ++ GP_1_14_IN, GP_1_14_OUT, ++ GP_1_13_IN, GP_1_13_OUT, ++ GP_1_12_IN, GP_1_12_OUT, ++ GP_1_11_IN, GP_1_11_OUT, ++ GP_1_10_IN, GP_1_10_OUT, ++ GP_1_9_IN, GP_1_9_OUT, ++ GP_1_8_IN, GP_1_8_OUT, ++ GP_1_7_IN, GP_1_7_OUT, ++ GP_1_6_IN, GP_1_6_OUT, ++ GP_1_5_IN, GP_1_5_OUT, ++ GP_1_4_IN, GP_1_4_OUT, ++ GP_1_3_IN, GP_1_3_OUT, ++ GP_1_2_IN, GP_1_2_OUT, ++ GP_1_1_IN, GP_1_1_OUT, ++ GP_1_0_IN, GP_1_0_OUT, ++ } ++ }, ++ { PINMUX_CFG_REG("INOUTSEL2", 0xE6052004, 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_IN, GP_2_16_OUT, ++ GP_2_15_IN, GP_2_15_OUT, ++ GP_2_14_IN, GP_2_14_OUT, ++ GP_2_13_IN, GP_2_13_OUT, ++ GP_2_12_IN, GP_2_12_OUT, ++ GP_2_11_IN, GP_2_11_OUT, ++ GP_2_10_IN, GP_2_10_OUT, ++ GP_2_9_IN, GP_2_9_OUT, ++ GP_2_8_IN, GP_2_8_OUT, ++ GP_2_7_IN, GP_2_7_OUT, ++ GP_2_6_IN, GP_2_6_OUT, ++ GP_2_5_IN, GP_2_5_OUT, ++ GP_2_4_IN, GP_2_4_OUT, ++ GP_2_3_IN, GP_2_3_OUT, ++ GP_2_2_IN, GP_2_2_OUT, ++ GP_2_1_IN, GP_2_1_OUT, ++ GP_2_0_IN, GP_2_0_OUT, ++ } ++ }, ++ { PINMUX_CFG_REG("INOUTSEL3", 0xE6053004, 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_IN, GP_3_16_OUT, ++ GP_3_15_IN, GP_3_15_OUT, ++ GP_3_14_IN, GP_3_14_OUT, ++ GP_3_13_IN, GP_3_13_OUT, ++ GP_3_12_IN, GP_3_12_OUT, ++ GP_3_11_IN, GP_3_11_OUT, ++ GP_3_10_IN, GP_3_10_OUT, ++ GP_3_9_IN, GP_3_9_OUT, ++ GP_3_8_IN, GP_3_8_OUT, ++ GP_3_7_IN, GP_3_7_OUT, ++ GP_3_6_IN, GP_3_6_OUT, ++ GP_3_5_IN, GP_3_5_OUT, ++ GP_3_4_IN, GP_3_4_OUT, ++ GP_3_3_IN, GP_3_3_OUT, ++ GP_3_2_IN, GP_3_2_OUT, ++ GP_3_1_IN, GP_3_1_OUT, ++ GP_3_0_IN, GP_3_0_OUT, ++ } ++ }, ++ { PINMUX_CFG_REG("INOUTSEL4", 0xE6054004, 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_IN, GP_4_5_OUT, ++ GP_4_4_IN, GP_4_4_OUT, ++ GP_4_3_IN, GP_4_3_OUT, ++ GP_4_2_IN, GP_4_2_OUT, ++ GP_4_1_IN, GP_4_1_OUT, ++ GP_4_0_IN, GP_4_0_OUT, ++ } ++ }, ++ { PINMUX_CFG_REG("INOUTSEL5", 0xE6055004, 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_IN, GP_5_14_OUT, ++ GP_5_13_IN, GP_5_13_OUT, ++ GP_5_12_IN, GP_5_12_OUT, ++ GP_5_11_IN, GP_5_11_OUT, ++ GP_5_10_IN, GP_5_10_OUT, ++ GP_5_9_IN, GP_5_9_OUT, ++ GP_5_8_IN, GP_5_8_OUT, ++ GP_5_7_IN, GP_5_7_OUT, ++ GP_5_6_IN, GP_5_6_OUT, ++ GP_5_5_IN, GP_5_5_OUT, ++ GP_5_4_IN, GP_5_4_OUT, ++ GP_5_3_IN, GP_5_3_OUT, ++ GP_5_2_IN, GP_5_2_OUT, ++ GP_5_1_IN, GP_5_1_OUT, ++ GP_5_0_IN, GP_5_0_OUT, ++ } ++ }, ++ { }, ++ { }, ++ { }, ++}; ++ ++static struct pinmux_data_reg pinmux_data_regs[] = { ++ /* use OUTDT registers? */ ++ { PINMUX_DATA_REG("INDT0", 0xE6050008, 32) { ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, GP_0_21_DATA, GP_0_20_DATA, ++ GP_0_19_DATA, GP_0_18_DATA, GP_0_17_DATA, GP_0_16_DATA, ++ GP_0_15_DATA, GP_0_14_DATA, GP_0_13_DATA, GP_0_12_DATA, ++ GP_0_11_DATA, GP_0_10_DATA, GP_0_9_DATA, GP_0_8_DATA, ++ GP_0_7_DATA, GP_0_6_DATA, GP_0_5_DATA, GP_0_4_DATA, ++ GP_0_3_DATA, GP_0_2_DATA, GP_0_1_DATA, GP_0_0_DATA } ++ }, ++ { PINMUX_DATA_REG("INDT1", 0xE6051008, 32) { ++ 0, 0, 0, 0, ++ GP_1_27_DATA, GP_1_26_DATA, GP_1_25_DATA, GP_1_24_DATA, ++ GP_1_23_DATA, GP_1_22_DATA, GP_1_21_DATA, GP_1_20_DATA, ++ GP_1_19_DATA, GP_1_18_DATA, GP_1_17_DATA, GP_1_16_DATA, ++ GP_1_15_DATA, GP_1_14_DATA, GP_1_13_DATA, GP_1_12_DATA, ++ GP_1_11_DATA, GP_1_10_DATA, GP_1_9_DATA, GP_1_8_DATA, ++ GP_1_7_DATA, GP_1_6_DATA, GP_1_5_DATA, GP_1_4_DATA, ++ GP_1_3_DATA, GP_1_2_DATA, GP_1_1_DATA, GP_1_0_DATA } ++ }, ++ { PINMUX_DATA_REG("INDT2", 0xE6052008, 32) { ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, GP_2_16_DATA, ++ GP_2_15_DATA, GP_2_14_DATA, GP_2_13_DATA, GP_2_12_DATA, ++ GP_2_11_DATA, GP_2_10_DATA, GP_2_9_DATA, GP_2_8_DATA, ++ GP_2_7_DATA, GP_2_6_DATA, GP_2_5_DATA, GP_2_4_DATA, ++ GP_2_3_DATA, GP_2_2_DATA, GP_2_1_DATA, GP_2_0_DATA } ++ }, ++ { PINMUX_DATA_REG("INDT3", 0xE6053008, 32) { ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, GP_3_16_DATA, ++ GP_3_15_DATA, GP_3_14_DATA, GP_3_13_DATA, GP_3_12_DATA, ++ GP_3_11_DATA, GP_3_10_DATA, GP_3_9_DATA, GP_3_8_DATA, ++ GP_3_7_DATA, GP_3_6_DATA, GP_3_5_DATA, GP_3_4_DATA, ++ GP_3_3_DATA, GP_3_2_DATA, GP_3_1_DATA, GP_3_0_DATA } ++ }, ++ { PINMUX_DATA_REG("INDT4", 0xE6054008, 32) { ++ 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_DATA, GP_4_4_DATA, ++ GP_4_3_DATA, GP_4_2_DATA, GP_4_1_DATA, GP_4_0_DATA } ++ }, ++ { PINMUX_DATA_REG("INDT5", 0xE6055008, 32) { ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, GP_5_14_DATA, GP_5_13_DATA, GP_5_12_DATA, ++ GP_5_11_DATA, GP_5_10_DATA, GP_5_9_DATA, GP_5_8_DATA, ++ GP_5_7_DATA, GP_5_6_DATA, GP_5_5_DATA, GP_5_4_DATA, ++ GP_5_3_DATA, GP_5_2_DATA, GP_5_1_DATA, GP_5_0_DATA } ++ }, ++ { }, ++ { }, ++ { }, ++}; ++ ++static struct pinmux_info r8a7797_pinmux_info = { ++ .name = "r8a7797_pfc", ++ ++ .unlock_reg = 0xe6060000, /* PMMR */ ++ ++ .reserved_id = PINMUX_RESERVED, ++ .data = { PINMUX_DATA_BEGIN, PINMUX_DATA_END }, ++ .input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END }, ++ .output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END }, ++ .mark = { PINMUX_MARK_BEGIN, PINMUX_MARK_END }, ++ .function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END }, ++ ++ .first_gpio = GPIO_GP_0_0, ++ .last_gpio = GPIO_FN_DIGRF_CLKEN_OUT, ++ ++ .gpios = pinmux_gpios, ++ .cfg_regs = pinmux_config_regs, ++ .data_regs = pinmux_data_regs, ++ ++ .gpio_data = pinmux_data, ++ .gpio_data_size = ARRAY_SIZE(pinmux_data), ++}; ++ ++void r8a7797_pinmux_init(void) ++{ ++ register_pinmux(&r8a7797_pinmux_info); ++} +diff --git a/arch/arm/cpu/armv8/rcar_gen3/prr_depend.c b/arch/arm/cpu/armv8/rcar_gen3/prr_depend.c +index 27e40aa..67d3838 100644 +--- a/arch/arm/cpu/armv8/rcar_gen3/prr_depend.c ++++ b/arch/arm/cpu/armv8/rcar_gen3/prr_depend.c +@@ -16,12 +16,14 @@ + /* PRR PRODUCT for RCAR */ + #define PRR_PRODUCT_RCAR_H3 (0x4f00ul) + #define PRR_PRODUCT_RCAR_M3 (0x5200ul) ++#define PRR_PRODUCT_RCAR_V3M (0x5400ul) + #define PRR_PRODUCT_MASK (0x7f00ul) + + /* PRR PRODUCT and CUT for RCAR */ + #define PRR_PRODUCT_CUT_RCAR_H3_WS10 (PRR_PRODUCT_RCAR_H3 | 0x00ul) + #define PRR_PRODUCT_CUT_RCAR_H3_WS11 (PRR_PRODUCT_RCAR_H3 | 0x01ul) + #define PRR_PRODUCT_CUT_RCAR_M3_ES10 (PRR_PRODUCT_RCAR_M3 | 0x00ul) ++#define PRR_PRODUCT_CUT_RCAR_V3M_ES10 (PRR_PRODUCT_RCAR_V3M | 0x00ul) + #define PRR_PRODUCT_CUT_MASK (PRR_PRODUCT_MASK | 0xfful) + + #define RCAR_PRR_INIT() rcar_prr_init() +@@ -93,10 +95,37 @@ int rcar_need_reconfig_sdhi_drvctrl(void) + #define SDH800_SD200 (SD_SRCFC_DIV1 | SD_FC_DIV4) + #define SDH400_SD200 (SD_SRCFC_DIV1 | SD_FC_DIV2) + ++/* ++ * for sd/mmc function(V3M) ++ */ ++#define SDHFC_BIT (8) ++#define SD_SDHFC_DIV2 (0 << SDHFC_BIT) ++#define SD_SDHFC_DIV3 (1 << SDHFC_BIT) ++#define SD_SDHFC_DIV4 (2 << SDHFC_BIT) ++#define SD_SDHFC_DIV6 (3 << SDHFC_BIT) ++#define SD_SDHFC_DIV8 (4 << SDHFC_BIT) ++#define SD_SDHFC_DIV12 (5 << SDHFC_BIT) ++#define SD_SDHFC_DIV16 (6 << SDHFC_BIT) ++#define SD_SDHFC_DIV18 (7 << SDHFC_BIT) ++#define SD_SDHFC_DIV24 (8 << SDHFC_BIT) ++#define SD_SDHFC_DIV36 (10 << SDHFC_BIT) ++#define SD_SDHFC_DIV48 (11 << SDHFC_BIT) ++#define SD0FC_BIT (4) ++#define SD_SD0FC_DIV8 (4 << SD0FC_BIT) ++#define SD_SD0FC_DIV10 (12 << SD0FC_BIT) ++#define SD_SD0FC_DIV12 (5 << SD0FC_BIT) ++#define SD_SD0FC_DIV16 (6 << SD0FC_BIT) ++#define SD_SD0FC_DIV18 (7 << SD0FC_BIT) ++#define SD_SD0FC_DIV24 (8 << SD0FC_BIT) ++#define SD_SD0FC_DIV36 (10 << SD0FC_BIT) ++#define SD_SD0FC_DIV48 (11 << SD0FC_BIT) ++ + int rcar_get_sdhi_config_clk(void) + { + if (RCAR_PRR_IS_PRODUCT(H3) && (!RCAR_PRR_CHK_CUT(H3, WS10))) + return SDH400_SD200; ++ else if (RCAR_PRR_IS_PRODUCT(V3M) && (!RCAR_PRR_CHK_CUT(V3M, ES10))) ++ return (SD_SDHFC_DIV2 | SD_SD0FC_DIV16); + else + return SDH800_SD200; + } +diff --git a/arch/arm/include/asm/arch-rcar_gen3/gpio.h b/arch/arm/include/asm/arch-rcar_gen3/gpio.h +index 339da49..01d3c59 100644 +--- a/arch/arm/include/asm/arch-rcar_gen3/gpio.h ++++ b/arch/arm/include/asm/arch-rcar_gen3/gpio.h +@@ -16,6 +16,8 @@ + #include <asm/arch/r8a7795-gpio.h> + #elif defined(CONFIG_R8A7796) + #include <asm/arch/r8a7796-gpio.h> ++#elif defined(CONFIG_R8A7797) ++#include <asm/arch/r8a7797-gpio.h> + #endif + + #if defined(CONFIG_R8A7795) +@@ -23,6 +25,8 @@ void r8a7795_pinmux_init(void); + void r8a7795_es_pinmux_init(void); + #elif defined(CONFIG_R8A7796) + void r8a7796_pinmux_init(void); ++#elif defined(CONFIG_R8A7797) ++void r8a7797_pinmux_init(void); + #endif + void pinmux_init(void); + +diff --git a/arch/arm/include/asm/arch-rcar_gen3/r8a7797-gpio.h b/arch/arm/include/asm/arch-rcar_gen3/r8a7797-gpio.h +new file mode 100644 +index 0000000..40cccd9 +--- /dev/null ++++ b/arch/arm/include/asm/arch-rcar_gen3/r8a7797-gpio.h +@@ -0,0 +1,456 @@ ++/* ++ * arch/arm/include/asm/arch-rcar_gen3/r8a7797-gpio.h ++ * This file defines pin function control of gpio. ++ * ++ * Copyright (C) 2016 Renesas Electronics Corporation ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ */ ++#ifndef __ASM_R8A7797_GPIO_H__ ++#define __ASM_R8A7797_GPIO_H__ ++ ++/* Pin Function Controller: ++ * GPIO_FN_xx - GPIO used to select pin function ++ * GPIO_GP_x_x - GPIO mapped to real I/O pin on CPU ++ */ ++enum { ++ GPIO_GP_0_0, GPIO_GP_0_1, GPIO_GP_0_2, GPIO_GP_0_3, ++ GPIO_GP_0_4, GPIO_GP_0_5, GPIO_GP_0_6, GPIO_GP_0_7, ++ GPIO_GP_0_8, GPIO_GP_0_9, GPIO_GP_0_10, GPIO_GP_0_11, ++ GPIO_GP_0_12, GPIO_GP_0_13, GPIO_GP_0_14, GPIO_GP_0_15, ++ GPIO_GP_0_16, GPIO_GP_0_17, GPIO_GP_0_18, GPIO_GP_0_19, ++ GPIO_GP_0_20, GPIO_GP_0_21, ++ ++ GPIO_GP_1_0, GPIO_GP_1_1, GPIO_GP_1_2, GPIO_GP_1_3, ++ GPIO_GP_1_4, GPIO_GP_1_5, GPIO_GP_1_6, GPIO_GP_1_7, ++ GPIO_GP_1_8, GPIO_GP_1_9, GPIO_GP_1_10, GPIO_GP_1_11, ++ GPIO_GP_1_12, GPIO_GP_1_13, GPIO_GP_1_14, GPIO_GP_1_15, ++ GPIO_GP_1_16, GPIO_GP_1_17, GPIO_GP_1_18, GPIO_GP_1_19, ++ GPIO_GP_1_20, GPIO_GP_1_21, GPIO_GP_1_22, GPIO_GP_1_23, ++ GPIO_GP_1_24, GPIO_GP_1_25, GPIO_GP_1_26, GPIO_GP_1_27, ++ ++ GPIO_GP_2_0, GPIO_GP_2_1, GPIO_GP_2_2, GPIO_GP_2_3, ++ GPIO_GP_2_4, GPIO_GP_2_5, GPIO_GP_2_6, GPIO_GP_2_7, ++ GPIO_GP_2_8, GPIO_GP_2_9, GPIO_GP_2_10, GPIO_GP_2_11, ++ GPIO_GP_2_12, GPIO_GP_2_13, GPIO_GP_2_14, GPIO_GP_2_15, ++ GPIO_GP_2_16, ++ ++ GPIO_GP_3_0, GPIO_GP_3_1, GPIO_GP_3_2, GPIO_GP_3_3, ++ GPIO_GP_3_4, GPIO_GP_3_5, GPIO_GP_3_6, GPIO_GP_3_7, ++ GPIO_GP_3_8, GPIO_GP_3_9, GPIO_GP_3_10, GPIO_GP_3_11, ++ GPIO_GP_3_12, GPIO_GP_3_13, GPIO_GP_3_14, GPIO_GP_3_15, ++ GPIO_GP_3_16, ++ ++ GPIO_GP_4_0, GPIO_GP_4_1, GPIO_GP_4_2, GPIO_GP_4_3, ++ GPIO_GP_4_4, GPIO_GP_4_5, ++ ++ GPIO_GP_5_0, GPIO_GP_5_1, GPIO_GP_5_2, GPIO_GP_5_3, ++ GPIO_GP_5_4, GPIO_GP_5_5, GPIO_GP_5_6, GPIO_GP_5_7, ++ GPIO_GP_5_8, GPIO_GP_5_9, GPIO_GP_5_10, GPIO_GP_5_11, ++ GPIO_GP_5_12, GPIO_GP_5_13, GPIO_GP_5_14, ++ ++ /* GPSR0 */ ++ GPIO_GFN_DU_EXODDF_DU_ODDF_DISP_CDE, ++ GPIO_GFN_DU_EXVSYNC_DU_VSYNC, ++ GPIO_GFN_DU_EXHSYNC_DU_HSYNC, ++ GPIO_GFN_DU_DOTCLKOUT, ++ GPIO_GFN_DU_DB7, ++ GPIO_GFN_DU_DB6, ++ GPIO_GFN_DU_DB5, ++ GPIO_GFN_DU_DB4, ++ GPIO_GFN_DU_DB3, ++ GPIO_GFN_DU_DB2, ++ GPIO_GFN_DU_DG7, ++ GPIO_GFN_DU_DG6, ++ GPIO_GFN_DU_DG5, ++ GPIO_GFN_DU_DG4, ++ GPIO_GFN_DU_DG3, ++ GPIO_GFN_DU_DG2, ++ GPIO_GFN_DU_DR7, ++ GPIO_GFN_DU_DR6, ++ GPIO_GFN_DU_DR5, ++ GPIO_GFN_DU_DR4, ++ GPIO_GFN_DU_DR3, ++ GPIO_GFN_DU_DR2, ++ ++ /* GPSR1 */ ++ GPIO_GFN_DIGRF_CLKOUT, ++ GPIO_GFN_DIGRF_CLKIN, ++ GPIO_GFN_CANFD_CLK_A, ++ GPIO_GFN_CANFD1_RX, ++ GPIO_GFN_CANFD1_TX, ++ GPIO_GFN_CANFD0_RX_A, ++ GPIO_GFN_CANFD0_TX_A, ++ GPIO_GFN_AVB0_AVTP_CAPTURE, ++ GPIO_FN_AVB0_AVTP_MATCH, ++ GPIO_FN_AVB0_LINK, ++ GPIO_FN_AVB0_PHY_INT, ++ GPIO_FN_AVB0_MAGIC, ++ GPIO_FN_AVB0_MDC, ++ GPIO_FN_AVB0_MDIO, ++ GPIO_FN_AVB0_TXCREFCLK, ++ GPIO_FN_AVB0_TD3, ++ GPIO_FN_AVB0_TD2, ++ GPIO_FN_AVB0_TD1, ++ GPIO_FN_AVB0_TD0, ++ GPIO_FN_AVB0_TXC, ++ GPIO_FN_AVB0_TX_CTL, ++ GPIO_FN_AVB0_RD3, ++ GPIO_FN_AVB0_RD2, ++ GPIO_FN_AVB0_RD1, ++ GPIO_FN_AVB0_RD0, ++ GPIO_FN_AVB0_RXC, ++ GPIO_FN_AVB0_RX_CTL, ++ GPIO_GFN_IRQ0, ++ ++ /* GPSR2 */ ++ GPIO_GFN_VI0_FIELD, ++ GPIO_GFN_VI0_DATA11, ++ GPIO_GFN_VI0_DATA10, ++ GPIO_GFN_VI0_DATA9, ++ GPIO_GFN_VI0_DATA8, ++ GPIO_GFN_VI0_DATA7, ++ GPIO_GFN_VI0_DATA6, ++ GPIO_GFN_VI0_DATA5, ++ GPIO_GFN_VI0_DATA4, ++ GPIO_GFN_VI0_DATA3, ++ GPIO_GFN_VI0_DATA2, ++ GPIO_GFN_VI0_DATA1, ++ GPIO_GFN_VI0_DATA0, ++ GPIO_GFN_VI0_VSYNC_N, ++ GPIO_GFN_VI0_HSYNC_N, ++ GPIO_GFN_VI0_CLKENB, ++ GPIO_GFN_VI0_CLK, ++ ++ /* GPSR3 */ ++ GPIO_GFN_VI1_FIELD, ++ GPIO_GFN_VI1_DATA11, ++ GPIO_GFN_VI1_DATA10, ++ GPIO_GFN_VI1_DATA9, ++ GPIO_GFN_VI1_DATA8, ++ GPIO_GFN_VI1_DATA7, ++ GPIO_GFN_VI1_DATA6, ++ GPIO_GFN_VI1_DATA5, ++ GPIO_GFN_VI1_DATA4, ++ GPIO_GFN_VI1_DATA3, ++ GPIO_GFN_VI1_DATA2, ++ GPIO_GFN_VI1_DATA1, ++ GPIO_GFN_VI1_DATA0, ++ GPIO_GFN_VI1_VSYNC_N, ++ GPIO_GFN_VI1_HSYNC_N, ++ GPIO_GFN_VI1_CLKENB, ++ GPIO_GFN_VI1_CLK, ++ ++ /* GPSR4 */ ++ GPIO_GFN_SDA2, ++ GPIO_GFN_SCL2, ++ GPIO_GFN_SDA1, ++ GPIO_GFN_SCL1, ++ GPIO_GFN_SDA0, ++ GPIO_GFN_SCL0, ++ ++ /* GPSR5 */ ++ GPIO_FN_RPC_INT_N, ++ GPIO_FN_RPC_WP_N, ++ GPIO_FN_RPC_RESET_N, ++ GPIO_FN_QSPI1_SSL, ++ GPIO_FN_QSPI1_IO3, ++ GPIO_FN_QSPI1_IO2, ++ GPIO_FN_QSPI1_MISO_IO1, ++ GPIO_FN_QSPI1_MOSI_IO0, ++ GPIO_FN_QSPI1_SPCLK, ++ GPIO_FN_QSPI0_SSL, ++ GPIO_FN_QSPI0_IO3, ++ GPIO_FN_QSPI0_IO2, ++ GPIO_FN_QSPI0_MISO_IO1, ++ GPIO_FN_QSPI0_MOSI_IO0, ++ GPIO_FN_QSPI0_SPCLK, ++ ++ /* IPSR0 */ ++ GPIO_IFN_DU_DR2, ++ GPIO_FN_HSCK0, ++ GPIO_FN_A0, ++ GPIO_IFN_DU_DR3, ++ GPIO_FN_HRTS0_N, ++ GPIO_FN_A1, ++ GPIO_IFN_DU_DR4, ++ GPIO_FN_HCTS0_N, ++ GPIO_FN_A2, ++ GPIO_IFN_DU_DR5, ++ GPIO_FN_HTX0, ++ GPIO_FN_A3, ++ GPIO_IFN_DU_DR6, ++ GPIO_FN_MSIOF3_RXD, ++ GPIO_FN_A4, ++ GPIO_IFN_DU_DR7, ++ GPIO_FN_MSIOF3_TXD, ++ GPIO_FN_A5, ++ GPIO_IFN_DU_DG2, ++ GPIO_FN_MSIOF3_SS1, ++ GPIO_FN_A6, ++ GPIO_IFN_DU_DG3, ++ GPIO_FN_MSIOF3_SS2, ++ GPIO_FN_A7, ++ GPIO_FN_PWMFSW0, ++ ++ /* IPSR1 */ ++ GPIO_IFN_DU_DG4, ++ GPIO_FN_A8, ++ GPIO_FN_FSO_CFE_0_N_A, ++ GPIO_IFN_DU_DG5, ++ GPIO_FN_A9, ++ GPIO_FN_FSO_CFE_1_N_A, ++ GPIO_IFN_DU_DG6, ++ GPIO_FN_A10, ++ GPIO_FN_FSO_TOE_N_A, ++ GPIO_IFN_DU_DG7, ++ GPIO_FN_A11, ++ GPIO_FN_IRQ1, ++ GPIO_IFN_DU_DB2, ++ GPIO_FN_A12, ++ GPIO_FN_IRQ2, ++ GPIO_IFN_DU_DB3, ++ GPIO_FN_A13, ++ GPIO_FN_FXR_CLKOUT1, ++ GPIO_IFN_DU_DB4, ++ GPIO_FN_A14, ++ GPIO_FN_FXR_CLKOUT2, ++ GPIO_IFN_DU_DB5, ++ GPIO_FN_A15, ++ GPIO_FN_FXR_TXENA_N, ++ ++ /* IPSR2 */ ++ GPIO_IFN_DU_DB6, ++ GPIO_FN_A16, ++ GPIO_FN_FXR_TXENB_N, ++ GPIO_IFN_DU_DB7, ++ GPIO_FN_A17, ++ GPIO_FN_STPWT_EXTFXR, ++ GPIO_IFN_DU_DOTCLKOUT, ++ GPIO_FN_SCIF_CLK_A, ++ GPIO_FN_A18, ++ GPIO_IFN_DU_EXHSYNC_DU_HSYNC, ++ GPIO_FN_HRX0, ++ GPIO_FN_A19, ++ GPIO_FN_IRQ3, ++ GPIO_IFN_DU_EXVSYNC_DU_VSYNC, ++ GPIO_FN_MSIOF3_SCK, ++ GPIO_FN_A20, ++ GPIO_IFN_DU_EXODDF_DU_ODDF_DISP_CDE, ++ GPIO_FN_MSIOF3_SYNC, ++ GPIO_FN_A21, ++ GPIO_IFN_IRQ0, ++ GPIO_FN_CC5_OSCOUT, ++ GPIO_IFN_VI0_CLK, ++ GPIO_FN_MSIOF2_SCK, ++ GPIO_FN_SCK3, ++ GPIO_FN_HSCK3, ++ ++ /* IPSR3 */ ++ GPIO_IFN_VI0_CLKENB, ++ GPIO_FN_MSIOF2_RXD, ++ GPIO_FN_RX3, ++ GPIO_FN_RD_WR_N, ++ GPIO_FN_HCTS3_N, ++ GPIO_IFN_VI0_HSYNC_N, ++ GPIO_FN_MSIOF2_TXD, ++ GPIO_FN_TX3, ++ GPIO_FN_HRTS3_N, ++ GPIO_IFN_VI0_VSYNC_N, ++ GPIO_FN_MSIOF2_SYNC, ++ GPIO_FN_CTS3_N, ++ GPIO_FN_HTX3, ++ GPIO_IFN_VI0_DATA0, ++ GPIO_FN_MSIOF2_SS1, ++ GPIO_FN_RTS3_N_TANS, ++ GPIO_FN_HRX3, ++ GPIO_IFN_VI0_DATA1, ++ GPIO_FN_MSIOF2_SS2, ++ GPIO_FN_SCK1, ++ GPIO_FN_SPEEDIN_A, ++ GPIO_IFN_VI0_DATA2, ++ GPIO_FN_AVB0_AVTP_PPS, ++ GPIO_FN_SDA3_A, ++ GPIO_IFN_VI0_DATA3, ++ GPIO_FN_HSCK1, ++ GPIO_FN_SCL3_A, ++ GPIO_IFN_VI0_DATA4, ++ GPIO_FN_HRTS1_N, ++ GPIO_FN_RX1_A, ++ ++ /* IPSR4 */ ++ GPIO_IFN_VI0_DATA5, ++ GPIO_FN_HCTS1_N, ++ GPIO_FN_TX1_A, ++ GPIO_IFN_VI0_DATA6, ++ GPIO_FN_HTX1, ++ GPIO_FN_CTS1_N, ++ GPIO_IFN_VI0_DATA7, ++ GPIO_FN_HRX1, ++ GPIO_FN_RTS1_N_TANS, ++ GPIO_IFN_VI0_DATA8, ++ GPIO_FN_HSCK2, ++ GPIO_FN_PWM0_A, ++ GPIO_FN_A22, ++ GPIO_IFN_VI0_DATA9, ++ GPIO_FN_HCTS2_N, ++ GPIO_FN_PWM1_A, ++ GPIO_FN_A23, ++ GPIO_FN_FSO_CFE_0_N_B, ++ GPIO_IFN_VI0_DATA10, ++ GPIO_FN_HRTS2_N, ++ GPIO_FN_PWM2_A, ++ GPIO_FN_A24, ++ GPIO_FN_FSO_CFE_1_N_B, ++ GPIO_IFN_VI0_DATA11, ++ GPIO_FN_HTX2, ++ GPIO_FN_PWM3_A, ++ GPIO_FN_A25, ++ GPIO_FN_FSO_TOE_N_B, ++ GPIO_IFN_VI0_FIELD, ++ GPIO_FN_HRX2, ++ GPIO_FN_PWM4_A, ++ GPIO_FN_CS1_N_A26, ++ GPIO_FN_FSCLKST2_N_A, ++ ++ /* IPSR5 */ ++ GPIO_IFN_VI1_CLK, ++ GPIO_FN_MSIOF1_RXD, ++ GPIO_FN_CS0_N, ++ GPIO_IFN_VI1_CLKENB, ++ GPIO_FN_MSIOF1_TXD, ++ GPIO_FN_D0, ++ GPIO_IFN_VI1_HSYNC_N, ++ GPIO_FN_MSIOF1_SCK, ++ GPIO_FN_D1, ++ GPIO_IFN_VI1_VSYNC_N, ++ GPIO_FN_MSIOF1_SYNC, ++ GPIO_FN_D2, ++ GPIO_IFN_VI1_DATA0, ++ GPIO_FN_MSIOF1_SS1, ++ GPIO_FN_D3, ++ GPIO_IFN_VI1_DATA1, ++ GPIO_FN_MSIOF1_SS2, ++ GPIO_FN_D4, ++ GPIO_FN_MMC_CMD, ++ GPIO_IFN_VI1_DATA2, ++ GPIO_FN_CANFD0_TX_B, ++ GPIO_FN_D5, ++ GPIO_FN_MMC_D0, ++ GPIO_IFN_VI1_DATA3, ++ GPIO_FN_CANFD0_RX_B, ++ GPIO_FN_D6, ++ GPIO_FN_MMC_D1, ++ ++ /* IPSR6 */ ++ GPIO_IFN_VI1_DATA4, ++ GPIO_FN_CANFD_CLK_B, ++ GPIO_FN_D7, ++ GPIO_FN_MMC_D2, ++ GPIO_IFN_VI1_DATA5, ++ GPIO_FN_SCK4, ++ GPIO_FN_D8, ++ GPIO_FN_MMC_D3, ++ GPIO_IFN_VI1_DATA6, ++ GPIO_FN_RX4, ++ GPIO_FN_D9, ++ GPIO_FN_MMC_CLK, ++ GPIO_IFN_VI1_DATA7, ++ GPIO_FN_TX4, ++ GPIO_FN_D10, ++ GPIO_FN_MMC_D4, ++ GPIO_IFN_VI1_DATA8, ++ GPIO_FN_CTS4_N, ++ GPIO_FN_D11, ++ GPIO_FN_MMC_D5, ++ GPIO_IFN_VI1_DATA9, ++ GPIO_FN_RTS4_N_TANS, ++ GPIO_FN_D12, ++ GPIO_FN_MMC_D6, ++ GPIO_FN_SCL3_B, ++ GPIO_IFN_VI1_DATA10, ++ GPIO_FN_D13, ++ GPIO_FN_MMC_D7, ++ GPIO_FN_SDA3_B, ++ GPIO_IFN_VI1_DATA11, ++ GPIO_FN_SCL4, ++ GPIO_FN_IRQ4, ++ GPIO_FN_D14, ++ GPIO_FN_MMC_WP, ++ ++ /* IPSR7 */ ++ GPIO_IFN_VI1_FIELD, ++ GPIO_FN_SDA4, ++ GPIO_FN_IRQ5, ++ GPIO_FN_D15, ++ GPIO_FN_MMC_CD, ++ GPIO_IFN_SCL0, ++ GPIO_FN_DU_DR0, ++ GPIO_FN_TPU0TO0, ++ GPIO_FN_CLKOUT, ++ GPIO_FN_MSIOF0_RXD, ++ GPIO_IFN_SDA0, ++ GPIO_FN_DU_DR1, ++ GPIO_FN_TPU0TO1, ++ GPIO_FN_BS_N, ++ GPIO_FN_SCK0, ++ GPIO_FN_MSIOF0_TXD, ++ GPIO_IFN_SCL1, ++ GPIO_FN_DU_DG0, ++ GPIO_FN_TPU0TO2, ++ GPIO_FN_RD_N, ++ GPIO_FN_CTS0_N, ++ GPIO_FN_MSIOF0_SCK, ++ GPIO_IFN_SDA1, ++ GPIO_FN_DU_DG1, ++ GPIO_FN_TPU0TO3, ++ GPIO_FN_WE0_N, ++ GPIO_FN_RTS0_N_TANS, ++ GPIO_FN_MSIOF0_SYNC, ++ GPIO_IFN_SCL2, ++ GPIO_FN_DU_DB0, ++ GPIO_FN_TCLK1_A, ++ GPIO_FN_WE1_N, ++ GPIO_FN_RX0, ++ GPIO_FN_MSIOF0_SS1, ++ GPIO_IFN_SDA2, ++ GPIO_FN_DU_DB1, ++ GPIO_FN_TCLK2_A, ++ GPIO_FN_EX_WAIT0, ++ GPIO_FN_TX0, ++ GPIO_FN_MSIOF0_SS2, ++ GPIO_IFN_AVB0_AVTP_CAPTURE, ++ GPIO_FN_FSCLKST2_N_B, ++ ++ /* IPSR8 */ ++ GPIO_IFN_CANFD0_TX_A, ++ GPIO_FN_FXR_TXDA, ++ GPIO_FN_PWM0_B, ++ GPIO_FN_DU_DISP, ++ GPIO_FN_FSCLKST2_N_C, ++ GPIO_IFN_CANFD0_RX_A, ++ GPIO_FN_RXDA_EXTFXR, ++ GPIO_FN_PWM1_B, ++ GPIO_FN_DU_CDE, ++ GPIO_IFN_CANFD1_TX, ++ GPIO_FN_FXR_TXDB, ++ GPIO_FN_PWM2_B, ++ GPIO_FN_TCLK1_B, ++ GPIO_FN_TX1_B, ++ GPIO_IFN_CANFD1_RX, ++ GPIO_FN_RXDB_EXTFXR, ++ GPIO_FN_PWM3_B, ++ GPIO_FN_TCLK2_B, ++ GPIO_FN_RX1_B, ++ GPIO_IFN_CANFD_CLK_A, ++ GPIO_FN_CLK_EXTFXR, ++ GPIO_FN_PWM4_B, ++ GPIO_FN_SPEEDIN_B, ++ GPIO_FN_SCIF_CLK_B, ++ GPIO_IFN_DIGRF_CLKIN, ++ GPIO_FN_DIGRF_CLKEN_IN, ++ GPIO_IFN_DIGRF_CLKOUT, ++ GPIO_FN_DIGRF_CLKEN_OUT, ++}; ++ ++#endif /* __ASM_R8A7797_GPIO_H__ */ +diff --git a/arch/arm/include/asm/arch-rcar_gen3/r8a7797.h b/arch/arm/include/asm/arch-rcar_gen3/r8a7797.h +new file mode 100644 +index 0000000..09e83ba +--- /dev/null ++++ b/arch/arm/include/asm/arch-rcar_gen3/r8a7797.h +@@ -0,0 +1,33 @@ ++/* ++ * arch/arm/include/asm/arch-rcar_gen3/r8a7797.h ++ * This file defines registers and value for r8a7797. ++ * ++ * Copyright (C) 2016 Renesas Electronics Corporation ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ */ ++ ++#ifndef __ASM_ARCH_R8A7797_H ++#define __ASM_ARCH_R8A7797_H ++ ++#include "rcar-base.h" ++ ++/* Module stop control/status register bits */ ++#define MSTP0_BITS 0x00230000 ++#define MSTP1_BITS 0xFFFFFFFF ++#define MSTP2_BITS 0x14062FD8 ++#define MSTP3_BITS 0xFFFFFFDF ++#define MSTP4_BITS 0x80000184 ++#define MSTP5_BITS 0x83FFFFFF ++#define MSTP6_BITS 0xFFFFFFFF ++#define MSTP7_BITS 0xFFFFFFFF ++#define MSTP8_BITS 0x7FF3FFF4 ++#define MSTP9_BITS 0xFBF7FF97 ++#define MSTP10_BITS 0xFFFEFFE0 ++#define MSTP11_BITS 0x000000B7 ++ ++/* SDHI */ ++#define CONFIG_SYS_SH_SDHI2_BASE 0xEE140000 /* either MMC0 */ ++#define CONFIG_SYS_SH_SDHI_NR_CHANNEL 1 ++ ++#endif /* __ASM_ARCH_R8A7797_H */ +diff --git a/arch/arm/include/asm/arch-rcar_gen3/rcar-base.h b/arch/arm/include/asm/arch-rcar_gen3/rcar-base.h +index dde46ea..a51a060 100644 +--- a/arch/arm/include/asm/arch-rcar_gen3/rcar-base.h ++++ b/arch/arm/include/asm/arch-rcar_gen3/rcar-base.h +@@ -70,6 +70,11 @@ + #define SMSTPCR10 0xE6150998 + #define SMSTPCR11 0xE615099C + ++/* PLL */ ++#define PLL0CR 0xE61500D8 ++#define PLL0_STC_MASK 0x7F000000 ++#define PLL0_STC_BIT 24 ++ + /* SH-I2C */ + #define CONFIG_SYS_I2C_SH_BASE0 0xE60B0000 + +diff --git a/arch/arm/include/asm/arch-rcar_gen3/rcar_gen3.h b/arch/arm/include/asm/arch-rcar_gen3/rcar_gen3.h +index 584bd1c..568fc6e 100644 +--- a/arch/arm/include/asm/arch-rcar_gen3/rcar_gen3.h ++++ b/arch/arm/include/asm/arch-rcar_gen3/rcar_gen3.h +@@ -14,6 +14,8 @@ + #include <asm/arch/r8a7795.h> + #elif defined(CONFIG_R8A7796) + #include <asm/arch/r8a7796.h> ++ #elif defined(CONFIG_R8A7797) ++ #include <asm/arch/r8a7797.h> + #else + #error "SOC Name not defined" + #endif +diff --git a/drivers/serial/serial_sh.h b/drivers/serial/serial_sh.h +index d4efe9a..0d532c2 100644 +--- a/drivers/serial/serial_sh.h ++++ b/drivers/serial/serial_sh.h +@@ -226,7 +226,8 @@ struct uart_port { + # define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ + #elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) || \ + defined(CONFIG_R8A7793) || defined(CONFIG_R8A7794) || \ +- defined(CONFIG_R8A7795) || defined(CONFIG_R8A7796) ++ defined(CONFIG_R8A7795) || defined(CONFIG_R8A7796) || \ ++ defined(CONFIG_R8A7797) + # define SCIF_ORER 0x0001 + # define SCSCR_INIT(port) (port->clk_mode == EXT_CLK ? 0x32 : 0x30) + /* TIE=0,RIE=0,TE=1,RE=1,REIE=0, */ +diff --git a/include/configs/rcar-gen3-common.h b/include/configs/rcar-gen3-common.h +index 2fe7d3c..32cd265 100644 +--- a/include/configs/rcar-gen3-common.h ++++ b/include/configs/rcar-gen3-common.h +@@ -93,7 +93,11 @@ + #define CONFIG_SYS_BAUDRATE_TABLE { 115200, 38400 } + + /* MEMORY */ ++#if defined(CONFIG_R8A7797) ++#define CONFIG_SYS_TEXT_BASE 0x58280000 ++#else + #define CONFIG_SYS_TEXT_BASE 0x50000000 ++#endif + #define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_TEXT_BASE + 0x7fff0) + + +@@ -118,6 +122,14 @@ + #define PHYS_SDRAM_2_SIZE ((unsigned long)0x80000000) + #define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1 + #define CONFIG_SYS_SDRAM_SIZE PHYS_SDRAM_1_SIZE ++#elif defined(CONFIG_R8A7797) ++#define CONFIG_NR_DRAM_BANKS 1 ++#define PHYS_SDRAM_1 (0x40000000 + DRAM_RSV_SIZE) /* legacy */ ++#define PHYS_SDRAM_1_SIZE ((unsigned long)(0x40000000 - DRAM_RSV_SIZE)) ++#define PHYS_SDRAM_2 0x0600000000 /* ext */ ++#define PHYS_SDRAM_2_SIZE ((unsigned long)0x80000000) ++#define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1 ++#define CONFIG_SYS_SDRAM_SIZE PHYS_SDRAM_1_SIZE + #else + #define CONFIG_NR_DRAM_BANKS 1 + #define CONFIG_SYS_SDRAM_BASE 0x40000000 +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0015-board-renesas-Add-V3M-Eagle-board.patch b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0015-board-renesas-Add-V3M-Eagle-board.patch new file mode 100644 index 0000000..35ff456 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0015-board-renesas-Add-V3M-Eagle-board.patch @@ -0,0 +1,499 @@ +From 423d01a1b367d82a3855972483530968309cbbd4 Mon Sep 17 00:00:00 2001 +From: Daisuke Matsushita <daisuke.matsushita.ns@hitachi.com> +Date: Tue, 21 Mar 2017 15:05:15 +0900 +Subject: [PATCH] board: renesas: Add V3M Eagle board + +V3M Eagle is a board based on R-Car V3M SoC (R8A7797) + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + arch/arm/cpu/armv8/Kconfig | 6 + board/renesas/eagle/Kconfig | 15 + + board/renesas/eagle/MAINTAINERS | 6 + board/renesas/eagle/Makefile | 9 + board/renesas/eagle/eagle.c | 398 ++++++++++++++++++++++++++++++++++++++++ + configs/r8a7797_eagle_defconfig | 9 + include/configs/r8a7797_eagle.h | 155 +++++++++++++++ + 7 files changed, 597 insertions(+), 1 deletion(-) + create mode 100644 board/renesas/eagle/Kconfig + create mode 100644 board/renesas/eagle/MAINTAINERS + create mode 100644 board/renesas/eagle/Makefile + create mode 100644 board/renesas/eagle/eagle.c + create mode 100644 configs/r8a7797_eagle_defconfig + create mode 100644 include/configs/r8a7797_eagle.h + +diff --git a/arch/arm/cpu/armv8/Kconfig b/arch/arm/cpu/armv8/Kconfig +index 2daadc9..a645e21 100644 +--- a/arch/arm/cpu/armv8/Kconfig ++++ b/arch/arm/cpu/armv8/Kconfig +@@ -13,6 +13,9 @@ choice + config TARGET_ULCB + bool "ULCB board" + ++config TARGET_EAGLE ++ bool "EAGLE board" ++ + endchoice + + choice +@@ -40,5 +43,6 @@ config SYS_SOC + + source "board/renesas/salvator-x/Kconfig" + source "board/renesas/ulcb/Kconfig" ++source "board/renesas/eagle/Kconfig" + + endif +diff --git a/board/renesas/eagle/Kconfig b/board/renesas/eagle/Kconfig +new file mode 100644 +index 0000000..3024836 +--- /dev/null ++++ b/board/renesas/eagle/Kconfig +@@ -0,0 +1,15 @@ ++if TARGET_EAGLE ++ ++config SYS_SOC ++ default "rcar_gen3" ++ ++config SYS_BOARD ++ default "eagle" ++ ++config SYS_VENDOR ++ default "renesas" ++ ++config SYS_CONFIG_NAME ++ default "r8a7797_eagle" if R8A7797 ++ ++endif +diff --git a/board/renesas/eagle/MAINTAINERS b/board/renesas/eagle/MAINTAINERS +new file mode 100644 +index 0000000..c411373 +--- /dev/null ++++ b/board/renesas/eagle/MAINTAINERS +@@ -0,0 +1,6 @@ ++EAGLE BOARD ++M: foo <foo@renesas.com> ++S: Maintained ++F: board/renesas/eagle/ ++F: include/configs/r8a7797_eagle.h ++F: configs/r8a7797_eagle_defconfig +diff --git a/board/renesas/eagle/Makefile b/board/renesas/eagle/Makefile +new file mode 100644 +index 0000000..87d63e1 +--- /dev/null ++++ b/board/renesas/eagle/Makefile +@@ -0,0 +1,9 @@ ++# ++# board/renesas/eagle/Makefile ++# ++# Copyright (C) 2016 Renesas Electronics Corporation ++# ++# SPDX-License-Identifier: GPL-2.0+ ++# ++ ++obj-y := eagle.o ../rcar-gen3-common/common.o +diff --git a/board/renesas/eagle/eagle.c b/board/renesas/eagle/eagle.c +new file mode 100644 +index 0000000..137097d +--- /dev/null ++++ b/board/renesas/eagle/eagle.c +@@ -0,0 +1,224 @@ ++/* ++ * board/renesas/eagle/eagle.c ++ * This file is Eagle board support. ++ * ++ * Copyright (C) 2016 Renesas Electronics Corporation ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ */ ++ ++#include <common.h> ++#include <malloc.h> ++#include <netdev.h> ++#include <dm.h> ++#include <dm/platform_data/serial_sh.h> ++#include <asm/processor.h> ++#include <asm/mach-types.h> ++#include <asm/io.h> ++#include <asm/errno.h> ++#include <asm/arch/sys_proto.h> ++#include <asm/gpio.h> ++#include <asm/arch/prr_depend.h> ++#include <asm/arch/gpio.h> ++#include <asm/arch/rcar_gen3.h> ++#include <asm/arch/rcar-mstp.h> ++#include <asm/arch/sh_sdhi.h> ++#include <i2c.h> ++#include <mmc.h> ++ ++DECLARE_GLOBAL_DATA_PTR; ++ ++#define SCIF0_MSTP207 (1 << 7) ++#define ETHERAVB_MSTP812 (1 << 12) ++#define RPC_MSTP917 (1 << 17) ++ ++#define CLK2MHZ(clk) (clk / 1000 / 1000) ++void s_init(void) ++{ ++ struct rcar_rwdt *rwdt = (struct rcar_rwdt *)RWDT_BASE; ++ struct rcar_swdt *swdt = (struct rcar_swdt *)SWDT_BASE; ++ u32 stc; ++ ++ /* Watchdog init */ ++ writel(0xA5A5A500, &rwdt->rwtcsra); ++ writel(0xA5A5A500, &swdt->swtcsra); ++ ++ /* CPU frequency setting. Set to 0.8GHz */ ++ stc = ((800 / CLK2MHZ(CONFIG_SYS_CLK_FREQ)) - 1) << PLL0_STC_BIT; ++ clrsetbits_le32(PLL0CR, PLL0_STC_MASK, stc); ++} ++ ++int board_early_init_f(void) ++{ ++ rcar_prr_init(); ++ ++ writel(0xa5a5ffff, 0xe6150900); ++ writel(0x5a5a0000, 0xe6150904); ++ mstp_clrbits_le32(MSTPSR1, SMSTPCR1, 0x02000000); ++ /* SCIF0 */ ++ mstp_clrbits_le32(MSTPSR2, SMSTPCR2, SCIF0_MSTP207); ++ /* EHTERAVB */ ++ mstp_clrbits_le32(MSTPSR8, SMSTPCR8, ETHERAVB_MSTP812); ++ /* QSPI */ ++ mstp_clrbits_le32(MSTPSR9, SMSTPCR9, RPC_MSTP917); ++ ++ return 0; ++} ++ ++int board_init(void) ++{ ++ /* adress of boot parameters */ ++ gd->bd->bi_boot_params = CONFIG_SYS_TEXT_BASE + 0x50000; ++ ++ /* Init PFC controller */ ++ pinmux_init(); ++ ++#ifdef CONFIG_RAVB ++ /* GPSR1 */ ++ gpio_request(GPIO_GFN_AVB0_AVTP_CAPTURE, NULL); ++ gpio_request(GPIO_FN_AVB0_AVTP_MATCH, NULL); ++ gpio_request(GPIO_FN_AVB0_LINK, NULL); ++ gpio_request(GPIO_FN_AVB0_PHY_INT, NULL); ++ gpio_request(GPIO_FN_AVB0_MAGIC, NULL); ++ gpio_request(GPIO_FN_AVB0_MDC, NULL); ++ gpio_request(GPIO_FN_AVB0_MDIO, NULL); ++ gpio_request(GPIO_FN_AVB0_TXCREFCLK, NULL); ++ gpio_request(GPIO_FN_AVB0_TD3, NULL); ++ gpio_request(GPIO_FN_AVB0_TD2, NULL); ++ gpio_request(GPIO_FN_AVB0_TD1, NULL); ++ gpio_request(GPIO_FN_AVB0_TD0, NULL); ++ gpio_request(GPIO_FN_AVB0_TXC, NULL); ++ gpio_request(GPIO_FN_AVB0_TX_CTL, NULL); ++ gpio_request(GPIO_FN_AVB0_RD3, NULL); ++ gpio_request(GPIO_FN_AVB0_RD2, NULL); ++ gpio_request(GPIO_FN_AVB0_RD1, NULL); ++ gpio_request(GPIO_FN_AVB0_RD0, NULL); ++ gpio_request(GPIO_FN_AVB0_RXC, NULL); ++ gpio_request(GPIO_FN_AVB0_RX_CTL, NULL); ++ ++ /* IPSR7 */ ++ gpio_request(GPIO_IFN_AVB0_AVTP_CAPTURE, NULL); ++ /* IPSR3 */ ++ gpio_request(GPIO_FN_AVB0_AVTP_PPS, NULL); ++ ++ /* AVB_PHY_RST */ ++ gpio_request(GPIO_GP_1_16, NULL); ++ gpio_direction_output(GPIO_GP_1_16, 0); ++ mdelay(20); ++ gpio_set_value(GPIO_GP_1_16, 1); ++ udelay(1); ++#endif ++ ++ /* QSPI */ ++#if !defined(CONFIG_SYS_NO_FLASH) ++ gpio_request(GPIO_FN_QSPI0_SPCLK, NULL); ++ gpio_request(GPIO_FN_QSPI0_MOSI_IO0, NULL); ++ gpio_request(GPIO_FN_QSPI0_MISO_IO1, NULL); ++ gpio_request(GPIO_FN_QSPI0_IO2, NULL); ++ gpio_request(GPIO_FN_QSPI0_IO3, NULL); ++ gpio_request(GPIO_FN_QSPI0_SSL, NULL); ++ gpio_request(GPIO_FN_QSPI1_SPCLK, NULL); ++ gpio_request(GPIO_FN_QSPI1_MOSI_IO0, NULL); ++ gpio_request(GPIO_FN_QSPI1_MISO_IO1, NULL); ++ gpio_request(GPIO_FN_QSPI1_IO2, NULL); ++ gpio_request(GPIO_FN_QSPI1_IO3, NULL); ++ gpio_request(GPIO_FN_QSPI1_SSL, NULL); ++ gpio_request(GPIO_FN_RPC_RESET_N, NULL); ++ gpio_request(GPIO_FN_RPC_WP_N, NULL); ++ gpio_request(GPIO_FN_RPC_INT_N, NULL); ++#endif ++ return 0; ++} ++ ++#define MAHR 0xE68005C0 ++#define MALR 0xE68005C8 ++int board_eth_init(bd_t *bis) ++{ ++ int ret = -ENODEV; ++ u32 val; ++ unsigned char enetaddr[6]; ++ ++ if (!eth_getenv_enetaddr("ethaddr", enetaddr)) ++ return ret; ++ ++ /* Set Mac address */ ++ val = enetaddr[0] << 24 | enetaddr[1] << 16 | ++ enetaddr[2] << 8 | enetaddr[3]; ++ writel(val, MAHR); ++ ++ val = enetaddr[4] << 8 | enetaddr[5]; ++ writel(val, MALR); ++ ++#ifdef CONFIG_RAVB ++ ret = ravb_initialize(bis); ++#endif ++ return ret; ++} ++ ++/* Salvator-X has KSZ9031RNX */ ++/* Tri-color dual-LED mode(Pin 41 pull-down) */ ++int board_phy_config(struct phy_device *phydev) ++{ ++ /* hardware use default(Tri-color:0) setting. */ ++ ++ return 0; ++} ++ ++int board_mmc_init(bd_t *bis) ++{ ++ return -ENODEV; ++} ++ ++ ++int dram_init(void) ++{ ++ gd->ram_size = PHYS_SDRAM_1_SIZE; ++#if (CONFIG_NR_DRAM_BANKS >= 2) ++ gd->ram_size += PHYS_SDRAM_2_SIZE; ++#endif ++#if (CONFIG_NR_DRAM_BANKS >= 3) ++ gd->ram_size += PHYS_SDRAM_3_SIZE; ++#endif ++#if (CONFIG_NR_DRAM_BANKS >= 4) ++ gd->ram_size += PHYS_SDRAM_4_SIZE; ++#endif ++ ++ return 0; ++} ++ ++void dram_init_banksize(void) ++{ ++ gd->bd->bi_dram[0].start = PHYS_SDRAM_1; ++ gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; ++#if (CONFIG_NR_DRAM_BANKS >= 2) ++ gd->bd->bi_dram[1].start = PHYS_SDRAM_2; ++ gd->bd->bi_dram[1].size = PHYS_SDRAM_2_SIZE; ++#endif ++#if (CONFIG_NR_DRAM_BANKS >= 3) ++ gd->bd->bi_dram[2].start = PHYS_SDRAM_3; ++ gd->bd->bi_dram[2].size = PHYS_SDRAM_3_SIZE; ++#endif ++#if (CONFIG_NR_DRAM_BANKS >= 4) ++ gd->bd->bi_dram[3].start = PHYS_SDRAM_4; ++ gd->bd->bi_dram[3].size = PHYS_SDRAM_4_SIZE; ++#endif ++} ++ ++const struct rcar_sysinfo sysinfo = { ++ CONFIG_RCAR_BOARD_STRING ++}; ++ ++void reset_cpu(ulong addr) ++{ ++#if defined(CONFIG_SYS_I2C) && defined(CONFIG_SYS_I2C_SH) ++ i2c_reg_write(CONFIG_SYS_I2C_POWERIC_ADDR, 0x20, 0x80); ++#endif ++} ++ ++#if defined(CONFIG_DISPLAY_BOARDINFO) ++int checkboard(void) ++{ ++ printf("Board: %s\n", sysinfo.board_string); ++ return 0; ++} ++#endif +diff --git a/configs/r8a7797_eagle_defconfig b/configs/r8a7797_eagle_defconfig +new file mode 100644 +index 0000000..fd745a8 +--- /dev/null ++++ b/configs/r8a7797_eagle_defconfig +@@ -0,0 +1,9 @@ ++CONFIG_ARM=y ++CONFIG_RCAR_GEN3=y ++CONFIG_DM_SERIAL=y ++CONFIG_TARGET_EAGLE=y ++CONFIG_R8A7797=y ++CONFIG_SPL=y ++CONFIG_SH_SDHI=y ++CONFIG_SPI_FLASH=y ++CONFIG_SPI_FLASH_SPANSION=y +diff --git a/include/configs/r8a7797_eagle.h b/include/configs/r8a7797_eagle.h +new file mode 100644 +index 0000000..c4e3e5e +--- /dev/null ++++ b/include/configs/r8a7797_eagle.h +@@ -0,0 +1,152 @@ ++/* ++ * include/configs/eagle.h ++ * This file is eagle board configuration. ++ * CPU r8a7797. ++ * ++ * Copyright (C) 2016 Renesas Electronics Corporation ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ */ ++ ++#ifndef __EAGLE_H ++#define __EAGLE_H ++ ++#undef DEBUG ++#define CONFIG_RCAR_BOARD_STRING "R-Car EAGLE" ++#define CONFIG_RCAR_TARGET_STRING "r8a7797" ++ ++#include "rcar-gen3-common.h" ++ ++/* Cache Definitions */ ++#define CONFIG_SYS_DCACHE_OFF ++#define CONFIG_SYS_ICACHE_OFF ++ ++/* SCIF */ ++#define CONFIG_SCIF_CONSOLE ++#define CONFIG_CONS_SCIF0 ++#define CONFIG_SH_SCIF_CLK_FREQ CONFIG_S3D4_CLK_FREQ ++ ++/* [A] Hyper Flash */ ++/* use to RPC(SPI Multi I/O Bus Controller) */ ++ ++ /* underconstruction */ ++ ++#define CONFIG_SYS_NO_FLASH ++#if defined(CONFIG_SYS_NO_FLASH) ++#define CONFIG_SPI ++#define CONFIG_RCAR_GEN3_QSPI ++#define CONFIG_SH_QSPI_BASE 0xEE200000 ++#define CONFIG_CMD_SF ++#define CONFIG_CMD_SPI ++#define CONFIG_SPI_FLASH ++#define CONFIG_SPI_FLASH_SPANSION ++#else ++#undef CONFIG_CMD_SF ++#undef CONFIG_CMD_SPI ++#undef CONFIG_SPI_FLASH ++#undef CONFIG_SPI_FLASH_SPANSION ++#endif ++ ++/* Ethernet RAVB */ ++#define CONFIG_RAVB ++#define CONFIG_RAVB_PHY_ADDR 0x0 ++#define CONFIG_RAVB_PHY_MODE PHY_INTERFACE_MODE_RGMII_ID ++#define CONFIG_NET_MULTI ++#define CONFIG_PHYLIB ++#define CONFIG_PHY_MICREL ++#define CONFIG_BITBANGMII ++#define CONFIG_BITBANGMII_MULTI ++#define CONFIG_SH_ETHER_BITBANG ++ ++/* Board Clock */ ++/* XTAL_CLK : 33.33MHz */ ++#define RCAR_XTAL_CLK 33333333u ++#define CONFIG_SYS_CLK_FREQ RCAR_XTAL_CLK ++/* ch0to2 CPclk, ch3to11 S3D2_PEREclk, ch12to14 S3D2_RTclk */ ++/* CPclk 16.66MHz, S3D2 133.33MHz , S3D4 66.66MHz */ ++#define CONFIG_CP_CLK_FREQ (CONFIG_SYS_CLK_FREQ / 2) ++#define CONFIG_PLL1_CLK_FREQ (CONFIG_SYS_CLK_FREQ * 192 / 2) ++#define CONFIG_S3D2_CLK_FREQ (266666666u/2) ++#define CONFIG_S3D4_CLK_FREQ (266666666u/4) ++ ++/* Generic Timer Definitions (use in assembler source) */ ++#define COUNTER_FREQUENCY 0xFE502A /* 16.66MHz from CPclk */ ++ ++/* Generic Interrupt Controller Definitions */ ++#define GICD_BASE (0xF1010000) ++#define GICC_BASE (0xF1020000) ++#define CONFIG_GICV2 ++ ++/* i2c */ ++#define CONFIG_SYS_I2C ++#define CONFIG_SYS_I2C_SH ++#define CONFIG_SYS_I2C_SLAVE 0x60 ++#define CONFIG_SYS_I2C_SH_NUM_CONTROLLERS 1 ++#define CONFIG_SYS_I2C_SH_SPEED0 400000 ++#define CONFIG_SH_I2C_DATA_HIGH 4 ++#define CONFIG_SH_I2C_DATA_LOW 5 ++#define CONFIG_SH_I2C_CLOCK 10000000 ++ ++#define CONFIG_SYS_I2C_POWERIC_ADDR 0x30 ++ ++/* USB */ ++#undef CONFIG_CMD_USB ++ ++/* Module clock supply/stop status bits */ ++/* MFIS */ ++#define CONFIG_SMSTP2_ENA 0x00002000 ++/* serial(SCIF0) */ ++#define CONFIG_SMSTP3_ENA 0x00000400 ++/* INTC-AP, INTC-EX */ ++#define CONFIG_SMSTP4_ENA 0x00000180 ++ ++/* SDHI */ ++#define CONFIG_MMC ++#define CONFIG_CMD_MMC ++#define CONFIG_GENERIC_MMC ++#define CONFIG_SH_SDHI_FREQ 200000000 ++#define CONFIG_SH_SDHI_MMC ++ ++#define CONFIG_SH_MMCIF ++#define CONFIG_SH_MMCIF_ADDR 0xee140000 ++#define CONFIG_SH_MMCIF_CLK (CONFIG_SH_SDHI_FREQ) ++ ++/* Environment */ ++#define CONFIG_ENV_IS_IN_SPI_FLASH ++ ++#define CONFIG_ENV_OVERWRITE ++#define CONFIG_ENV_SECT_SIZE (256 * 1024) ++#define CONFIG_ENV_SIZE (CONFIG_ENV_SECT_SIZE) ++ ++/* Environment in eMMC, at the end of 2nd "boot sector" */ ++#if defined(CONFIG_ENV_IS_IN_MMC) ++#define CONFIG_ENV_OFFSET (-CONFIG_ENV_SIZE) ++#define CONFIG_SYS_MMC_ENV_DEV 0 ++#define CONFIG_SYS_MMC_ENV_PART 2 ++#define CONFIG_GENERIC_MMC ++ ++#elif defined(CONFIG_ENV_IS_IN_SPI_FLASH) ++/* Environment in QSPI */ ++#define CONFIG_ENV_ADDR 0x700000 ++#define CONFIG_ENV_OFFSET (CONFIG_ENV_ADDR) ++ ++#else ++/* Unused Environment */ ++#define CONFIG_ENV_IS_NOWHERE ++#endif ++ ++#define CONFIG_EXTRA_ENV_SETTINGS \ ++ "fdt_high=0xffffffffffffffff\0" \ ++ "initrd_high=0xffffffffffffffff\0" \ ++ "ethact=ravb\0" ++ ++#define CONFIG_BOOTARGS \ ++ "root=/dev/nfs rw " \ ++ "nfsroot=192.168.0.1:/export/rfs ip=192.168.0.20" ++ ++#define CONFIG_BOOTCOMMAND \ ++ "tftp 0x48080000 Image; " \ ++ "tftp 0x48000000 Image-r8a7797-eagle.dtb; " \ ++ "booti 0x48080000 - 0x48000000" ++ ++#endif /* __EAGLE_H */ +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0016-tools-fix-build-fail.patch b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0016-tools-fix-build-fail.patch new file mode 100644 index 0000000..ab66851 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0016-tools-fix-build-fail.patch @@ -0,0 +1,29 @@ +From 34b8d92c5139b37322548cc41c5c3a788c51d3ad Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Tue, 2 May 2017 12:55:23 +0300 +Subject: [PATCH] tools: fix build fail + +Build fail fix for CONFIG_ENV_IS_IN_SPI_FLASH + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + tools/Makefile | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/tools/Makefile b/tools/Makefile +index 4bbb153..12719ac 100644 +--- a/tools/Makefile ++++ b/tools/Makefile +@@ -211,7 +211,8 @@ HOST_EXTRACFLAGS += -include $(srctree)/include/libfdt_env.h \ + -DCONFIG_SYS_TEXT_BASE=$(CONFIG_SYS_TEXT_BASE) \ + -DUSE_HOSTCC \ + -D__KERNEL_STRICT_NAMES \ +- -D_GNU_SOURCE ++ -D_GNU_SOURCE \ ++ -include $(srctree)/include/generated/autoconf.h + + __build: $(LOGO-y) + +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0021-ARM-rcar_gen3-Add-RPC-flash-definitions.patch b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0021-ARM-rcar_gen3-Add-RPC-flash-definitions.patch new file mode 100644 index 0000000..42782cf --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0021-ARM-rcar_gen3-Add-RPC-flash-definitions.patch @@ -0,0 +1,224 @@ +From 2b31e91d7ea86934badebcebb2309b09b79725ca Mon Sep 17 00:00:00 2001 +From: Valentine Barshak <valentine.barshak@cogentembedded.com> +Date: Mon, 4 Apr 2016 18:39:26 +0300 +Subject: [PATCH] ARM: rcar_gen3: Add RPC flash definitions + +This adds common RPC flash definitions to RCAR Gen3 platform. + +Signed-off-by: Valentine Barshak <valentine.barshak@cogentembedded.com> +--- + arch/arm/include/asm/arch-rcar_gen3/rcar-base.h | 6 + + arch/arm/include/asm/arch-rcar_gen3/rpc-flash.h | 184 ++++++++++++++++++++++++ + 2 files changed, 190 insertions(+) + create mode 100644 arch/arm/include/asm/arch-rcar_gen3/rpc-flash.h + +diff --git a/arch/arm/include/asm/arch-rcar_gen3/rcar-base.h b/arch/arm/include/asm/arch-rcar_gen3/rcar-base.h +index 59d34b8..538cdc2 100644 +--- a/arch/arm/include/asm/arch-rcar_gen3/rcar-base.h ++++ b/arch/arm/include/asm/arch-rcar_gen3/rcar-base.h +@@ -78,6 +78,12 @@ + #define CONFIG_SYS_SH_SDHI2_BASE 0xEE140000 + #define CONFIG_SYS_SH_SDHI3_BASE 0xEE160000 + ++/* RPC */ ++#define CONFIG_SYS_RPC_BASE 0xEE200000 ++ ++#define CONFIG_SYS_RPC_FLASH_BASE 0x08000000 ++#define CONFIG_SYS_RPC_FLASH_SIZE 0x04000000 ++ + /* PFC */ + #define PFC_PUEN6 0xE6060418 + #define PUEN_USB1_OVC (1 << 2) +diff --git a/arch/arm/include/asm/arch-rcar_gen3/rpc-flash.h b/arch/arm/include/asm/arch-rcar_gen3/rpc-flash.h +new file mode 100644 +index 0000000..403aaee +--- /dev/null ++++ b/arch/arm/include/asm/arch-rcar_gen3/rpc-flash.h +@@ -0,0 +1,184 @@ ++/* ++ * Copyright (C) 2016 Renesas Electronics Corporation ++ * Copyright (C) 2016 Cogent Embedded, Inc. ++ * ++ * SPDX-License-Identifier: GPL-2.0 ++ */ ++ ++#ifndef __RPC_FLASH_H__ ++#define __RPC_FLASH_H__ ++ ++#include <common.h> ++#include <flash.h> ++#include <asm/io.h> ++#include <asm/arch/rcar_gen3.h> ++ ++#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 ++ ++#ifndef CONFIG_SYS_NO_FLASH ++static inline phys_addr_t rpc_addr(flash_info_t *info, u32 offset) ++{ ++ return offset + CONFIG_SYS_RPC_BASE; ++} ++ ++static inline u32 rpc_readl(flash_info_t *info, u32 offset) ++{ ++ u32 val; ++ ++ val = readl(rpc_addr(info, offset)); ++ return val; ++} ++ ++static inline void rpc_writel(flash_info_t *info, u32 offset, u32 val) ++{ ++ writel(val, rpc_addr(info, offset)); ++} ++ ++static inline void rpc_setl(flash_info_t *info, u32 offset, u32 msk, u32 set) ++{ ++ phys_addr_t addr; ++ u32 val; ++ ++ addr = rpc_addr(info, offset); ++ val = readl(addr); ++ val &= msk; ++ val |= set; ++ writel(val, addr); ++} ++ ++static void rpc_wait_tend(flash_info_t *info) ++{ ++ while (!(rpc_readl(info, RPC_CMNSR) & RPC_CMNSR_TEND)) ++ barrier(); ++} ++#endif /* CONFIG_SYS_NO_FLASH */ ++ ++#endif /* __RPC_FLASH_H__ */ +-- +1.9.3 + diff --git a/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0022-mtd-Add-RPC-HyperFlash-support.patch b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0022-mtd-Add-RPC-HyperFlash-support.patch new file mode 100644 index 0000000..8d34bce --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0022-mtd-Add-RPC-HyperFlash-support.patch @@ -0,0 +1,727 @@ +From 00ea5714ecc7ca61919cb3942d0edf20e8190160 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak <valentine.barshak@cogentembedded.com> +Date: Mon, 4 Apr 2016 18:40:39 +0300 +Subject: [PATCH] mtd: Add RPC HyperFlash support + +This adds RCAR Gen3 RPC HyperFlash driver. + +Signed-off-by: Valentine Barshak <valentine.barshak@cogentembedded.com> +--- + drivers/mtd/Makefile | 1 + + drivers/mtd/rpc_hyperflash.c | 695 +++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 696 insertions(+) + create mode 100644 drivers/mtd/rpc_hyperflash.c + +diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile +index 5467a95..8e794a2 100644 +--- a/drivers/mtd/Makefile ++++ b/drivers/mtd/Makefile +@@ -18,3 +18,4 @@ obj-$(CONFIG_FTSMC020) += ftsmc020.o + obj-$(CONFIG_FLASH_CFI_LEGACY) += jedec_flash.o + obj-$(CONFIG_MW_EEPROM) += mw_eeprom.o + obj-$(CONFIG_ST_SMI) += st_smi.o ++obj-$(CONFIG_RPC_HYPERFLASH) += rpc_hyperflash.o +diff --git a/drivers/mtd/rpc_hyperflash.c b/drivers/mtd/rpc_hyperflash.c +new file mode 100644 +index 0000000..fc67ecd +--- /dev/null ++++ b/drivers/mtd/rpc_hyperflash.c +@@ -0,0 +1,695 @@ ++/* ++ * Copyright (C) 2016 Renesas Electronics Corporation ++ * Copyright (C) 2016 Cogent Embedded, Inc. ++ * ++ * SPDX-License-Identifier: GPL-2.0 ++ */ ++ ++#include <asm/arch/rpc-flash.h> ++ ++#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), ++}; ++ ++static inline u32 rpc_hf_flash_map(flash_info_t *info, int sector) ++{ ++ return info->start[sector] - CONFIG_SYS_RPC_FLASH_BASE; ++} ++ ++static inline int rpc_hf_flash_sector(flash_info_t *info, u32 addr) ++{ ++ return (addr - info->start[0]) / RPC_HF_ERASE_SIZE; ++} ++ ++static inline int rpc_hf_flash_sector_size(flash_info_t *info, int sector) ++{ ++ return RPC_HF_ERASE_SIZE; ++} ++ ++static void rpc_hf_mode_man(flash_info_t *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(flash_info_t *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(flash_info_t *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(flash_info_t *info, u32 addr) ++{ ++ 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_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); ++ ++ /* ++ * 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(flash_info_t *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(flash_info_t *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(flash_info_t *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(flash_info_t *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(flash_info_t *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(flash_info_t *info, int enable) ++{ ++ rpc_setl(info, RPC_PHYINT, ~RPC_PHYINT_WP, enable ? RPC_PHYINT_WP : 0); ++} ++ ++static void rpc_hf_unlock(flash_info_t *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(flash_info_t *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) ++ udelay(delay); ++ } ++ ++ if (!(status & RPC_CFI_STATUS_DRB)) { ++ retval = ERR_TIMOUT; ++ goto out; ++ } ++ ++ if (status & RPC_CFI_STATUS_PSB) { ++ retval = ERR_PROG_ERROR; ++ goto out; ++ } ++ ++ if (status & RPC_CFI_STATUS_ESB) { ++ retval = ERR_NOT_ERASED; ++ goto out; ++ } ++ ++ return ERR_OK; ++ ++out: ++ rpc_hf_write_cmd(info, 0, RPC_CFI_CMD_RESET); ++ return retval; ++} ++ ++static int rpc_hf_sector_erase(flash_info_t *info, int sector) ++{ ++ u32 addr = rpc_hf_flash_map(info, sector); ++ ++ 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, 10000, 1000); ++} ++ ++static ulong rpc_hf_get_size(phys_addr_t base, int banknum) ++{ ++ flash_info_t *info = &flash_info[banknum]; ++ u16 data[2] = { 0, 0 }; ++ ulong id, size = 0; ++ ushort sectors, i; ++ ++ info->flash_id = FLASH_UNKNOWN; ++ info->sector_count = -1; ++ info->size = 0; ++ ++ 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) ++ 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 & (RPC_HF_ERASE_SIZE - 1)) ++ goto out; ++ ++ sectors = size / RPC_HF_ERASE_SIZE; ++ if (sectors < 1 || sectors > CONFIG_SYS_MAX_FLASH_SECT) ++ goto out; ++ ++ info->flash_id = id; ++ info->size = size; ++ info->sector_count = sectors; ++ ++ for (i = 0; i < sectors; i++) { ++ info->start[i] = base; ++ base += RPC_HF_ERASE_SIZE; ++ } ++ ++out: ++ rpc_hf_write_cmd(info, 0, RPC_CFI_CMD_RESET); ++ rpc_hf_mode_ext(info); ++ return info->size; ++} ++ ++/* ++ * Flash erase, returns: ++ * ERR_OK : OK ++ * ERR_ABORTED : Aborted by user ++ * ERR_PROTECTED : Protected sector ++ */ ++int flash_erase(flash_info_t *info, int s_first, int s_last) ++{ ++ int s, retval = ERR_OK; ++ ++ puts("Erasing Flash... "); ++ for (s = s_first; s <= s_last; s++) { ++ if (ctrlc()) { ++ printf("aborted sector %i\n", s); ++ retval = ERR_ABORTED; ++ goto out; ++ } ++ ++ if (info->protect[s]) { ++ printf("protected sector %i\n", s); ++ retval = ERR_PROTECTED; ++ goto out; ++ } ++ ++ putc('.'); ++ ++ retval = rpc_hf_sector_erase(info, s); ++ if (retval != ERR_OK) { ++ printf("error sector %i\n", s); ++ goto out; ++ } ++ } ++ puts("done\n"); ++ ++out: ++ rpc_hf_mode_ext(info); ++ return retval; ++} ++ ++/* ++ * Copy memory to flash, returns: ++ * ERR_OK : OK ++ * ERR_ABORTED : Aborted by user ++ * ERR_PROTECTED : Protected sector ++ */ ++int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt) ++{ ++ union { ++ u8 b[4]; ++ u16 w[2]; ++ u32 d; ++ } data; ++ ulong offset, size; ++ int sector, idx, retval; ++ u8 last; ++ ++ retval = ERR_OK; ++ idx = 0; ++ ++ /* Handle unaligned start */ ++ if (addr & 0x1) { ++ addr--; ++ data.b[idx] = readb(addr); ++ idx++; ++ } ++ ++ /* Handle unaligned end */ ++ offset = addr + idx + cnt; ++ last = offset & 0x1 ? readb(offset) : 0xFF; ++ ++ sector = rpc_hf_flash_sector(info, addr); ++ offset = addr - info->start[sector]; ++ size = rpc_hf_flash_sector_size(info, sector) - offset; ++ offset += rpc_hf_flash_map(info, sector); ++ ++ while (cnt) { ++ if (ctrlc()) { ++ retval = ERR_ABORTED; ++ goto out; ++ } ++ ++ if (info->protect[sector]) { ++ retval = ERR_PROTECTED; ++ goto out; ++ } ++ ++ if (size > cnt) ++ size = cnt; ++ ++ putc('.'); ++ ++ cnt -= size; ++ while (size) { ++ rpc_hf_unlock(info, info->start[sector]); ++ rpc_hf_write_cmd(info, ++ info->start[sector] + 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, offset); ++ 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; ++ } ++ ++ rpc_wait_tend(info); ++ 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)); ++ ++ retval = rpc_hf_status(info, info->start[sector], ++ 1000000, 10); ++ if (retval) ++ goto out; ++ } ++ ++ sector++; ++ offset = rpc_hf_flash_map(info, sector); ++ size = rpc_hf_flash_sector_size(info, sector); ++ } ++ ++out: ++ rpc_hf_mode_ext(info); ++ return retval; ++} ++ ++/* Print flash information */ ++void flash_print_info(flash_info_t *info) ++{ ++ if (info->flash_id == FLASH_UNKNOWN) ++ return; ++ ++ printf("HyperFlash Id: %lx\n", info->flash_id); ++ printf("Base Address: %lx\n", info->start[0]); ++ printf("Size: %lu MiB\n", info->size >> 20); ++ printf("Sectors: %u\n", info->sector_count); ++} ++ ++flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; ++ ++unsigned long flash_init(void) ++{ ++ int i; ++ ++ for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i) { ++ flash_info[i].flash_id = FLASH_UNKNOWN; ++ flash_info[i].sector_count = -1; ++ flash_info[i].size = 0; ++ } ++ ++ return rpc_hf_get_size(CONFIG_SYS_RPC_FLASH_BASE, 0); ++} +-- +1.9.3 + diff --git a/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0023-board-renesas-salvator-x-Enable-RPC-clock.patch b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0023-board-renesas-salvator-x-Enable-RPC-clock.patch new file mode 100644 index 0000000..0186c20 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0023-board-renesas-salvator-x-Enable-RPC-clock.patch @@ -0,0 +1,37 @@ +From 23e0725daf7ab27d9fa85201b4097112d8c74e1e Mon Sep 17 00:00:00 2001 +From: Valentine Barshak <valentine.barshak@cogentembedded.com> +Date: Sat, 11 Jun 2016 00:50:06 +0300 +Subject: [PATCH] board: renesas: salvator-x: Enable RPC clock + +The RPC clock should have been enabled by the ARM trusted firmware. +Enable it here just in case. + +Signed-off-by: Valentine Barshak <valentine.barshak@cogentembedded.com> +--- + board/renesas/salvator-x/salvator-x.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/board/renesas/salvator-x/salvator-x.c b/board/renesas/salvator-x/salvator-x.c +index 491d378..803636e 100644 +--- a/board/renesas/salvator-x/salvator-x.c ++++ b/board/renesas/salvator-x/salvator-x.c +@@ -31,6 +31,7 @@ DECLARE_GLOBAL_DATA_PTR; + #define SCIF2_MSTP310 (1 << 10) + #define ETHERAVB_MSTP812 (1 << 12) + #define DVFS_MSTP926 (1 << 26) ++#define RPC_MSTP917 (1 << 17) + #define SD0_MSTP314 (1 << 14) + #define SD1_MSTP313 (1 << 13) + #define SD2_MSTP312 (1 << 12) /* either MMC0 */ +@@ -51,6 +52,8 @@ int board_early_init_f(void) + mstp_clrbits_le32(MSTPSR3, SMSTPCR3, SCIF2_MSTP310); + /* EHTERAVB */ + mstp_clrbits_le32(MSTPSR8, SMSTPCR8, ETHERAVB_MSTP812); ++ /* RPC */ ++ mstp_clrbits_le32(MSTPSR9, SMSTPCR9, RPC_MSTP917); + /* eMMC */ + mstp_clrbits_le32(MSTPSR3, SMSTPCR3, SD1_MSTP313 | SD2_MSTP312); + /* SDHI0, 3 */ +-- +1.9.3 + diff --git a/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0024-board-renesas-ulcb-Enable-RPC-clock.patch b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0024-board-renesas-ulcb-Enable-RPC-clock.patch new file mode 100644 index 0000000..1e2c155 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0024-board-renesas-ulcb-Enable-RPC-clock.patch @@ -0,0 +1,37 @@ +From 721d2a219485d106b577701e8643638a500bba30 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak <valentine.barshak@cogentembedded.com> +Date: Wed, 2 Nov 2016 21:31:24 +0300 +Subject: [PATCH] board: renesas: ulcb: Enable RPC clock + +The RPC clock should have been enabled by the ARM trusted firmware. +Enable it here just in case. + +Signed-off-by: Valentine Barshak <valentine.barshak@cogentembedded.com> +--- + board/renesas/ulcb/ulcb.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/board/renesas/ulcb/ulcb.c b/board/renesas/ulcb/ulcb.c +index 3939f97..2e9baac 100644 +--- a/board/renesas/ulcb/ulcb.c ++++ b/board/renesas/ulcb/ulcb.c +@@ -33,6 +33,7 @@ DECLARE_GLOBAL_DATA_PTR; + #define SCIF2_MSTP310 (1 << 10) + #define ETHERAVB_MSTP812 (1 << 12) + #define DVFS_MSTP926 (1 << 26) ++#define RPC_MSTP917 (1 << 17) + #define SD0_MSTP314 (1 << 14) + #define SD1_MSTP313 (1 << 13) + #define SD2_MSTP312 (1 << 12) +@@ -53,6 +54,8 @@ int board_early_init_f(void) + mstp_clrbits_le32(MSTPSR3, SMSTPCR3, SCIF2_MSTP310); + /* EHTERAVB */ + mstp_clrbits_le32(MSTPSR8, SMSTPCR8, ETHERAVB_MSTP812); ++ /* RPC */ ++ mstp_clrbits_le32(MSTPSR9, SMSTPCR9, RPC_MSTP917); + /* eMMC */ + mstp_clrbits_le32(MSTPSR3, SMSTPCR3, SD1_MSTP313 | SD2_MSTP312); + /* SDHI0 */ +-- +1.9.3 + diff --git a/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0025-configs-r8a7795_salvator-x-Enable-RPC-HyperFlash-sup.patch b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0025-configs-r8a7795_salvator-x-Enable-RPC-HyperFlash-sup.patch new file mode 100644 index 0000000..55f141e --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0025-configs-r8a7795_salvator-x-Enable-RPC-HyperFlash-sup.patch @@ -0,0 +1,35 @@ +From 3b35b4c283d4dc95cf92d4a5e15f1a048eb4013f Mon Sep 17 00:00:00 2001 +From: Valentine Barshak <valentine.barshak@cogentembedded.com> +Date: Mon, 4 Apr 2016 18:41:55 +0300 +Subject: [PATCH] configs: r8a7795_salvator-x: Enable RPC HyperFlash support + +This enables flash commands along with the RPC HyperFlash support. + +Signed-off-by: Valentine Barshak <valentine.barshak@cogentembedded.com> +--- + include/configs/r8a7795_salvator-x.h | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/include/configs/r8a7795_salvator-x.h b/include/configs/r8a7795_salvator-x.h +index d5c4c93..db5eae5 100644 +--- a/include/configs/r8a7795_salvator-x.h ++++ b/include/configs/r8a7795_salvator-x.h +@@ -28,10 +28,13 @@ + + /* [A] Hyper Flash */ + /* use to RPC(SPI Multi I/O Bus Controller) */ ++#define CONFIG_RPC_HYPERFLASH + +- /* underconstruction */ ++#define CONFIG_SYS_FLASH_BASE CONFIG_SYS_RPC_FLASH_BASE ++#define CONFIG_SYS_MAX_FLASH_BANKS 1 ++#define CONFIG_SYS_MAX_FLASH_SECT 256 + +-#define CONFIG_SYS_NO_FLASH ++#define CONFIG_CMD_FLASH + + /* Ethernet RAVB */ + #define CONFIG_RAVB +-- +1.9.3 + diff --git a/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0026-configs-r8a7796_salvator-x-Enable-RPC-HyperFlash-sup.patch b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0026-configs-r8a7796_salvator-x-Enable-RPC-HyperFlash-sup.patch new file mode 100644 index 0000000..cbc8ac2 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0026-configs-r8a7796_salvator-x-Enable-RPC-HyperFlash-sup.patch @@ -0,0 +1,35 @@ +From 573a190264dabefd8899c681f62d3eb3ec94a78f Mon Sep 17 00:00:00 2001 +From: Valentine Barshak <valentine.barshak@cogentembedded.com> +Date: Wed, 2 Nov 2016 22:17:32 +0300 +Subject: [PATCH] configs: r8a7796_salvator-x: Enable RPC HyperFlash support + +This enables flash commands along with the RPC HyperFlash support. + +Signed-off-by: Valentine Barshak <valentine.barshak@cogentembedded.com> +--- + include/configs/r8a7796_salvator-x.h | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/include/configs/r8a7796_salvator-x.h b/include/configs/r8a7796_salvator-x.h +index 2926b95..6d6a2ef 100644 +--- a/include/configs/r8a7796_salvator-x.h ++++ b/include/configs/r8a7796_salvator-x.h +@@ -28,10 +28,13 @@ + + /* [A] Hyper Flash */ + /* use to RPC(SPI Multi I/O Bus Controller) */ ++#define CONFIG_RPC_HYPERFLASH + +- /* underconstruction */ ++#define CONFIG_SYS_FLASH_BASE CONFIG_SYS_RPC_FLASH_BASE ++#define CONFIG_SYS_MAX_FLASH_BANKS 1 ++#define CONFIG_SYS_MAX_FLASH_SECT 256 + +-#define CONFIG_SYS_NO_FLASH ++#define CONFIG_CMD_FLASH + + /* Ethernet RAVB */ + #define CONFIG_RAVB +-- +1.9.3 + diff --git a/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0027-configs-h3ulcb-Enable-RPC-HyperFlash-support.patch b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0027-configs-h3ulcb-Enable-RPC-HyperFlash-support.patch new file mode 100644 index 0000000..ecc5768 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0027-configs-h3ulcb-Enable-RPC-HyperFlash-support.patch @@ -0,0 +1,36 @@ +From be046fe3844db04b04a0c1051375ce7bde7c1dc7 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak <valentine.barshak@cogentembedded.com> +Date: Wed, 2 Nov 2016 21:34:50 +0300 +Subject: [PATCH] configs: h3ulcb: Enable RPC HyperFlash support + +This enables flash commands along with the RPC HyperFlash support. + +Signed-off-by: Valentine Barshak <valentine.barshak@cogentembedded.com> +--- + include/configs/h3ulcb.h | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/include/configs/h3ulcb.h b/include/configs/h3ulcb.h +index 73e856d..edda5e8 100644 +--- a/include/configs/h3ulcb.h ++++ b/include/configs/h3ulcb.h +@@ -27,7 +27,15 @@ + #define CONFIG_CONS_SCIF2 + #define CONFIG_SH_SCIF_CLK_FREQ CONFIG_S3D4_CLK_FREQ + +-#define CONFIG_SYS_NO_FLASH ++/* [A] Hyper Flash */ ++/* use to RPC(SPI Multi I/O Bus Controller) */ ++#define CONFIG_RPC_HYPERFLASH ++ ++#define CONFIG_SYS_FLASH_BASE CONFIG_SYS_RPC_FLASH_BASE ++#define CONFIG_SYS_MAX_FLASH_BANKS 1 ++#define CONFIG_SYS_MAX_FLASH_SECT 256 ++ ++#define CONFIG_CMD_FLASH + + /* Ethernet RAVB */ + #define CONFIG_RAVB +-- +1.9.3 + diff --git a/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0028-configs-m3ulcb-Enable-RPC-HyperFlash-support.patch b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0028-configs-m3ulcb-Enable-RPC-HyperFlash-support.patch new file mode 100644 index 0000000..9903433 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0028-configs-m3ulcb-Enable-RPC-HyperFlash-support.patch @@ -0,0 +1,36 @@ +From 592ada9568e8cd9ebbee8f3a609435471e5357d6 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak <valentine.barshak@cogentembedded.com> +Date: Wed, 2 Nov 2016 21:33:43 +0300 +Subject: [PATCH] configs: m3ulcb: Enable RPC HyperFlash support + +This enables flash commands along with the RPC HyperFlash support. + +Signed-off-by: Valentine Barshak <valentine.barshak@cogentembedded.com> +--- + include/configs/m3ulcb.h | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/include/configs/m3ulcb.h b/include/configs/m3ulcb.h +index a242079..e3fd75b 100644 +--- a/include/configs/m3ulcb.h ++++ b/include/configs/m3ulcb.h +@@ -27,7 +27,15 @@ + #define CONFIG_CONS_SCIF2 + #define CONFIG_SH_SCIF_CLK_FREQ CONFIG_S3D4_CLK_FREQ + +-#define CONFIG_SYS_NO_FLASH ++/* [A] Hyper Flash */ ++/* use to RPC(SPI Multi I/O Bus Controller) */ ++#define CONFIG_RPC_HYPERFLASH ++ ++#define CONFIG_SYS_FLASH_BASE CONFIG_SYS_RPC_FLASH_BASE ++#define CONFIG_SYS_MAX_FLASH_BANKS 1 ++#define CONFIG_SYS_MAX_FLASH_SECT 256 ++ ++#define CONFIG_CMD_FLASH + + /* MEMORY */ + /* M3ULCB has 2 banks each 1GB */ +-- +1.9.3 + diff --git a/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0041-board-renesas-ulcb-console-on-scif1.patch b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0041-board-renesas-ulcb-console-on-scif1.patch new file mode 100644 index 0000000..479f23f --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0041-board-renesas-ulcb-console-on-scif1.patch @@ -0,0 +1,28 @@ +From 4afdb59d00b3cf8c92006b929bd9e48f4f87d6ce Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Thu, 19 May 2016 08:32:56 +0300 +Subject: [PATCH] uboot: H3ULCB console on scif1 + +Set console on SCIF1 port for H3ULCB. +This is only for H3ULCB.HAD + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + include/configs/h3ulcb.h | 4 ++-- + 1 file changed, 1 insertions(+), 1 deletions(-) + +diff --git a/include/configs/h3ulcb.h b/include/configs/h3ulcb.h +index b9be845..3da2e5a 100644 +--- a/include/configs/h3ulcb.h ++++ b/include/configs/h3ulcb.h +@@ -23,6 +23,6 @@ + + /* SCIF */ + #define CONFIG_SCIF_CONSOLE +-#define CONFIG_CONS_SCIF2 ++#define CONFIG_CONS_SCIF1 + #define CONFIG_SH_SCIF_CLK_FREQ CONFIG_S3D4_CLK_FREQ + +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0042-board-renesas-ulcb-set-all-RAVB-pins-strengh-to-maximum.patch b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0042-board-renesas-ulcb-set-all-RAVB-pins-strengh-to-maximum.patch new file mode 100644 index 0000000..638fa7c --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0042-board-renesas-ulcb-set-all-RAVB-pins-strengh-to-maximum.patch @@ -0,0 +1,55 @@ +From b247dea7b49d7e66e1848da71e28ff5fe9acf5e1 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Thu, 16 Jun 2016 11:41:43 +0300 +Subject: [PATCH] board: renesas: ulcb: set all RAVB pins strengh to maximum + +This is only for H3ULCB.HAD with custom TTTeck ethernet switch +parameters + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + board/renesas/ulcb/ulcb.c | 21 +++++++++++++++++++++ + 2 files changed, 21 insertions(+), 5 deletions(-) + +diff --git a/board/renesas/ulcb/ulcb.c b/board/renesas/ulcb/ulcb.c +index 5652014..f77f946 100644 +--- a/board/renesas/ulcb/ulcb.c ++++ b/board/renesas/ulcb/ulcb.c +@@ -72,6 +72,22 @@ int board_early_init_f(void) + + DECLARE_GLOBAL_DATA_PTR; + ++#define PFC_PMMR 0xE6060000 ++#define PFC_DRVCTRL1 0xE6060304 ++#define PFC_DRVCTRL2 0xE6060308 ++#define PFC_DRVCTRL3 0xE606030C ++ ++static void write_drvctrl(u32 value, u32 modify_bit, void *reg) ++{ ++ u32 val; ++ ++ val = readl(reg); ++ val &= ~modify_bit; ++ val |= value; ++ writel(~val, PFC_PMMR); ++ writel(val, reg); ++} ++ + int board_init(void) + { + u32 val; +@@ -86,6 +102,11 @@ int board_init(void) + val = readl(PFC_PUEN6) | PUEN_USB1_OVC | PUEN_USB1_PWEN; + writel(val, PFC_PUEN6); + ++ /* EtherAVB pin strength */ ++ write_drvctrl(0x00000007, 0x00000007, (void *)PFC_DRVCTRL1); ++ write_drvctrl(0x77777777, 0x77777777, (void *)PFC_DRVCTRL2); ++ write_drvctrl(0x77700000, 0x77700000, (void *)PFC_DRVCTRL3); ++ + #ifdef CONFIG_RAVB + #if defined(CONFIG_R8A7795) + if (rcar_is_legacy()) { +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0043-board-renesas-ulcb-support-fixed-PHY.patch b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0043-board-renesas-ulcb-support-fixed-PHY.patch new file mode 100644 index 0000000..b646d99 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0043-board-renesas-ulcb-support-fixed-PHY.patch @@ -0,0 +1,54 @@ +From 8f65b4710c1f51d01032db201543d0a8269a715f Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Fri, 20 May 2016 01:18:44 +0300 +Subject: [PATCH] board: renesas/ ulcb: support fixed-PHY + +Add support for fixed-PHY on ULCB board + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + board/renesas/ulcb/ulcb.c | 5 +++++ + include/configs/h3ulcb.h | 3 +++ + 2 files changed, 8 insertions(+), 0 deletion(-) + +diff --git a/board/renesas/ulcb/ulcb.c b/board/renesas/ulcb/ulcb.c +index 32a63c9..dcca4f8 100644 +--- a/board/renesas/ulcb/ulcb.c ++++ b/board/renesas/ulcb/ulcb.c +@@ -26,6 +26,7 @@ + #include <asm/arch/sh_sdhi.h> + #include <i2c.h> + #include <mmc.h> ++#include <phy.h> + + DECLARE_GLOBAL_DATA_PTR; + +@@ -193,6 +193,10 @@ int board_eth_init(bd_t *bis) + /* ULCB has KSZ9031RNX */ + int board_phy_config(struct phy_device *phydev) + { ++#ifdef CONFIG_PHY_FIXED ++ if (!strncmp(phydev->drv->name, "fixed-PHY", 9) && phydev->drv->config) ++ return phydev->drv->config(phydev); ++#endif + return 0; + } + +diff --git a/include/configs/h3ulcb.h b/include/configs/h3ulcb.h +index 8582b64..b9be845 100644 +--- a/include/configs/h3ulcb.h ++++ b/include/configs/h3ulcb.h +@@ -40,7 +40,9 @@ + #define CONFIG_RAVB_PHY_MODE PHY_INTERFACE_MODE_RGMII_ID + #define CONFIG_NET_MULTI + #define CONFIG_PHYLIB +-#define CONFIG_PHY_MICREL ++#define CONFIG_PHY_FIXED ++#define CONFIG_PHY_FIXED_SPEED SPEED_1000 ++#define CONFIG_PHY_FIXED_DUPLEX DUPLEX_FULL + #define CONFIG_BITBANGMII + #define CONFIG_BITBANGMII_MULTI + #define CONFIG_SH_ETHER_BITBANG +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot_2015.04.bbappend b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot_2015.04.bbappend new file mode 100644 index 0000000..02eafb8 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot_2015.04.bbappend @@ -0,0 +1,27 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" + +SRC_URI_append = " \ + file://0001-net-phy-support-fixed-PHY.patch \ + ${@bb.utils.contains('MACHINE_FEATURES', 'h3ulcb-had', ' file://0002-net-ravb-remove-APSR-quirk.patch', '', d)} \ + file://0003-net-ravb-fix-unsafe-phy-access.patch \ + file://0004-configs-rcar-gen3-add-CMD_GPIO.patch \ + file://0005-common-cmd_source.c-Fix-the-source-command-failure-u.patch \ + file://0006-configs-rcar-gen3-common-Enable-U-Boot-scripts.patch \ + file://0007-configs-rcar-gen3-common-Enable-echo-command.patch \ + file://0008-configs-rcar-gen3-common-Enable-setexpr-command.patch \ + file://0009-configs-rcar-gen3-common-Enable-askenv-command.patch \ + file://0010-configs-rcar-gen3-common-Enable-hush-parser.patch \ + file://0011-configs-rcar-gen3-common-Enable-GPT-support.patch \ + file://0012-board-ulcb-Fix-reset-command-clock-setting.patch \ + file://0013-mtd-spi-QSPI-flash-support.patch \ + file://0014-arm-renesas-Add-Renesas-R8A7797-SoC-support.patch \ + file://0015-board-renesas-Add-V3M-Eagle-board.patch \ + file://0016-tools-fix-build-fail.patch \ + file://0021-ARM-rcar_gen3-Add-RPC-flash-definitions.patch \ + file://0022-mtd-Add-RPC-HyperFlash-support.patch \ + file://0023-board-renesas-salvator-x-Enable-RPC-clock.patch \ + file://0024-board-renesas-ulcb-Enable-RPC-clock.patch \ + ${@bb.utils.contains('MACHINE_FEATURES', 'h3ulcb-had', ' file://0041-board-renesas-ulcb-console-on-scif1.patch', '', d)} \ + ${@bb.utils.contains('MACHINE_FEATURES', 'h3ulcb-had', ' file://0042-board-renesas-ulcb-set-all-RAVB-pins-strengh-to-maximum.patch', '', d)} \ + ${@bb.utils.contains('MACHINE_FEATURES', 'h3ulcb-had', ' file://0043-board-renesas-ulcb-support-fixed-PHY.patch', '', d)} \ +" diff --git a/meta-rcar-gen3-adas/recipes-bsp/v4l2-fw/files/v4l2-fw.tar.gz b/meta-rcar-gen3-adas/recipes-bsp/v4l2-fw/files/v4l2-fw.tar.gz Binary files differnew file mode 100644 index 0000000..fe7c713 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/v4l2-fw/files/v4l2-fw.tar.gz diff --git a/meta-rcar-gen3-adas/recipes-bsp/v4l2-fw/v4l2-fw_1.0.bb b/meta-rcar-gen3-adas/recipes-bsp/v4l2-fw/v4l2-fw_1.0.bb new file mode 100644 index 0000000..0503ec0 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/v4l2-fw/v4l2-fw_1.0.bb @@ -0,0 +1,39 @@ +SUMMARY = "OV10640/OV490 SPI flash firmware update tool" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://COPYING;md5=eb766567485731157b3c21013c3ce4b8" + +S = "${WORKDIR}/v4l2-fw" + +SRC_URI = " \ + file://v4l2-fw.tar.gz \ +" + +do_compile() { + cd ${S} + make all || die +} + +do_install() { + install -d ${D}${bindir} + install -m 755 ${S}/v4l2-fw ${D}${bindir} + + install -d ${D}/usr/share/factory/ + install -m 644 ${S}/OV10640_OV490_combine_general_v491_20160105_common_withSPIHeader_1280x1080@30_96Mhz.bin ${D}/usr/share/factory/ + install -m 644 ${S}/OV10640_OV490_combine_general_v491_20160105_common_withSPIHeader_1280x800@30_96Mhz.bin ${D}/usr/share/factory/ + install -m 644 ${S}/OV10640_OV490_combine_general_v491_20160105_common_withSPIHeader_1280x966@30_96Mhz.bin ${D}/usr/share/factory/ + install -m 644 ${S}/OV10640_OV490_combine_general_v491_20160105_common_withSPIHeader_640x480@30_96Mhz.bin ${D}/usr/share/factory/ + install -m 644 ${S}/OV10640_OV490_combine_general_v491_20160105_common_withSPIHeader_640x480@60_96MHz.bin ${D}/usr/share/factory/ + install -m 755 ${S}/ov10640_ov490_flash_0-3.sh ${D}/usr/share/factory/ + install -m 755 ${S}/ov10640_ov490_flash_4-7.sh ${D}/usr/share/factory/ +} + +FILES_${PN} = " \ + ${bindir}/v4l2-fw \ + /usr/share/factory/OV10640_OV490_combine_general_v491_20160105_common_withSPIHeader_1280x1080@30_96Mhz.bin \ + /usr/share/factory/OV10640_OV490_combine_general_v491_20160105_common_withSPIHeader_1280x800@30_96Mhz.bin \ + /usr/share/factory/OV10640_OV490_combine_general_v491_20160105_common_withSPIHeader_1280x966@30_96Mhz.bin \ + /usr/share/factory/OV10640_OV490_combine_general_v491_20160105_common_withSPIHeader_640x480@30_96Mhz.bin \ + /usr/share/factory/OV10640_OV490_combine_general_v491_20160105_common_withSPIHeader_640x480@60_96MHz.bin \ + /usr/share/factory/ov10640_ov490_flash_0-3.sh \ + /usr/share/factory/ov10640_ov490_flash_4-7.sh \ +" diff --git a/meta-rcar-gen3-adas/recipes-graphics/libpng/libpng_%.bbappend b/meta-rcar-gen3-adas/recipes-graphics/libpng/libpng_%.bbappend new file mode 100644 index 0000000..252fec3 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-graphics/libpng/libpng_%.bbappend @@ -0,0 +1,2 @@ +# ...use neon acceleration +EXTRA_OECONF_append_aarch64 = " --enable-arm-neon=on" diff --git a/meta-rcar-gen3-adas/recipes-graphics/wayland/weston-1.11.0/0001-Allow-to-boot-without-input-device.patch b/meta-rcar-gen3-adas/recipes-graphics/wayland/weston-1.11.0/0001-Allow-to-boot-without-input-device.patch new file mode 100644 index 0000000..ff7dd0c --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-graphics/wayland/weston-1.11.0/0001-Allow-to-boot-without-input-device.patch @@ -0,0 +1,24 @@ +From d04c556bc8eac439cc87c7cdf9b4446d4a9cecaa Mon Sep 17 00:00:00 2001 +From: Grigory Kletsko <grigory.kletsko@cogentembedded.com> +Date: Fri, 17 Feb 2017 03:06:27 +0300 +Subject: [PATCH] Allow to boot without input device + +--- + src/libinput-seat.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/src/libinput-seat.c b/src/libinput-seat.c +index c9f9ed2..20fcaa6 100644 +--- a/src/libinput-seat.c ++++ b/src/libinput-seat.c +@@ -258,7 +258,6 @@ udev_input_enable(struct udev_input *input) + "\t- seats misconfigured " + "(Weston backend option 'seat', " + "udev device property ID_SEAT)\n"); +- return -1; + } + + return 0; +-- +2.7.4 + diff --git a/meta-rcar-gen3-adas/recipes-graphics/wayland/weston-init.bbappend b/meta-rcar-gen3-adas/recipes-graphics/wayland/weston-init.bbappend new file mode 100644 index 0000000..708990e --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-graphics/wayland/weston-init.bbappend @@ -0,0 +1,21 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" + +SRC_URI_append = " \ + file://weston.service \ +" + +do_install_append() { + if [ "X${USE_GLES}" = "X1" ]; then + sed -e "/RequiresMountsFor=\/run/a Wants=rc.pvr.service" \ + -e "/RequiresMountsFor=\/run/a After=rc.pvr.service" \ + -e "s/\$OPTARGS/--idle-time=0 \$OPTARGS/" \ + -i ${D}/${systemd_system_unitdir}/weston.service + fi + + if [ "X${USE_MULTIMEDIA}" = "X1" ]; then + if [ "X${USE_V4L2_RENDERER}" = "X1" ]; then + sed -e "s/\$OPTARGS/--use-v4l2 \$OPTARGS/" \ + -i ${D}/${systemd_system_unitdir}/weston.service + fi + fi +} diff --git a/meta-rcar-gen3-adas/recipes-graphics/wayland/weston-init/weston.service b/meta-rcar-gen3-adas/recipes-graphics/wayland/weston-init/weston.service new file mode 100644 index 0000000..af27f33 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-graphics/wayland/weston-init/weston.service @@ -0,0 +1,12 @@ +[Unit] +Description=Weston Wayland compositor +After=dbus.service rc.pvr.service + +[Service] +ExecStart=/usr/bin/weston-launch -u root -- $OPTARGS +ExecStop=/usr/bin/killall -s KILL weston +Type=simple +Restart=always + +[Install] +WantedBy=multi-user.target diff --git a/meta-rcar-gen3-adas/recipes-graphics/wayland/weston_1.11.0.bbappend b/meta-rcar-gen3-adas/recipes-graphics/wayland/weston_1.11.0.bbappend new file mode 100644 index 0000000..1a7bccf --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-graphics/wayland/weston_1.11.0.bbappend @@ -0,0 +1,5 @@ +FILESEXTRAPATHS_prepend := '${THISDIR}/${PN}-${PV}:' + +SRC_URI_append = " \ + file://0001-Allow-to-boot-without-input-device.patch \ +" diff --git a/meta-rcar-gen3-adas/recipes-kernel/kernel-module-gles/kernel-module-gles.bbappend b/meta-rcar-gen3-adas/recipes-kernel/kernel-module-gles/kernel-module-gles.bbappend new file mode 100644 index 0000000..d3b3e6f --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/kernel-module-gles/kernel-module-gles.bbappend @@ -0,0 +1,5 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" + +SRC_URI_append_r8a7795 = " \ + file://clockfreq-fix-out-of-bounds-access.patch \ +" diff --git a/meta-rcar-gen3-adas/recipes-kernel/kernel-module-gles/kernel-module-gles/clockfreq-fix-out-of-bounds-access.patch b/meta-rcar-gen3-adas/recipes-kernel/kernel-module-gles/kernel-module-gles/clockfreq-fix-out-of-bounds-access.patch new file mode 100644 index 0000000..5ac3e12 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/kernel-module-gles/kernel-module-gles/clockfreq-fix-out-of-bounds-access.patch @@ -0,0 +1,23 @@ +diff -pruN '--exclude=*~' '--exclude=binary*' rogue_km/build/linux/r8a7795_linux/Makefile rogue_km.new/build/linux/r8a7795_linux/Makefile +--- rogue_km/build/linux/r8a7795_linux/Makefile 2016-08-03 23:17:38.000000000 -0700 ++++ rogue_km.new/build/linux/r8a7795_linux/Makefile 2016-11-01 07:02:27.887988779 -0700 +@@ -91,6 +91,7 @@ endif + SYSROOT := $(SDKTARGETSYSROOT) + + SUPPORT_WRAPEXTMEM ?= 1 ++SUPPORT_PVRTL := 1 + + SUPPORT_EXTENSION_REL ?= 1 + ifeq ($(SUPPORT_EXTENSION_REL),1) +diff -pruN '--exclude=*~' '--exclude=binary*' rogue_km/services/server/devices/rgx/rgxdevice.h rogue_km.new/services/server/devices/rgx/rgxdevice.h +--- rogue_km/services/server/devices/rgx/rgxdevice.h 2016-08-03 23:14:20.000000000 -0700 ++++ rogue_km.new/services/server/devices/rgx/rgxdevice.h 2016-11-22 02:23:56.136282383 -0800 +@@ -81,7 +81,7 @@ typedef struct { + *****************************************************************************/ + + #define RGX_GPU_DVFS_TABLE_SIZE 100 /* DVFS Table size */ +-#define RGX_GPU_DVFS_GET_INDEX(clockfreq) ((clockfreq) / 10000000) /* Assuming different GPU clocks are separated by at least 10MHz ++#define RGX_GPU_DVFS_GET_INDEX(clockfreq) (((clockfreq) / 10000000) % RGX_GPU_DVFS_TABLE_SIZE) /* Assuming different GPU clocks are separated by at least 10MHz + * WARNING: this macro must be used only with nominal values of + * the GPU clock speed (the ones provided by the customer code) */ + #define RGX_GPU_DVFS_FIRST_CALIBRATION_TIME_US 25000 /* Time required to calibrate a clock frequency the first time */ diff --git a/meta-rcar-gen3-adas/recipes-kernel/kernel-module-mmngr/files/0001-free-dma-buf-on-error.patch b/meta-rcar-gen3-adas/recipes-kernel/kernel-module-mmngr/files/0001-free-dma-buf-on-error.patch new file mode 100644 index 0000000..e41f141 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/kernel-module-mmngr/files/0001-free-dma-buf-on-error.patch @@ -0,0 +1,23 @@ +From 9362c86c52dcd1577e07f01604e1a7b363c504ca Mon Sep 17 00:00:00 2001 +From: Roman Meshkevich <roman.meshkevich@cogentembedded.com> +Date: Wed, 22 Feb 2017 01:27:51 +0300 +Subject: [PATCH] unref dma_fb descriptor + +--- + mmngr_drv/mmngrbuf/mmngrbuf-module/files/mmngrbuf/drv/mmngr_buf_drv.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/mmngr_drv/mmngrbuf/mmngrbuf-module/files/mmngrbuf/drv/mmngr_buf_drv.c b/mmngr_drv/mmngrbuf/mmngrbuf-module/files/mmngrbuf/drv/mmngr_buf_drv.c +index 2e260cb..6a4d0a6 100644 +--- a/mmngr_drv/mmngrbuf/mmngrbuf-module/files/mmngrbuf/drv/mmngr_buf_drv.c ++++ b/mmngr_drv/mmngrbuf/mmngrbuf-module/files/mmngrbuf/drv/mmngr_buf_drv.c +@@ -99,6 +99,7 @@ static int close(struct inode *inode, struct file *file) + if (priv->attach) { + pr_err("detach@close\n"); + dma_buf_detach(priv->dma_buf, priv->attach); ++ dma_buf_put(priv->dma_buf); + } + + kfree(priv); +-- +2.7.4
\ No newline at end of file diff --git a/meta-rcar-gen3-adas/recipes-kernel/kernel-module-mmngr/kernel-module-mmngrbuf.bbappend b/meta-rcar-gen3-adas/recipes-kernel/kernel-module-mmngr/kernel-module-mmngrbuf.bbappend new file mode 100644 index 0000000..5120cb1 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/kernel-module-mmngr/kernel-module-mmngrbuf.bbappend @@ -0,0 +1,3 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +SRC_URI_append = " file://0001-free-dma-buf-on-error.patch" diff --git a/meta-rcar-gen3-adas/recipes-kernel/kernel-module-uvcs/kernel-module-uvcs-drv.bbappend b/meta-rcar-gen3-adas/recipes-kernel/kernel-module-uvcs/kernel-module-uvcs-drv.bbappend new file mode 100644 index 0000000..f145074 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/kernel-module-uvcs/kernel-module-uvcs-drv.bbappend @@ -0,0 +1 @@ +KERNEL_MODULE_AUTOLOAD = "uvcs_drv" diff --git a/meta-rcar-gen3-adas/recipes-kernel/kernel-module-vspmif/kernel-module-vspmif.bbappend b/meta-rcar-gen3-adas/recipes-kernel/kernel-module-vspmif/kernel-module-vspmif.bbappend new file mode 100644 index 0000000..098e1b0 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/kernel-module-vspmif/kernel-module-vspmif.bbappend @@ -0,0 +1 @@ +KERNEL_MODULE_AUTOLOAD = "vspm_if" diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0001-spi-sh-msiof-fixes.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0001-spi-sh-msiof-fixes.patch new file mode 100644 index 0000000..d8806ba --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0001-spi-sh-msiof-fixes.patch @@ -0,0 +1,33 @@ +From 32db8cc989d7dfdf0315d286b06234e008e56d7c Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Sun, 15 May 2016 21:53:13 +0300 +Subject: [PATCH] spi: sh-msiof: fixes + +speed up polling of CTR register + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + drivers/spi/spi-sh-msiof.c | 30 ++++++++++++++++++++---------- + 1 file changed, 20 insertions(+), 10 deletions(-) + +diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c +index d096f5a..6817304 100644 +--- a/drivers/spi/spi-sh-msiof.c ++++ b/drivers/spi/spi-sh-msiof.c +@@ -228,11 +228,11 @@ static int sh_msiof_modify_ctr_wait(struct sh_msiof_spi_priv *p, + data |= set; + sh_msiof_write(p, CTR, data); + +- for (k = 100; k > 0; k--) { ++ for (k = 1000; k > 0; k--) { + if ((sh_msiof_read(p, CTR) & mask) == set) + break; + +- udelay(10); ++ udelay(1); + } + + return k > 0 ? 0 : -ETIMEDOUT; +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0002-spi-spidev-add-spi-gpio-into-spidev.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0002-spi-spidev-add-spi-gpio-into-spidev.patch new file mode 100644 index 0000000..2aec664 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0002-spi-spidev-add-spi-gpio-into-spidev.patch @@ -0,0 +1,27 @@ +From 4f85719492ae77bc166f90a046e97bb169396062 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Sun, 15 May 2016 21:47:02 +0300 +Subject: [PATCH] spi: spidev: add spi-gpio into spidev + +Add spi-gpio to spidev + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + drivers/spi/spidev.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c +index b016a5a..bcee148 100644 +--- a/drivers/spi/spidev.c ++++ b/drivers/spi/spidev.c +@@ -697,6 +697,7 @@ static const struct of_device_id spidev_dt_ids[] = { + { .compatible = "rohm,dh2228fv" }, + { .compatible = "lineartechnology,ltc2488" }, + { .compatible = "renesas,sh-msiof" }, ++ { .compatible = "spi-gpio" }, + {}, + }; + MODULE_DEVICE_TABLE(of, spidev_dt_ids); +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0003-spi-spi-gpio-fix-CPOL-mode.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0003-spi-spi-gpio-fix-CPOL-mode.patch new file mode 100644 index 0000000..e802f68 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0003-spi-spi-gpio-fix-CPOL-mode.patch @@ -0,0 +1,42 @@ +From db37427756bc9e42723f58067a3f387a2861fbbb Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Sun, 29 May 2016 23:18:49 +0300 +Subject: [PATCH] spi: spi-gpio: fix CPOL mode + +This fixes the SPI SPOL mode, since the cs_gpios is already used +in generic code spi.c + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + drivers/spi/spi-gpio.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c +index 1c34c93..428417d 100644 +--- a/drivers/spi/spi-gpio.c ++++ b/drivers/spi/spi-gpio.c +@@ -218,10 +218,6 @@ static void spi_gpio_chipselect(struct spi_device *spi, int is_active) + struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi); + unsigned long cs = spi_gpio->cs_gpios[spi->chip_select]; + +- /* set initial clock polarity */ +- if (is_active) +- setsck(spi, spi->mode & SPI_CPOL); +- + if (cs != SPI_GPIO_NO_CHIPSELECT) { + /* SPI is normally active-low */ + gpio_set_value_cansleep(cs, (spi->mode & SPI_CS_HIGH) ? is_active : !is_active); +@@ -257,6 +253,10 @@ static int spi_gpio_setup(struct spi_device *spi) + !(spi->mode & SPI_CS_HIGH)); + } + } ++ ++ /* set initial clock polarity */ ++ setsck(spi, spi->mode & SPI_CPOL); ++ + if (!status) { + /* in case it was initialized from static board data */ + spi_gpio->cs_gpios[spi->chip_select] = cs; +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0004-xhci-rcar-add-firmware-for-R-Car-H2-M2-USB-3.0-host-.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0004-xhci-rcar-add-firmware-for-R-Car-H2-M2-USB-3.0-host-.patch new file mode 100644 index 0000000..8487d5f --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0004-xhci-rcar-add-firmware-for-R-Car-H2-M2-USB-3.0-host-.patch @@ -0,0 +1,205 @@ +From 63aa7951b66cc771b23a002748a20a5555cf847f Mon Sep 17 00:00:00 2001 +From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> +Date: Thu, 10 Jul 2014 10:41:55 +0900 +Subject: [PATCH] xhci-rcar: add firmware for R-Car H2/M2 USB 3.0 host + controller + +This patch adds a firmware for the USB 3.0 host controller of Renesas +R-Car H2 and M2 SoCs. + +Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> +Signed-off-by: Kyle McMartin <kyle@kernel.org> +--- + firmware/LICENCE.r8a779x_usb3 | 26 ++++++++++++++++++++++++++ + firmware/WHENCE | 8 ++++++++ + firmware/r8a779x_usb3_v1.dlmem | Bin 0 -> 9452 bytes + 3 files changed, 34 insertions(+) + create mode 100644 firmware/LICENCE.r8a779x_usb3 + create mode 100644 firmware/r8a779x_usb3_v1.dlmem + +diff --git a/firmware/LICENCE.r8a779x_usb3 b/firmware/LICENCE.r8a779x_usb3 +new file mode 100644 +index 0000000..e2afcc9 +--- /dev/null ++++ b/firmware/LICENCE.r8a779x_usb3 +@@ -0,0 +1,26 @@ ++Copyright (c) 2014, Renesas Electronics Corporation ++All rights reserved. ++ ++Redistribution and use in binary form, without modification, are permitted ++provided that the following conditions are met: ++ ++1. Redistribution in binary form must reproduce the above copyright notice, ++ this list of conditions and the following disclaimer in the documentation ++ and/or other materials provided with the distribution. ++2. The name of Renesas Electronics Corporation may not be used to endorse or ++ promote products derived from this software without specific prior written ++ permission. ++3. Reverse engineering, decompilation, or disassembly of this software is ++ not permitted. ++ ++THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS ELECTRONICS CORPORATION DISCLAIMS ++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND ++NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL RENESAS ELECTRONICS ++CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, ++OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++POSSIBILITY OF SUCH DAMAGE. +diff --git a/firmware/WHENCE b/firmware/WHENCE +index 8388f02..4b45ad1 100644 +--- a/firmware/WHENCE ++++ b/firmware/WHENCE +@@ -852,3 +852,11 @@ Licence: + Found in hex form in kernel source. + + -------------------------------------------------------------------------- ++ ++Driver: xhci-rcar -- Renesas R-Car H2/M2 USB 3.0 host controller driver ++ ++File: r8a779x_usb3_v1.dlmem ++ ++Licence: Redistributable. See LICENCE.r8a779x_usb3 for details. ++ ++-------------------------------------------------------------------------- +diff --git a/firmware/r8a779x_usb3_v1.dlmem b/firmware/r8a779x_usb3_v1.dlmem +new file mode 100644 +index 0000000000000000000000000000000000000000..d094157084173b3c741d3d3d214bdd83f2c48d6b +GIT binary patch +literal 9452 +zcmai44O~=J+J9z-JD0DEGZ$tq5~HKdn7P^_tEi-cgshqM3Mwd?%7<iTW^K8>tsf%} +zN@k|M>6%}e4VGlBlDK6#(FA717NCr1io*zgj4mLntf_S0|G5L=zU}*4e!u@c=bn4c +zbDrlp&w0*so}qZ!Zx2LJEwR7LL>5+Z=2=lWvWjeSA9@gFa?}dyZt<$RTWow5S+!gH +zsEK=o5*e%=WE-U2aF*zWX@j&8=ZFF%(ftS1eFma=8Fd9NV;iZp9@%HINY<t|#nYVG +zNV;6qEt0|gu6WR7ZMCjW&=!)KRI$s5Vx96PjVIO1v04*qM>tBmY4G>@1ic8o*w~%o +z=bTesCzMMOZp$voePRTWQ?8z<N=wwPpjQqL)o$xWl%UNGBU(ZEjQ6*C+bk_anwSLb +z4N!WKtZNLm0orOdcYK02P^G5DWNPC$6*p#iAZeB*8p)<N2!<eorGq+yxW1ysVEv=X +z_TUH=^$~L={j3D-Sd3akNtl!AM|;^RhYHIwRK&P&^1*_|XqE<PX@{&?tIy^8Nowsi +z`E|k4VU|?GHC(><w8$A&K%#z9ioV3e+SSv7buO`7pPev73O1@pW3XgAEO}GE;BtAZ +z1U-UY3;vWo8ABxh%&V2TJ@`IjR`B$d;z7Z4Ws_i$IB4oL=PzqILnbr6hHBl9_UPu< +z>zd403o0>LsuAq1HA0rJk#h+-z8axjC^gvR6vFzLZ1RqXn}SU?sw(h|SC?`&d9KDL +zJ0dDL71mBI*%NAn&Qa~>`fEvFT&y0&TI-EB>lg=YPN%#T>szVxZoyl8v{PPvujMSP +zab$o^-V@L__AB|zU!3xSd*8~SFTtHJUNJc3ACj;(ZZeqD<?9pmDg%?0*_maR%6(!D +z3|#u$oh!8kI^{w4#@onmPj}URt8>a>_rB#~UUvYj!lDLGmrb73cFfYE?&dVPYwSpk +z-xfV<=Bk)vuNqWo$r;sxU%JK^#s}5DDeePDjMo}v4GP5f1j{aRpOBcf1}EEOFV#Ko +zl%pnCq${WFVog`?jhJ&lAB&`NZ-t$gf2DRadfOovY%(Ahb$|bToT}C@@kXpQo98s= +zsX2n3ai)*8^<aL2wgG&y9mBru8}6y`4QCozDgJD=OaBP;=#N-cJ}c~8-B3<-22;#x +z@U^!dD=Z9xl|On(g+0_iKut@r>Xlsin$O%t!Z;tZGIiQY5%Z_{uAFLS*79>;`CFlG +zPt6(3o@utp2Q-OVIYzNAWsffa6}HEn@=K7e!O(374%k_ic*J0rW;A*9?SfNoPqMZ? +zZ%fc_!wB%ctC#ykU!r8bMzQAt@d{V|P>I_nZ=$;K*4ED<Wx3MRlj_3UeIkp-U_UiM +z7XtGl4dK?-uhHkS(udi0(Gd2%Q1Kv>`!mn<x>BE{)YmF?x5X*nQe;-e9+jW^g^gGV +zihgd-z`p!kmA@MbP6jCZy+_t`&Tkz~IUBMrGBQ~eAJp0#a=nbNnwVu>mXv?5?>eJX +zK4fIx#oB6O^5YBBmqqgXmqx53<6<TBFsjKeevLi1fhxLma9ru_*TLGz&10;sb&%TA +zMcvw}UzMP}ru1=0|70tV(Q#~tsqJ{r7W1wC_DYjeUN}D3<CMn^wYD~bMt?2i!`gZs +z^+%MtQ+_Sh)7TDeCyi%5+9}@{jMctR#_8zSBV!)k*xJLQeeg|OIZr;=sFCg6>4wB~ +z9R=%WKvPjtkMvu+X8pJzLF?$MGwqdhQFh8t-Pik=(xclC_Z2~T77x!I0{@MACue{k +z?Vu~1foG+gGiVL@;zpq_{5a=kr=b7O+N#1F5xiewc0OE#hgai#7}(X;58sC=b-xAo +zqoZ=w9ka2Tw{(2g%NAivm*tgH^QW$gFdL)E(h(VWAUq)L;1rEm68>qpD)Z3H(kUxv +znbVI`{#5hq4XRbM%(HXJKC58r>VP!?=JeZCi1xv%*JrIo89{HLZ<%J@R4#4Xl<iZr +z**kKA7VLa(*UWdP?4I&oPH^U)ndaF#dVi)m(=oGX=HBoR!aoe(H?w%=N8$U!KMwz7 +z%3o$CY7@FVt~rwJ9Bb>7u!UQS3{Lq-<iA>{80cR)2mC{pxE3cj=iVWHXMpDkRCFbF +z>xyWc_>8!v)8FGDm(2eIem2Sq8-xulvi7WHE@-mV=iG_uq?xF9VXa3-;k`3oZ0y?A +z8#^}(JtMX#BiMTO?3?{voZ&1O;7MhErfmTH`a?aVs_u=l@%^xK%ny4~OVID)pl%&l +zTZbavxS{m(Tkeur|2j4<rdsC5rUfeg@P`<Ux?z~cB9;2omn(hSd@f@Gd9S#JpELF) +zZ(Jyq57kPC-X0Kl;O%;GhnOW^H`Q`E@b4}|k!h6TH#38n->ftEz36=9tyn9|E<sgW +zBs_X4h!V8Rl~#6oj-_$FbLk0`oN?G!SCNR5A9m`~7%~m_&%gF)R_$%h+Bym=cm!jY +z!Sl$Andi~A<xbax*Jtj?tQX%Ak3g#`8?+rWQD19i^-6J@sGjUfD^DGifiHPvo0OVw +z3emR7H8{JjX5dtvGrZ{ucz*RruQ3$+{mFuIz4!Ou^-7LS&<+Up&&AH}MjEZ9{>8<X +z4hPM>Y}c>|As-RKMxjKgga6*2REL;g7!~2Ugl<Crw~{J2HGJ{4FndA~b&jg#qDQg! +z<6(AbAHf%$W8Q;F;b<))MsJfLN1<8-dIKM0PxoVtk~z78(_rMDFo!}ZUqF2EI~HFA +zp!L<TuC*k4>j&hx^Z}W4YVF_U#wU{~oQ%|)qNy+SCo2u4-_Rp8l!nm=il;G@NRQFu +zlmeRxNG=)!`pGwkJ7q_5#c-Rvl{VvflA4Fu<Oo$Mo*$|T@bswatTy=<brGHixSNQH +zPI48n{Q1vr#&h(7W<*N?S{5_)(H6ksKU>JO6YxBf=D_nznpYQ9aE$Mhf<55_=tYqx +znMo6f)?&ed*1MxNF&U?^R&$&V9Bx9CA(KP;fSwgUG9^(kh0+5QMmju2ionx|*mG^N +zlOH|a$$tnO2Zp6M`KiEx6fV}uXA3L3D15I_FoA{+G>i%b6Gei8@%K)?4VeA7lV3N% +z$xoi><Q>4<cwhg77F43UsHnA<<eKqG&~FN6H$lh!=s{@tA$k~k9zwr`rhiAn@pS}^ +zqDP_c6iNWbVU}%AIQds6Ir#xkViw>Uu=gn^Kls0#eBNXyuS<3EDS!tUoaW@?r#Shg +zQ=PmIh)8$x6Mz!H2c%4Q@`q>e;4DA1TfR3G`FcaXFz}}XL?8k)PtSDnZeY<&Cw~$c +zJ<G|bKMl?E$z7wfaMtD<a>VOgt&l5vIjk8!_GufBRp3+R1fgdXdamXh7u!eZ11&~- +zzV>p3&vk{J&*Y_AOM`=7g?Pm=;!_^ClZDOmoU*RiB&q1MxKqp(w+ZL|sU<JB^Ab<0 +z+IsK1-Y+D97%l6Mf5Q&nBdDoCd{<PD{BKg>OxsU8!gp#sHThOg;~Bvu8Q>$PUOgx7 +z62B2$*ZYbpoN`5m?w+QM5UNb?OXJdfQW?z=cZOR!4)H2Z!<GMeYFK%%sbP;M2vp8b +z4b#ByeL#H7*4Xdkx5pogcgnW|EphwFY)m9g8>n(tY3C}-*r{Q`i6Ij>*z!d#Me#fR +z6f4TYN!o766*pSj4SC{9lULY`-4G9t-@CIy+$<)EE~AE$r3k42yCGJ^_Cf3%<{$Q| +z*gg=mD!5=+d{waDPb1QqbC9>RICu;ERETb?;<>6)J$h(FdtScI4T28g-E2vSK0;zE +zo@SmdDb+j86(>`O?t9UC$z<OSy&(b$V_rBpLl?M~g69ibm3)NbVoS$YED&_%`u@^8 +z`7R?*Sz`N`9MLyCSXUsr@-$QlFR#k<&MBkZXL?Jn>`<le<G$QECg}-1yU*T}Y>DQc +zoJ`6V{kG2XXNTOQTLSwj7Rs{*OON}KX4G<8Mb{Mub6hwbP3VRFJn*?X!G9xJ-^(8- +zu@!WXJ$zL-+vzOov&?qzh(B?Q7}c~2<wqkhl3%{SF6jd+a9iw_BS&oK*w|GXm1qwy +zg6HooSu#u#yDj!-9He%0j++hFvo3XlJ;NX|{(bt}+(+Px@rNC`U<DQ8EVVpy&{vzi +zEj!dG%UR;5kZF_QS+QMsPOKH47fY}zt#ZDgHvS!7zu{)!Jly`IJp+4Uwmm;sS0R3{ +z&&n?0va^o}{u8Lcwm$7N?)Evn3MYgm<N2#O894DWUc9Pl(@eu^KEO@mIblj=x`x)K +z+vv?HVKe)q$M>^6RJo`x2{YEuJel@R+FMgX5pQLsUErQgb8*4o!pG&qs=poEi|RN_ +z!a-kE{Em1{j8mQ*z$u!afM|&M&VRSJkIi=S4RhcL=7wNzj}7ehA^*RZojey_HOtAD +z0Ulsdwv%57__9Mm;V$o|kcInSiI6S2xH@={v|RX{c>=zlz3;o1%kJ_pne&`{WS*0^ +z<%OZoXFN_^9lPIG_{y&=<6qBT#=i+{1U3Wj06T&A^0l5d#Mk4De9j~l<UcSnI>zs1 +zDzU>BEiA=z_d?i{4)hlD_1h`1dK(2D*LrqPG-xyL<+@^up?GtO8CIFBjgEO>WK?4B +z2{@k?M#nI(<$w26UCU0iMa+Noo)DGDW@GaVd!ZT6`7f~97QKMk5S#RH-_2pnV#eW^ +z7JELM!%xo#pD=haqt{Jq`C>-PvzXBmU-WaHMNAXr;MT#pt_+ko;-|ks>dESu>a?wC +z!DCglhBm}zW$qc0lj$<$W)=@W15cX;&E|;t!aQ*gB9uT_!{CCOR#t|sE>+65)i+J- +z{qUMnlYc}BH&0{|y;N8PNtYJh6#ljSwL-?-?n1`hvBK`04~t>$=kVLs0Qgl#r$Ont +z;q_%1oN`-S%QwpAxG$k;_qyQS$c?Pa$zVB$YLo#ee?Y0lE@VB9qaN5*FGoEXZ5=2> +zQMRBALwOCQuB*>Q)Dfl^(-A76O2g%En7#tAx@~jopDD}n+&FJmM?%_J>r8D~I^QL; +z`a*_=F3jP`Cz;jrCjZoUHN&hvt9PYdn8Q=9?kZZd>nrsaGJ+`2<5NbvPCMn8b!@Du +z?We}M)fc1?ij2vr_ntDVaSQiTM$Zcw0x0+DqI~8wqx_RXS>H{$no$m?ym}wTM#i{m +zaOYjeW;t{E?&tfs=+EvP+{Zm|z|@jR<0{{w+{&+a8jvGXPcBbg@YPWba%F!#rx{ng +zndTQ?FPMl3n??UxDFC*>){J?ztoVb|Ttjl=YsPpDx$$S7%n}<puaJXhzR*10DMvdh +z@LcZLjOW~<W<-F|drQaM->Y=EQ?7k~GoHg7%|oDXM=72k78MM+zgL0PDKB}y8S$U* +z{Zc%)I12DgE2=Zx-;14paqpMnS@wPbo=J{64(C8o5%MYi6R;oIrLTJ-9|CXwS+8ef +z3N^6R{T4~zX=nH6zJZ-xCuJKuIdF49j9zK*-?ESaEL$mFxkTi@$&^v4DO$<wR2>Vx +z?732cJdaJ@O=Cu=Xw-R@;R!IR=}(je4|?uL4V56Pv{@MEWmz83L9WW%xTe{ELdBqG +zBytx~$Rx^bY;P;MAl&Ma3+l=wl~Hq7CTZ5OV2`KKD@0?y7#fZF{CA<3L1iiCEBRF} +z>Dy+424vl=r~&XdgS09{YdNTWFTNp8)F-BkIG=oiT1=6UVfi<IEO%|`un0Dd*?5*# +zhO5Q=@Ku^z{$ZgoTqV99?!Uj-TN{HMml}gix@W}g)+7p~5JZQ1M1>MXA%3;Vi*RqV +z$!ay*`{~s;u||8UEASL+HX~{osb+g$SIhQ(*a>?=V^F6*O3(90>CAs#Q#sJy6}|t_ +z-=2u}lPbH^8068H;Lf*S3t4gRVNq0L5IZH>6+gx17);IRv4z+iEq`;$u3CErxRx#i +zc~fg)6<-E9!i$h&OHl4j;IGQRUe|~CSLzHj<j=Xhawj-uy;x(iOIfp6^yKRF*BWFm +z@>s9jIq_SfW}%!<zSG_A>g;YWUz2>tPj6sk_YJTRKF&W^<MS5jy)qVuP1JA0jk6yz +z1;})6dC*;pj9t&SJx^;`My712VX|SOzGRx8;!;rT=5ReS48P{jhj?e_9hWwgZr`+Q +zdF4*+Ux>=z$}Ll7c$ct8YH+IF#;*mccuG=FbjrUBRpXRz46;aBW%=TF$VoH?l_IZB +zWtn5957#9fm4E2881DwMsMc&OLw4P4Br|8QN*}MZ#C;jW;#=NuR6cNff|959uZ&0U +z<#G{O&BGb88CI~mimiWD6<eFhSepSgJ!?~fn*z%ZK3;Z$hYo(VPVqmo_0JQ}Am)1# +z88usPrdMlgD(dT$dUsw4S+-icWC(`m5Lj-3`6@R1#acG|p%ZNO^(VXi1#-N>zkxN$ +zGNnDC&&ElYxFv?#^|&o=8H&<Bw*4d<TU*D*UPdmSSr4K+jHNW!Y{br5o9r`e#ff>) +zz-)1)ut#_S@g1{$qnph>z|APcxfzAgZbrc&^#YG8mHyYk;|qQ*@x$CsJ`=D3+uUsD +zF|WpEQe&2%1uv)8E|;%#NmZ@T^(b_2D|A_3))V<f-h4`}U7^&HPT|gXs+;ToEb-k_ +zjNeb{8NbKs8NW>bs<b?j(Y;Z>;$Pk~PcuGY-z`*O!U=icv?(qKyVivgCn|16XHe^{ +z)U;<zakwR*?HJkyD7E&}{?+TDa1Gx$P`J_cr4hf9Ee-PDIZB{mmOWkY6Wc2VV$Bd_ +zRtk%Y9jz~hB=d_yvXq=kj?X2`^VJG@KCi$$k?Sm5jfit>H4dL+(uFp#4ANe5B)k~X +zIm(OdiaE}PyySfB^cO=s`n6s86*l+i|1<ZdpI~QKJ*k`U%fLMzsu&L$p~-xD=)dRT +zu$S==c!BZYy1;lyZ(=<B0v<9#yLq61qjJ+-yOa^y!$THwGk*v%>7Em}4^P6aycayY +z0r`dps1LFR7UT>DA!C5d`MJ$jn>>ryS$gdpJ4+)Q*jc)$p$<NINdxoD%Nv+J#Pf_7 +z`+3I8k@Jj~>ho;1AMw}|{s4U_`IC429+*@|<+QuqYvceYSw3dtIlhBJEwt>{u+GCM +z#(5aUmpqK3%fl$X)adA;_(c~*^--DbQM9+t2>s8p?YYn+TgL?^+tel|+mR+Fo41L{ +z7TnBa>(k6Qxz)@#$-KxoS$vUkqP}ELm;pU2vYqSVB=D%b<W7%lGq83mAr&%d0(@7O +zY)uy##js0^V$@|ualvIqao1%>55<-)in^n+<sL=mQ&)@c2xg<1a#2^uvi;D};%Kdd +zrJTNJDPJ2(pvkWVzb?hAY`&3K*?eVJ*?g93Y`#6$90_&Z63AWinUBhcZabvYu$ME+ +zFNF>Gb#}0h5GfMv0;2UqnLrY<@>7AmsJ8%nu{kFLH-IJKM8~U$?gB6Ujp#!l_y?jY +z;4osO@*jyJtBJCKI7A|k)SwR#P)qbOPz?+_LG%ldeG<Qu0~71e4#eWOg4X~q5Pyp3 +z5HP78rxIX1O*9{90^-gPl>h-hfnUH5IDmSfKYlTv46t9$j{)qL^K4)>um?B-`~Y}? +zTY%U=G!PgI*nwYwlJi6tfhZ4X0jq&8fp+%ZNVEf}21GA-xB#9}Mxt~8gPMo}kAWB9 +zsc(rE0ILBvkawIY<~yRfz<S^~&;Z;8238U+1U3MBfF_{ud-R8%(|}i-p?e?r0v23F +zKb&SxpraLYw-Mb&eRPzX`dlYU0di4)8yMRTy#c#`19(6F59l1YhWcG#?G2*P2h{Ww +zu>2<K9pDdG3+w?(fV04Sd~X60f5tikvwwk3Wax}k<l$7*f@rco@(tO*THqEiD^Nwd +zfXhMX6QUw}sETd?`GSge17Tq*nhP8PB73PQ4_E{&0S*Hv0e2tB(hqa>2hR^ePe6>7 +zl)sZGCq0C<z%LGmh7nZ`C;B9g=#de?Nbm^gMnN86J#ZJ8A5XLu_yGue6#am?zyhF& +z(Ls4+G|_}HL?;2;SfT+5m=3=O#3Vv5fN>mtF$J1{fsf%m8GB$n_5<)Ca2J@ILbMKO +z05<#{^$Ea4qWvfjpuGPtauSgTZS9aT_bJ%VBJj2l<!j&rI0BpjZUOm!BB})vmqJ!x +zhh9zBfJ{+Mc02ZP0qhZ|1ZJ-$n!W~l1NIbx*6T!5*TU`qT<qyA&<;#mhrI^OeiQZu +zEL@L0`WD`S8$iki%nw9wL>*WUd;;7Cnl=&b{vYfo!16Ze0);>&5V{$B0;_@jTZlUT +z%zTNOO148UfVcxZg{!G}Cy{v<_y!IEQSTBh2i!pLZs-+#s!;0QBT5H00bXGJ9?14S +zXgkms7*s?wcrW%lu=E4`7XZ)%m_Gz<AYvbA0kOr<2XN~ntl!7r0XP7peS$Rt3jac+ +zJ^&ek;)6tOCHVd+{Nf>^#XwXk))#mc*alPq9l(Uc;OVc>A@KHRu(1d=E%^exehEKu +z6m7s(Cun_zeFd}wbIaf>fazbuUjbp?fCl_%A<F7<yjOrOPzW3cn!@4#BA_2&FVFzA +z11SdhNr3%#&?F=10_%ZFpbh9FVLgGZfD>o};v-@AKot<*8#Lkb^H8n_Dxu#)F6=wB +Ty<7#|>98+>v#~@WEkyqdyL9e; + +literal 0 +HcmV?d00001 + +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0005-usb-host-xhci-plat-add-support-for-the-R-Car-H3-xHCI.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0005-usb-host-xhci-plat-add-support-for-the-R-Car-H3-xHCI.patch new file mode 100644 index 0000000..564d4fe --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0005-usb-host-xhci-plat-add-support-for-the-R-Car-H3-xHCI.patch @@ -0,0 +1,174 @@ +From 98d922b9bc891f33efd04b9cf8efde22d7949213 Mon Sep 17 00:00:00 2001 +From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> +Date: Mon, 5 Oct 2015 21:05:56 +0900 +Subject: [PATCH] usb: host: xhci-plat: add support for the R-Car H3 xHCI + controllers + +This patch adds a firmware for the USB 3.0 host controllers of Renesas +R-Car H3 SoC. +This firmware is possible to use on R-Car H2 and M2. However, this +version causes performance degradation on R-Car H2 and M2. So, we would +like to keep the v1 firmware. + +Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> +Signed-off-by: Kyle McMartin <kyle@kernel.org> +--- + firmware/WHENCE | 3 ++- + firmware/r8a779x_usb3_v2.dlmem | Bin 0 -> 9472 bytes + 2 files changed, 2 insertions(+), 1 deletion(-) + create mode 100644 r8a779x_usb3_v2.dlmem + +diff --git a/WHENCE b/WHENCE +index c310c8b..2890465 100644 +--- a/firmware/WHENCE ++++ b/firmware/WHENCE +@@ -853,9 +853,10 @@ Licence: + + -------------------------------------------------------------------------- + +-Driver: xhci-rcar -- Renesas R-Car H2/M2 USB 3.0 host controller driver ++Driver: xhci-rcar -- Renesas R-Car H2/M2/H3 USB 3.0 host controller driver + + File: r8a779x_usb3_v1.dlmem ++File: r8a779x_usb3_v2.dlmem + + Licence: Redistributable. See LICENCE.r8a779x_usb3 for details. + +diff --git a/firmware/r8a779x_usb3_v2.dlmem b/firmware/r8a779x_usb3_v2.dlmem +new file mode 100644 +index 0000000000000000000000000000000000000000..7db71726f45943e7162d8e21ce7d80885bd79184 +GIT binary patch +literal 9472 +zcmai44O~=J+J9z-JD0DE%!QeY<mgB<W~{cz`bjBB=$cutpn@Ny@*$Ox*>2nRww5Cf +zN@k|M>6%}e4W?AC61Zi0qY280H9#4W6o(P~7+pbD-BR(s|8ob#ecSi9{C@v?&b{~C +z=R9BMInQ~9k{Q48Mp8YozY7#;Wv$+l8J(kO$gcFK`_ZOEFQuL*UQN#vJD){1{m1>a +z#63hw47M9&kJYa|MfAdqSbgMaq5w&B{~mpxk!V3iL!rymL0Y{>@tLiXt@SPOBxf;E +zcrN-@$>@Gh+;6tE+g2p%i%3hF_}7TyWo5n2lj`MIuNA$69Hm`1`bX`>D8eZA?Kbgq +zPF7Y6l~SbJx?OS~8$~25wUaezN&2Pq%=KaV&3%Xx^|@h0OR0eI{&rux^$L+LE>V9C +zlwKs;N~3*{zLw3Mkf;yTXlXH-J2+0mjeR|kbgw0u$ZjwS#vr5h26Y8-14NzC_D8e* +z{!tq0FXl>y%tZY-e6@&@F(=cH{(`K83a@2oh;bqF!GhIfkz)0<Rne_7<njY0t^Ts| +zhG4y6ku)Q8T!HwM$QhSHqJh#xL#dfP*UktIcZrpT?8Ko`ut`HYqc!6}$(#BGm&@BE +z=n?d;;7=WsF;w!;yh5GZgZHyCgJ&)i_Y0nj>jkUCK~pC=e_PiTGL`W)Oz(cUS2w@3 +zYYJa0Xv7q$PH?o>30b}t&L!md>V!_A+-O%O66|BPD|;ia3wFh%slqiuTh7^)`8vCD +zAhL?nz;;^6kys~mjp;lcqbEa2iFOQo+Gx7oz&K!Y%E~6#w^|*21$PPkWM#$OC#T?z +zqXX>9&VT{&Un+<0$jZXI?<$}#!CfF;G|I}+WZ1?{MoYSKb+SQYWRfyJvu@Y8kF6w( +z{M?-@bp*;v?A`C}<oBoBTEExHO4!|ZxtP}-Fi78O)q<xBW>0D-X1Sv6;WVZD+tE6| +zFM3wa*D%RmF>2CMGHM0CbS-g=52}Al+yjmnuXU;o3dQ#Y>vnP<lbE*#r`Q!QH9RjX +z(UYvw#S;#(u6y)4%sHsPRnoXO!Ottd)VdkHEszU78IX&<fBYU!Q}35}9c<0!ImvnI +z4q|0A^|!U}FG$okgHN_%*t<O=JaxViOe4$0pKT85AAugjL7T>BgP&`gE2+U~j#~k~ +zb~VDnLM*)e;qw}-p_l+IErHdmxyqHFxr>GIKIUcGv}GdZPxD<o(Z;;x=fKLhL*1Ub +zCd@wDVpm+cB)t-+dY8J!7lH~~<FfKQNY`xa@dGFPEK59SbV##WJ%&y}Ryvby?a$j2 +z^_%epc;DW~eQW?x3SX!CbD?;Vt9+o;ZCBP)!vtIV=a8~e9qCDRVebA>#bdFaTA>Sp +zMUmzRTl-fSb3q-$e7krkdtanRkf|{&GQFYpr>Ol^YTs>@m7i3ZHSvd)C-1N?mVu(5 +z+a~yzpR3CELcz%(b-nk>n$G#XLsqgO>mn1ARgFRIeIeINc&m$ht=p3d?v7n;l9e(O +zi!QcyGm{^0n7*u%KfbiUj*N?C(8HKkhxirN+*+#Y*1-{Vv|k6SqBe}RwKqU&Pd9a2 +zyJ2~v{<1p8DgBdK9$!zw3M<n(aGxy}*!<6{&9ag|A=o1;<A&MVTR<a5&-k#lUq$~R +zwJ$5L#(P>iq3z@eEJn-9wIQ(fJu=S3xLz6aaK~&9kM<!pag{vz;G-tCc4r!s(!(j( +zFbkTBmU^Y%)IIAbg^7A+cb{pmw41W5JbBOPZ`2Vzad?0T%9%VOcL?G)`dyq6ar6dV +z<cvIP-JDTxED+ZT0}#hKH`@jMf3|iF=7{9|60`l`G9tVd`@`VwX9MwmxZ3x7@IX4O +z)ZDU|YI*C8&-&OS?dgiLY<j`;<&hRsKeFD43fvbFkhXuCPArZ1G(t1GY)<*KWto=r +zBUCWmGIy<Jd8TD<E;%v_r>_WD8DL4jNkw=*MDs@GDzuUGCdO9iR!`^BHc#6!O`p9r +zCurfe=eEyzZ`zJ&@8<;1-Z{rIH=I70qn+)XQ#@x^#D@{PBlgTGne$P^#}S`I?49<P +zIZ66NHR3{UPm0m9QRzrC6qrae0U8gBVr$9P{sg=uIMDBJyQBWqU#)n~Z0SVA$P!m! +zFX!A_#qW%WMS-gJ#2)PtjTfI5H+K0)?B`PWe<1P(+TfM&s!Ut2bzfHJV&jt1NjKTx +z0xyH2ao<%Swsf!abzK{T-Y<5mUoZ>zt|YmeGg+BA$dk$<PxByIiF%;-tLD33+4+H3 +zOJNUsQcE%Jcx;bWZ0*C4f#`#n?0#R)jrUu&Wii#W$TlNTjgUv<blT?OI;&Lf(_X0d +zZT7iLiR8WL8gbe*fV?9^sdAWJDtl+p$bIiLid)4j@v6C=%R$6<8H>$h)JU3-S(YHq +z`s3=W>RpLmQCxzizF2tpd=Mq-*Q!t1emaiE`%b4PQcA`FUqe+AasgP-r!&qr-aG%Q +z!&&t=Ia~V}Sg=Nw0xNMbi$(g5+?l$F#@SnEH;V6y2ccDs9omkYY^b-fezmw+)J}D! +zRi?&f;7uOcr=%8`L-ZX=9d@%z8Q5p%jc9!wdx3Ve*A$8f@I+yy!Ta0q`lQ4s>PH7N +zjdg2^9??@wNs0A_ljdJ==vdBBfSh5SP%1PaqHj)aK$b9^igA6Ju0#LllB+l^qH|N2 +zBe9se#?*8D#<2SXVGd~zAv&FA@q|g?Y%eB8Z@n=`rCJPnrbpSe@=-=9ETxLm;mfsQ +zPL)!DfQ;ieEaM2k)4Z@A4jt_ulJoqBWDeKr|E{z=kxUU}qQ2CR22c#yXfXYX9-?71 +zoJLUsjin@dlpdpr@R`m>i^qa~%JmV*PE)Ez*p*GR0oUWyHq@>}YRYllttrISqiL|& +zl{?yET=#L;ktH4Hs^IzQ&u+jqc3~UxrvN?6qWbF#;qkljnRYt!nKav<XVT;?s^S>m +zF2RxbA@rh3lftA4#M4cJ6HjlCS<hsg!Jb-1hJ!;p@(u;-^Fw-8{K%Y4!4yjOQ5c2e +zDpDk_CS;?pq{w{i1exCm8~|b_%6u}geIgex^HYVT-4wo8DVRYc95hTS1v5o~Lcnij +zz8RSEn9RRAN#@5*mihHS0q&PPt_PLiZYo;+d8KYbGW0tUvzwvgfpkB#`~W=&JrAW{ +zL({*Z5qLX_#?Zsi_e4qr#$%SE$7Mcmip)nofmwhi;GHLBKKj38e)?3IzXJ?UmHDGU +zbehZ$o+k4Pr^|dJpiP(gk-!e15g0yG=AE;6aJD$KN4_^z`T9b>Fz^=+h(IJ}o;X|P +zD}l^8GVcOnGi5&IDQKRL@BTUqyKjLpN4(0_3%R0~gU$FMPuY1`fge6E2qObAas}VA +z*fGiwXf-(s^cSjpu8VBPCNI@no1Oe}WH8QApYpOI=eI48l{<UPl7>!-+r(UPvvB&K +zdh&AH&hw<HZ}h(B{X!Cm(X##UH>~h7K}*fzd!lyqf0G8g+{d&vVw=uWS77tBGzn(O +zh!`>b(rIzK__gS|IzZH5-zzruj5KG2P<8qM8lUEqDrla#Ey8-EjMs2FuJX^*!z%ks +z4|_OKph|vvm=1C8L*nB$#ebi$CE=R{<idg0ksp)Altj7?P~~jWw&m7w)5C(3LMCzW +z<>TB$HSP>ly(kNNYo{?+TxaVv=84P9USR`PLjp2@zFk$~1~FN5nRJvQMM{NO4e=Vb +z4lMIneAuO7>wvPVxL|nv!C-%!M(#6jKX1L_<gJKPA>o_U$W@c-G3*qy`ZLN^E*3gO +zbh9TT9|?)CdWuE5<W%nr*GPpz!oL@7=gp2S&|9LuGmJ&yl#KAeRTTV;pw}n|IWE3@ +zLe)YcywVUOy<6Zi@suTYj?EE$BZ9*VMOU7VsuATiv%T{wDEH~Uk}Eq@9s8Iscb-{# +z+`vw_cO`pScUMj(<rTx`uF7YJ-lba#|0xkFvxZ2I`I2YVb9z<RRYuFm2s)hD2kY7N +zT!Y|0qwMJ8&zzVAo#cpE9>G>R%LA=*ojfv9oGZq(E=T*(D16E1FLX$Tz$%;{d*sLw +zJ3034a-BwWL=+?P_m!*}W{I62V;BdiJ)GmL!}Z#wL2zUkCC0zcaFhE8d@=s8A{Q>D +zBJ8Esr}z8nvo~jlniM5V{1h^+H$E$N3eSo4!t-J&tkSL&2wKzM@%C$O7WTs}PdGBL +zCgwT{g2SuC?+sbmrCfIQLBYQR724ONoy2KBhu2_-ux31eDJKIvUdD@;bRD`Gu;zW- +z44xCFRj2D{Rl1$tnie)E1|z<o>!IpJ14x*)X3p`nchlaU7K#ikEA1@zY?_M;1{XfA +z0ABs=xIWatSrhmBY7(|4=;Dyy25_q8Cm}y#vGd=p?XtNtUo#JpV15YJ_K?7y81nx| +z*>Up`RkLJ%FK`q{$d>upKx1|&DEN3kg)E#1ONDIF#Wf&;B;_LJED-R%`kwb*F1tIz +zOj;oG`aGFmloy6EyLda_63$NiRldrLukmjbyvDx;tOGUx?*iL^_Y3r%mBcq<k9^K7 +z6&Bn#x?h|>%2Z>8W#*UTx+Wj~6b^ce`Nl02Si6~mj_5sGsUK*w=;gX-j-v$2L<_t! +zUf(b7zR}T1eJ5dm%I_D)qL%;OPjwaB(H61z)pt^K5}S?96Z1kFuIVqZ*)m_iY{*S| +zx$ohy|6<1B*ei|#Hiw^{4>2KnF{9T*D}OPgb#yVKMKAg}&myLYN^tAsTo(sR9Pu;X +zB<)mfTy5H>wBT_XT1ji;vu5ucnlsyF&YfK{q6v{U3!2Rl3xoyYPGl&7@P_EZ>o(Tj +zE-Y8u<`vh??B2Pu-0c6Nlv^M&iRKp-L(+vs*M)z5{!9_$ZcP#6uB@o13dC}ldpZ2J +zJpgf)(Wy~KzW&B*8JwC&t>Rl0%g95}bmi*c9kTMx>YNN#g^<w(pgn|Ek5$M<96&#? +zyI+caFrKxd4MlqjZ5Y}nwBg-jj-!t>y@U=@DODRUe9iO~0PA+lZ+yBU$8+tBMH>Za +zC$BblWQF_ATeN30baZweM?T4-T`={>mP;8H?J0vR_3S*Ja>Fm-X?A0^;cP|_<#~MS +z*RGQ|eXnNUnmc}MnO}QW3ZbaDoJQ{nixzb;KV^(On<0R5pKi)cCmH1*Rmz4Q%C(Gg +z1m!jQ@NHC_t4>zL)ohlglea(L!}a^@*8V-*ef!K;l4yMOyOdk~)ixulX4<KhsSCe6 +ztV8weucvk6OE%CmC07e4Bg1Cdzg`M}FEE?2sFszme}-#lPD0&SuQ4~F>4_|{h4TtI +zxE2U)6HuLTR^giO+<@zo#cjv{gLjpWy?0dk2wAE4U<0l(&bFb@x3e7Ajm3pS?;TZW +zla<^L+K~S>eo&69!&!)HQgMUv-cfA-vwl#H>)sCvagB2}aM%Zmi&0_m?|=izA$`>c +z6%s`A&-y$YSEPfleq@ylT@H4l9uU~oy;F9uodYKq<mji2EJs&sf)&fei|2{_Cz%Q= +zH}_L(JqN!DzTml7ipq~&*+FARX=uzDR`W5LwDc#+LIgeigN{m3XWAf)_cBVLgX)#H +zWo4Uxhf2oCD4Y(XQCn0x*xFXBLpbN7I@DcTs-U*++S252f<2xVuh0+k#nB^}&wmzL +z0V+!{U+FKZOW(E;G@yiMMh`-~iPdY6t>vKiz4)d$*^rbjVt?`pT5+O;n#;fWW7TZy +z4Xa?+Sxl#BS%g+Bh*+-6<sTG^A~fO~5v&^7LXP&9Am{m(AanTB;uc#n1yTsILj$rx +ziK3Ce+Lc8(x7ih~maYAi+Uu~<+S)2yscr+ZmeE?a_V3iOwST+bk=PQ{<<HXd{8>7S +zpG_Jko_A;OfAl|3!gH6#A+-c~45c{peXNJ9;D}{WEkSIT=v3nrn_~#IVZ=sabDa8{ +ztn90IWPoewY>+p#9$s-M$Qe<Ls+<3`5B_TW_PRRMZ>h`BkiQD^hg-pMYs5OUL(0lz +z*^{fw-)mO9sBHb=*0Em`wF#Ac%B`N~uCAWvl`B(j`ROG@^_&2U5aaxFwLEW?-mhSJ +z*kr?IoHz%fQh?g$#{1p%sNwa#+xe7^)o3b)8K)X28%k&RDXsy<9uC)_!thJ}e8_jU +z-E!$e>E?Co#y{Mu{|iy&+qo6$4DS)vNF8?7oA~`elR(MZ$+B{Jm=?QyOORE{swfb@ +zLrtP3s2r7cs+c`?=7{j*!^)v9tLb(i%W5sA3e?*zCbDowoAk*t>&QbvEWhQAhn4L& +zC#jWdzhyiIFPDqVY613;4e)}OYMA{G)-c<QgKZ+~dTmpRlLD(4K2~vzhYo&Wr@=ok +z`{#*G$oZZ?jct8jrdL~gD*D^izW)r%>KD({J0xQ;B8R|g3oKT#*^k$=*>@gevoAT` +z6E9Hp4gM9pNl_^6aYHtCx}=S9)M;3cb{Ja!x1Qtd+lmJEtsB*O<~_*n@GYge<|232 +z+ZCU26L!q~M&^slgq^|*$nTi%2e{enk#0u8>Sh#T-Hd`$>H{8^spGGL#~1us;$z%0 +zKM7a_6uH^TV^NLGq{S>h3tmpEe_grQEtRa&J*v{ZpweYy*+^6z`LGjO{Zh3TcLHa= +z6Fpr2XNi3$7{6N^8NX$Xj9;dIO<JDF=z1HM{>%NOlZ;RJ_Z6x#V~5;+(mXN<me_|D +zJ1R~_N6_o5_O79aQv#lqp*KkFc~1JR*Gr)Z?>JEKcE4%C?`BJa{AZ3*XqeSgXa306 +zN}*Uc6qS{tk`ib8iy<le;*c!0rjp}x2@8DnLY~hnut>D;6tjl*G_!{DG?VV;X;wkn +zMb5+*L%POzQC+c&w4+j)j+Opmh{v$1yS~Eae&qkmZT}H|cFB{v9={db<)Mc0kP(`~ +zr-%M~9-Lmr!woOvVc%KCLrN>-;SPAn2<_p40uC$nw;fVOXfF?0h`zrMF^4}VZW)n` +zQ+Xdmcq8f!_fdaT4Xmgc#G+y#D^pKzu-TPNVtZ-RX||W@o7rBP+1!AboZHMIbAB_^ +z2c2QO{O%0nW%n7zi+qMzyPwCA_<QI>t)IN>kHDlktR&s;v5^y;Wciqn=lJ#u_0Y0k +z!*^7QRu7{%-@_>G^Dv6@Tb#WVzv!l@J*-^0)kD$IJ}dM;%eMAxuWYSnnQY0eOt#&v +zOt#uqCfiS~Ot#QACfm6-#>u2}jFY+N7$+U)9Er1_XH~Y--JAp-R&wuh;shs5wtC3c +zA|Q5k%T|AmQM`SQQ4GAmD9*gVD6YQX?4@|6n_~E3MZ8Oq#nctzyMo1Jp<MK}@oYV` +zUU9ZJz*A1%^^~uSrO@P8f?t<(iOo0Y5}R-DB{rXUna#KMvNN%vM*^jLKFeWc=S`<{ +z68_Sp{&q;zj9+YrgcEW_qU}IG1JP_C8I}6!z%KN!0K2d}rvlf2mm`Rd)DYbUe)l(` +z-9YeBq8i``vZTr%h@xtVvVlp+MINfd7$BgY=p~>Q7=DcC4v>8uznue<8}J;6$L|NP +z0$w2D1W_3<r4joQU^+?k4A2UUY$7TJ0)7O)fCF#>jX(^3MV|_=U(>$<*stl?zzSd| +za1b~Oc!8e)v6*NvFb;44cYx9}MCX8L4`=}^fI~nhyKf=d3e*Ck7d)H=&uF92I)T_$ +zqQGy!3-IK(L<@lxfE&m=LKOEM(R^SHa0F-uZUcj>iSmK9z)qkQDEc1bq31N<l{V<! +z2fl!XmoNtVSuJp*9dmaOg+^=XNud8#qKUxE=<fo?bwY2zcEE-EBmaQTfjj7j-KV8h +z*NFO~oe#Wz9dvGhKVTKG6DS2v0k7iy4It@fq65I(JJ5*&osot-oQAF-pNv7pAsbi) +z`~+kMYG^xfAqZnaG~@`?&^4ey(9jMbEKEc5fifVfkB0JqMZn9z0pK{`?hpSQh`C~j +zF5eG50dY1`|Bj=b@&Ig!-zLh26IG8O+B=fyp;5qS@CbyDfjqz(;5P6~0?{VmC=m8A +z#sTwzg}@C)2kpT};Jagqjsx~_M1vAxYy2V*mjt~4rt$a{6=($pKZ^Sltbqww55R8V +zHZXM}(Q2R>So>S_Cjpa*K1RC_?Y)0dQ;0lx)(IJNpM?J`0&n?fUj-k)L7)lv2`Kmz +zQ9Y2f1hO(1v~&l^7q#SYU=0_-RzNi{cLmYRmCzfovk0`_Aez1keh1)aPp5!RV9IK& +zHDK;r@Gl^L4c6$}xCgEQ6W3yXpx-+5fi=Kh;3m+zo@mGazy^Tz9nb}efNCIg1Na11 +z03UCJe*aAL8Tc&S0=)p@R;=F$EtPB|vTO(6Kp7DI9?|Q78wlP3AH$d$wBhd)r332$ +zFR*4OWcvWLofr$m784EGh4l_B`4ImZ0JH*@-JlIb?tzVf_!8&?_~|3q?-S?+*axKT +zg^hrszYuBnK}MitKT$_1-hYa?SVpuMh%SeHfmeXdKn-vMm~;R<{S`U{-uVnRjnvZ1 +zUx3#`h!cnL4A>-t)|XgUKqoN20<i*^`4!?75cW0ni8xw>wzd-YRiFzL0Y`w=2*kfg +z=m*#ZGy|Q$L?hxP!2V-siV1XqH9$4c0rZz(Phb-u1Fb+p6#O2j0TTLxCSrab+BHBm +Z^jqe_y2G=VYM{GttV`fjJa~cL{uf;D@)rOA + +literal 0 +HcmV?d00001 + +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0006-spi-spi-gpio-fix-set-CPOL-default-inverted.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0006-spi-spi-gpio-fix-set-CPOL-default-inverted.patch new file mode 100644 index 0000000..d7b42f3 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0006-spi-spi-gpio-fix-set-CPOL-default-inverted.patch @@ -0,0 +1,30 @@ +From db37427756bc9e42723f58067a3f387a2861fbbb Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Sun, 29 May 2016 23:18:49 +0300 +Subject: [PATCH] spi: spi-gpio: set CPOL default inverted + +Workaround: + Set default value at probe to 1 due to issue with H3ULCB.HAD FPGA + ethernet switch + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + drivers/spi/spi-gpio.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c +index 1c34c93..428417d 100644 +--- a/drivers/spi/spi-gpio.c ++++ b/drivers/spi/spi-gpio.c +@@ -289,7 +289,7 @@ static int spi_gpio_alloc(unsigned pin, const char *label, bool is_in) + if (is_in) + value = gpio_direction_input(pin); + else +- value = gpio_direction_output(pin, 0); ++ value = gpio_direction_output(pin, 1); + } + return value; + } +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0007-mmc-sh_mobile_sdhi-Add-R-CarGen3-SDHI-SEQUENCER-supp.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0007-mmc-sh_mobile_sdhi-Add-R-CarGen3-SDHI-SEQUENCER-supp.patch new file mode 100644 index 0000000..803c2ed --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0007-mmc-sh_mobile_sdhi-Add-R-CarGen3-SDHI-SEQUENCER-supp.patch @@ -0,0 +1,1070 @@ +From 3b81bfa8f0dcf10e59172b10efce2c591b35a590 Mon Sep 17 00:00:00 2001 +From: Masaharu Hayakawa <masaharu.hayakawa.ry@renesas.com> +Date: Wed, 1 Feb 2017 10:59:39 +0900 +Subject: [PATCH] mmc: sh_mobile_sdhi: Add R-CarGen3 SDHI-SEQUENCER support + +This is Workaround patch for SDHI-DMAC restriction of R-Car H3(WS1.1)/M3(WS1.0). +Restriction: Mismatch of the transfer completion interrupt time and data transfer +completion time. +Overview: It does not take into account the bus response, the transfer completion +interrupt IP outputs is in the early out.Therefore, when carrying out the data +verification data read from the SD card, there is a possibility that the data of +the last sector might be missing.(MMC Interface is also the same.) + +S/W Workaround: The last sector data is preserved by reading data for 2 sectors +extra in the SDHI Driver of Linux kernel. + +The SDHI Driver achieves a dummy read for 2 sectors by the SDHI-SEQ function. +In case of eMMC: CMD17(MMC_READ_SINGLE_BLOCK) and CMD18(MMC_READ_MULTIPLE_BLOCK) + were requested, CMD8(SEND_EXT_CSD) is carried out additionally twice. +In case of SD card: CMD17(MMC_READ_SINGLE_BLOCK) and CMD18(MMC_READ_MULTIPLE_BLOCK) + were requested, 1024 bytes are read additionally by CMD18. +In other cases: CMD17 and CMD53(SD_IO_RW_EXTENDED) is carried out additionally twice. + +Signed-off-by: Kouei Abe <kouei.abe.cp@renesas.com> +Signed-off-by: Masaharu Hayakawa <masaharu.hayakawa.ry@renesas.com> +--- + drivers/mmc/host/Kconfig | 10 + + drivers/mmc/host/sh_mobile_sdhi.c | 13 + + drivers/mmc/host/tmio_mmc.h | 56 ++++ + drivers/mmc/host/tmio_mmc_dma_gen3.c | 490 +++++++++++++++++++++++++++++++++++ + drivers/mmc/host/tmio_mmc_pio.c | 245 ++++++++++++++++++ + 5 files changed, 814 insertions(+) + +diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig +index 7ec33c5..47b29b6 100644 +--- a/drivers/mmc/host/Kconfig ++++ b/drivers/mmc/host/Kconfig +@@ -568,6 +568,16 @@ config MMC_SDHI_PIO + When switching the transfer mode from DMA to PIO, say Y here. + When switching the transfer mode from PIO to DMA, say N here. + ++config MMC_SDHI_PRE_REQ ++ bool "SDHI pre_req/post_req API support" ++ depends on MMC_SDHI && ARM64 && !MMC_SDHI_PIO ++ default y ++ ++config MMC_SDHI_SEQ ++ bool "SDHI Sequencer read/write support" ++ depends on MMC_SDHI && ARM64 && !MMC_SDHI_PIO ++ default y ++ + config MMC_CB710 + tristate "ENE CB710 MMC/SD Interface support" + depends on PCI +diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c +index ee7b188..35cd37f 100644 +--- a/drivers/mmc/host/sh_mobile_sdhi.c ++++ b/drivers/mmc/host/sh_mobile_sdhi.c +@@ -114,9 +114,22 @@ struct sh_mobile_sdhi_of_data { + .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ | + MMC_CAP_CMD23, + .bus_shift = 2, ++#ifdef CONFIG_MMC_SDHI_SEQ ++ /* Gen3 SDHI SEQ can handle 0xffffffff/DM_SEQ_SIZE blk count */ ++ .max_blk_count = 0xffffffff / 512, ++ /* Gen3 SDHI SEQ can handle max 8 commands */ ++#ifdef CONFIG_MMC_BLOCK_BOUNCE ++ /* (CMD23+CMD18)*1 + (dummy read command) */ ++ .max_segs = 1, ++#else ++ /* (CMD23+CMD18)*3 + (dummy read command) */ ++ .max_segs = 3, ++#endif ++#else //CONFIG_MMC_SDHI_SEQ + /* Gen3 SDHI DMAC can handle 0xffffffff blk count, but seg = 1 */ + .max_blk_count = 0xffffffff, + .max_segs = 1, ++#endif //CONFIG_MMC_SDHI_SEQ + .sdbuf_64bit = true, + .scc_offset = 0x1000, + .taps = rcar_gen3_scc_taps, +diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h +index 438e4f8..52191ac 100644 +--- a/drivers/mmc/host/tmio_mmc.h ++++ b/drivers/mmc/host/tmio_mmc.h +@@ -51,6 +51,29 @@ + #define CTL_CLK_AND_WAIT_CTL 0x138 + #define CTL_RESET_SDIO 0x1e0 + ++#ifdef CONFIG_MMC_SDHI_SEQ ++#define DM_CM_SEQ_REGSET 0x800 ++#define DM_CM_SEQ_MODE 0x808 ++#define DM_CM_SEQ_CTRL 0x810 ++#define DM_CM_DTRAN_MODE 0x820 ++#define DM_CM_DTRAN_CTRL 0x828 ++#define DM_CM_RST 0x830 ++#define DM_CM_INFO1 0x840 ++#define DM_CM_INFO1_MASK 0x848 ++#define DM_CM_INFO2 0x850 ++#define DM_CM_INFO2_MASK 0x858 ++#define DM_CM_TUNING_STAT 0x860 ++#define DM_CM_SEQ_STAT 0x868 ++#define DM_DTRAN_ADDR 0x880 ++#define DM_SEQ_CMD 0x8a0 ++#define DM_SEQ_ARG 0x8a8 ++#define DM_SEQ_SIZE 0x8b0 ++#define DM_SEQ_SECCNT 0x8b8 ++#define DM_SEQ_RSP 0x8c0 ++#define DM_SEQ_RSP_CHK 0x8c8 ++#define DM_SEQ_ADDR 0x8d0 ++#endif ++ + /* Definitions for values the CTRL_STATUS register can take. */ + #define TMIO_STAT_CMDRESPEND BIT(0) + #define TMIO_STAT_DATAEND BIT(2) +@@ -78,6 +101,14 @@ + #define TMIO_STAT_CMD_BUSY BIT(30) + #define TMIO_STAT_ILL_ACCESS BIT(31) + ++#ifdef CONFIG_MMC_SDHI_SEQ ++/* Definitions for values the DM_CM_INFO1 register can take. */ ++#define DM_CM_INFO_SEQEND 0x00000001 ++#define DM_CM_INFO_SEQSUSPEND 0x00000100 ++#define DM_CM_INFO_DTRAEND_CH0 0x00010000 ++#define DM_CM_INFO_DTRAEND_CH1 0x00020000 ++#endif ++ + #define CLK_CTL_DIV_MASK 0xff + #define CLK_CTL_SCLKEN BIT(8) + +@@ -110,6 +141,13 @@ + struct tmio_mmc_data; + struct tmio_mmc_host; + ++#ifdef CONFIG_MMC_SDHI_PRE_REQ ++enum tmio_cookie { ++ COOKIE_UNMAPPED, ++ COOKIE_PRE_MAPPED, ++}; ++#endif ++ + struct tmio_mmc_dma { + enum dma_slave_buswidth dma_buswidth; + bool sdbuf_64bit; +@@ -145,6 +183,9 @@ struct tmio_mmc_host { + struct dma_chan *chan_tx; + struct tasklet_struct dma_complete; + struct tasklet_struct dma_issue; ++#ifdef CONFIG_MMC_SDHI_SEQ ++ struct tasklet_struct seq_complete; ++#endif + struct scatterlist bounce_sg; + u8 *bounce_buf; + u32 dma_tranend1; +@@ -243,6 +284,9 @@ static inline void tmio_mmc_kunmap_atomic(struct scatterlist *sg, + void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdata); + void tmio_mmc_release_dma(struct tmio_mmc_host *host); + void tmio_mmc_abort_dma(struct tmio_mmc_host *host); ++#ifdef CONFIG_MMC_SDHI_SEQ ++void tmio_mmc_start_sequencer(struct tmio_mmc_host *host); ++#endif + #else + static inline void tmio_mmc_start_dma(struct tmio_mmc_host *host, + struct mmc_data *data) +@@ -327,4 +371,16 @@ static inline void sd_ctrl_write32_as_16_and_16(struct tmio_mmc_host *host, int + writew(val >> 16, host->ctl + ((addr + 2) << host->bus_shift)); + } + ++#ifdef CONFIG_MMC_SDHI_SEQ ++static inline u64 tmio_dm_read(struct tmio_mmc_host *host, int addr) ++{ ++ return readq(host->ctl + addr); ++} ++ ++static inline void tmio_dm_write(struct tmio_mmc_host *host, int addr, u64 val) ++{ ++ writeq(val, host->ctl + addr); ++} ++#endif ++ + #endif +diff --git a/drivers/mmc/host/tmio_mmc_dma_gen3.c b/drivers/mmc/host/tmio_mmc_dma_gen3.c +index d1c6c40..faee4ae 100644 +--- a/drivers/mmc/host/tmio_mmc_dma_gen3.c ++++ b/drivers/mmc/host/tmio_mmc_dma_gen3.c +@@ -19,9 +19,15 @@ + #include <linux/pagemap.h> + #include <linux/scatterlist.h> + #include <linux/sys_soc.h> ++#ifdef CONFIG_MMC_SDHI_SEQ ++#include <linux/mmc/mmc.h> ++#include <linux/mmc/sd.h> ++#include <linux/mmc/sdio.h> ++#endif + + #include "tmio_mmc.h" + ++#if !defined(CONFIG_MMC_SDHI_SEQ) + #define DM_CM_DTRAN_MODE 0x820 + #define DM_CM_DTRAN_CTRL 0x828 + #define DM_CM_RST 0x830 +@@ -30,6 +36,7 @@ + #define DM_CM_INFO2 0x850 + #define DM_CM_INFO2_MASK 0x858 + #define DM_DTRAN_ADDR 0x880 ++#endif + + /* DM_CM_DTRAN_MODE */ + #define DTRAN_MODE_CH_NUM_CH0 0 /* "downstream" = for write commands */ +@@ -43,6 +50,9 @@ + /* DM_CM_RST */ + #define RST_DTRANRST1 BIT(9) + #define RST_DTRANRST0 BIT(8) ++#ifdef CONFIG_MMC_SDHI_SEQ ++#define RST_SEQRST BIT(0) ++#endif + #define RST_RESERVED_BITS GENMASK_ULL(32, 0) + + /* DM_CM_INFO1 and DM_CM_INFO1_MASK */ +@@ -68,15 +78,17 @@ + * this driver cannot use original sd_ctrl_{write,read}32 functions. + */ + ++#if !defined(CONFIG_MMC_SDHI_SEQ) + static void tmio_dm_write(struct tmio_mmc_host *host, int addr, u64 val) + { + writeq(val, host->ctl + addr); + } + + static u32 tmio_dm_read(struct tmio_mmc_host *host, int addr) + { + return readl(host->ctl + addr); + } ++#endif + + void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable) + { +@@ -95,7 +107,11 @@ void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable) + + void tmio_mmc_abort_dma(struct tmio_mmc_host *host) + { ++#ifdef CONFIG_MMC_SDHI_SEQ ++ u64 val = RST_SEQRST | RST_DTRANRST1 | RST_DTRANRST0; ++#else + u64 val = RST_DTRANRST1 | RST_DTRANRST0; ++#endif + + dev_dbg(&host->pdev->dev, "%s\n", __func__); + +@@ -149,11 +165,17 @@ void tmio_mmc_start_dma(struct tmio_mmc_host *host, struct mmc_data *data) + irq_mask = TMIO_STAT_TXRQ; + } + ++#ifdef CONFIG_MMC_SDHI_PRE_REQ ++ if (host->data->host_cookie != COOKIE_PRE_MAPPED) { ++#endif + ret = dma_map_sg(&host->pdev->dev, sg, host->sg_len, dir); + if (ret < 0) { + dev_err(&host->pdev->dev, "%s: dma_map_sg failed\n", __func__); + return; + } ++#ifdef CONFIG_MMC_SDHI_PRE_REQ ++ } ++#endif + + tmio_clear_transtate(host); + tmio_mmc_enable_dma(host, true); +@@ -195,11 +217,450 @@ static void tmio_mmc_complete_tasklet_fn(unsigned long arg) + dir = DMA_TO_DEVICE; + + tmio_mmc_enable_dma(host, false); ++#ifdef CONFIG_MMC_SDHI_PRE_REQ ++ if (host->data->host_cookie != COOKIE_PRE_MAPPED) ++#endif + dma_unmap_sg(&host->pdev->dev, host->sg_ptr, host->sg_len, dir); + tmio_mmc_do_data_irq(host); + } + #endif + ++#ifdef CONFIG_MMC_SDHI_SEQ ++/* DM_CM_SEQ_REGSET bits */ ++#define DM_CM_SEQ_REGSET_TABLE_NUM BIT(8) ++/* DM_CM_SEQ_CTRL bits */ ++#define DM_CM_SEQ_CTRL_SEQ_TABLE BIT(28) ++#define DM_CM_SEQ_CTRL_T_NUM BIT(24) ++#define DM_CM_SEQ_CTRL_SEQ_TYPE_SD BIT(16) ++#define DM_CM_SEQ_CTRL_START_NUM(x) ((x) << 12) ++#define DM_CM_SEQ_CTRL_END_NUM(x) ((x) << 8) ++#define DM_CM_SEQ_CTRL_SEQ_START BIT(0) ++/* DM_SEQ_CMD bits */ ++#define DM_SEQ_CMD_MULTI BIT(13) ++#define DM_SEQ_CMD_DIO BIT(12) ++#define DM_SEQ_CMD_CMDTYP BIT(11) ++#define DM_SEQ_CMD_RSP_NONE (BIT(9) | BIT(8)) ++#define DM_SEQ_CMD_RSP_R1 BIT(10) ++#define DM_SEQ_CMD_RSP_R1B (BIT(10) | BIT(8)) ++#define DM_SEQ_CMD_RSP_R2 (BIT(10) | BIT(9)) ++#define DM_SEQ_CMD_RSP_R3 (BIT(10) | BIT(9) | BIT(8)) ++#define DM_SEQ_CMD_NONAUTOSTP BIT(7) ++#define DM_SEQ_CMD_APP BIT(6) ++ ++#define MAX_CONTEXT_NUM 8 ++ ++struct tmio_mmc_context { ++ u64 seq_cmd; ++ u64 seq_arg; ++ u64 seq_size; ++ u64 seq_seccnt; ++ u64 seq_rsp; ++ u64 seq_rsp_chk; ++ u64 seq_addr; ++}; ++ ++static void tmio_mmc_set_seq_context(struct tmio_mmc_host *host, int ctxt_num, ++ struct tmio_mmc_context *ctxt) ++{ ++ u64 val; ++ ++ WARN_ON(ctxt_num >= MAX_CONTEXT_NUM); ++ ++ /* set sequencer table/context number */ ++ if (ctxt_num < 4) ++ val = ctxt_num; ++ else ++ val = DM_CM_SEQ_REGSET_TABLE_NUM | (ctxt_num - 4); ++ tmio_dm_write(host, DM_CM_SEQ_REGSET, val); ++ ++ /* set command parameter */ ++ tmio_dm_write(host, DM_SEQ_CMD, ctxt->seq_cmd); ++ tmio_dm_write(host, DM_SEQ_ARG, ctxt->seq_arg); ++ tmio_dm_write(host, DM_SEQ_SIZE, ctxt->seq_size); ++ tmio_dm_write(host, DM_SEQ_SECCNT, ctxt->seq_seccnt); ++ tmio_dm_write(host, DM_SEQ_RSP, ctxt->seq_rsp); ++ tmio_dm_write(host, DM_SEQ_RSP_CHK, ctxt->seq_rsp_chk); ++ tmio_dm_write(host, DM_SEQ_ADDR, ctxt->seq_addr); ++} ++ ++static int tmio_mmc_set_seq_table(struct tmio_mmc_host *host, ++ struct mmc_request *mrq, ++ struct scatterlist *sg, ++ bool ipmmu_on) ++{ ++ struct mmc_card *card = host->mmc->card; ++ struct mmc_data *data = mrq->data; ++ struct scatterlist *sg_tmp; ++ struct tmio_mmc_context ctxt; ++ unsigned int blksz, blocks; ++ u32 cmd_opcode, cmd_flag, cmd_arg; ++ u32 sbc_opcode = 0, sbc_arg = 0; ++ int i, ctxt_cnt = 0; ++ ++ /* FIXME: SD_COMBO media not tested */ ++ cmd_opcode = (mrq->cmd->opcode & 0x3f); ++ cmd_flag = DM_SEQ_CMD_CMDTYP; ++ if (data->flags & MMC_DATA_READ) ++ cmd_flag |= DM_SEQ_CMD_DIO; ++ if (mmc_op_multi(mrq->cmd->opcode) || ++ (cmd_opcode == SD_IO_RW_EXTENDED && mrq->cmd->arg & 0x08000000)) //FIXME ++ cmd_flag |= DM_SEQ_CMD_MULTI; ++ if (mrq->sbc || ++ cmd_opcode == SD_IO_RW_EXTENDED) //FIXME ++ cmd_flag |= DM_SEQ_CMD_NONAUTOSTP; ++ ++ switch (mmc_resp_type(mrq->cmd)) { ++ case MMC_RSP_NONE: ++ cmd_flag |= DM_SEQ_CMD_RSP_NONE; ++ break; ++ case MMC_RSP_R1: ++ case MMC_RSP_R1 & ~MMC_RSP_CRC: ++ cmd_flag |= DM_SEQ_CMD_RSP_R1; ++ break; ++ case MMC_RSP_R1B: ++ cmd_flag |= DM_SEQ_CMD_RSP_R1B; ++ break; ++ case MMC_RSP_R2: ++ cmd_flag |= DM_SEQ_CMD_RSP_R2; ++ break; ++ case MMC_RSP_R3: ++ cmd_flag |= DM_SEQ_CMD_RSP_R3; ++ break; ++ default: ++ pr_debug("Unknown response type %d\n", mmc_resp_type(mrq->cmd)); ++ return -EINVAL; ++ } ++ ++ cmd_arg = mrq->cmd->arg; ++ if (cmd_opcode == SD_IO_RW_EXTENDED && cmd_arg & 0x08000000) { ++ /* SDIO CMD53 block mode */ ++ cmd_arg &= ~0x1ff; ++ } ++ ++ if (mrq->sbc) { ++ sbc_opcode = (mrq->sbc->opcode & 0x3f) | DM_SEQ_CMD_RSP_R1; ++ sbc_arg = mrq->sbc->arg & (MMC_CMD23_ARG_REL_WR | ++ MMC_CMD23_ARG_PACKED | MMC_CMD23_ARG_TAG_REQ); ++ } ++ ++ blksz = data->blksz; ++ if (ipmmu_on) { ++ blocks = data->blocks; ++ memset(&ctxt, 0, sizeof(ctxt)); ++ ++ if (sbc_opcode) { ++ /* set CMD23 */ ++ ctxt.seq_cmd = sbc_opcode; ++ ctxt.seq_arg = sbc_arg | blocks; ++ tmio_mmc_set_seq_context(host, ctxt_cnt, &ctxt); ++ ctxt_cnt++; ++ } ++ ++ /* set CMD */ ++ ctxt.seq_cmd = cmd_opcode | cmd_flag; ++ ctxt.seq_arg = cmd_arg; ++ if (cmd_opcode == SD_IO_RW_EXTENDED && cmd_arg & 0x08000000) { ++ /* SDIO CMD53 block mode */ ++ ctxt.seq_arg |= blocks; ++ } ++ ctxt.seq_size = blksz; ++ ctxt.seq_seccnt = blocks; ++ ctxt.seq_addr = sg_dma_address(sg); ++ tmio_mmc_set_seq_context(host, ctxt_cnt, &ctxt); ++ } else { ++ for_each_sg(sg, sg_tmp, host->sg_len, i) { ++ blocks = sg_tmp->length / blksz; ++ memset(&ctxt, 0, sizeof(ctxt)); ++ ++ if (sbc_opcode) { ++ /* set CMD23 */ ++ ctxt.seq_cmd = sbc_opcode; ++ ctxt.seq_arg = sbc_arg | blocks; ++ if (sbc_arg & MMC_CMD23_ARG_TAG_REQ && card && ++ card->ext_csd.data_tag_unit_size && ++ blksz * blocks < card->ext_csd.data_tag_unit_size) ++ ctxt.seq_arg &= ~MMC_CMD23_ARG_TAG_REQ; ++ tmio_mmc_set_seq_context(host, ctxt_cnt, &ctxt); ++ ctxt_cnt++; ++ } ++ ++ /* set CMD */ ++ ctxt.seq_cmd = cmd_opcode | cmd_flag; ++ ctxt.seq_arg = cmd_arg; ++ if (cmd_opcode == SD_IO_RW_EXTENDED && ++ cmd_arg & 0x08000000) { ++ /* SDIO CMD53 block mode */ ++ ctxt.seq_arg |= blocks; ++ } ++ ctxt.seq_size = blksz; ++ ctxt.seq_seccnt = blocks; ++ ctxt.seq_addr = sg_dma_address(sg_tmp); ++ tmio_mmc_set_seq_context(host, ctxt_cnt, &ctxt); ++ ++ if (i < (host->sg_len - 1)) { ++ /* increment address */ ++ if (cmd_opcode == SD_IO_RW_EXTENDED) { ++ /* ++ * sg_len should be 1 in SDIO CMD53 ++ * byte mode ++ */ ++ WARN_ON(!(cmd_arg & 0x08000000)); ++ if (cmd_arg & 0x04000000) { ++ /* ++ * SDIO CMD53 address ++ * increment mode ++ */ ++ cmd_arg += (blocks * blksz) << 9; ++ } ++ } else { ++ if (card && !mmc_card_blockaddr(card)) ++ cmd_arg += blocks * blksz; ++ else ++ cmd_arg += blocks; ++ } ++ ctxt_cnt++; ++ } ++ } ++ } ++ ++ if (data->flags & MMC_DATA_READ) { ++ /* dummy read */ ++ if (cmd_opcode == MMC_READ_MULTIPLE_BLOCK && sbc_opcode && ++ data->blocks > 1) { ++ memset(&ctxt, 0, sizeof(ctxt)); ++ /* set CMD23 */ ++ ctxt.seq_cmd = sbc_opcode; ++ ctxt.seq_arg = sbc_arg | 2; ++ if (sbc_arg & MMC_CMD23_ARG_TAG_REQ && ++ card->ext_csd.data_tag_unit_size && ++ blksz * 2 < card->ext_csd.data_tag_unit_size) ++ ctxt.seq_arg &= ~MMC_CMD23_ARG_TAG_REQ; ++ ctxt_cnt++; ++ tmio_mmc_set_seq_context(host, ctxt_cnt, &ctxt); ++ ++ /* set CMD18 */ ++ ctxt.seq_cmd = cmd_opcode | cmd_flag; ++ ctxt.seq_arg = mrq->cmd->arg + data->blocks - 2; ++ ctxt.seq_size = 512; ++ ctxt.seq_seccnt = 2; ++ ctxt.seq_addr = sg_dma_address(&host->bounce_sg); ++ ctxt_cnt++; ++ tmio_mmc_set_seq_context(host, ctxt_cnt, &ctxt); ++ } else { ++ if ((card && mmc_card_mmc(card)) || ++ cmd_opcode == MMC_SEND_TUNING_BLOCK_HS200) { ++ /* In case of eMMC, set CMD8 twice */ ++ memset(&ctxt, 0, sizeof(ctxt)); ++ ctxt.seq_cmd = MMC_SEND_EXT_CSD | ++ DM_SEQ_CMD_CMDTYP | ++ DM_SEQ_CMD_DIO | ++ DM_SEQ_CMD_RSP_R1; ++ ctxt.seq_arg = 0; ++ ctxt.seq_size = 512; ++ ctxt.seq_seccnt = 1; ++ ctxt.seq_addr = sg_dma_address(&host->bounce_sg); ++ } else if (cmd_opcode == SD_SWITCH) { ++ /* set SD CMD6 twice */ ++ ctxt.seq_addr = sg_dma_address(&host->bounce_sg); ++ } else if ((card && (mmc_card_sdio(card) || ++ card->type == MMC_TYPE_SD_COMBO)) || ++ cmd_opcode == SD_IO_RW_EXTENDED) { ++ /* FIXME: ++ * In case of SDIO/SD_COMBO, ++ * read Common I/O Area 0x0-0x1FF twice. ++ */ ++ memset(&ctxt, 0, sizeof(ctxt)); ++ ctxt.seq_cmd = SD_IO_RW_EXTENDED | ++ DM_SEQ_CMD_CMDTYP | ++ DM_SEQ_CMD_DIO | ++ DM_SEQ_CMD_NONAUTOSTP | ++ DM_SEQ_CMD_RSP_R1; ++ /* ++ * SD_IO_RW_EXTENDED argument format: ++ * [31] R/W flag -> 0 ++ * [30:28] Function number -> 0x0 selects ++ * Common I/O Area ++ * [27] Block mode -> 0 ++ * [26] Increment address -> 1 ++ * [25:9] Regiser address -> 0x0 ++ * [8:0] Byte/block count -> 0x0 -> 512Bytes ++ */ ++ ctxt.seq_arg = 0x04000000; ++ ctxt.seq_size = 512; ++ ctxt.seq_seccnt = 1; ++ ctxt.seq_addr = sg_dma_address(&host->bounce_sg); ++ } else { ++ /* set CMD17 twice */ ++ memset(&ctxt, 0, sizeof(ctxt)); ++ ctxt.seq_cmd = MMC_READ_SINGLE_BLOCK | ++ DM_SEQ_CMD_CMDTYP | ++ DM_SEQ_CMD_DIO | ++ DM_SEQ_CMD_RSP_R1; ++ if (cmd_opcode == MMC_READ_SINGLE_BLOCK || ++ cmd_opcode == MMC_READ_MULTIPLE_BLOCK) ++ ctxt.seq_arg = mrq->cmd->arg; ++ else ++ ctxt.seq_arg = 0; //FIXME ++ ctxt.seq_size = 512; ++ ctxt.seq_seccnt = 1; ++ ctxt.seq_addr = sg_dma_address(&host->bounce_sg); ++ } ++ ++ for (i = 0; i < 2; i++) { ++ ctxt_cnt++; ++ tmio_mmc_set_seq_context(host, ctxt_cnt, &ctxt); ++ } ++ } ++ } ++ ++ return ctxt_cnt; ++} ++ ++void tmio_mmc_start_sequencer(struct tmio_mmc_host *host) ++{ ++ struct mmc_card *card = host->mmc->card; ++ struct scatterlist *sg = host->sg_ptr, *sg_tmp; ++ struct mmc_host *mmc = host->mmc; ++ struct mmc_request *mrq = host->mrq; ++ struct mmc_data *data = mrq->data; ++ enum dma_data_direction dir; ++ int ret, i, ctxt_num; ++ u32 val; ++ bool ipmmu_on = false; ++ ++ /* This DMAC cannot handle if sg_len larger than max_segs */ ++ if (mmc->max_segs == 1 || mmc->max_segs == 3) ++ WARN_ON(host->sg_len > mmc->max_segs); ++ else ++ ipmmu_on = true; ++ ++ dev_dbg(&host->pdev->dev, "%s: %d, %x\n", __func__, host->sg_len, ++ data->flags); ++ ++ if (!card && host->mrq->cmd->opcode == MMC_SEND_TUNING_BLOCK) { ++ /* ++ * workaround: if card is NULL, ++ * we can not decide a dummy read command to be added ++ * to the CMD19. ++ */ ++ host->force_pio = true; ++ tmio_mmc_enable_dma(host, false); ++ return; /* return for PIO */ ++ } ++ ++ if (ipmmu_on) { ++ if (!IS_ALIGNED(sg->offset, 8) || ++ ((sg_dma_address(sg) + data->blksz * data->blocks) > ++ GENMASK_ULL(32, 0))) { ++ dev_dbg(&host->pdev->dev, "%s: force pio\n", __func__); ++ host->force_pio = true; ++ tmio_mmc_enable_dma(host, false); ++ return; ++ } ++#if 1 //FIXME ++ /* ++ * workaround: if we use IPMMU, sometimes unhandled error ++ * happened ++ */ ++ switch (host->mrq->cmd->opcode) { ++ case MMC_SEND_TUNING_BLOCK_HS200: ++ case MMC_SEND_TUNING_BLOCK: ++ host->force_pio = true; ++ tmio_mmc_enable_dma(host, false); ++ return; /* return for PIO */ ++ default: ++ break; ++ } ++#endif ++ } else { ++ for_each_sg(sg, sg_tmp, host->sg_len, i) { ++ /* ++ * This DMAC cannot handle if buffer is not 8-bytes ++ * alignment ++ */ ++ if (!IS_ALIGNED(sg_tmp->offset, 8) || ++ !IS_ALIGNED(sg_tmp->length, data->blksz) || ++ ((sg_dma_address(sg_tmp) + sg_tmp->length) > ++ GENMASK_ULL(32, 0))) { ++ dev_dbg(&host->pdev->dev, "%s: force pio\n", ++ __func__); ++ host->force_pio = true; ++ tmio_mmc_enable_dma(host, false); ++ return; ++ } ++ } ++ } ++ ++#ifdef CONFIG_MMC_SDHI_PRE_REQ ++ if (host->data->host_cookie != COOKIE_PRE_MAPPED) { ++#endif ++ if (data->flags & MMC_DATA_READ) ++ dir = DMA_FROM_DEVICE; ++ else ++ dir = DMA_TO_DEVICE; ++ ++ ret = dma_map_sg(&host->pdev->dev, sg, host->sg_len, dir); ++ if (ret <= 0) { ++ dev_err(&host->pdev->dev, "%s: dma_map_sg failed\n", __func__); ++ host->force_pio = true; ++ tmio_mmc_enable_dma(host, false); ++ return; ++ } ++#ifdef CONFIG_MMC_SDHI_PRE_REQ ++ } ++#endif ++ ++ tmio_mmc_enable_dma(host, true); ++ /* set context */ ++ ctxt_num = tmio_mmc_set_seq_table(host, mrq, sg, ipmmu_on); ++ if (ctxt_num < 0) { ++ host->force_pio = true; ++ tmio_mmc_enable_dma(host, false); ++ return; ++ } ++ /* set dma mode */ ++ //FIXME ++ tmio_dm_write(host, DM_CM_DTRAN_MODE, ++ DTRAN_MODE_BUS_WID_TH); ++ //DTRAN_MODE_BUS_WID_TH | DTRAN_MODE_ADDR_MODE); ++ /* enable SEQEND irq */ ++ tmio_dm_write(host, DM_CM_INFO1_MASK, ++ GENMASK_ULL(32, 0) & ~DM_CM_INFO_SEQEND); ++ ++ if (ctxt_num < 4) { ++ /* issue table0 commands */ ++ val = DM_CM_SEQ_CTRL_SEQ_TYPE_SD | ++ DM_CM_SEQ_CTRL_START_NUM(0) | ++ DM_CM_SEQ_CTRL_END_NUM(ctxt_num) | ++ DM_CM_SEQ_CTRL_SEQ_START; ++ tmio_dm_write(host, DM_CM_SEQ_CTRL, val); ++ } else { ++ /* issue table0 commands */ ++ val = DM_CM_SEQ_CTRL_SEQ_TYPE_SD | ++ DM_CM_SEQ_CTRL_T_NUM | ++ DM_CM_SEQ_CTRL_START_NUM(0) | ++ DM_CM_SEQ_CTRL_END_NUM(3) | ++ DM_CM_SEQ_CTRL_SEQ_START; ++ tmio_dm_write(host, DM_CM_SEQ_CTRL, val); ++ /* issue table1 commands */ ++ val = DM_CM_SEQ_CTRL_SEQ_TABLE | ++ DM_CM_SEQ_CTRL_SEQ_TYPE_SD | ++ DM_CM_SEQ_CTRL_T_NUM | ++ DM_CM_SEQ_CTRL_START_NUM(0) | ++ DM_CM_SEQ_CTRL_END_NUM(ctxt_num - 4) | ++ DM_CM_SEQ_CTRL_SEQ_START; ++ tmio_dm_write(host, DM_CM_SEQ_CTRL, val); ++ } ++ ++ return; ++} ++ ++static void tmio_mmc_seq_complete_tasklet_fn(unsigned long arg) ++{ ++ tmio_mmc_complete_tasklet_fn(arg); ++} ++#endif //CONFIG_MMC_SDHI_SEQ ++ + bool __tmio_mmc_dma_irq(struct tmio_mmc_host *host) + { + unsigned int ireg, status; +@@ -237,6 +698,27 @@ void tmio_mmc_request_dma(struct tmio_mmc_host *host, + (unsigned long)host); + tasklet_init(&host->dma_issue, tmio_mmc_issue_tasklet_fn, + (unsigned long)host); ++#ifdef CONFIG_MMC_SDHI_SEQ ++ tasklet_init(&host->seq_complete, tmio_mmc_seq_complete_tasklet_fn, ++ (unsigned long)host); ++ /* alloc bounce_buf for dummy read */ ++ host->bounce_buf = (u8 *)__get_free_page(GFP_KERNEL | GFP_DMA); ++ if (!host->bounce_buf) ++ goto ebouncebuf; ++ /* setup bounce_sg for dummy read */ ++ sg_init_one(&host->bounce_sg, host->bounce_buf, 1024); ++ if (dma_map_sg(&host->pdev->dev, &host->bounce_sg, 1, DMA_FROM_DEVICE) <= 0) { ++ free_pages((unsigned long)host->bounce_buf, 0); ++ host->bounce_buf = NULL; ++ goto ebouncebuf; ++ } ++ ++ return; ++ ++ebouncebuf: ++ host->chan_rx = host->chan_tx = NULL; ++ return; ++#endif + #endif + } + +@@ -244,4 +726,12 @@ void tmio_mmc_release_dma(struct tmio_mmc_host *host) + { + /* Each value is set to zero to assume "disabling" each DMA */ + host->chan_rx = host->chan_tx = NULL; ++#ifdef CONFIG_MMC_SDHI_SEQ ++ /* free bounce_buf for dummy read */ ++ if (host->bounce_buf) { ++ dma_unmap_sg(&host->pdev->dev, &host->bounce_sg, 1, DMA_FROM_DEVICE); ++ free_pages((unsigned long)host->bounce_buf, 0); ++ host->bounce_buf = NULL; ++ } ++#endif + } +diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c +index 57a954a..e255503 100644 +--- a/drivers/mmc/host/tmio_mmc_pio.c ++++ b/drivers/mmc/host/tmio_mmc_pio.c +@@ -50,6 +50,9 @@ + #include <linux/scatterlist.h> + #include <linux/spinlock.h> + #include <linux/workqueue.h> ++#ifdef CONFIG_MMC_SDHI_PRE_REQ ++#include <linux/dma-mapping.h> ++#endif + + #include "tmio_mmc.h" + +@@ -587,6 +590,79 @@ void tmio_mmc_do_data_irq(struct tmio_mmc_host *host) + schedule_work(&host->done); + } + ++#ifdef CONFIG_MMC_SDHI_SEQ ++static void tmio_mmc_seq_irq(struct tmio_mmc_host *host, unsigned int stat, ++ u32 seq_stat1, u32 seq_stat2) ++{ ++ struct mmc_data *data; ++ struct mmc_command *cmd, *sbc; ++ ++ spin_lock(&host->lock); ++ data = host->data; ++ cmd = host->mrq->cmd; ++ sbc = host->mrq->sbc; ++ ++ //FIXME: How to get SEQ commands response? ++ ++ if (seq_stat2) { ++ //FIXME ++ pr_debug("sequencer error, CMD%d SD_INFO2=0x%x\n", ++ cmd->opcode, stat >> 16); ++ if (stat & TMIO_STAT_CMDTIMEOUT) { ++ cmd->error = -ETIMEDOUT; ++ if (sbc) ++ sbc->error = -ETIMEDOUT; ++ } else if ((stat & TMIO_STAT_CRCFAIL && ++ cmd->flags & MMC_RSP_CRC) || ++ stat & TMIO_STAT_STOPBIT_ERR || ++ stat & TMIO_STAT_CMD_IDX_ERR) { ++ cmd->error = -EILSEQ; ++ if (sbc) ++ sbc->error = -EILSEQ; ++ } ++ ++ if (stat & TMIO_STAT_DATATIMEOUT) ++ data->error = -ETIMEDOUT; ++ else if (stat & TMIO_STAT_CRCFAIL || ++ stat & TMIO_STAT_STOPBIT_ERR || ++ stat & TMIO_STAT_TXUNDERRUN) ++ data->error = -EILSEQ; ++ } ++ ++ if (host->chan_tx && (data->flags & MMC_DATA_WRITE)) { ++ //FIXME ++ u32 status = sd_ctrl_read16_and_16_as_32(host, CTL_STATUS); ++ bool done = false; ++ ++ /* ++ * Has all data been written out yet? Testing on SuperH showed, ++ * that in most cases the first interrupt comes already with the ++ * BUSY status bit clear, but on some operations, like mount or ++ * in the beginning of a write / sync / umount, there is one ++ * DATAEND interrupt with the BUSY bit set, in this cases ++ * waiting for one more interrupt fixes the problem. ++ */ ++ if (host->pdata->flags & TMIO_MMC_HAS_IDLE_WAIT) { ++ if (status & TMIO_STAT_ILL_FUNC) ++ done = true; ++ } else { ++ if (!(status & TMIO_STAT_CMD_BUSY)) ++ done = true; ++ } ++ ++ if (!done) ++ goto out; ++ } ++ ++ /* mask sequencer irq */ ++ tmio_dm_write(host, DM_CM_INFO1_MASK, 0xffffffff); ++ tasklet_schedule(&host->seq_complete); ++ ++out: ++ spin_unlock(&host->lock); ++} ++#endif //CONFIG_MMC_SDHI_SEQ ++ + static void tmio_mmc_data_irq(struct tmio_mmc_host *host, unsigned int stat) + { + struct mmc_data *data; +@@ -737,6 +813,22 @@ static bool __tmio_mmc_card_detect_irq(struct tmio_mmc_host *host, + static bool __tmio_mmc_sdcard_irq(struct tmio_mmc_host *host, + int ireg, int status) + { ++#ifdef CONFIG_MMC_SDHI_SEQ ++ u64 dm_cm_info1; ++ ++ dm_cm_info1 = tmio_dm_read(host, DM_CM_INFO1); ++ if (dm_cm_info1 & DM_CM_INFO_SEQEND) { ++ u64 dm_cm_info2; ++ dm_cm_info2 = tmio_dm_read(host, DM_CM_INFO2); ++ tmio_dm_write(host, DM_CM_INFO1, 0x0); ++ tmio_dm_write(host, DM_CM_INFO2, 0x0); ++ tmio_mmc_ack_mmc_irqs(host, ++ TMIO_MASK_IRQ & ~(TMIO_STAT_CARD_REMOVE | ++ TMIO_STAT_CARD_INSERT)); ++ tmio_mmc_seq_irq(host, status, dm_cm_info1, dm_cm_info2); ++ return true; ++ } ++#endif //CONFIG_MMC_SDHI_SEQ + /* Command completion */ + if (ireg & (TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDTIMEOUT)) { + tmio_mmc_ack_mmc_irqs(host, +@@ -814,6 +906,61 @@ irqreturn_t tmio_mmc_irq(int irq, void *devid) + } + EXPORT_SYMBOL(tmio_mmc_irq); + ++#ifdef CONFIG_MMC_SDHI_SEQ ++static int tmio_mmc_start_seq(struct tmio_mmc_host *host, ++ struct mmc_request *mrq) ++{ ++ struct tmio_mmc_data *pdata = host->pdata; ++ struct mmc_data *data = mrq->data; ++ ++ pr_debug("setup data transfer: blocksize %08x nr_blocks %d\n", ++ data->blksz, data->blocks); ++ ++ if (!host->chan_rx || !host->chan_tx) { ++ host->force_pio = true; ++ return 0; ++ } ++ ++ /* Some hardware cannot perform 2 byte requests in 4 bit mode */ ++ if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_4) { ++ int blksz_2bytes = pdata->flags & TMIO_MMC_BLKSZ_2BYTES; ++ ++ if (data->blksz < 2 || (data->blksz < 4 && !blksz_2bytes)) { ++ pr_err("%s: %d byte block unsupported in 4 bit mode\n", ++ mmc_hostname(host->mmc), data->blksz); ++ return -EINVAL; ++ } ++ } ++ ++ tmio_mmc_init_sg(host, data); ++ host->cmd = mrq->cmd; ++ host->data = data; ++ ++ //FIXME ++ sd_ctrl_write16(host, CTL_STOP_INTERNAL_ACTION, 0x000); ++ //sd_ctrl_write16(host, CTL_STOP_INTERNAL_ACTION, 0x100); ++ ++ tmio_mmc_start_sequencer(host); ++ ++ if (host->force_pio) { ++ host->cmd = NULL; ++ host->data = NULL; ++ } ++ ++ return 0; ++} ++ ++static void tmio_mmc_set_blklen_and_blkcnt(struct tmio_mmc_host *host, ++ struct mmc_data *data) ++{ ++ host->force_pio = true; ++ tmio_mmc_init_sg(host, data); ++ host->data = data; ++ ++ sd_ctrl_write16(host, CTL_SD_XFER_LEN, data->blksz); ++ sd_ctrl_write16(host, CTL_XFER_BLK_COUNT, data->blocks); ++} ++#else + static int tmio_mmc_start_data(struct tmio_mmc_host *host, + struct mmc_data *data) + { +@@ -845,6 +992,58 @@ static int tmio_mmc_start_data(struct tmio_mmc_host *host, + + return 0; + } ++#endif //CONFIG_MMC_SDHI_SEQ ++ ++#ifdef CONFIG_MMC_SDHI_PRE_REQ ++static void tmio_mmc_post_req(struct mmc_host *mmc, struct mmc_request *req, ++ int err) ++{ ++ struct tmio_mmc_host *host = mmc_priv(mmc); ++ struct mmc_data *data = req->data; ++ enum dma_data_direction dir; ++ ++ if (data && data->host_cookie == COOKIE_PRE_MAPPED) { ++ if (req->data->flags & MMC_DATA_READ) ++ dir = DMA_FROM_DEVICE; ++ else ++ dir = DMA_TO_DEVICE; ++ ++ dma_unmap_sg(&host->pdev->dev, data->sg, data->sg_len, dir); ++ data->host_cookie = COOKIE_UNMAPPED; ++ } ++} ++ ++static void tmio_mmc_pre_req(struct mmc_host *mmc, struct mmc_request *req, ++ bool is_first_req) ++{ ++ struct tmio_mmc_host *host = mmc_priv(mmc); ++ struct mmc_data *data = req->data; ++ enum dma_data_direction dir; ++ int ret; ++ ++#if 1 //FIXME: IPMMU workaround, skip pre_dma_mapping ++#ifdef CONFIG_MMC_SDHI_SEQ ++ if (mmc->max_segs != 1 && mmc->max_segs != 3) ++#else ++ if (mmc->max_segs != 1) ++#endif ++ return; ++#endif ++ ++ if (data && data->host_cookie == COOKIE_UNMAPPED) { ++ if (req->data->flags & MMC_DATA_READ) ++ dir = DMA_FROM_DEVICE; ++ else ++ dir = DMA_TO_DEVICE; ++ ++ ret = dma_map_sg(&host->pdev->dev, data->sg, data->sg_len, dir); ++ if (ret <= 0) ++ dev_err(&host->pdev->dev, "%s: dma_map_sg failed\n", __func__); ++ else ++ data->host_cookie = COOKIE_PRE_MAPPED; ++ } ++} ++#endif //CONFIG_MMC_SDHI_PRE_REQ + + static void tmio_mmc_hw_reset(struct mmc_host *mmc) + { +@@ -934,6 +1133,25 @@ static void tmio_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq) + + spin_unlock_irqrestore(&host->lock, flags); + ++#ifdef CONFIG_MMC_SDHI_SEQ ++ //FIXME: SD_COMBO media not tested ++ if (mrq->data) { ++ /* Start SEQ */ ++ ret = tmio_mmc_start_seq(host, mrq); ++ if (ret) ++ goto fail; ++ else if (!host->force_pio) { ++ /* ++ * Successed to start SEQ ++ * Wait SEQ interrupt ++ */ ++ schedule_delayed_work(&host->delayed_reset_work, ++ msecs_to_jiffies(CMDREQ_TIMEOUT)); ++ return; ++ } ++ } ++#endif //CONFIG_MMC_SDHI_SEQ ++ + if (mrq->sbc) { + init_completion(&host->completion); + ret = tmio_mmc_start_command(host, mrq->sbc); +@@ -965,9 +1183,32 @@ static void tmio_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq) + } + + if (mrq->data) { ++#ifdef CONFIG_MMC_SDHI_SEQ ++ /* ++ * Failed to start SEQ ++ * Set blklen and blkcnt to transfer in PIO mode ++ */ ++ tmio_mmc_set_blklen_and_blkcnt(host, mrq->data); ++#else + ret = tmio_mmc_start_data(host, mrq->data); + if (ret) + goto fail; ++#endif ++ ++#ifdef CONFIG_MMC_SDHI_PRE_REQ ++ if (host->force_pio && ++ mrq->data->host_cookie == COOKIE_PRE_MAPPED) { ++ /* PIO mode, unmap pre_dma_mapped sg */ ++ enum dma_data_direction dir; ++ if (mrq->data->flags & MMC_DATA_READ) ++ dir = DMA_FROM_DEVICE; ++ else ++ dir = DMA_TO_DEVICE; ++ dma_unmap_sg(&host->pdev->dev, mrq->data->sg, ++ mrq->data->sg_len, dir); ++ mrq->data->host_cookie = COOKIE_UNMAPPED; ++ } ++#endif + } + + ret = tmio_mmc_start_command(host, mrq->cmd); +@@ -1160,6 +1401,10 @@ static int tmio_multi_io_quirk(struct mmc_card *card, + } + + static struct mmc_host_ops tmio_mmc_ops = { ++#ifdef CONFIG_MMC_SDHI_PRE_REQ ++ .post_req = tmio_mmc_post_req, ++ .pre_req = tmio_mmc_pre_req, ++#endif + .request = tmio_mmc_request, + .set_ios = tmio_mmc_set_ios, + .get_ro = tmio_mmc_get_ro, +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0008-arm64-do-not-set-dma-masks-that-device-connection-ca.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0008-arm64-do-not-set-dma-masks-that-device-connection-ca.patch new file mode 100644 index 0000000..14612cd --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0008-arm64-do-not-set-dma-masks-that-device-connection-ca.patch @@ -0,0 +1,132 @@ +From e3218ab51b0bf3f193a9f64e5c0dafe74e292ad2 Mon Sep 17 00:00:00 2001 +From: Nikita Yushchenko <nikita.yoush@cogentembedded.com> +Date: Fri, 6 Jan 2017 17:12:49 +0300 +Subject: [PATCH] arm64: do not set dma masks that device connection can't + handle + +It is possible that device is capable of 64-bit DMA addresses, and +device driver tries to set wide DMA mask, but bridge or bus used to +connect device to the system can't handle wide addresses. + +With swiotlb, memory above 4G still can be used by drivers for streaming +DMA, but *dev->mask and dev->dma_coherent_mask must still keep values +that hardware handles physically. + +This patch enforces that. Based on original version by +Arnd Bergmann <arnd@arndb.de>, extended with coherent mask hadnling. + +Signed-off-by: Nikita Yushchenko <nikita.yoush@cogentembedded.com> +CC: Arnd Bergmann <arnd@arndb.de> +--- + arch/arm64/Kconfig | 3 +++ + arch/arm64/include/asm/device.h | 1 + + arch/arm64/mm/dma-mapping.c | 51 +++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 55 insertions(+) + +diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig +index 76747d92bc72..9513d2eb5c8a 100644 +--- a/arch/arm64/Kconfig ++++ b/arch/arm64/Kconfig +@@ -191,6 +191,9 @@ config NEED_DMA_MAP_STATE + config NEED_SG_DMA_LENGTH + def_bool y + ++config ARCH_HAS_DMA_SET_COHERENT_MASK ++ def_bool y ++ + config SMP + def_bool y + +diff --git a/arch/arm64/include/asm/device.h b/arch/arm64/include/asm/device.h +index 243ef256b8c9..a57e7bb10e71 100644 +--- a/arch/arm64/include/asm/device.h ++++ b/arch/arm64/include/asm/device.h +@@ -22,6 +22,7 @@ struct dev_archdata { + void *iommu; /* private IOMMU data */ + #endif + bool dma_coherent; ++ u64 parent_dma_mask; + }; + + struct pdev_archdata { +diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c +index 46a4157adc17..04b9bce96f1b 100644 +--- a/arch/arm64/mm/dma-mapping.c ++++ b/arch/arm64/mm/dma-mapping.c +@@ -351,6 +351,30 @@ static int __swiotlb_dma_supported(struct device *hwdev, u64 mask) + return 1; + } + ++static int __swiotlb_set_dma_mask(struct device *dev, u64 mask) ++{ ++ /* device is not DMA capable */ ++ if (!dev->dma_mask) ++ return -EIO; ++ ++ /* mask is below swiotlb bounce buffer, so fail */ ++ if (!swiotlb_dma_supported(dev, mask)) ++ return -EIO; ++ ++ /* ++ * because of the swiotlb, we can return success for ++ * larger masks, but need to ensure that bounce buffers ++ * are used above parent_dma_mask, so set that as ++ * the effective mask. ++ */ ++ if (mask > dev->archdata.parent_dma_mask) ++ mask = dev->archdata.parent_dma_mask; ++ ++ *dev->dma_mask = mask; ++ ++ return 0; ++} ++ + static struct dma_map_ops swiotlb_dma_ops = { + .alloc = __dma_alloc, + .free = __dma_free, +@@ -366,8 +390,23 @@ static struct dma_map_ops swiotlb_dma_ops = { + .sync_sg_for_device = __swiotlb_sync_sg_for_device, + .dma_supported = __swiotlb_dma_supported, + .mapping_error = swiotlb_dma_mapping_error, ++ .set_dma_mask = __swiotlb_set_dma_mask, + }; + ++int dma_set_coherent_mask(struct device *dev, u64 mask) ++{ ++ if (!dma_supported(dev, mask)) ++ return -EIO; ++ ++ if (get_dma_ops(dev) == &swiotlb_dma_ops && ++ mask > dev->archdata.parent_dma_mask) ++ mask = dev->archdata.parent_dma_mask; ++ ++ dev->coherent_dma_mask = mask; ++ return 0; ++} ++EXPORT_SYMBOL(dma_set_coherent_mask); ++ + static int __init atomic_pool_init(void) + { + pgprot_t prot = __pgprot(PROT_NORMAL_NC); +@@ -971,6 +1010,18 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, + if (!dev->archdata.dma_ops) + dev->archdata.dma_ops = &swiotlb_dma_ops; + ++ /* ++ * we don't yet support buses that have a non-zero mapping. ++ * Let's hope we won't need it ++ */ ++ WARN_ON(dma_base != 0); ++ ++ /* ++ * Whatever the parent bus can set. A device must not set ++ * a DMA mask larger than this. ++ */ ++ dev->archdata.parent_dma_mask = size - 1; ++ + dev->archdata.dma_coherent = coherent; + __iommu_setup_dma_ops(dev, dma_base, size, iommu); + } +-- +2.11.0 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0009-swiotlb-ensure-that-page-sized-mappings-are-page-ali.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0009-swiotlb-ensure-that-page-sized-mappings-are-page-ali.patch new file mode 100644 index 0000000..cccc80d --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0009-swiotlb-ensure-that-page-sized-mappings-are-page-ali.patch @@ -0,0 +1,38 @@ +From c92eeec67eb96b79fe3d01b0045789de52fd5af3 Mon Sep 17 00:00:00 2001 +From: Nikita Yushchenko <nikita.yoush@cogentembedded.com> +Date: Tue, 3 Jan 2017 14:24:58 +0300 +Subject: [PATCH] swiotlb: ensure that page-sized mappings are page-aligned + +Some drivers (e.g. nvme) do depend on page mappings to be page +aligned. + +Swiotlb already enforces such alignment for mappings greater than page, +extend that to page-sized mappings as well. + +Signed-off-by: Nikita Yushchenko <nikita.yoush@cogentembedded.com> +--- + lib/swiotlb.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/lib/swiotlb.c b/lib/swiotlb.c +index 76f29ecba8f4..771234d050c7 100644 +--- a/lib/swiotlb.c ++++ b/lib/swiotlb.c +@@ -452,11 +452,11 @@ phys_addr_t swiotlb_tbl_map_single(struct device *hwdev, + : 1UL << (BITS_PER_LONG - IO_TLB_SHIFT); + + /* +- * For mappings greater than a page, we limit the stride (and +- * hence alignment) to a page size. ++ * For mappings greater than or equal to a page, we limit the stride ++ * (and hence alignment) to a page size. + */ + nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT; +- if (size > PAGE_SIZE) ++ if (size >= PAGE_SIZE) + stride = (1 << (PAGE_SHIFT - IO_TLB_SHIFT)); + else + stride = 1; +-- +2.11.0 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0010-can-rcar_can-add-enable-and-standby-control-pins.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0010-can-rcar_can-add-enable-and-standby-control-pins.patch new file mode 100644 index 0000000..38d8e09 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0010-can-rcar_can-add-enable-and-standby-control-pins.patch @@ -0,0 +1,156 @@ +From 5d5eef59a48e3b8e0f67c2ab0963d380c7a7399d Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Mon, 2 May 2016 22:05:53 +0300 +Subject: [PATCH] can: rcar_can: add enable and standby control pins + +Add enable and standby can transceiver control pins + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + .../devicetree/bindings/net/can/rcar_can.txt | 4 ++ + drivers/net/can/rcar/rcar_can.c | 58 +++++++++++++++++----- + include/linux/can/platform/rcar_can.h | 2 + + 3 files changed, 51 insertions(+), 13 deletions(-) + +diff --git a/Documentation/devicetree/bindings/net/can/rcar_can.txt b/Documentation/devicetree/bindings/net/can/rcar_can.txt +index 8d40ab2..9293cf8 100644 +--- a/Documentation/devicetree/bindings/net/can/rcar_can.txt ++++ b/Documentation/devicetree/bindings/net/can/rcar_can.txt +@@ -38,6 +38,7 @@ Optional properties: + <0x0> (default) : Peripheral clock (clkp1) + <0x1> : Peripheral clock (clkp2) + <0x3> : Externally input clock ++- gpios: GPIO used for controlling the enable pin and standby pin + + Example + ------- +@@ -59,5 +60,8 @@ Board specific .dts file: + &can0 { + pinctrl-0 = <&can0_pins>; + pinctrl-names = "default"; ++ gpios = <&gpio5 29 GPIO_ACTIVE_HIGH /* enable */ ++ &gpio5 30 GPIO_ACTIVE_LOW /* standby */ ++ >; + status = "okay"; + }; +diff --git a/drivers/net/can/rcar/rcar_can.c b/drivers/net/can/rcar/rcar_can.c +index 788459f..887ca37 100644 +--- a/drivers/net/can/rcar/rcar_can.c ++++ b/drivers/net/can/rcar/rcar_can.c +@@ -21,6 +21,7 @@ + #include <linux/clk.h> + #include <linux/can/platform/rcar_can.h> + #include <linux/of.h> ++#include <linux/of_gpio.h> + + #define RCAR_CAN_DRV_NAME "rcar_can" + +@@ -94,6 +95,8 @@ struct rcar_can_priv { + u32 tx_tail; + u8 clock_select; + u8 ier; ++ unsigned int enable_pin; /* transceiver enable */ ++ unsigned int standby_pin; /* transceiver standby */ + }; + + static const struct can_bittiming_const rcar_can_bittiming_const = { +@@ -505,6 +508,10 @@ static int rcar_can_open(struct net_device *ndev) + struct rcar_can_priv *priv = netdev_priv(ndev); + int err; + ++ /* transceiver normal mode */ ++ if (gpio_is_valid(priv->standby_pin)) ++ gpio_set_value(priv->standby_pin, 1); ++ + err = clk_prepare_enable(priv->clk); + if (err) { + netdev_err(ndev, +@@ -581,6 +588,9 @@ static int rcar_can_close(struct net_device *ndev) + clk_disable_unprepare(priv->clk); + close_candev(ndev); + can_led_event(ndev, CAN_LED_EVENT_STOP); ++ /* transceiver stanby mode */ ++ if (gpio_is_valid(priv->standby_pin)) ++ gpio_set_value(priv->standby_pin, 0); + return 0; + } + +@@ -743,20 +753,9 @@ static int rcar_can_probe(struct platform_device *pdev) + struct resource *mem; + void __iomem *addr; + u32 clock_select = CLKR_CLKP1; +- int err = -ENODEV; ++ int err = -ENODEV, ret; + int irq; +- +- if (pdev->dev.of_node) { +- of_property_read_u32(pdev->dev.of_node, +- "renesas,can-clock-select", &clock_select); +- } else { +- pdata = dev_get_platdata(&pdev->dev); +- if (!pdata) { +- dev_err(&pdev->dev, "No platform data provided!\n"); +- goto fail; +- } +- clock_select = pdata->clock_select; +- } ++ enum of_gpio_flags enable_flags, standby_flags; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { +@@ -826,6 +825,39 @@ static int rcar_can_probe(struct platform_device *pdev) + + devm_can_led_init(ndev); + ++ if (pdev->dev.of_node) { ++ of_property_read_u32(pdev->dev.of_node, ++ "renesas,can-clock-select", &clock_select); ++ priv->enable_pin = of_get_gpio_flags(pdev->dev.of_node, 0, &enable_flags); ++ priv->standby_pin = of_get_gpio_flags(pdev->dev.of_node, 1, &standby_flags); ++ } else { ++ pdata = dev_get_platdata(&pdev->dev); ++ if (!pdata) { ++ dev_err(&pdev->dev, "No platform data provided!\n"); ++ goto fail; ++ } ++ clock_select = pdata->clock_select; ++ priv->enable_pin = pdata->enable_pin; ++ priv->standby_pin = pdata->standby_pin; ++ } ++ ++ if (gpio_is_valid(priv->enable_pin)) { ++ int val = enable_flags & OF_GPIO_ACTIVE_LOW ? ++ GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH; ++ ret = devm_gpio_request_one(&pdev->dev, priv->enable_pin, val, "enable"); ++ if (ret) ++ dev_info(&pdev->dev, "Failed to request enable pin\n"); ++ } ++ ++ if (gpio_is_valid(priv->standby_pin)) { ++ int val = standby_flags & OF_GPIO_ACTIVE_LOW ? ++ GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH; ++ /* transceiver standby mode */ ++ ret = devm_gpio_request_one(&pdev->dev, priv->standby_pin, val, "standby"); ++ if (ret) ++ dev_info(&pdev->dev, "Failed to request standby pin\n"); ++ } ++ + dev_info(&pdev->dev, "device registered (regs @ %p, IRQ%d)\n", + priv->regs, ndev->irq); + +diff --git a/include/linux/can/platform/rcar_can.h b/include/linux/can/platform/rcar_can.h +index 0f4a2f3..7ef810d 100644 +--- a/include/linux/can/platform/rcar_can.h ++++ b/include/linux/can/platform/rcar_can.h +@@ -12,6 +12,8 @@ enum CLKR { + + struct rcar_can_platform_data { + enum CLKR clock_select; /* Clock source select */ ++ unsigned int enable_pin; ++ unsigned int standby_pin; + }; + + #endif /* !_CAN_PLATFORM_RCAR_CAN_H_ */ +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0011-can-rcar_canfd-add-enable-and-standby-control-pins.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0011-can-rcar_canfd-add-enable-and-standby-control-pins.patch new file mode 100644 index 0000000..c35cacc --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0011-can-rcar_canfd-add-enable-and-standby-control-pins.patch @@ -0,0 +1,126 @@ +From 0f55d888c83aed7ea5a10761edaff52de8dc06a1 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Mon, 30 May 2016 01:51:47 +0300 +Subject: [PATCH] can: rcar_canfd: add enable and standby control pins + +Add enable and standby can transceiver control pins + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + .../devicetree/bindings/net/can/rcar_canfd.txt | 5 +++ + drivers/net/can/rcar/rcar_canfd.c | 48 ++++++++++++++++++---- + 2 files changed, 44 insertions(+), 9 deletions(-) + +diff --git a/Documentation/devicetree/bindings/net/can/rcar_canfd.txt b/Documentation/devicetree/bindings/net/can/rcar_canfd.txt +index 4299bd8..eede77a 100644 +--- a/Documentation/devicetree/bindings/net/can/rcar_canfd.txt ++++ b/Documentation/devicetree/bindings/net/can/rcar_canfd.txt +@@ -16,6 +16,7 @@ Required properties: + - clock-names: 3 clock input name strings: "fck", "canfd", "can_clk". + - pinctrl-0: pin control group to be used for this controller. + - pinctrl-names: must be "default". ++- gpios: GPIO used for controlling the enable pin and standby pin + + Required child nodes: + The controller supports two channels and each is represented as a child node. +@@ -49,6 +50,10 @@ SoC common .dtsi file: + power-domains = <&cpg>; + status = "disabled"; + ++ gpios = <&gpio5 29 GPIO_ACTIVE_HIGH /* enable */ ++ &gpio5 30 GPIO_ACTIVE_LOW /* standby */ ++ >; ++ + channel0 { + status = "disabled"; + }; +diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c +index 15a14c5..4aa670d 100644 +--- a/drivers/net/can/rcar/rcar_canfd.c ++++ b/drivers/net/can/rcar/rcar_canfd.c +@@ -21,6 +21,7 @@ + #include <linux/clk.h> + #include <linux/of.h> + #include <linux/of_device.h> ++#include <linux/of_gpio.h> + #include <linux/bitmap.h> + #include <linux/bitops.h> + #include <linux/iopoll.h> +@@ -386,6 +387,8 @@ struct rcar_canfd_global { + enum rcar_canfd_fcanclk fcan; /* CANFD or Ext clock */ + unsigned long channels_mask; /* Enabled channels mask */ + bool fdmode; /* CAN FD or Classical CAN only mode */ ++ unsigned int enable_pin; /* transceiver enable */ ++ unsigned int standby_pin; /* transceiver standby */ + }; + + /* CAN FD mode nominal rate constants */ +@@ -1063,6 +1066,10 @@ static int rcar_canfd_open(struct net_device *ndev) + struct rcar_canfd_global *gpriv = priv->gpriv; + int err; + ++ /* transceiver normal mode */ ++ if (gpio_is_valid(gpriv->standby_pin)) ++ gpio_set_value(gpriv->standby_pin, 1); ++ + /* Peripheral clock is already enabled in probe */ + err = clk_prepare_enable(gpriv->can_clk); + if (err) { +@@ -1131,6 +1138,9 @@ static int rcar_canfd_close(struct net_device *ndev) + clk_disable_unprepare(gpriv->can_clk); + close_candev(ndev); + can_led_event(ndev, CAN_LED_EVENT_STOP); ++ /* transceiver stanby mode */ ++ if (gpio_is_valid(gpriv->standby_pin)) ++ gpio_set_value(gpriv->standby_pin, 0); + return 0; + } + +@@ -1409,8 +1419,9 @@ static int rcar_canfd_probe(struct platform_device *pdev) + struct rcar_canfd_global *gpriv; + struct device_node *of_child; + unsigned long channels_mask = 0; +- int err, ch_irq, g_irq; ++ int err, ret, ch_irq, g_irq; + bool fdmode = true; /* CAN FD only mode - default */ ++ enum of_gpio_flags enable_flags, standby_flags; + + if (of_property_read_bool(pdev->dev.of_node, "renesas,no-can-fd")) + fdmode = false; /* Classical CAN only mode */ +@@ -1552,6 +1555,33 @@ static int rcar_canfd_probe(struct platform_device *pdev) + goto fail_channel; + } + ++ of_property_read_u32(pdev->dev.of_node, ++ "renesas,can-clock-select", &clock_select); ++ if (clock_select >= ARRAY_SIZE(clock_names)) { ++ err = -EINVAL; ++ dev_err(&pdev->dev, "invalid CAN clock selected\n"); ++ goto fail_dev; ++ } ++ gpriv->enable_pin = of_get_gpio_flags(pdev->dev.of_node, 0, &enable_flags); ++ gpriv->standby_pin = of_get_gpio_flags(pdev->dev.of_node, 1, &standby_flags); ++ ++ if (gpio_is_valid(gpriv->enable_pin)) { ++ int val = enable_flags & OF_GPIO_ACTIVE_LOW ? ++ GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH; ++ ret = devm_gpio_request_one(&pdev->dev, gpriv->enable_pin, val, "enable"); ++ if (ret) ++ dev_info(&pdev->dev, "Failed to request enable pin\n"); ++ } ++ ++ if (gpio_is_valid(gpriv->standby_pin)) { ++ int val = standby_flags & OF_GPIO_ACTIVE_LOW ? ++ GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH; ++ /* transceiver standby mode */ ++ ret = devm_gpio_request_one(&pdev->dev, gpriv->standby_pin, val, "standby"); ++ if (ret) ++ dev_info(&pdev->dev, "Failed to request standby pin\n"); ++ } ++ + platform_set_drvdata(pdev, gpriv); + dev_info(&pdev->dev, "global operational state (clk %d, fdmode %d)\n", + gpriv->fcan, gpriv->fdmode); +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0012-mtd-Add-RPC-HyperFlash-driver.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0012-mtd-Add-RPC-HyperFlash-driver.patch new file mode 100644 index 0000000..a6d08e7 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0012-mtd-Add-RPC-HyperFlash-driver.patch @@ -0,0 +1,1028 @@ +From cc3bccbe6c479d8ad76a09b62fb63126403d0bab Mon Sep 17 00:00:00 2001 +From: Valentine Barshak <valentine.barshak@cogentembedded.com> +Date: Fri, 3 Jun 2016 23:04:20 +0300 +Subject: [PATCH] mtd: Add RPC HyperFlash driver + +This adds RPC HyperFlash driver. + +Signed-off-by: Valentine Barshak <valentine.barshak@cogentembedded.com> +--- + drivers/mtd/Kconfig | 5 + + drivers/mtd/Makefile | 1 + + drivers/mtd/rpc_hyperflash.c | 976 +++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 982 insertions(+) + create mode 100644 drivers/mtd/rpc_hyperflash.c + +diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig +index 42cc953..0c58a89 100644 +--- a/drivers/mtd/Kconfig ++++ b/drivers/mtd/Kconfig +@@ -11,6 +11,11 @@ menuconfig MTD + particular hardware and users of MTD devices. If unsure, say N. + + if MTD ++config MTD_RPC_HYPERFLASH ++ tristate "MTD Renesas R-Car Gen3 RPC HyperFlash" ++ depends on ARCH_R8A7795 ++ ---help--- ++ This option includes Renesas R-Car Gen3 RPC HyperFlash support. + + config MTD_TESTS + tristate "MTD tests support (DANGEROUS)" +diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile +index 99bb9a1..3b81efb 100644 +--- a/drivers/mtd/Makefile ++++ b/drivers/mtd/Makefile +@@ -13,6 +13,7 @@ obj-$(CONFIG_MTD_AFS_PARTS) += afs.o + obj-$(CONFIG_MTD_AR7_PARTS) += ar7part.o + obj-$(CONFIG_MTD_BCM63XX_PARTS) += bcm63xxpart.o + obj-$(CONFIG_MTD_BCM47XX_PARTS) += bcm47xxpart.o ++obj-$(CONFIG_MTD_RPC_HYPERFLASH) += rpc_hyperflash.o + + # 'Users' - code which presents functionality to userspace. + obj-$(CONFIG_MTD_BLKDEVS) += mtd_blkdevs.o +diff --git a/drivers/mtd/rpc_hyperflash.c b/drivers/mtd/rpc_hyperflash.c +new file mode 100644 +index 0000000..f8a2c90 +--- /dev/null ++++ b/drivers/mtd/rpc_hyperflash.c +@@ -0,0 +1,976 @@ ++/* ++ * Linux driver for R-Car Gen3 RPC HyperFlash ++ * ++ * Copyright (C) 2016 Renesas Electronics Corporation ++ * Copyright (C) 2016 Cogent Embedded, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include <linux/delay.h> ++#include <linux/io.h> ++#include <linux/module.h> ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/partitions.h> ++#include <linux/of.h> ++#include <linux/rwsem.h> ++#include <linux/slab.h> ++ ++/* RPC */ ++#define RPC_BASE 0xEE200000 ++#define RPC_SIZE 0x8100 ++#define RPC_FLASH_BASE 0x08000000 ++#define RPC_FLASH_SIZE 0x04000000 ++ ++#define RPC_CMNCR 0x0000 /* R/W */ ++#define RPC_CMNCR_MD (0x1 << 31) ++#define RPC_CMNCR_MOIIO0(val) (((val) & 0x3) << 16) ++#define RPC_CMNCR_MOIIO1(val) (((val) & 0x3) << 18) ++#define RPC_CMNCR_MOIIO2(val) (((val) & 0x3) << 20) ++#define RPC_CMNCR_MOIIO3(val) (((val) & 0x3) << 22) ++#define RPC_CMNCR_MOIIO_HIZ (RPC_CMNCR_MOIIO0(3) | RPC_CMNCR_MOIIO1(3) | \ ++ RPC_CMNCR_MOIIO2(3) | RPC_CMNCR_MOIIO3(3)) ++#define RPC_CMNCR_IO0FV(val) (((val) & 0x3) << 8) ++#define RPC_CMNCR_IO2FV(val) (((val) & 0x3) << 12) ++#define RPC_CMNCR_IO3FV(val) (((val) & 0x3) << 14) ++#define RPC_CMNCR_IOFV_HIZ (RPC_CMNCR_IO0FV(3) | RPC_CMNCR_IO2FV(3) | \ ++ RPC_CMNCR_IO3FV(3)) ++#define RPC_CMNCR_BSZ(val) (((val) & 0x3) << 0) ++ ++#define RPC_SSLDR 0x0004 /* R/W */ ++#define RPC_SSLDR_SPNDL(d) (((d) & 0x7) << 16) ++#define RPC_SSLDR_SLNDL(d) (((d) & 0x7) << 8) ++#define RPC_SSLDR_SCKDL(d) (((d) & 0x7) << 0) ++ ++#define RPC_DRCR 0x000C /* R/W */ ++#define RPC_DRCR_SSLN (0x1 << 24) ++#define RPC_DRCR_RBURST(v) (((v) & 0x1F) << 16) ++#define RPC_DRCR_RCF (0x1 << 9) ++#define RPC_DRCR_RBE (0x1 << 8) ++#define RPC_DRCR_SSLE (0x1 << 0) ++ ++#define RPC_DRCMR 0x0010 /* R/W */ ++#define RPC_DRCMR_CMD(c) (((c) & 0xFF) << 16) ++#define RPC_DRCMR_OCMD(c) (((c) & 0xFF) << 0) ++ ++#define RPC_DREAR 0x0014 /* R/W */ ++#define RPC_DREAR_EAV(v) (((v) & 0xFF) << 16) ++#define RPC_DREAR_EAC(v) (((v) & 0x7) << 0) ++ ++#define RPC_DROPR 0x0018 /* R/W */ ++#define RPC_DROPR_OPD3(o) (((o) & 0xFF) << 24) ++#define RPC_DROPR_OPD2(o) (((o) & 0xFF) << 16) ++#define RPC_DROPR_OPD1(o) (((o) & 0xFF) << 8) ++#define RPC_DROPR_OPD0(o) (((o) & 0xFF) << 0) ++ ++#define RPC_DRENR 0x001C /* R/W */ ++#define RPC_DRENR_CDB(o) (((o) & 0x3) << 30) ++#define RPC_DRENR_OCDB(o) (((o) & 0x3) << 28) ++#define RPC_DRENR_ADB(o) (((o) & 0x3) << 24) ++#define RPC_DRENR_OPDB(o) (((o) & 0x3) << 20) ++#define RPC_DRENR_SPIDB(o) (((o) & 0x3) << 16) ++#define RPC_DRENR_DME (0x1 << 15) ++#define RPC_DRENR_CDE (0x1 << 14) ++#define RPC_DRENR_OCDE (0x1 << 12) ++#define RPC_DRENR_ADE(v) (((v) & 0xF) << 8) ++#define RPC_DRENR_OPDE(v) (((v) & 0xF) << 4) ++ ++#define RPC_SMCR 0x0020 /* R/W */ ++#define RPC_SMCR_SSLKP (0x1 << 8) ++#define RPC_SMCR_SPIRE (0x1 << 2) ++#define RPC_SMCR_SPIWE (0x1 << 1) ++#define RPC_SMCR_SPIE (0x1 << 0) ++ ++#define RPC_SMCMR 0x0024 /* R/W */ ++#define RPC_SMCMR_CMD(c) (((c) & 0xFF) << 16) ++#define RPC_SMCMR_OCMD(c) (((c) & 0xFF) << 0) ++ ++#define RPC_SMADR 0x0028 /* R/W */ ++#define RPC_SMOPR 0x002C /* R/W */ ++#define RPC_SMOPR_OPD0(o) (((o) & 0xFF) << 0) ++#define RPC_SMOPR_OPD1(o) (((o) & 0xFF) << 8) ++#define RPC_SMOPR_OPD2(o) (((o) & 0xFF) << 16) ++#define RPC_SMOPR_OPD3(o) (((o) & 0xFF) << 24) ++ ++#define RPC_SMENR 0x0030 /* R/W */ ++#define RPC_SMENR_CDB(o) (((o) & 0x3) << 30) ++#define RPC_SMENR_OCDB(o) (((o) & 0x3) << 28) ++#define RPC_SMENR_ADB(o) (((o) & 0x3) << 24) ++#define RPC_SMENR_OPDB(o) (((o) & 0x3) << 20) ++#define RPC_SMENR_SPIDB(o) (((o) & 0x3) << 16) ++#define RPC_SMENR_DME (0x1 << 15) ++#define RPC_SMENR_CDE (0x1 << 14) ++#define RPC_SMENR_OCDE (0x1 << 12) ++#define RPC_SMENR_ADE(v) (((v) & 0xF) << 8) ++#define RPC_SMENR_OPDE(v) (((v) & 0xF) << 4) ++#define RPC_SMENR_SPIDE(v) (((v) & 0xF) << 0) ++ ++#define RPC_SMRDR0 0x0038 /* R */ ++#define RPC_SMRDR1 0x003C /* R */ ++#define RPC_SMWDR0 0x0040 /* R/W */ ++#define RPC_SMWDR1 0x0044 /* R/W */ ++#define RPC_CMNSR 0x0048 /* R */ ++#define RPC_CMNSR_SSLF (0x1 << 1) ++#define RPC_CMNSR_TEND (0x1 << 0) ++ ++#define RPC_DRDMCR 0x0058 /* R/W */ ++#define RPC_DRDMCR_DMCYC(v) (((v) & 0xF) << 0) ++ ++#define RPC_DRDRENR 0x005C /* R/W */ ++#define RPC_DRDRENR_HYPE (0x5 << 12) ++#define RPC_DRDRENR_ADDRE (0x1 << 0x8) ++#define RPC_DRDRENR_OPDRE (0x1 << 0x4) ++#define RPC_DRDRENR_DRDRE (0x1 << 0x0) ++ ++#define RPC_SMDMCR 0x0060 /* R/W */ ++#define RPC_SMDMCR_DMCYC(v) (((v) & 0xF) << 0) ++ ++#define RPC_SMDRENR 0x0064 /* R/W */ ++#define RPC_SMDRENR_HYPE (0x5 << 12) ++#define RPC_SMDRENR_ADDRE (0x1 << 0x8) ++#define RPC_SMDRENR_OPDRE (0x1 << 0x4) ++#define RPC_SMDRENR_SPIDRE (0x1 << 0x0) ++ ++#define RPC_PHYCNT 0x007C /* R/W */ ++#define RPC_PHYCNT_CAL (0x1 << 31) ++#define PRC_PHYCNT_OCTA_AA (0x1 << 22) ++#define PRC_PHYCNT_OCTA_SA (0x2 << 22) ++#define PRC_PHYCNT_EXDS (0x1 << 21) ++#define RPC_PHYCNT_OCT (0x1 << 20) ++#define RPC_PHYCNT_WBUF2 (0x1 << 4) ++#define RPC_PHYCNT_WBUF (0x1 << 2) ++#define RPC_PHYCNT_MEM(v) (((v) & 0x3) << 0) ++ ++#define RPC_PHYINT 0x0088 /* R/W */ ++#define RPC_PHYINT_RSTEN (0x1 << 18) ++#define RPC_PHYINT_WPEN (0x1 << 17) ++#define RPC_PHYINT_INTEN (0x1 << 16) ++#define RPC_PHYINT_RST (0x1 << 2) ++#define RPC_PHYINT_WP (0x1 << 1) ++#define RPC_PHYINT_INT (0x1 << 0) ++ ++#define RPC_WBUF 0x8000 /* R/W size=4/8/16/32/64Bytes */ ++#define RPC_WBUF_SIZE 0x100 ++ ++struct rpc_info { ++ struct rw_semaphore lock; ++ void __iomem *rpc_base; ++ void __iomem *flash_base; ++ struct resource *rpc_res; ++ struct resource *flash_res; ++ u32 flash_id; ++ struct mtd_info mtd; ++}; ++ ++static inline void __iomem *rpc_addr(struct rpc_info *info, u32 offset) ++{ ++ return info->rpc_base + offset; ++} ++ ++static inline u32 rpc_readl(struct rpc_info *info, u32 offset) ++{ ++ u32 val; ++ ++ val = readl(rpc_addr(info, offset)); ++ return val; ++} ++ ++static inline void rpc_writel(struct rpc_info *info, u32 offset, u32 val) ++{ ++ writel(val, rpc_addr(info, offset)); ++} ++ ++static inline void rpc_setl(struct rpc_info *info, u32 offset, u32 mask, u32 set) ++{ ++ void __iomem *addr; ++ u32 val; ++ ++ addr = rpc_addr(info, offset); ++ val = readl(addr); ++ val &= mask; ++ val |= set; ++ writel(val, addr); ++} ++ ++static void rpc_wait_tend(struct rpc_info *info) ++{ ++ while (!(rpc_readl(info, RPC_CMNSR) & RPC_CMNSR_TEND)) ++ cpu_relax(); ++} ++ ++/* RPC HyperFlash */ ++#define RPC_HF_CMD_CA47 (0x1 << 7) /* Read */ ++#define RPC_HF_CMD_CA46 (0x1 << 6) /* Register space */ ++#define RPC_HF_CMD_CA45 (0x1 << 5) /* Liner burst */ ++ ++#define RPC_HF_CMD_READ_REG (RPC_HF_CMD_CA47 | RPC_HF_CMD_CA46) ++#define RPC_HF_CMD_READ_MEM RPC_HF_CMD_CA47 ++#define RPC_HF_CMD_WRITE_REG RPC_HF_CMD_CA46 ++#define RPC_HF_CMD_WRITE_MEM 0x0 ++ ++#define RPC_HF_ERASE_SIZE 0x40000 ++ ++#define RPC_CFI_STATUS_DRB (0x1 << 7) ++#define RPC_CFI_STATUS_ESSB (0x1 << 6) ++#define RPC_CFI_STATUS_ESB (0x1 << 5) ++#define RPC_CFI_STATUS_PSB (0x1 << 4) ++#define RPC_CFI_STATUS_WBASB (0x1 << 3) ++#define RPC_CFI_STATUS_PSSB (0x1 << 2) ++#define RPC_CFI_STATUS_SLSB (0x1 << 1) ++#define RPC_CFI_STATUS_ESTAT (0x1 << 0) ++ ++#define RPC_CFI_UNLOCK1 (0x555 << 1) ++#define RPC_CFI_UNLOCK2 (0x2AA << 1) ++ ++#define RPC_CFI_CMD_UNLOCK_START 0xAA ++#define RPC_CFI_CMD_UNLOCK_ACK 0x55 ++#define RPC_CFI_CMD_RESET 0xF0 ++#define RPC_CFI_CMD_READ_STATUS 0x70 ++#define RPC_CFI_CMD_READ_ID 0x90 ++#define RPC_CFI_CMD_WRITE 0xA0 ++#define RPC_CFI_CMD_ERASE_START 0x80 ++#define RPC_CFI_CMD_ERASE_SECTOR 0x30 ++ ++#define RPC_CFI_ID_MASK 0x000F ++#define RPC_CFI_ID_MAN_SPANSION 0x0001 ++#define RPC_CFI_ID_TYPE_HYPERFLASH 0x000E ++ ++enum rpc_hf_size { ++ RPC_HF_SIZE_16BIT = RPC_SMENR_SPIDE(0x8), ++ RPC_HF_SIZE_32BIT = RPC_SMENR_SPIDE(0xC), ++ RPC_HF_SIZE_64BIT = RPC_SMENR_SPIDE(0xF), ++}; ++ ++struct rpc_info *rpc_info; ++ ++static void rpc_hf_mode_man(struct rpc_info *info) ++{ ++ rpc_wait_tend(info); ++ ++ /* ++ * RPC_PHYCNT = 0x80000263 ++ * bit31 CAL = 1 : PHY calibration ++ * bit1-0 PHYMEM[1:0] = 11 : HyperFlash ++ */ ++ rpc_setl(info, RPC_PHYCNT, ++ ~(RPC_PHYCNT_WBUF | RPC_PHYCNT_WBUF2 | ++ RPC_PHYCNT_CAL | RPC_PHYCNT_MEM(3)), ++ RPC_PHYCNT_CAL | RPC_PHYCNT_MEM(3)); ++ ++ /* ++ * RPC_CMNCR = 0x81FFF301 ++ * bit31 MD = 1 : Manual mode ++ * bit1-0 BSZ[1:0] = 01 : QSPI Flash x 2 or HyperFlash ++ */ ++ rpc_setl(info, RPC_CMNCR, ++ ~(RPC_CMNCR_MD | RPC_CMNCR_BSZ(3)), ++ RPC_CMNCR_MOIIO_HIZ | RPC_CMNCR_IOFV_HIZ | ++ RPC_CMNCR_MD | RPC_CMNCR_BSZ(1)); ++} ++ ++static void rpc_hf_mode_ext(struct rpc_info *info) ++{ ++ rpc_wait_tend(info); ++ ++ /* ++ * RPC_PHYCNT = 0x80000263 ++ * bit31 CAL = 1 : PHY calibration ++ * bit1-0 PHYMEM[1:0] = 11 : HyperFlash ++ */ ++ rpc_setl(info, RPC_PHYCNT, ++ ~(RPC_PHYCNT_WBUF | RPC_PHYCNT_WBUF2 | ++ RPC_PHYCNT_CAL | RPC_PHYCNT_MEM(3)), ++ RPC_PHYCNT_CAL | RPC_PHYCNT_MEM(3)); ++ ++ /* ++ * RPC_CMNCR = 0x81FFF301 ++ * bit31 MD = 1 : Manual mode ++ * bit1-0 BSZ[1:0] = 01 : QSPI Flash x 2 or HyperFlash ++ */ ++ rpc_setl(info, RPC_CMNCR, ++ ~(RPC_CMNCR_MD | RPC_CMNCR_BSZ(3)), ++ RPC_CMNCR_MOIIO_HIZ | RPC_CMNCR_IOFV_HIZ | ++ RPC_CMNCR_BSZ(1)); ++ ++ /* ++ * RPC_DRCR = 0x001F0100 ++ * bit21-16 RBURST[4:0] = 11111 : Read burst 32 64-bit data units ++ * bit9 RCF = 1 : Clear cache ++ * bit8 RBE = 1 : Read burst enable ++ */ ++ rpc_writel(info, RPC_DRCR, ++ RPC_DRCR_RBURST(0x1F) | RPC_DRCR_RCF | RPC_DRCR_RBE); ++ ++ rpc_writel(info, RPC_DRCMR, RPC_DRCMR_CMD(0xA0)); ++ rpc_writel(info, RPC_DRENR, ++ RPC_DRENR_CDB(2) | RPC_DRENR_OCDB(2) | ++ RPC_DRENR_ADB(2) | RPC_DRENR_SPIDB(2) | ++ RPC_DRENR_CDE | RPC_DRENR_OCDE | RPC_DRENR_ADE(4)); ++ rpc_writel(info, RPC_DRDMCR, RPC_DRDMCR_DMCYC(0xE)); ++ rpc_writel(info, RPC_DRDRENR, ++ RPC_DRDRENR_HYPE | RPC_DRDRENR_ADDRE | RPC_DRDRENR_DRDRE); ++ ++ /* Dummy read */ ++ rpc_readl(info, RPC_DRCR); ++} ++ ++static void rpc_hf_xfer(struct rpc_info *info, u32 addr, u16 *data, ++ enum rpc_hf_size size, u8 cmd) ++{ ++ u32 val; ++ ++ rpc_hf_mode_man(info); ++ ++ /* ++ * bit23-21 CMD[7:5] : CA47-45 ++ * CA47 = 0/1 : Write/Read ++ * CA46 = 0/1 : Memory Space/Register Space ++ * CA45 = 0/1 : Wrapped Burst/Linear Burst ++ */ ++ rpc_writel(info, RPC_SMCMR, RPC_SMCMR_CMD(cmd)); ++ ++ rpc_writel(info, RPC_SMADR, addr >> 1); ++ ++ rpc_writel(info, RPC_SMOPR, 0x0); ++ ++ /* ++ * RPC_SMDRENR = 0x00005101 ++ * bit14-12 HYPE = 101: Hyperflash mode ++ * bit8 ADDRE = 1 : Address DDR transfer ++ * bit0 SPIDRE = 1 : DATA DDR transfer ++ */ ++ rpc_writel(info, RPC_SMDRENR, ++ RPC_SMDRENR_HYPE | RPC_SMDRENR_ADDRE | RPC_SMDRENR_SPIDRE); ++ ++ val = RPC_SMENR_CDB(2) | RPC_SMENR_OCDB(2) | ++ RPC_SMENR_ADB(2) | RPC_SMENR_SPIDB(2) | ++ RPC_SMENR_CDE | RPC_SMENR_OCDE | RPC_SMENR_ADE(4) | size; ++ ++ if (cmd & RPC_HF_CMD_CA47) ++ goto read_transfer; ++ ++ /* ++ * RPC_SMENR = 0xA222540x ++ * bit31-30 CDB[1:0] = 10 : 4bit width command ++ * bit25-24 ADB[1:0] = 10 : 4bit width address ++ * bit17-16 SPIDB[1:0] = 10 : 4bit width transfer data ++ * bit15 DME = 0 : dummy cycle disable ++ * bit14 CDE = 1 : Command enable ++ * bit12 OCDE = 1 : Option Command enable ++ * bit11-8 ADE[3:0] = 0100 : ADR[23:0] output ++ * bit7-4 OPDE[3:0] = 0000 : Option data disable ++ * bit3-0 SPIDE[3:0] = xxxx : Transfer size ++ */ ++ rpc_writel(info, RPC_SMENR, val); ++ ++ switch (size) { ++ case RPC_HF_SIZE_64BIT: ++ val = cmd & RPC_HF_CMD_CA46 ? ++ cpu_to_be16(data[0]) | cpu_to_be16(data[1]) << 16 : ++ data[0] | data[1] << 16; ++ rpc_writel(info, RPC_SMWDR1, val); ++ val = cmd & RPC_HF_CMD_CA46 ? ++ cpu_to_be16(data[2]) | cpu_to_be16(data[3]) << 16 : ++ data[2] | data[3] << 16; ++ break; ++ case RPC_HF_SIZE_32BIT: ++ val = cmd & RPC_HF_CMD_CA46 ? ++ cpu_to_be16(data[0]) | cpu_to_be16(data[1]) << 16 : ++ data[0] | data[1] << 16; ++ break; ++ default: ++ val = cmd & RPC_HF_CMD_CA46 ? ++ cpu_to_be16(data[0]) << 16 : ++ data[0] << 16; ++ break; ++ } ++ ++ rpc_writel(info, RPC_SMWDR0, val); ++ /* ++ * RPC_SMCR = 0x00000003 ++ * bit1 SPIWE = 1 : Data write enable ++ * bit0 SPIE = 1 : SPI transfer start ++ */ ++ rpc_writel(info, RPC_SMCR, RPC_SMCR_SPIWE | RPC_SMCR_SPIE); ++ return; ++ ++read_transfer: ++ rpc_writel(info, RPC_SMDMCR, RPC_SMDMCR_DMCYC(0xE)); ++ val |= RPC_SMENR_DME; ++ ++ /* ++ * RPC_SMENR = 0xA222D40x ++ * bit31-30 CDB[1:0] = 10 : 4bit width command ++ * bit25-24 ADB[1:0] = 10 : 4bit width address ++ * bit17-16 SPIDB[1:0] = 10 : 4bit width transfer data ++ * bit15 DME = 1 : dummy cycle disable ++ * bit14 CDE = 1 : Command enable ++ * bit12 OCDE = 1 : Option Command enable ++ * bit11-8 ADE[3:0] = 0100 : ADR[23:0] output (24 Bit Address) ++ * bit7-4 OPDE[3:0] = 0000 : Option data disable ++ * bit3-0 SPIDE[3:0] = xxxx : Transfer size ++ */ ++ rpc_writel(info, RPC_SMENR, val); ++ ++ /* ++ * RPC_SMCR = 0x00000005 ++ * bit2 SPIRE = 1 : Data read disable ++ * bit0 SPIE = 1 : SPI transfer start ++ */ ++ rpc_writel(info, RPC_SMCR, RPC_SMCR_SPIRE | RPC_SMCR_SPIE); ++ ++ rpc_wait_tend(info); ++ val = rpc_readl(info, RPC_SMRDR0); ++ ++ /* ++ * Read data from either register or memory space. ++ * Register space is always big-endian. ++ */ ++ switch (size) { ++ case RPC_HF_SIZE_64BIT: ++ if (cmd & RPC_HF_CMD_CA46) { ++ data[3] = be16_to_cpu((val >> 16) & 0xFFFF); ++ data[2] = be16_to_cpu(val & 0xFFFF); ++ } else { ++ data[3] = (val >> 16) & 0xFFFF; ++ data[2] = val & 0xFFFF; ++ } ++ val = rpc_readl(info, RPC_SMRDR1); ++ if (cmd & RPC_HF_CMD_CA46) { ++ data[1] = be16_to_cpu((val >> 16) & 0xFFFF); ++ data[0] = be16_to_cpu(val & 0xFFFF); ++ } else { ++ data[1] = (val >> 16) & 0xFFFF; ++ data[0] = val & 0xFFFF; ++ } ++ break; ++ case RPC_HF_SIZE_32BIT: ++ if (cmd & RPC_HF_CMD_CA46) { ++ data[1] = be16_to_cpu((val >> 16) & 0xFFFF); ++ data[0] = be16_to_cpu(val & 0xFFFF); ++ } else { ++ data[1] = (val >> 16) & 0xFFFF; ++ data[0] = val & 0xFFFF; ++ } ++ break; ++ default: ++ data[0] = cmd & RPC_HF_CMD_CA46 ? ++ be16_to_cpu((val >> 16) & 0xFFFF) : ++ (val >> 16) & 0xFFFF; ++ break; ++ } ++} ++ ++static void rpc_hf_wbuf_enable(struct rpc_info *info) ++{ ++ rpc_wait_tend(info); ++ ++ /* ++ * RPC_PHYCNT = 0x80000277 ++ * bit31 CAL = 1 : PHY calibration ++ * bit4 WBUF2 = 1 : Write buffer enable 2 ++ * bit2 WBUF = 1 : Write buffer enable ++ * bit1-0 PHYMEM[1:0] = 11 : HyperFlash ++ */ ++ rpc_setl(info, RPC_PHYCNT, ++ ~(RPC_PHYCNT_WBUF2 | RPC_PHYCNT_WBUF | ++ RPC_PHYCNT_CAL | RPC_PHYCNT_MEM(3)), ++ RPC_PHYCNT_WBUF2 | RPC_PHYCNT_WBUF | ++ RPC_PHYCNT_CAL | RPC_PHYCNT_MEM(3)); ++ ++ /* ++ * RPC_DRCR = 0x001F0100 ++ * bit21-16 RBURST[4:0] = 11111 : Read burst 32 64-bit data units ++ * bit9 RCF = 1 : Clear cache ++ * bit8 RBE = 1 : Read burst enable ++ */ ++ rpc_writel(info, RPC_DRCR, ++ RPC_DRCR_RBURST(0x1F) | RPC_DRCR_RCF | RPC_DRCR_RBE); ++ ++ rpc_writel(info, RPC_SMCMR, RPC_SMCMR_CMD(RPC_HF_CMD_WRITE_MEM)); ++ ++ rpc_writel(info, RPC_SMOPR, 0x0); ++ ++ /* ++ * RPC_SMDRENR = 0x00005101 ++ * bit14-12 HYPE = 101:Hyperflash mode ++ * bit8 ADDRE = 1 : Address DDR transfer ++ * bit0 SPIDRE = 1 : DATA DDR transfer ++ */ ++ rpc_writel(info, RPC_SMDRENR, ++ RPC_SMDRENR_HYPE | RPC_SMDRENR_ADDRE | RPC_SMDRENR_SPIDRE); ++ ++ /* ++ * RPC_SMENR = 0xA222540F ++ * bit31-30 CDB[1:0] = 10 : 4bit width command ++ * bit25-24 ADB[1:0] = 10 : 4bit width address ++ * bit17-16 SPIDB[1:0] = 10 : 4bit width transfer data ++ * bit15 DME = 0 : dummy cycle disable ++ * bit14 CDE = 1 : Command enable ++ * bit12 OCDE = 1 : Option Command enable ++ * bit11-8 ADE[3:0] = 0100 : ADR[23:0] output (24 Bit Address) ++ * bit7-4 OPDE[3:0] = 0000 : Option data disable ++ * bit3-0 SPIDE[3:0] = 1111 : 64-bit transfer size ++ */ ++ rpc_writel(info, RPC_SMENR, ++ RPC_SMENR_CDB(2) | RPC_SMENR_OCDB(2) | ++ RPC_SMENR_ADB(2) | RPC_SMENR_SPIDB(2) | ++ RPC_SMENR_CDE | RPC_SMENR_OCDE | ++ RPC_SMENR_ADE(4) | RPC_HF_SIZE_64BIT); ++ ++ /* Dummy read */ ++ rpc_readl(info, RPC_DRCR); ++} ++ ++static inline void rpc_hf_write_cmd(struct rpc_info *info, u32 addr, u16 cmd) ++{ ++ rpc_hf_xfer(info, addr, &cmd, RPC_HF_SIZE_16BIT, RPC_HF_CMD_WRITE_REG); ++} ++ ++static inline void rpc_hf_read_reg(struct rpc_info *info, u32 addr, u16 *data, ++ enum rpc_hf_size size) ++{ ++ rpc_hf_xfer(info, addr, data, size, RPC_HF_CMD_READ_REG); ++} ++ ++static inline void rpc_hf_write_reg(struct rpc_info *info, u32 addr, u16 *data, ++ enum rpc_hf_size size) ++{ ++ rpc_hf_xfer(info, addr, data, size, RPC_HF_CMD_WRITE_REG); ++} ++ ++static inline void rpc_hf_read_mem(struct rpc_info *info, u32 addr, u16 *data, ++ enum rpc_hf_size size) ++{ ++ rpc_hf_xfer(info, addr, data, size, RPC_HF_CMD_READ_MEM); ++} ++ ++static inline void rpc_hf_write_mem(struct rpc_info *info, u32 addr, u16 *data, ++ enum rpc_hf_size size) ++{ ++ rpc_hf_xfer(info, addr, data, size, RPC_HF_CMD_WRITE_MEM); ++} ++ ++static void rpc_hf_wp(struct rpc_info *info, int enable) ++{ ++ rpc_setl(info, RPC_PHYINT, ~RPC_PHYINT_WP, enable ? RPC_PHYINT_WP : 0); ++} ++ ++static void rpc_hf_unlock(struct rpc_info *info, u32 addr) ++{ ++ rpc_hf_write_cmd(info, addr + RPC_CFI_UNLOCK1, ++ RPC_CFI_CMD_UNLOCK_START); ++ rpc_hf_write_cmd(info, addr + RPC_CFI_UNLOCK2, ++ RPC_CFI_CMD_UNLOCK_ACK); ++} ++ ++static inline int rpc_hf_status(struct rpc_info *info, u32 addr, ++ int iterations, int delay) ++{ ++ int retval; ++ u16 status = 0; ++ ++ while (iterations-- > 0) { ++ rpc_hf_write_cmd(info, addr + RPC_CFI_UNLOCK1, RPC_CFI_CMD_READ_STATUS); ++ rpc_hf_read_reg(info, addr, &status, RPC_HF_SIZE_16BIT); ++ ++ if (status & RPC_CFI_STATUS_DRB) ++ break; ++ ++ if (delay < 10000) ++ usleep_range(delay, delay * 2); ++ else ++ msleep(delay / 1000); ++ } ++ ++ if (!(status & RPC_CFI_STATUS_DRB)) { ++ retval = -ETIMEDOUT; ++ goto out; ++ } ++ ++ if (status & (RPC_CFI_STATUS_PSB | RPC_CFI_STATUS_ESB)) { ++ retval = -EIO; ++ goto out; ++ } ++ ++ return 0; ++ ++out: ++ /* Reset the flash */ ++ rpc_hf_write_cmd(info, 0, RPC_CFI_CMD_RESET); ++ return retval; ++} ++ ++static int rpc_hf_sector_erase(struct rpc_info *info, u32 addr) ++{ ++ rpc_hf_unlock(info, addr); ++ rpc_hf_write_cmd(info, addr + RPC_CFI_UNLOCK1, RPC_CFI_CMD_ERASE_START); ++ rpc_hf_unlock(info, addr); ++ rpc_hf_write_cmd(info, addr, RPC_CFI_CMD_ERASE_SECTOR); ++ ++ return rpc_hf_status(info, addr, 1000, 10000); ++} ++ ++/* Flash read */ ++static int rpc_hf_mtd_read(struct mtd_info *mtd, loff_t from, size_t len, ++ size_t *retlen, u_char *buf) ++{ ++ struct rpc_info *info = mtd->priv; ++ ++ down_read(&info->lock); ++ memcpy_fromio(buf, info->flash_base + from, len); ++ up_read(&info->lock); ++ ++ *retlen = len; ++ return 0; ++} ++ ++/* Flash erase */ ++static int rpc_hf_mtd_erase(struct mtd_info *mtd, struct erase_info *instr) ++{ ++ struct rpc_info *info = mtd->priv; ++ u32 addr, end; ++ int retval = 0; ++ ++ if (mtd_mod_by_eb(instr->addr, mtd)) { ++ pr_debug("%s: unaligned address\n", __func__); ++ return -EINVAL; ++ } ++ ++ if (mtd_mod_by_eb(instr->len, mtd)) { ++ pr_debug("%s: unaligned length\n", __func__); ++ return -EINVAL; ++ } ++ ++ end = instr->addr + instr->len; ++ ++ down_write(&info->lock); ++ for (addr = instr->addr; addr < end; addr += mtd->erasesize) { ++ retval = rpc_hf_sector_erase(info, addr); ++ ++ if (retval) ++ break; ++ } ++ ++ rpc_hf_mode_ext(info); ++ up_write(&info->lock); ++ ++ instr->state = retval ? MTD_ERASE_FAILED : MTD_ERASE_DONE; ++ mtd_erase_callback(instr); ++ ++ return retval; ++} ++ ++/* Copy memory to flash */ ++static int rpc_hf_mtd_write(struct mtd_info *mtd, loff_t offset, size_t len, ++ size_t *retlen, const u_char *src) ++{ ++ struct rpc_info *info = mtd->priv; ++ union { ++ u8 b[4]; ++ u16 w[2]; ++ u32 d; ++ } data; ++ loff_t addr; ++ size_t size, cnt; ++ int retval, idx; ++ u8 last; ++ ++ retval = 0; ++ *retlen = 0; ++ cnt = len; ++ idx = 0; ++ ++ down_write(&info->lock); ++ ++ /* Handle unaligned start */ ++ if (offset & 0x1) { ++ offset--; ++ data.b[idx] = readb(info->flash_base + offset); ++ idx++; ++ } ++ ++ /* Handle unaligned end */ ++ addr = offset + idx + len; ++ last = addr & 0x1 ? readb(info->flash_base + addr) : 0xFF; ++ ++ addr = offset - mtd_mod_by_eb(offset, mtd); ++ size = mtd->erasesize - (offset - addr); ++ ++ while (cnt) { ++ if (size > cnt) ++ size = cnt; ++ ++ cnt -= size; ++ while (size) { ++ rpc_hf_unlock(info, addr); ++ rpc_hf_write_cmd(info, ++ addr + RPC_CFI_UNLOCK1, ++ RPC_CFI_CMD_WRITE); ++ ++ if (size > 0x7) { ++ u32 wbuf = RPC_WBUF; ++ int block = size >= RPC_WBUF_SIZE ? ++ RPC_WBUF_SIZE : size & ~0x7; ++ ++ rpc_hf_wbuf_enable(info); ++ ++ rpc_writel(info, RPC_SMADR, offset >> 1); ++ offset += block; ++ ++ block >>= 3; ++ while (block--) { ++ while (idx < 4) { ++ data.b[idx++] = *src++; ++ size--; ++ } ++ rpc_writel(info, wbuf, data.d); ++ wbuf += 4; ++ ++ idx = 0; ++ while (idx < 4) { ++ data.b[idx++] = *src++; ++ size--; ++ } ++ rpc_writel(info, wbuf, data.d); ++ wbuf += 4; ++ ++ idx = 0; ++ } ++ ++ rpc_writel(info, RPC_SMCR, ++ RPC_SMCR_SPIWE | RPC_SMCR_SPIE); ++ } else { ++ enum rpc_hf_size bits; ++ ++ while (idx < 4) { ++ data.b[idx++] = *src++; ++ size--; ++ ++ if (!size) ++ break; ++ } ++ ++ if (idx & 0x1) ++ data.b[idx++] = last; ++ ++ switch (idx) { ++ case 2: ++ bits = RPC_HF_SIZE_16BIT; ++ break; ++ default: ++ bits = RPC_HF_SIZE_32BIT; ++ break; ++ } ++ ++ rpc_hf_write_mem(info, offset, data.w, bits); ++ offset += idx; ++ idx = 0; ++ } ++ ++ retval = rpc_hf_status(info, addr, 1000000, 10); ++ if (retval) ++ goto out; ++ } ++ ++ size = mtd->erasesize; ++ addr += size; ++ offset = addr; ++ *retlen = len - cnt; ++ } ++ ++out: ++ rpc_hf_mode_ext(info); ++ up_write(&info->lock); ++ return retval; ++} ++ ++static struct mtd_partition partition_info[]={ ++ { ++ .name = "bootparam", ++ .offset = 0, ++ .size = 0x40000, ++ }, { ++ .name = "bl2", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0x140000 ++ }, { ++ .name = "cert_header", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0x40000, ++ }, { ++ .name = "bl31", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0x40000, ++ }, { ++ .name = "optee", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0x440000, ++ }, { ++ .name = "u-boot", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0x80000, ++ }, { ++ .name = "reserved", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0x80000, ++ }, { ++ .name = "u-boot-env", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0x40000, ++ }, { ++ .name = "dtb", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0x80000, ++ }, { ++ .name = "kernel", ++ .offset = MTDPART_OFS_APPEND, ++ .size = 0x1000000, ++ }, { ++ .name = "user", ++ .offset = MTDPART_OFS_APPEND, ++ .size = MTDPART_SIZ_FULL, ++ }, ++}; ++ ++static int rpc_hf_init_mtd(struct rpc_info *info) ++{ ++ struct mtd_info *mtd = &info->mtd; ++ u16 data[2] = { 0, 0 }; ++ u32 id, size; ++ int retval; ++ ++ rpc_hf_mode_ext(info); ++ ++ rpc_hf_wp(info, 0); ++ ++ rpc_hf_unlock(info, 0); ++ rpc_hf_write_cmd(info, RPC_CFI_UNLOCK1, RPC_CFI_CMD_READ_ID); ++ ++ rpc_hf_read_reg(info, 0x0, data, RPC_HF_SIZE_32BIT); ++ if ((data[0] & RPC_CFI_ID_MASK) != RPC_CFI_ID_MAN_SPANSION || ++ (data[1] & RPC_CFI_ID_MASK) != RPC_CFI_ID_TYPE_HYPERFLASH) { ++ retval = -ENODEV; ++ goto out; ++ } ++ ++ id = data[0] | data[1] << 16; ++ ++ rpc_hf_read_reg(info, 0x27 << 1, data, RPC_HF_SIZE_16BIT); ++ size = 1 << data[0]; ++ ++ if (size > resource_size(info->flash_res)) ++ size = resource_size(info->flash_res); ++ ++ if (size & (RPC_HF_ERASE_SIZE - 1)) { ++ retval = -EINVAL; ++ goto out; ++ } ++ ++ init_rwsem(&info->lock); ++ info->flash_id = id; ++ mtd->name = "HyperFlash"; ++ mtd->type = MTD_NORFLASH; ++ mtd->flags = MTD_CAP_NORFLASH; ++ mtd->size = size; ++ mtd->writesize = 1; ++ mtd->writebufsize = RPC_WBUF_SIZE; ++ mtd->erasesize = RPC_HF_ERASE_SIZE; ++ mtd->owner = THIS_MODULE; ++ mtd->priv = info; ++ mtd->_erase = rpc_hf_mtd_erase; ++ mtd->_write = rpc_hf_mtd_write; ++ mtd->_read = rpc_hf_mtd_read; ++ retval = mtd_device_register(mtd, partition_info, ++ ARRAY_SIZE(partition_info)); ++out: ++ rpc_hf_write_cmd(info, 0, RPC_CFI_CMD_RESET); ++ rpc_hf_mode_ext(info); ++ return retval; ++} ++ ++static int rpc_flash_init(void) ++{ ++ struct rpc_info *info; ++ struct resource *res; ++ void __iomem *base; ++ int retval = -ENODEV; ++ ++ if (!of_machine_is_compatible("renesas,r8a7795")) ++ return -ENODEV; ++ ++ info = kzalloc(sizeof(*info), GFP_KERNEL); ++ if (!info) ++ return -ENOMEM; ++ ++ res = request_mem_region(RPC_BASE, RPC_SIZE, "RPC"); ++ if (!res) ++ goto out_info; ++ ++ info->rpc_res = res; ++ base = ioremap(res->start, resource_size(res)); ++ if (!base) ++ goto out_rpc_res; ++ ++ info->rpc_base = base; ++ res = request_mem_region(RPC_FLASH_BASE, RPC_FLASH_SIZE, "RPC-ext"); ++ if (!res) ++ goto out_rpc_base; ++ ++ info->flash_res = res; ++ base = ioremap(res->start, resource_size(res)); ++ if (!base) ++ goto out_flash_res; ++ ++ info->flash_base = base; ++ retval = rpc_hf_init_mtd(info); ++ if (retval) ++ goto out_flash_base; ++ ++ pr_info("HyperFlash Id: %x\n", info->flash_id); ++ ++ rpc_info = info; ++ return 0; ++ ++out_flash_base: ++ iounmap(info->flash_base); ++out_flash_res: ++ release_mem_region(info->flash_res->start, ++ resource_size(info->flash_res)); ++out_rpc_base: ++ iounmap(info->rpc_base); ++out_rpc_res: ++ release_mem_region(info->rpc_res->start, ++ resource_size(info->rpc_res)); ++out_info: ++ kfree(info); ++ return retval; ++} ++ ++static void rpc_flash_exit(void) ++{ ++ struct rpc_info *info = rpc_info; ++ ++ if (!info) ++ return; ++ ++ rpc_info = NULL; ++ ++ mtd_device_unregister(&info->mtd); ++ ++ iounmap(info->flash_base); ++ release_mem_region(info->flash_res->start, ++ resource_size(info->flash_res)); ++ iounmap(info->rpc_base); ++ release_mem_region(info->rpc_res->start, ++ resource_size(info->rpc_res)); ++ kfree(info); ++} ++ ++module_init(rpc_flash_init); ++module_exit(rpc_flash_exit); ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_DESCRIPTION("Renesas RPC HyperFlash MTD driver"); +-- +2.7.4 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0013-IMR-driver-interim-patch.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0013-IMR-driver-interim-patch.patch new file mode 100644 index 0000000..e863466 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0013-IMR-driver-interim-patch.patch @@ -0,0 +1,2104 @@ +From 240504b182a2816696c6a02fe37a5048925cc1fb Mon Sep 17 00:00:00 2001 +From: Konstantin Kozhevnikov <Konstantin.Kozhevnikov@cogentembedded.com> +Date: Wed, 7 Sep 2016 22:55:37 +0300 +Subject: [PATCH] IMR driver - interim patch + +Signed-off-by: Konstantin Kozhevnikov <Konstantin.Kozhevnikov@cogentembedded.com> +--- + arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi | 32 + + arch/arm64/boot/dts/renesas/r8a7795.dtsi | 32 + + drivers/clk/renesas/r8a7795-cpg-mssr.c | 4 + + drivers/media/platform/Kconfig | 11 + + drivers/media/platform/Makefile | 1 + + drivers/media/platform/rcar_imr.c | 1840 ++++++++++++++++++++++++++ + include/uapi/linux/rcar-imr.h | 98 ++ + 7 files changed, 2018 insertions(+) + create mode 100644 drivers/media/platform/rcar_imr.c + create mode 100644 include/uapi/linux/rcar-imr.h + +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi b/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi +index 09e1284..d530100 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi +@@ -2713,5 +2713,37 @@ + }; + }; + }; ++ ++ imrlx4_ch0: imr-lx4@fe860000 { ++ compatible = "renesas,imr-lx4"; ++ reg = <0 0xfe860000 0 0x2000>; ++ interrupts = <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>; ++ clocks = <&cpg CPG_MOD 823>; ++ power-domains = <&sysc R8A7795_PD_A3VC>; ++ }; ++ ++ imrlx4_ch1: imr-lx4@fe870000 { ++ compatible = "renesas,imr-lx4"; ++ reg = <0 0xfe870000 0 0x2000>; ++ interrupts = <GIC_SPI 193 IRQ_TYPE_LEVEL_HIGH>; ++ clocks = <&cpg CPG_MOD 822>; ++ power-domains = <&sysc R8A7795_PD_A3VC>; ++ }; ++ ++ imrlx4_ch2: imr-lx4@fe880000 { ++ compatible = "renesas,imr-lx4"; ++ reg = <0 0xfe880000 0 0x2000>; ++ interrupts = <GIC_SPI 194 IRQ_TYPE_LEVEL_HIGH>; ++ clocks = <&cpg CPG_MOD 821>; ++ power-domains = <&sysc R8A7795_PD_A3VC>; ++ }; ++ ++ imrlx4_ch3: imr-lx4@fe890000 { ++ compatible = "renesas,imr-lx4"; ++ reg = <0 0xfe890000 0 0x2000>; ++ interrupts = <GIC_SPI 195 IRQ_TYPE_LEVEL_HIGH>; ++ clocks = <&cpg CPG_MOD 820>; ++ power-domains = <&sysc R8A7795_PD_A3VC>; ++ }; + }; + }; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795.dtsi b/arch/arm64/boot/dts/renesas/r8a7795.dtsi +index 82ebfd4..9b4ee2f 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi +@@ -2699,5 +2699,37 @@ + }; + }; + }; ++ ++ imrlx4_ch0: imr-lx4@fe860000 { ++ compatible = "renesas,imr-lx4"; ++ reg = <0 0xfe860000 0 0x2000>; ++ interrupts = <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>; ++ clocks = <&cpg CPG_MOD 823>; ++ power-domains = <&sysc R8A7795_PD_A3VC>; ++ }; ++ ++ imrlx4_ch1: imr-lx4@fe870000 { ++ compatible = "renesas,imr-lx4"; ++ reg = <0 0xfe870000 0 0x2000>; ++ interrupts = <GIC_SPI 193 IRQ_TYPE_LEVEL_HIGH>; ++ clocks = <&cpg CPG_MOD 822>; ++ power-domains = <&sysc R8A7795_PD_A3VC>; ++ }; ++ ++ imrlx4_ch2: imr-lx4@fe880000 { ++ compatible = "renesas,imr-lx4"; ++ reg = <0 0xfe880000 0 0x2000>; ++ interrupts = <GIC_SPI 194 IRQ_TYPE_LEVEL_HIGH>; ++ clocks = <&cpg CPG_MOD 821>; ++ power-domains = <&sysc R8A7795_PD_A3VC>; ++ }; ++ ++ imrlx4_ch3: imr-lx4@fe890000 { ++ compatible = "renesas,imr-lx4"; ++ reg = <0 0xfe890000 0 0x2000>; ++ interrupts = <GIC_SPI 195 IRQ_TYPE_LEVEL_HIGH>; ++ clocks = <&cpg CPG_MOD 820>; ++ power-domains = <&sysc R8A7795_PD_A3VC>; ++ }; + }; + }; +diff --git a/drivers/clk/renesas/r8a7795-cpg-mssr.c b/drivers/clk/renesas/r8a7795-cpg-mssr.c +index 718afd6..f833031 100644 +--- a/drivers/clk/renesas/r8a7795-cpg-mssr.c ++++ b/drivers/clk/renesas/r8a7795-cpg-mssr.c +@@ -229,6 +229,10 @@ enum clk_ids { + DEF_MOD("vin0", 811, R8A7795_CLK_S0D2), + DEF_MOD("etheravb", 812, R8A7795_CLK_S0D6), + DEF_MOD("sata0", 815, R8A7795_CLK_S3D2), ++ DEF_MOD("imr3", 820, R8A7795_CLK_S2D1), ++ DEF_MOD("imr2", 821, R8A7795_CLK_S2D1), ++ DEF_MOD("imr1", 822, R8A7795_CLK_S2D1), ++ DEF_MOD("imr0", 823, R8A7795_CLK_S2D1), + DEF_MOD("gpio7", 905, R8A7795_CLK_CP), + DEF_MOD("gpio6", 906, R8A7795_CLK_CP), + DEF_MOD("gpio5", 907, R8A7795_CLK_CP), +diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig +index ba2b892..f4d12f5 100644 +--- a/drivers/media/platform/Kconfig ++++ b/drivers/media/platform/Kconfig +@@ -315,6 +315,17 @@ config VIDEO_RENESAS_FCP + To compile this driver as a module, choose M here: the module + will be called rcar-fcp. + ++config VIDEO_RENESAS_IMR ++ tristate "Renesas Image Renderer (Distortion Correction) Unit" ++ depends on VIDEO_DEV && VIDEO_V4L2 ++ select VIDEOBUF2_DMA_CONTIG ++ select V4L2_MEM2MEM_DEV ++ ---help--- ++ This is a V4L2 driver for the Renesas IMR-X2/LX2/LX4 Processing Unit. ++ ++ To compile this driver as a module, choose M here: the module ++ will be called rcar_imr. ++ + config VIDEO_RENESAS_VSP1 + tristate "Renesas VSP1 Video Processing Engine" + depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && HAS_DMA +diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile +index 40b18d1..9e9464c 100644 +--- a/drivers/media/platform/Makefile ++++ b/drivers/media/platform/Makefile +@@ -49,6 +49,7 @@ obj-$(CONFIG_SOC_CAMERA) += soc_camera/ + + obj-$(CONFIG_VIDEO_RENESAS_FCP) += rcar-fcp.o + obj-$(CONFIG_VIDEO_RENESAS_JPU) += rcar_jpu.o ++obj-$(CONFIG_VIDEO_RENESAS_IMR) += rcar_imr.o + obj-$(CONFIG_VIDEO_RENESAS_VSP1) += vsp1/ + + obj-y += omap/ +diff --git a/drivers/media/platform/rcar_imr.c b/drivers/media/platform/rcar_imr.c +new file mode 100644 +index 0000000..30c6742 +--- /dev/null ++++ b/drivers/media/platform/rcar_imr.c +@@ -0,0 +1,1840 @@ ++/* ++ * rcar_imr.c -- R-Car IMR-LX4 Driver ++ * ++ * Copyright (C) 2015 Cogent Embedded, Inc. <source@cogentembedded.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/platform_device.h> ++#include <linux/clk.h> ++#include <linux/interrupt.h> ++#include <linux/pm_runtime.h> ++#include <linux/delay.h> ++#include <linux/rcar-imr.h> ++#include <media/v4l2-device.h> ++#include <media/v4l2-ctrls.h> ++#include <media/v4l2-fh.h> ++#include <media/v4l2-mem2mem.h> ++#include <media/v4l2-ioctl.h> ++#include <media/videobuf2-dma-contig.h> ++ ++#define DRV_NAME "rcar_imr" ++ ++/******************************************************************************* ++ * Module parameters ++ ******************************************************************************/ ++ ++static int debug; ++module_param(debug, int, 0644); ++MODULE_PARM_DESC(debug, "Debug level (0-4)"); ++ ++/******************************************************************************* ++ * Local types definitions ++ ******************************************************************************/ ++ ++/* ...configuration data */ ++struct imr_cfg { ++ /* ...display-list main program data */ ++ void *dl_vaddr; ++ dma_addr_t dl_dma_addr; ++ u32 dl_size; ++ u32 dl_start_offset; ++ ++ /* ...pointers to the source/destination planes */ ++ u32 *src_pa_ptr[2]; ++ u32 *dst_pa_ptr[2]; ++ ++ /* ...subpixel destination coordinates space */ ++ int dst_subpixel; ++ ++ /* ...reference counter */ ++ u32 refcount; ++ ++ /* ...identifier (for debug output) */ ++ u32 id; ++}; ++ ++struct imr_buffer { ++ /* ...standard M2M buffer descriptor */ ++ struct v4l2_m2m_buffer buf; ++ ++ /* ...pointer to mesh configuration for processing */ ++ struct imr_cfg *cfg; ++}; ++ ++struct imr_q_data { ++ /* ...latched pixel format */ ++ struct v4l2_pix_format fmt; ++ ++ /* ...current format flags */ ++ u32 flags; ++}; ++ ++struct imr_format_info { ++ char *name; ++ u32 fourcc; ++ u32 flags; ++}; ++ ++/* ...per-device data */ ++struct imr_device { ++ struct device *dev; ++ struct clk *clock; ++ void __iomem *mmio; ++ int irq; ++ struct mutex mutex; ++ spinlock_t lock; ++ ++ struct v4l2_device v4l2_dev; ++ struct video_device video_dev; ++ struct v4l2_m2m_dev *m2m_dev; ++ ++ /* ...do we need that counter really? framework counts fh structures for us - tbd */ ++ int refcount; ++ ++ /* ...should we include media-dev? likely, no - tbd */ ++}; ++ ++/* ...per file-handle context */ ++struct imr_ctx { ++ struct v4l2_fh fh; ++ struct imr_device *imr; ++ struct v4l2_m2m_ctx *m2m_ctx; ++ struct imr_q_data queue[2]; ++ ++ /* ...current job configuration */ ++ struct imr_cfg *cfg; ++ ++ /* ...frame sequence counter */ ++ u32 sequence; ++ ++ /* ...cropping parameters (in pixels) */ ++ u16 crop[4]; ++ ++ /* ...number of active configurations (debugging) */ ++ u32 cfg_num; ++}; ++ ++/******************************************************************************* ++ * IMR registers ++ ******************************************************************************/ ++ ++#define IMR_CR 0x08 ++#define IMR_CR_RS (1 << 0) ++#define IMR_CR_SWRST (1 << 15) ++ ++#define IMR_SR 0x0C ++#define IMR_SRCR 0x10 ++#define IMR_SR_TRA (1 << 0) ++#define IMR_SR_IER (1 << 1) ++#define IMR_SR_INT (1 << 2) ++#define IMR_SR_REN (1 << 5) ++ ++#define IMR_ICR 0x14 ++#define IMR_IMR 0x18 ++#define IMR_ICR_TRAEN (1 << 0) ++#define IMR_ICR_IEREN (1 << 1) ++#define IMR_ICR_INTEN (1 << 2) ++ ++#define IMR_DLSP 0x1C ++#define IMR_DLSR 0x20 ++#define IMR_DLSAR 0x30 ++ ++#define IMR_DSAR 0x34 ++#define IMR_SSAR 0x38 ++#define IMR_DSTR 0x3C ++#define IMR_SSTR 0x40 ++#define IMR_DSOR 0x50 ++ ++#define IMR_CMRCR 0x54 ++#define IMR_CMRCSR 0x58 ++#define IMR_CMRCCR 0x5C ++#define IMR_CMR_LUCE (1 << 1) ++#define IMR_CMR_CLCE (1 << 2) ++#define IMR_CMR_DUV_SHIFT 3 ++#define IMR_CMR_DUV_MASK (3 << IMR_CMR_DUV_SHIFT) ++#define IMR_CMR_SUV_SHIFT 5 ++#define IMR_CMR_SUV_MASK (3 << IMR_CMR_SUV_SHIFT) ++#define IMR_CMR_YISM (1 << 7) ++#define IMR_CMR_DY10 (1 << 8) ++#define IMR_CMR_DY12 (1 << 9) ++#define IMR_CMR_SY10 (1 << 11) ++#define IMR_CMR_SY12 (1 << 12) ++#define IMR_CMR_YCM (1 << 14) ++#define IMR_CMR_CP16E (1 << 15) ++ ++#define IMR_CMRCR2 0xE4 ++#define IMR_CMRCSR2 0xE8 ++#define IMR_CMRCCR2 0xEC ++#define IMR_CMR2_LUTE (1 << 0) ++#define IMR_CMR2_YUV422E (1 << 2) ++#define IMR_CMR2_YUV422FORM (1 << 5) ++#define IMR_CMR2_UVFORM (1 << 6) ++#define IMR_CMR2_TCTE (1 << 12) ++#define IMR_CMR2_DCTE (1 << 15) ++ ++#define IMR_TRIMR 0x60 ++#define IMR_TRIMSR 0x64 ++#define IMR_TRIMCR 0x68 ++#define IMR_TRIM_TME (1 << 0) ++#define IMR_TRIM_BFE (1 << 1) ++#define IMR_TRIM_AUTODG (1 << 2) ++#define IMR_TRIM_AUTOSG (1 << 3) ++#define IMR_TRIM_DYDXM (1 << 4) ++#define IMR_TRIM_DUDVM (1 << 5) ++#define IMR_TRIM_TCM (1 << 6) ++ ++#define IMR_TRICR 0x6C ++#define IMR_TRIC_YCFORM (1 << 31) ++ ++#define IMR_UVDPOR 0x70 ++#define IMR_SUSR 0x74 ++#define IMR_SVSR 0x78 ++ ++#define IMR_XMINR 0x80 ++#define IMR_YMINR 0x84 ++#define IMR_XMAXR 0x88 ++#define IMR_YMAXR 0x8C ++ ++#define IMR_AMXSR 0x90 ++#define IMR_AMYSR 0x94 ++#define IMR_AMXOR 0x98 ++#define IMR_AMYOR 0x9C ++ ++#define IMR_CPDPOR 0xD0 ++#define IMR_CPDP_YLDPO_SHIFT 8 ++#define IMR_CPDP_UBDPO_SHIFT 4 ++#define IMR_CPDP_VRDPO_SHIFT 0 ++ ++/******************************************************************************* ++ * Auxiliary helpers ++ ******************************************************************************/ ++ ++static inline struct imr_ctx * fh_to_ctx(struct v4l2_fh *fh) ++{ ++ return container_of(fh, struct imr_ctx, fh); ++} ++ ++static inline struct imr_buffer * to_imr_buffer(struct vb2_v4l2_buffer *vbuf) ++{ ++ struct v4l2_m2m_buffer *b = container_of(vbuf, struct v4l2_m2m_buffer, vb); ++ ++ return container_of(b, struct imr_buffer, buf); ++} ++ ++/******************************************************************************* ++ * Local constants definition ++ ******************************************************************************/ ++ ++#define IMR_F_Y8 (1 << 0) ++#define IMR_F_Y10 (1 << 1) ++#define IMR_F_Y12 (1 << 2) ++#define IMR_F_UV8 (1 << 3) ++#define IMR_F_UV10 (1 << 4) ++#define IMR_F_UV12 (1 << 5) ++#define IMR_F_PLANAR (1 << 6) ++#define IMR_F_INTERLEAVED (1 << 7) ++#define IMR_F_PLANES_MASK ((1 << 8) - 1) ++#define IMR_F_UV_SWAP (1 << 8) ++#define IMR_F_YUV_SWAP (1 << 9) ++ ++/* ...get common planes bits */ ++static inline u32 __imr_flags_common(u32 iflags, u32 oflags) ++{ ++ return (iflags & oflags) & IMR_F_PLANES_MASK; ++} ++ ++static const struct imr_format_info imr_lx4_formats[] = { ++ { ++ .name = "YUV 4:2:2 semiplanar (NV16)", ++ .fourcc = V4L2_PIX_FMT_NV16, ++ .flags = IMR_F_Y8 | IMR_F_UV8 | IMR_F_PLANAR, ++ }, ++ { ++ .name = "YVU 4:2:2 semiplanar (NV61)", ++ .fourcc = V4L2_PIX_FMT_NV61, ++ .flags = IMR_F_Y8 | IMR_F_UV8 | IMR_F_PLANAR | IMR_F_UV_SWAP, ++ }, ++ { ++ .name = "YUV 4:2:2 interleaved (YUYV)", ++ .fourcc = V4L2_PIX_FMT_YUYV, ++ .flags = IMR_F_Y8 | IMR_F_UV8, ++ }, ++ { ++ .name = "YUV 4:2:2 interleaved (UYVY)", ++ .fourcc = V4L2_PIX_FMT_UYVY, ++ .flags = IMR_F_Y8 | IMR_F_UV8 | IMR_F_YUV_SWAP, ++ }, ++ { ++ .name = "YUV 4:2:2 interleaved (YVYU)", ++ .fourcc = V4L2_PIX_FMT_YVYU, ++ .flags = IMR_F_Y8 | IMR_F_UV8 | IMR_F_UV_SWAP, ++ }, ++ { ++ .name = "YUV 4:2:2 interleaved (UYVY)", ++ .fourcc = V4L2_PIX_FMT_VYUY, ++ .flags = IMR_F_Y8 | IMR_F_UV8 | IMR_F_UV_SWAP | IMR_F_YUV_SWAP, ++ }, ++ { ++ .name = "Greyscale 8-bit", ++ .fourcc = V4L2_PIX_FMT_GREY, ++ .flags = IMR_F_Y8 | IMR_F_PLANAR, ++ }, ++ { ++ .name = "Greyscale 10-bit", ++ .fourcc = V4L2_PIX_FMT_Y10, ++ .flags = IMR_F_Y8 | IMR_F_Y10 | IMR_F_PLANAR, ++ }, ++ { ++ .name = "Greyscale 12-bit", ++ .fourcc = V4L2_PIX_FMT_Y12, ++ .flags = IMR_F_Y8 | IMR_F_Y10 | IMR_F_Y12 | IMR_F_PLANAR, ++ }, ++ { ++ .name = "Chrominance UV 8-bit", ++ .fourcc = V4L2_PIX_FMT_UV8, ++ .flags = IMR_F_UV8 | IMR_F_PLANAR, ++ }, ++}; ++ ++/* ...mesh configuration constructor */ ++static struct imr_cfg * imr_cfg_create(struct imr_ctx *ctx, u32 dl_size, u32 dl_start) ++{ ++ struct imr_device *imr = ctx->imr; ++ struct imr_cfg *cfg; ++ ++ /* ...allocate configuration descriptor */ ++ cfg = kmalloc(sizeof(*cfg), GFP_KERNEL); ++ if (!cfg) { ++ v4l2_err(&imr->v4l2_dev, "failed to allocate configuration descriptor\n"); ++ return ERR_PTR(-ENOMEM); ++ } ++ ++ /* ...allocate contiguous memory for a display list */ ++ cfg->dl_vaddr = dma_alloc_writecombine(imr->dev, dl_size, &cfg->dl_dma_addr, GFP_KERNEL); ++ if (!cfg->dl_vaddr) { ++ v4l2_err(&imr->v4l2_dev, "failed to allocate %u bytes for a DL\n", dl_size); ++ kfree(cfg); ++ return ERR_PTR(-ENOMEM); ++ } ++ ++ cfg->dl_size = dl_size; ++ cfg->dl_start_offset = dl_start; ++ cfg->refcount = 1; ++ cfg->id = ctx->sequence; ++ ++ /* ...for debugging purposes, advance number of active configurations */ ++ ctx->cfg_num++; ++ ++ return cfg; ++} ++ ++/* ...add reference to the current configuration */ ++static inline struct imr_cfg * imr_cfg_ref(struct imr_ctx *ctx) ++{ ++ struct imr_cfg *cfg = ctx->cfg; ++ ++ BUG_ON(!cfg); ++ cfg->refcount++; ++ return cfg; ++} ++ ++/* ...mesh configuration destructor */ ++static void imr_cfg_unref(struct imr_ctx *ctx, struct imr_cfg *cfg) ++{ ++ struct imr_device *imr = ctx->imr; ++ ++ /* ...no atomicity is required as operation is locked with device mutex */ ++ if (!cfg || --cfg->refcount) ++ return; ++ ++ /* ...release memory allocated for a display list */ ++ if (cfg->dl_vaddr) ++ dma_free_writecombine(imr->dev, cfg->dl_size, cfg->dl_vaddr, cfg->dl_dma_addr); ++ ++ /* ...destroy the configuration structure */ ++ kfree(cfg); ++ ++ /* ...decrement number of active configurations (debugging) */ ++ WARN_ON(!ctx->cfg_num--); ++} ++ ++ ++ ++/******************************************************************************* ++ * Context processing queue ++ ******************************************************************************/ ++ ++static int imr_queue_setup(struct vb2_queue *vq, ++ unsigned int *nbuffers, unsigned int *nplanes, ++ unsigned int sizes[], struct device *alloc_devs[]) ++{ ++ struct imr_ctx *ctx = vb2_get_drv_priv(vq); ++ struct imr_q_data *q_data = &ctx->queue[V4L2_TYPE_IS_OUTPUT(vq->type) ? 0 : 1]; ++ int w = q_data->fmt.width; ++ int h = q_data->fmt.height; ++ ++ /* ...we use only single-plane formats */ ++ *nplanes = 1; ++ ++ /* ...specify plane size */ ++ switch (q_data->fmt.pixelformat) { ++ case V4L2_PIX_FMT_UYVY: ++ case V4L2_PIX_FMT_YUYV: ++ case V4L2_PIX_FMT_VYUY: ++ case V4L2_PIX_FMT_YVYU: ++ case V4L2_PIX_FMT_NV16: ++ case V4L2_PIX_FMT_Y10: ++ case V4L2_PIX_FMT_Y16: ++ sizes[0] = w * h * 2; ++ break; ++ ++ case V4L2_PIX_FMT_UV8: ++ case V4L2_PIX_FMT_GREY: ++ sizes[0] = w * h; ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int imr_buf_prepare(struct vb2_buffer *vb) ++{ ++ /* ...unclear yet if we want to prepare a buffer somehow (cache invalidation? - tbd) */ ++ return 0; ++} ++ ++static void imr_buf_queue(struct vb2_buffer *vb) ++{ ++ struct vb2_queue *q = vb->vb2_queue; ++ struct imr_ctx *ctx = vb2_get_drv_priv(q); ++ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); ++ ++ WARN_ON_ONCE(!mutex_is_locked(&ctx->imr->mutex)); ++ ++ v4l2_dbg(3, debug, &ctx->imr->v4l2_dev, "%sput buffer <0x%08llx> submitted\n", ++ q->is_output ? "in" : "out", ++ vb2_dma_contig_plane_dma_addr(vb, 0)); ++ ++ /* ...for input buffer, put current configuration pointer (add reference) */ ++ if (q->is_output) ++ to_imr_buffer(vbuf)->cfg = imr_cfg_ref(ctx); ++ ++ v4l2_m2m_buf_queue(ctx->m2m_ctx, vbuf); ++} ++ ++static void imr_buf_finish(struct vb2_buffer *vb) ++{ ++ struct vb2_queue *q = vb->vb2_queue; ++ struct imr_ctx *ctx = vb2_get_drv_priv(q); ++ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); ++ ++ WARN_ON(!mutex_is_locked(&ctx->imr->mutex)); ++ ++ /* ...any special processing of completed buffer? - tbd */ ++ v4l2_dbg(3, debug, &ctx->imr->v4l2_dev, "%sput buffer <0x%08llx> done\n", ++ q->is_output ? "in" : "out", ++ vb2_dma_contig_plane_dma_addr(vb, 0)); ++ ++ /* ...unref configuration pointer as needed */ ++ if (q->is_output) ++ imr_cfg_unref(ctx, to_imr_buffer(vbuf)->cfg); ++} ++ ++static int imr_start_streaming(struct vb2_queue *vq, unsigned int count) ++{ ++ struct imr_ctx *ctx = vb2_get_drv_priv(vq); ++ int ret; ++ ++ ret = 0;//pm_runtime_get_sync(ctx->imr->dev); ++ if (ret < 0) { ++ v4l2_err(&ctx->imr->v4l2_dev, "failed to start %s streaming: %d\n", ++ (V4L2_TYPE_IS_OUTPUT(vq->type) ? "output" : "capture"), ret); ++ return ret; ++ } else { ++ v4l2_dbg(1, debug, &ctx->imr->v4l2_dev, "%s streaming started\n", ++ (V4L2_TYPE_IS_OUTPUT(vq->type) ? "output" : "capture")); ++ return 0; ++ } ++} ++ ++static void imr_stop_streaming(struct vb2_queue *vq) ++{ ++ struct imr_ctx *ctx = vb2_get_drv_priv(vq); ++ struct vb2_v4l2_buffer *vb; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&ctx->imr->lock, flags); ++ ++ /* ...purge all buffers from a queue */ ++ if (V4L2_TYPE_IS_OUTPUT(vq->type)) { ++ while ((vb = v4l2_m2m_src_buf_remove(ctx->m2m_ctx)) != NULL) ++ v4l2_m2m_buf_done(vb, VB2_BUF_STATE_ERROR); ++ } else { ++ while ((vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx)) != NULL) ++ v4l2_m2m_buf_done(vb, VB2_BUF_STATE_ERROR); ++ } ++ ++ spin_unlock_irqrestore(&ctx->imr->lock, flags); ++ ++ v4l2_dbg(1, debug, &ctx->imr->v4l2_dev, "%s streaming stopped\n", ++ (V4L2_TYPE_IS_OUTPUT(vq->type) ? "output" : "capture")); ++ ++ //pm_runtime_put(ctx->imr->dev); ++} ++ ++/* ...buffer queue operations */ ++static struct vb2_ops imr_qops = { ++ .queue_setup = imr_queue_setup, ++ .buf_prepare = imr_buf_prepare, ++ .buf_queue = imr_buf_queue, ++ .buf_finish = imr_buf_finish, ++ .start_streaming = imr_start_streaming, ++ .stop_streaming = imr_stop_streaming, ++ .wait_prepare = vb2_ops_wait_prepare, ++ .wait_finish = vb2_ops_wait_finish, ++}; ++ ++/* ...M2M device processing queue initialization */ ++static int imr_queue_init(void *priv, struct vb2_queue *src_vq, ++ struct vb2_queue *dst_vq) ++{ ++ struct imr_ctx *ctx = priv; ++ int ret; ++ ++ memset(src_vq, 0, sizeof(*src_vq)); ++ src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; ++ src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; ++ src_vq->drv_priv = ctx; ++ src_vq->buf_struct_size = sizeof(struct imr_buffer); ++ src_vq->ops = &imr_qops; ++ src_vq->mem_ops = &vb2_dma_contig_memops; ++ src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; ++ src_vq->lock = &ctx->imr->mutex; ++ src_vq->dev = ctx->imr->v4l2_dev.dev; ++ ret = vb2_queue_init(src_vq); ++ if (ret) ++ return ret; ++ ++ memset(dst_vq, 0, sizeof(*dst_vq)); ++ dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; ++ dst_vq->drv_priv = ctx; ++ dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); ++ dst_vq->ops = &imr_qops; ++ dst_vq->mem_ops = &vb2_dma_contig_memops; ++ dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; ++ dst_vq->lock = &ctx->imr->mutex; ++ ret = vb2_queue_init(dst_vq); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ ++/******************************************************************************* ++ * Display list commands ++ ******************************************************************************/ ++ ++/* ...display list opcodes */ ++#define IMR_OP_TRI(n) ((0x8A << 24) | ((n) & 0xFFFF)) ++#define IMR_OP_LINE(n) ((0x8B << 24) | ((n) & 0xFFFF)) ++#define IMR_OP_NOP(n) ((0x80 << 24) | ((n) & 0xFFFF)) ++#define IMR_OP_TRAP ((0x8F << 24)) ++#define IMR_OP_WTL(add, n) ((0x81 << 24) | (((add) / 4) << 16) | ((n) & 0xFFFF)) ++#define IMR_OP_WTS(add, data) ((0x82 << 24) | (((add) / 4) << 16) | ((data) & 0xFFFF)) ++#define IMR_OP_WTL2(add, n) ((0x83 << 24) | (((add) / 4) << 10) | ((n) & 0x3FF)) ++#define IMR_OP_INT ((0x88 << 24)) ++#define IMR_OP_SYNCM ((0x86 << 24)) ++#define IMR_OP_GOSUB ((0x8C << 24)) ++#define IMR_OP_RET ((0x8D << 24)) ++ ++/******************************************************************************* ++ * Operation type decoding helpers ++ ******************************************************************************/ ++ ++static inline u16 __imr_auto_sg_dg_tcm(u32 type) ++{ ++ return (type & IMR_MAP_AUTOSG ? IMR_TRIM_AUTOSG : (type & IMR_MAP_AUTODG ? IMR_TRIM_AUTODG : 0)) | ++ (type & IMR_MAP_TCM ? IMR_TRIM_TCM : 0); ++} ++ ++static inline u16 __imr_uvdp(u32 type) ++{ ++ return __IMR_MAP_UVDPOR(type) | (type & IMR_MAP_DDP ? (1 << 8) : 0); ++} ++ ++static inline u16 __imr_cpdp(u32 type) ++{ ++ return (__IMR_MAP_YLDPO(type) << 8) | (__IMR_MAP_UBDPO(type) << 4) | __IMR_MAP_VRDPO(type); ++} ++ ++static inline u16 __imr_luce(u32 type) ++{ ++ return (type & IMR_MAP_LUCE ? IMR_CMR_LUCE : 0); ++} ++ ++static inline u16 __imr_clce(u32 type) ++{ ++ return (type & IMR_MAP_CLCE ? IMR_CMR_CLCE : 0); ++} ++ ++/******************************************************************************* ++ * Type A (absolute coordinates of source/destination) mapping ++ ******************************************************************************/ ++ ++/* ...return size of the subroutine for type "a" mapping */ ++static inline u32 imr_tri_type_a_get_length(struct imr_mesh *mesh, int item_size) ++{ ++ return ((mesh->columns * (item_size / 2) + 1) * (mesh->rows - 1) + 1) * sizeof(u32); ++} ++ ++/* ...set a mesh rows * columns using absolute coordinates */ ++static inline u32 * imr_tri_set_type_a(u32 *dl, void *map, struct imr_mesh *mesh, int item_size) ++{ ++ int rows = mesh->rows; ++ int columns = mesh->columns; ++ u32 stride = item_size * columns; ++ int i, j; ++ ++ /* ...convert lattice into set of stripes */ ++ for (i = 0; i < rows - 1; i++) { ++ *dl++ = IMR_OP_TRI(columns * 2); ++ for (j = 0; j < columns; j++) { ++ memcpy((void *)dl, map, item_size); ++ memcpy((void *)dl + item_size, map + stride, item_size); ++ dl += item_size / 2; ++ map += item_size; ++ } ++ } ++ ++ *dl++ = IMR_OP_RET; ++ return dl; ++} ++ ++/******************************************************************************* ++ * Type B mapping (automatically generated source or destination coordinates) ++ ******************************************************************************/ ++ ++/* ...calculate length of a type "b" mapping */ ++static inline u32 imr_tri_type_b_get_length(struct imr_mesh *mesh, int item_size) ++{ ++ return ((mesh->columns * (item_size / 2) + 2) * (mesh->rows - 1) + 4) * sizeof(u32); ++} ++ ++/* ...set an auto-generated mesh n * m for a source/destination */ ++static inline u32 * imr_tri_set_type_b(u32 *dl, void *map, struct imr_mesh *mesh, int item_size) ++{ ++ int rows = mesh->rows; ++ int columns = mesh->columns; ++ int x0 = mesh->x0; ++ int y0 = mesh->y0; ++ int dx = mesh->dx; ++ int dy = mesh->dy; ++ int stride = item_size * columns; ++ int i, j; ++ ++ /* ...set mesh configuration */ ++ *dl++ = IMR_OP_WTS(IMR_AMXSR, dx); ++ *dl++ = IMR_OP_WTS(IMR_AMYSR, dy); ++ ++ /* ...origin by "x" coordinate is the same across all rows */ ++ *dl++ = IMR_OP_WTS(IMR_AMXOR, x0); ++ ++ /* ...convert lattice into set of stripes */ ++ for (i = 0; i < rows - 1; i++, y0 += dy) { ++ /* ...set origin by "y" coordinate for a current row */ ++ *dl++ = IMR_OP_WTS(IMR_AMYOR, y0); ++ *dl++ = IMR_OP_TRI(2 * columns); ++ ++ /* ...fill single row */ ++ for (j = 0; j < columns; j++) { ++ memcpy((void *)dl, map, item_size); ++ memcpy((void *)dl + item_size, map + stride, item_size); ++ dl += item_size / 2; ++ map += item_size; ++ } ++ } ++ ++ *dl++ = IMR_OP_RET; ++ return dl; ++} ++ ++/******************************************************************************* ++ * Type C mapping (vertex-buffer-object) ++ ******************************************************************************/ ++ ++/* ...calculate length of a type "c" mapping */ ++static inline u32 imr_tri_type_c_get_length(struct imr_vbo *vbo, int item_size) ++{ ++ return ((4 + 3 * item_size) * vbo->num + 4); ++} ++ ++/* ...set a VBO mapping using absolute coordinates */ ++static inline u32 * imr_tri_set_type_c(u32 *dl, void *map, struct imr_vbo *vbo, int item_size) ++{ ++ int num = vbo->num; ++ int i; ++ ++ /* ...prepare list of triangles to draw */ ++ for (i = 0; i < num; i++) { ++ *dl++ = IMR_OP_TRI(3); ++ memcpy((void *)dl, map, 3 * item_size); ++ dl += 3 * item_size / 4; ++ map += 3 * item_size; ++ } ++ ++ *dl++ = IMR_OP_RET; ++ return dl; ++} ++ ++/******************************************************************************* ++ * DL program creation ++ ******************************************************************************/ ++ ++/* ...return length of a DL main program */ ++static inline u32 imr_dl_program_length(struct imr_ctx *ctx) ++{ ++ u32 iflags = ctx->queue[0].flags; ++ u32 oflags = ctx->queue[1].flags; ++ u32 cflags = __imr_flags_common(iflags, oflags); ++ ++ /* ...check if formats are compatible */ ++ if (((iflags & IMR_F_PLANAR) != 0 && (oflags & IMR_F_PLANAR) == 0) || (cflags == 0)) { ++ v4l2_err(&ctx->imr->v4l2_dev, "formats are incompatible: if=%x, of=%x, cf=%x\n", iflags, oflags, cflags); ++ return 0; ++ } ++ ++ /* ...maximal possible length of the program is 27 32-bits words; round up to 32 */ ++ return 32 << 2; ++} ++ ++/* ...setup DL for Y/YUV planar/interleaved processing */ ++static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg, u32 type, u32 *dl, u32 subaddr) ++{ ++ u32 iflags = ctx->queue[0].flags; ++ u32 oflags = ctx->queue[1].flags; ++ u32 cflags = __imr_flags_common(iflags, oflags); ++ u16 src_y_fmt = (iflags & IMR_F_Y12 ? IMR_CMR_SY12 : (iflags & IMR_F_Y10 ? IMR_CMR_SY10 : 0)); ++ u16 src_uv_fmt = (iflags & IMR_F_UV12 ? 2 : (iflags & IMR_F_UV10 ? 1 : 0)) << IMR_CMR_SUV_SHIFT; ++ u16 dst_y_fmt = (cflags & IMR_F_Y12 ? IMR_CMR_DY12 : (cflags & IMR_F_Y10 ? IMR_CMR_DY10 : 0)); ++ u16 dst_uv_fmt = (cflags & IMR_F_UV12 ? 2 : (cflags & IMR_F_UV10 ? 1 : 0)) << IMR_CMR_DUV_SHIFT; ++ int w = ctx->queue[0].fmt.width; ++ int h = ctx->queue[0].fmt.height; ++ int W = ctx->queue[1].fmt.width; ++ int H = ctx->queue[1].fmt.height; ++ ++ v4l2_dbg(2, debug, &ctx->imr->v4l2_dev, "setup %u*%u -> %u*%u mapping (type=%x)\n", w, h, W, H, type); ++ ++ /* ...set triangle mode register from user-supplied descriptor */ ++ *dl++ = IMR_OP_WTS(IMR_TRIMCR, 0xFFFF); ++ ++ /* ...set automatic source / destination coordinates generation flags */ ++ *dl++ = IMR_OP_WTS(IMR_TRIMSR, __imr_auto_sg_dg_tcm(type) | IMR_TRIM_BFE | IMR_TRIM_TME); ++ ++ /* ...set source / destination coordinate precision */ ++ *dl++ = IMR_OP_WTS(IMR_UVDPOR, __imr_uvdp(type)); ++ ++ /* ...set luminance/chromacity correction parameters precision */ ++ *dl++ = IMR_OP_WTS(IMR_CPDPOR, __imr_cpdp(type)); ++ ++ /* ...reset rendering mode registers */ ++ *dl++ = IMR_OP_WTS(IMR_CMRCCR, 0xFFFF); ++ *dl++ = IMR_OP_WTS(IMR_CMRCCR2, 0xFFFF); ++ ++ /* ...set source/destination addresses of Y/UV plane */ ++ *dl++ = IMR_OP_WTL(IMR_DSAR, 2); ++ cfg->dst_pa_ptr[0] = dl++; ++ cfg->src_pa_ptr[0] = dl++; ++ ++ /* ...select planar/interleaved mode basing on input format */ ++ if (iflags & IMR_F_PLANAR) { ++ /* ...planar input means planar output; set Y-plane precision */ ++ if (cflags & IMR_F_Y8) { ++ /* ...setup Y-plane processing: YCM=0, SY/DY=xx, SUV/DUV=0 */ ++ *dl++ = IMR_OP_WTS(IMR_CMRCSR, src_y_fmt | src_uv_fmt | dst_y_fmt | dst_uv_fmt | __imr_luce(type)); ++ ++ /* ...set source/destination strides basing on Y-plane precision */ ++ *dl++ = IMR_OP_WTS(IMR_DSTR, W << (cflags & IMR_F_Y10 ? 1 : 0)); ++ *dl++ = IMR_OP_WTS(IMR_SSTR, w << (iflags & IMR_F_Y10 ? 1 : 0)); ++ } else { ++ /* ...setup UV-plane processing only */ ++ *dl++ = IMR_OP_WTS(IMR_CMRCSR, IMR_CMR_YCM | src_uv_fmt | dst_uv_fmt | __imr_clce(type)); ++ ++ /* ...set source/destination strides basing on UV-plane precision */ ++ *dl++ = IMR_OP_WTS(IMR_DSTR, W << (cflags & IMR_F_UV10 ? 1 : 0)); ++ *dl++ = IMR_OP_WTS(IMR_SSTR, w << (iflags & IMR_F_UV10 ? 1 : 0)); ++ } ++ } else { ++ u16 src_fmt = (iflags & IMR_F_UV_SWAP ? IMR_CMR2_UVFORM : 0) | (iflags & IMR_F_YUV_SWAP ? IMR_CMR2_YUV422FORM : 0); ++ u32 dst_fmt = (oflags & IMR_F_YUV_SWAP ? IMR_TRIC_YCFORM : 0); ++ ++ /* ...interleaved input; output is either interleaved or planar */ ++ *dl++ = IMR_OP_WTS(IMR_CMRCSR2, IMR_CMR2_YUV422E | src_fmt); ++ ++ /* ...destination is always YUYV or UYVY */ ++ *dl++ = IMR_OP_WTL(IMR_TRICR, 1); ++ *dl++ = dst_fmt; ++ ++ /* ...set precision of Y/UV planes and required correction */ ++ *dl++ = IMR_OP_WTS(IMR_CMRCSR, src_y_fmt | src_uv_fmt | dst_y_fmt | dst_uv_fmt | __imr_clce(type) | __imr_luce(type)); ++ ++ /* ...set source stride basing on precision (2 or 4 bytes/pixel) */ ++ *dl++ = IMR_OP_WTS(IMR_SSTR, w << (iflags & IMR_F_Y10 ? 2 : 1)); ++ ++ /* ...if output is planar, put the offset value */ ++ if (oflags & IMR_F_PLANAR) { ++ /* ...specify offset of a destination UV plane */ ++ *dl++ = IMR_OP_WTL(IMR_DSOR, 1); ++ *dl++ = W * H; ++ ++ /* ...destination stride is 1 or 2 bytes/pixel (same for both Y and UV planes) */ ++ *dl++ = IMR_OP_WTS(IMR_DSTR, W << (cflags & IMR_F_Y10 ? 1 : 0)); ++ } else { ++ /* ...destination stride if 2 or 4 bytes/pixel (Y and UV planes interleaved) */ ++ *dl++ = IMR_OP_WTS(IMR_DSTR, W << (cflags & IMR_F_Y10 ? 2 : 1)); ++ } ++ } ++ ++ /* ...set source width/height of Y/UV plane (for Y plane upper part of SUSR is ignored) */ ++ *dl++ = IMR_OP_WTL(IMR_SUSR, 2); ++ *dl++ = ((w - 2) << 16) | (w - 1); ++ *dl++ = h - 1; ++ ++ /* ...invoke subroutine for triangles drawing */ ++ *dl++ = IMR_OP_GOSUB; ++ *dl++ = subaddr; ++ ++ /* ...if we have a planar output with both Y and UV planes available */ ++ if ((cflags & (IMR_F_PLANAR | IMR_F_Y8 | IMR_F_UV8)) == (IMR_F_PLANAR | IMR_F_Y8 | IMR_F_UV8)) { ++ /* ...select UV-plane processing mode; put sync before switching */ ++ *dl++ = IMR_OP_SYNCM; ++ ++ /* ...setup UV-plane source/destination addresses */ ++ *dl++ = IMR_OP_WTL(IMR_DSAR, 2); ++ cfg->dst_pa_ptr[1] = dl++; ++ cfg->src_pa_ptr[1] = dl++; ++ ++ /* ...select correction mode */ ++ *dl++ = IMR_OP_WTS(IMR_CMRCSR, IMR_CMR_YCM | __imr_clce(type)); ++ ++ /* ...luminance correction bit must be cleared (if it was set) */ ++ *dl++ = IMR_OP_WTS(IMR_CMRCCR, IMR_CMR_LUCE); ++ ++ /* ...draw triangles */ ++ *dl++ = IMR_OP_GOSUB; ++ *dl++ = subaddr; ++ } else { ++ /* ...clear pointers to the source/destination UV-planes addresses */ ++ cfg->src_pa_ptr[1] = cfg->dst_pa_ptr[1] = NULL; ++ } ++ ++ /* ...signal completion of the operation */ ++ *dl++ = IMR_OP_SYNCM; ++ *dl++ = IMR_OP_TRAP; ++} ++ ++/******************************************************************************* ++ * Mapping specification processing ++ ******************************************************************************/ ++ ++/* ...set mapping data (function called with video device lock held) */ ++static int imr_ioctl_map(struct imr_ctx *ctx, struct imr_map_desc *desc) ++{ ++ struct imr_device *imr = ctx->imr; ++ struct imr_mesh *mesh; ++ struct imr_vbo *vbo; ++ struct imr_cfg *cfg; ++ void *buf, *map; ++ u32 type; ++ u32 length, item_size; ++ u32 tri_length; ++ void *dl_vaddr; ++ u32 dl_size; ++ u32 dl_start_offset; ++ dma_addr_t dl_dma_addr; ++ int ret; ++ ++ /* ...read remainder of data into temporary buffer */ ++ length = desc->size; ++ buf = kmalloc(length, GFP_KERNEL); ++ if (!buf) { ++ v4l2_err(&imr->v4l2_dev, "failed to allocate %u bytes for mapping reading\n", length); ++ return -ENOMEM; ++ } ++ ++ /* ...copy mesh data */ ++ if (copy_from_user(buf, (void __user *)desc->data, length)) { ++ v4l2_err(&imr->v4l2_dev, "failed to read %u bytes of mapping specification\n", length); ++ ret = -EFAULT; ++ goto out; ++ } ++ ++ type = desc->type; ++ ++ /* ...mesh item size calculation */ ++ item_size = (type & IMR_MAP_LUCE ? 4 : 0) + (type & IMR_MAP_CLCE ? 4 : 0); ++ ++ /* ...calculate the length of a display list */ ++ if (type & IMR_MAP_MESH) { ++ /* ...assure we have proper mesh descriptor */ ++ if (length < sizeof(struct imr_mesh)) { ++ v4l2_err(&imr->v4l2_dev, "invalid mesh specification size: %u\n", length); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ mesh = (struct imr_mesh *)buf; ++ length -= sizeof(struct imr_mesh); ++ map = buf + sizeof(struct imr_mesh); ++ ++ if (type & (IMR_MAP_AUTODG | IMR_MAP_AUTOSG)) { ++ /* ...source / destination vertex size is 4 bytes */ ++ item_size += 4; ++ ++ /* ...mapping is given using automatic generation pattern; check size */ ++ if (mesh->rows * mesh->columns * item_size != length) { ++ v4l2_err(&imr->v4l2_dev, "invalid mesh size: %u*%u*%u != %u\n", mesh->rows, mesh->columns, item_size, length); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ /* ...calculate size of triangles drawing subroutine */ ++ tri_length = imr_tri_type_b_get_length(mesh, item_size); ++ } else { ++ /* ...source / destination vertes size if 8 bytes */ ++ item_size += 8; ++ ++ /* ...mapping is done with absolute coordinates */ ++ if (mesh->rows * mesh->columns * item_size != length) { ++ v4l2_err(&imr->v4l2_dev, "invalid mesh size: %u*%u*%u != %u\n", mesh->rows, mesh->columns, item_size, length); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ /* ...calculate size of triangles drawing subroutine */ ++ tri_length = imr_tri_type_a_get_length(mesh, item_size); ++ } ++ } else { ++ /* ...assure we have proper VBO descriptor */ ++ if (length < sizeof(struct imr_vbo)) { ++ v4l2_err(&imr->v4l2_dev, "invalid vbo specification size: %u\n", length); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ /* ...make sure there is no automatic-generation flags */ ++ if (type & (IMR_MAP_AUTODG | IMR_MAP_AUTOSG)) { ++ v4l2_err(&imr->v4l2_dev, "invalid auto-dg/sg flags: 0x%x\n", type); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ vbo = (struct imr_vbo *)buf; ++ length -= sizeof(struct imr_vbo); ++ map = buf + sizeof(struct imr_vbo); ++ ++ /* ...vertex is given with absolute coordinates */ ++ item_size += 8; ++ ++ /* ...check the length is sane */ ++ if (length != vbo->num * 3 * item_size) { ++ v4l2_err(&imr->v4l2_dev, "invalid vbo size: %u*%u*3 != %u\n", vbo->num, item_size, length); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ /* ...calculate size of trangles drawing subroutine */ ++ tri_length = imr_tri_type_c_get_length(vbo, item_size); ++ } ++ ++ /* ...DL main program shall start with 8-byte aligned address */ ++ dl_start_offset = (tri_length + 7) & ~7; ++ ++ /* ...calculate main routine length */ ++ dl_size = imr_dl_program_length(ctx); ++ if (!dl_size) { ++ v4l2_err(&imr->v4l2_dev, "format configuration error\n"); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ /* ...we use a single display list, with TRI subroutine prepending MAIN */ ++ dl_size += dl_start_offset; ++ ++ /* ...unref current configuration (will not be used by subsequent jobs) */ ++ imr_cfg_unref(ctx, ctx->cfg); ++ ++ /* ...create new configuration */ ++ ctx->cfg = cfg = imr_cfg_create(ctx, dl_size, dl_start_offset); ++ if (IS_ERR(cfg)) { ++ ret = PTR_ERR(cfg); ++ v4l2_err(&imr->v4l2_dev, "failed to create configuration: %d\n", ret); ++ goto out; ++ } ++ ++ /* ...get pointer to the new display list */ ++ dl_vaddr = cfg->dl_vaddr; ++ dl_dma_addr = cfg->dl_dma_addr; ++ ++ /* ...prepare a triangles drawing subroutine */ ++ if (type & IMR_MAP_MESH) { ++ if (type & (IMR_MAP_AUTOSG | IMR_MAP_AUTODG)) { ++ imr_tri_set_type_b(dl_vaddr, map, mesh, item_size); ++ } else { ++ imr_tri_set_type_a(dl_vaddr, map, mesh, item_size); ++ } ++ } else { ++ imr_tri_set_type_c(dl_vaddr, map, vbo, item_size); ++ } ++ ++ /* ...prepare main DL-program */ ++ imr_dl_program_setup(ctx, cfg, type, dl_vaddr + dl_start_offset, (u32)dl_dma_addr); ++ ++ /* ...update cropping parameters */ ++ cfg->dst_subpixel = (type & IMR_MAP_DDP ? 2 : 0); ++ ++ /* ...display list updated successfully */ ++ v4l2_dbg(2, debug, &ctx->imr->v4l2_dev, "display-list created: #%u[%08X]:%u[%u]\n", ++ cfg->id, (u32)dl_dma_addr, dl_size, dl_start_offset); ++ ++ if (debug >= 4) ++ print_hex_dump_bytes("DL-", DUMP_PREFIX_OFFSET, dl_vaddr + dl_start_offset, dl_size - dl_start_offset); ++ ++ /* ...success */ ++ ret = 0; ++ ++out: ++ /* ...release interim buffer */ ++ kfree(buf); ++ ++ return ret; ++} ++ ++/******************************************************************************* ++ * V4L2 I/O controls ++ ******************************************************************************/ ++ ++/* ...test for a format supported */ ++static int __imr_try_fmt(struct imr_ctx *ctx, struct v4l2_format *f) ++{ ++ struct v4l2_pix_format *pix = &f->fmt.pix; ++ u32 fourcc = pix->pixelformat; ++ int i; ++ ++ /* ...both output and capture interface have the same set of supported formats */ ++ for (i = 0; i < ARRAY_SIZE(imr_lx4_formats); i++) { ++ if (fourcc == imr_lx4_formats[i].fourcc) { ++ /* ...fix-up format specification as needed */ ++ pix->field = V4L2_FIELD_NONE; ++ ++ v4l2_dbg(1, debug, &ctx->imr->v4l2_dev, "format request: '%c%c%c%c', %d*%d\n", ++ (fourcc >> 0) & 0xff, (fourcc >> 8) & 0xff, ++ (fourcc >> 16) & 0xff, (fourcc >> 24) & 0xff, ++ pix->width, pix->height); ++ ++ /* ...verify source/destination image dimensions */ ++ if (V4L2_TYPE_IS_OUTPUT(f->type)) ++ v4l_bound_align_image(&pix->width, 128, 2048, 7, &pix->height, 1, 2048, 0, 0); ++ else ++ v4l_bound_align_image(&pix->width, 64, 2048, 6, &pix->height, 1, 2048, 0, 0); ++ ++ return i; ++ } ++ } ++ ++ v4l2_err(&ctx->imr->v4l2_dev, "unsupported format request: '%c%c%c%c'\n", ++ (fourcc >> 0) & 0xff, (fourcc >> 8) & 0xff, ++ (fourcc >> 16) & 0xff, (fourcc >> 24) & 0xff); ++ ++ return -EINVAL; ++} ++ ++/* ...capabilities query */ ++static int imr_querycap(struct file *file, void *priv, struct v4l2_capability *cap) ++{ ++ strlcpy(cap->driver, DRV_NAME, sizeof(cap->driver)); ++ strlcpy(cap->card, DRV_NAME, sizeof(cap->card)); ++ strlcpy(cap->bus_info, DRV_NAME, sizeof(cap->bus_info)); ++ ++ cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT | ++ V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING; ++ ++ cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; ++ ++ return 0; ++} ++ ++/* ...enumerate supported formats */ ++static int imr_enum_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *f) ++{ ++ /* ...no distinction between output/capture formats */ ++ if (f->index < ARRAY_SIZE(imr_lx4_formats)) { ++ const struct imr_format_info *fmt = &imr_lx4_formats[f->index]; ++ strlcpy(f->description, fmt->name, sizeof(f->description)); ++ f->pixelformat = fmt->fourcc; ++ return 0; ++ } ++ ++ return -EINVAL; ++} ++ ++/* ...retrieve current queue format; operation is locked ? */ ++static int imr_g_fmt(struct file *file, void *priv, struct v4l2_format *f) ++{ ++ struct imr_ctx *ctx = fh_to_ctx(priv); ++ struct vb2_queue *vq; ++ struct imr_q_data *q_data; ++ ++ vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); ++ if (!vq) ++ return -EINVAL; ++ ++ q_data = &ctx->queue[V4L2_TYPE_IS_OUTPUT(f->type) ? 0 : 1]; ++ ++ /* ...processing is locked? tbd */ ++ f->fmt.pix = q_data->fmt; ++ ++ return 0; ++} ++ ++/* ...test particular format; operation is not locked */ ++static int imr_try_fmt(struct file *file, void *priv, struct v4l2_format *f) ++{ ++ struct imr_ctx *ctx = fh_to_ctx(priv); ++ struct vb2_queue *vq; ++ ++ /* ...make sure we have a queue of particular type */ ++ vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); ++ if (!vq) ++ return -EINVAL; ++ ++ /* ...test if format is supported (adjust as appropriate) */ ++ return (__imr_try_fmt(ctx, f) >= 0 ? 0 : -EINVAL); ++} ++ ++/* ...apply queue format; operation is locked ? */ ++static int imr_s_fmt(struct file *file, void *priv, struct v4l2_format *f) ++{ ++ struct imr_ctx *ctx = fh_to_ctx(priv); ++ struct vb2_queue *vq; ++ struct imr_q_data *q_data; ++ int i; ++ ++ vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); ++ if (!vq) ++ return -EINVAL; ++ ++ /* ...check if queue is busy */ ++ if (vb2_is_busy(vq)) ++ return -EBUSY; ++ ++ /* ...test if format is supported (adjust as appropriate) */ ++ i = __imr_try_fmt(ctx, f); ++ if (i < 0) ++ return -EINVAL; ++ ++ /* ...format is supported; save current format in a queue-specific data */ ++ q_data = &ctx->queue[V4L2_TYPE_IS_OUTPUT(f->type) ? 0 : 1]; ++ ++ /* ...processing is locked? tbd */ ++ q_data->fmt = f->fmt.pix; ++ q_data->flags = imr_lx4_formats[i].flags; ++ ++ /* ...set default crop factors */ ++ if (V4L2_TYPE_IS_OUTPUT(f->type) == 0) { ++ ctx->crop[0] = 0; ++ ctx->crop[1] = f->fmt.pix.width - 1; ++ ctx->crop[2] = 0; ++ ctx->crop[3] = f->fmt.pix.height - 1; ++ } ++ ++ return 0; ++} ++ ++static int imr_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *reqbufs) ++{ ++ struct imr_ctx *ctx = fh_to_ctx(priv); ++ ++ return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); ++} ++ ++static int imr_querybuf(struct file *file, void *priv, struct v4l2_buffer *buf) ++{ ++ struct imr_ctx *ctx = fh_to_ctx(priv); ++ ++ return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf); ++} ++ ++static int imr_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) ++{ ++ struct imr_ctx *ctx = fh_to_ctx(priv); ++ ++ /* ...operation is protected with a queue lock */ ++ WARN_ON(!mutex_is_locked(&ctx->imr->mutex)); ++ ++ /* ...verify the configuration is complete */ ++ if (!V4L2_TYPE_IS_OUTPUT(buf->type) && !ctx->cfg) { ++ v4l2_err(&ctx->imr->v4l2_dev, "stream configuration is not complete\n"); ++ return -EINVAL; ++ } ++ ++ return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); ++} ++ ++static int imr_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) ++{ ++ struct imr_ctx *ctx = fh_to_ctx(priv); ++ ++ return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); ++} ++ ++static int imr_expbuf(struct file *file, void *priv, struct v4l2_exportbuffer *eb) ++{ ++ struct imr_ctx *ctx = fh_to_ctx(priv); ++ ++ return v4l2_m2m_expbuf(file, ctx->m2m_ctx, eb); ++} ++ ++static int imr_streamon(struct file *file, void *priv, enum v4l2_buf_type type) ++{ ++ struct imr_ctx *ctx = fh_to_ctx(priv); ++ ++ /* ...context is prepared for a streaming */ ++ return v4l2_m2m_streamon(file, ctx->m2m_ctx, type); ++} ++ ++static int imr_streamoff(struct file *file, void *priv, enum v4l2_buf_type type) ++{ ++ struct imr_ctx *ctx = fh_to_ctx(priv); ++ ++ return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); ++} ++ ++static int imr_g_crop(struct file *file, void *priv, struct v4l2_crop *cr) ++{ ++ struct imr_ctx *ctx = fh_to_ctx(priv); ++ ++ /* ...subpixel resolution of output buffer is not counted here */ ++ cr->c.left = ctx->crop[0]; ++ cr->c.top = ctx->crop[2]; ++ cr->c.width = ctx->crop[1] - ctx->crop[0]; ++ cr->c.height = ctx->crop[3] - ctx->crop[2]; ++ ++ return 0; ++} ++ ++static int imr_s_crop(struct file *file, void *priv, const struct v4l2_crop *cr) ++{ ++ struct imr_ctx *ctx = fh_to_ctx(priv); ++ int x0 = cr->c.left; ++ int y0 = cr->c.top; ++ int x1 = x0 + cr->c.width; ++ int y1 = y0 + cr->c.height; ++ ++ if (x0 < 0 || x1 >= 2048 || y0 < 0 || y1 >= 2048) { ++ v4l2_err(&ctx->imr->v4l2_dev, "invalid cropping: %d/%d/%d/%d\n", x0, x1, y0, y1); ++ return -EINVAL; ++ } ++ ++ /* ...subpixel resolution of output buffer is not counted here */ ++ ctx->crop[0] = x0; ++ ctx->crop[1] = x1; ++ ctx->crop[2] = y0; ++ ctx->crop[3] = y1; ++ ++ return 0; ++} ++ ++/* ...customized I/O control processing */ ++static long imr_default(struct file *file, void *fh, bool valid_prio, unsigned int cmd, void *arg) ++{ ++ struct imr_ctx *ctx = fh_to_ctx(fh); ++ ++ switch (cmd) { ++ case VIDIOC_IMR_MESH: ++ /* ...set mesh data */ ++ return imr_ioctl_map(ctx, (struct imr_map_desc *)arg); ++ ++ default: ++ return -ENOIOCTLCMD; ++ } ++} ++ ++static const struct v4l2_ioctl_ops imr_ioctl_ops = { ++ .vidioc_querycap = imr_querycap, ++ ++ .vidioc_enum_fmt_vid_cap = imr_enum_fmt, ++ .vidioc_enum_fmt_vid_out = imr_enum_fmt, ++ .vidioc_g_fmt_vid_cap = imr_g_fmt, ++ .vidioc_g_fmt_vid_out = imr_g_fmt, ++ .vidioc_try_fmt_vid_cap = imr_try_fmt, ++ .vidioc_try_fmt_vid_out = imr_try_fmt, ++ .vidioc_s_fmt_vid_cap = imr_s_fmt, ++ .vidioc_s_fmt_vid_out = imr_s_fmt, ++ ++ .vidioc_reqbufs = imr_reqbufs, ++ .vidioc_querybuf = imr_querybuf, ++ .vidioc_qbuf = imr_qbuf, ++ .vidioc_dqbuf = imr_dqbuf, ++ .vidioc_expbuf = imr_expbuf, ++ .vidioc_streamon = imr_streamon, ++ .vidioc_streamoff = imr_streamoff, ++ ++ .vidioc_g_crop = imr_g_crop, ++ .vidioc_s_crop = imr_s_crop, ++ ++ .vidioc_default = imr_default, ++}; ++ ++/******************************************************************************* ++ * Generic device file operations ++ ******************************************************************************/ ++ ++static int imr_open(struct file *file) ++{ ++ struct imr_device *imr = video_drvdata(file); ++ struct video_device *vfd = video_devdata(file); ++ struct imr_ctx *ctx; ++ int ret; ++ ++ /* ...allocate processing context associated with given instance */ ++ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); ++ if (!ctx) ++ return -ENOMEM; ++ ++ /* ...initialize per-file-handle structure */ ++ v4l2_fh_init(&ctx->fh, vfd); ++ //ctx->fh.ctrl_handler = &ctx->ctrl_handler; ++ file->private_data = &ctx->fh; ++ v4l2_fh_add(&ctx->fh); ++ ++ /* ...set default source / destination formats - need that? */ ++ ctx->imr = imr; ++ ctx->queue[0].fmt.pixelformat = 0; ++ ctx->queue[1].fmt.pixelformat = 0; ++ ++ /* ...set default cropping parameters */ ++ ctx->crop[1] = ctx->crop[3] = 0x3FF; ++ ++ /* ...initialize M2M processing context */ ++ ctx->m2m_ctx = v4l2_m2m_ctx_init(imr->m2m_dev, ctx, imr_queue_init); ++ if (IS_ERR(ctx->m2m_ctx)) { ++ ret = PTR_ERR(ctx->m2m_ctx); ++ goto v4l_prepare_rollback; ++ } ++ ++#if 0 ++ /* ...initialize controls and stuff */ ++ ret = imr_controls_create(ctx); ++ if (ret < 0) ++ goto v4l_prepare_rollback; ++#endif ++ ++ /* ...lock access to global device data */ ++ if (mutex_lock_interruptible(&imr->mutex)) { ++ ret = -ERESTARTSYS; ++ goto v4l_prepare_rollback; ++ } ++ ++ /* ...bring-up device as needed */ ++ if (imr->refcount == 0) { ++ ret = clk_prepare_enable(imr->clock); ++ if (ret < 0) ++ goto device_prepare_rollback; ++ } ++ ++ imr->refcount++; ++ ++ mutex_unlock(&imr->mutex); ++ ++ v4l2_dbg(1, debug, &imr->v4l2_dev, "IMR device opened (refcount=%u)\n", imr->refcount); ++ ++ return 0; ++ ++device_prepare_rollback: ++ /* ...unlock global device data */ ++ mutex_unlock(&imr->mutex); ++ ++v4l_prepare_rollback: ++ /* ...destroy context */ ++ v4l2_fh_del(&ctx->fh); ++ v4l2_fh_exit(&ctx->fh); ++ kfree(ctx); ++ ++ return ret; ++} ++ ++static int imr_release(struct file *file) ++{ ++ struct imr_device *imr = video_drvdata(file); ++ struct imr_ctx *ctx = fh_to_ctx(file->private_data); ++ ++ /* ...I don't need to get a device-scope lock here really - tbd */ ++ mutex_lock(&imr->mutex); ++ ++ /* ...destroy M2M device processing context */ ++ v4l2_m2m_ctx_release(ctx->m2m_ctx); ++ //v4l2_ctrl_handler_free(&ctx->ctrl_handler); ++ v4l2_fh_del(&ctx->fh); ++ v4l2_fh_exit(&ctx->fh); ++ ++ /* ...drop active configuration as needed */ ++ imr_cfg_unref(ctx, ctx->cfg); ++ ++ /* ...make sure there are no more active configs */ ++ WARN_ON(ctx->cfg_num); ++ ++ /* ...destroy context data */ ++ kfree(ctx); ++ ++ /* ...disable hardware operation */ ++ if (--imr->refcount == 0) ++ clk_disable_unprepare(imr->clock); ++ ++ mutex_unlock(&imr->mutex); ++ ++ v4l2_dbg(1, debug, &imr->v4l2_dev, "closed device instance\n"); ++ ++ return 0; ++} ++ ++static unsigned int imr_poll(struct file *file, struct poll_table_struct *wait) ++{ ++ struct imr_device *imr = video_drvdata(file); ++ struct imr_ctx *ctx = fh_to_ctx(file->private_data); ++ unsigned int res; ++ ++ if (mutex_lock_interruptible(&imr->mutex)) ++ return -ERESTARTSYS; ++ ++ res = v4l2_m2m_poll(file, ctx->m2m_ctx, wait); ++ mutex_unlock(&imr->mutex); ++ ++ return res; ++} ++ ++static int imr_mmap(struct file *file, struct vm_area_struct *vma) ++{ ++ struct imr_device *imr = video_drvdata(file); ++ struct imr_ctx *ctx = fh_to_ctx(file->private_data); ++ int ret; ++ ++ /* ...should we protect all M2M operations with mutex? - tbd */ ++ if (mutex_lock_interruptible(&imr->mutex)) ++ return -ERESTARTSYS; ++ ++ ret = v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); ++ ++ mutex_unlock(&imr->mutex); ++ ++ return ret; ++} ++ ++static const struct v4l2_file_operations imr_fops = { ++ .owner = THIS_MODULE, ++ .open = imr_open, ++ .release = imr_release, ++ .poll = imr_poll, ++ .mmap = imr_mmap, ++ .unlocked_ioctl = video_ioctl2, ++}; ++ ++/******************************************************************************* ++ * M2M device interface ++ ******************************************************************************/ ++ ++#if 0 ++/* ...job cleanup function */ ++static void imr_cleanup(struct imr_ctx *ctx) ++{ ++ struct imr_device *imr = ctx->imr; ++ struct vb2_v4l2_buffer *src_buf, *dst_buf; ++ unsigned long flags; ++ ++ /* ...interlock buffer handling with interrupt */ ++ spin_lock_irqsave(&imr->lock, flags); ++ ++ while ((src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx)) != NULL) ++ v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR); ++ ++ while ((dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx)) != NULL) ++ v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR); ++ ++ /* ...release lock before we mark current job as finished */ ++ spin_unlock_irqrestore(&imr->lock, flags); ++} ++#endif ++ ++/* ...job execution function */ ++static void imr_device_run(void *priv) ++{ ++ struct imr_ctx *ctx = priv; ++ struct imr_device *imr = ctx->imr; ++ struct imr_cfg *cfg; ++ struct vb2_buffer *src_buf, *dst_buf; ++ u32 src_addr, dst_addr; ++ unsigned long flags; ++ ++ v4l2_dbg(3, debug, &imr->v4l2_dev, "run next job...\n"); ++ ++ /* ...protect access to internal device state */ ++ spin_lock_irqsave(&imr->lock, flags); ++ ++ /* ...retrieve input/output buffers */ ++ src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); ++ dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); ++ ++ /* ...take configuration pointer associated with input buffer */ ++ cfg = to_imr_buffer(to_vb2_v4l2_buffer(src_buf))->cfg; ++ ++ /* ...cancel software reset state as needed */ ++ iowrite32(0, imr->mmio + IMR_CR); ++ ++ /* ...set cropping data with respect to destination sub-pixel mode */ ++ iowrite32(ctx->crop[0] << cfg->dst_subpixel, imr->mmio + IMR_XMINR); ++ iowrite32(ctx->crop[1] << cfg->dst_subpixel, imr->mmio + IMR_XMAXR); ++ iowrite32(ctx->crop[2] << cfg->dst_subpixel, imr->mmio + IMR_YMINR); ++ iowrite32(ctx->crop[3] << cfg->dst_subpixel, imr->mmio + IMR_YMAXR); ++ ++ /* ...adjust source/destination parameters of the program (interleaved / semiplanar) */ ++ *cfg->src_pa_ptr[0] = src_addr = (u32)vb2_dma_contig_plane_dma_addr(src_buf, 0); ++ *cfg->dst_pa_ptr[0] = dst_addr = (u32)vb2_dma_contig_plane_dma_addr(dst_buf, 0); ++ ++ /* ...adjust source/destination parameters of the UV-plane as needed */ ++ if (cfg->src_pa_ptr[1] && cfg->dst_pa_ptr[1]) { ++ *cfg->src_pa_ptr[1] = src_addr + ctx->queue[0].fmt.width * ctx->queue[0].fmt.height; ++ *cfg->dst_pa_ptr[1] = dst_addr + ctx->queue[1].fmt.width * ctx->queue[1].fmt.height; ++ } ++ ++ v4l2_dbg(3, debug, &imr->v4l2_dev, "process buffer-pair 0x%08x:0x%08x\n", ++ *cfg->src_pa_ptr[0], *cfg->dst_pa_ptr[0]); ++ ++ /* ...force clearing of status register bits */ ++ iowrite32(0x7, imr->mmio + IMR_SRCR); ++ ++ /* ...unmask/enable interrupts */ ++ iowrite32(ioread32(imr->mmio + IMR_ICR) | (IMR_ICR_TRAEN | IMR_ICR_IEREN | IMR_ICR_INTEN), imr->mmio + IMR_ICR); ++ iowrite32(ioread32(imr->mmio + IMR_IMR) & ~(IMR_ICR_TRAEN | IMR_ICR_IEREN | IMR_ICR_INTEN), imr->mmio + IMR_IMR); ++ ++ /* ...set display list address */ ++ iowrite32(cfg->dl_dma_addr + cfg->dl_start_offset, imr->mmio + IMR_DLSAR); ++ ++ /* ...explicitly flush any pending write operations (don't need that, I guess) */ ++ wmb(); ++ ++ /* ...start rendering operation */ ++ iowrite32(IMR_CR_RS, imr->mmio + IMR_CR); ++ ++ /* ...timestamp input buffer */ ++ src_buf->timestamp = ktime_get_ns(); ++ ++ /* ...unlock device access */ ++ spin_unlock_irqrestore(&imr->lock, flags); ++ ++ v4l2_dbg(1, debug, &imr->v4l2_dev, "rendering started: status=%X, DLSAR=0x%08X, DLPR=0x%08X\n", ioread32(imr->mmio + IMR_SR), ioread32(imr->mmio + IMR_DLSAR), ioread32(imr->mmio + IMR_DLSR)); ++} ++ ++/* ...check whether a job is ready for execution */ ++static int imr_job_ready(void *priv) ++{ ++ /* ...no specific requirements on the job readiness */ ++ return 1; ++} ++ ++/* ...abort currently processed job */ ++static void imr_job_abort(void *priv) ++{ ++ struct imr_ctx *ctx = priv; ++ struct imr_device *imr = ctx->imr; ++ unsigned long flags; ++ ++ /* ...protect access to internal device state */ ++ spin_lock_irqsave(&imr->lock, flags); ++ ++ /* ...make sure current job is still current (may get finished by interrupt already) */ ++ if (v4l2_m2m_get_curr_priv(imr->m2m_dev) == ctx) { ++ v4l2_dbg(1, debug, &imr->v4l2_dev, "abort job: status=%X, DLSAR=0x%08X, DLPR=0x%08X\n", ++ ioread32(imr->mmio + IMR_SR), ioread32(imr->mmio + IMR_DLSAR), ioread32(imr->mmio + IMR_DLSR)); ++ ++ /* ...force device reset to stop processing of the buffers */ ++ //iowrite32(IMR_CR_SWRST, imr->mmio + IMR_CR); ++ ++ /* ...resetting the module while operation is active may lead to hw-stall */ ++ spin_unlock_irqrestore(&imr->lock, flags); ++ ++ /* ...finish current job as interrupt will probably not occur */ ++ //v4l2_m2m_job_finish(imr->m2m_dev, ctx->m2m_ctx); ++ } else { ++ spin_unlock_irqrestore(&imr->lock, flags); ++ v4l2_dbg(1, debug, &imr->v4l2_dev, "job has completed already\n"); ++ } ++} ++ ++/* ...M2M interface definition */ ++static struct v4l2_m2m_ops imr_m2m_ops = { ++ .device_run = imr_device_run, ++ .job_ready = imr_job_ready, ++ .job_abort = imr_job_abort, ++}; ++ ++/******************************************************************************* ++ * Interrupt handling ++ ******************************************************************************/ ++ ++static irqreturn_t imr_irq_handler(int irq, void *data) ++{ ++ struct imr_device *imr = data; ++ struct imr_ctx *ctx; ++ struct vb2_v4l2_buffer *src_buf, *dst_buf; ++ u32 status; ++ irqreturn_t ret = IRQ_NONE; ++ ++ /* ...check and ack interrupt status */ ++ status = ioread32(imr->mmio + IMR_SR); ++ iowrite32(status, imr->mmio + IMR_SRCR); ++ if (!(status & (IMR_SR_INT | IMR_SR_IER | IMR_SR_TRA))) { ++ v4l2_err(&imr->v4l2_dev, "spurious interrupt: %x\n", status); ++ return ret; ++ } ++ ++ /* ...protect access to current context */ ++ spin_lock(&imr->lock); ++ ++ /* ...get current job context (may have been cancelled already) */ ++ ctx = v4l2_m2m_get_curr_priv(imr->m2m_dev); ++ if (!ctx) { ++ v4l2_dbg(3, debug, &imr->v4l2_dev, "no active job\n"); ++ goto handled; ++ } ++ ++ /* ...remove buffers (may have been removed already?) */ ++ src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); ++ dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); ++ if (!src_buf || !dst_buf) { ++ v4l2_dbg(3, debug, &imr->v4l2_dev, "no buffers associated with current context\n"); ++ goto handled; ++ } ++ ++ /* ...check for a TRAP interrupt indicating completion of current DL */ ++ if (status & IMR_SR_TRA) { ++ /* ...operation completed normally; timestamp output buffer */ ++ dst_buf->vb2_buf.timestamp = ktime_get_ns(); ++ if (src_buf->flags & V4L2_BUF_FLAG_TIMECODE) ++ dst_buf->timecode = src_buf->timecode; ++ dst_buf->flags = src_buf->flags & (V4L2_BUF_FLAG_TIMECODE | V4L2_BUF_FLAG_KEYFRAME | ++ V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_BFRAME | V4L2_BUF_FLAG_TSTAMP_SRC_MASK); ++ dst_buf->sequence = src_buf->sequence = ctx->sequence++; ++ v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); ++ v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE); ++ ++ v4l2_dbg(3, debug, &imr->v4l2_dev, "buffers <0x%08x,0x%08x> done\n", ++ (u32)vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0), ++ (u32)vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0)); ++ } else { ++ /* ...operation completed in error; no way to understand what exactly went wrong */ ++ v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR); ++ v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR); ++ ++ v4l2_dbg(3, debug, &imr->v4l2_dev, "buffers <0x%08x,0x%08x> done in error\n", ++ (u32)vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0), ++ (u32)vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0)); ++ } ++ ++ spin_unlock(&imr->lock); ++ ++ /* ...finish current job (and start any pending) */ ++ v4l2_m2m_job_finish(imr->m2m_dev, ctx->m2m_ctx); ++ ++ return IRQ_HANDLED; ++ ++handled: ++ /* ...again, what exactly is to be protected? */ ++ spin_unlock(&imr->lock); ++ ++ return IRQ_HANDLED; ++} ++ ++/******************************************************************************* ++ * Device probing / removal interface ++ ******************************************************************************/ ++ ++static int imr_probe(struct platform_device *pdev) ++{ ++ struct imr_device *imr; ++ struct resource *res; ++ int ret; ++ ++ imr = devm_kzalloc(&pdev->dev, sizeof(*imr), GFP_KERNEL); ++ if (!imr) ++ return -ENOMEM; ++ ++ mutex_init(&imr->mutex); ++ spin_lock_init(&imr->lock); ++ imr->dev = &pdev->dev; ++ ++ /* ...memory-mapped registers */ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_err(&pdev->dev, "cannot get memory region\n"); ++ return -EINVAL; ++ } ++ ++ imr->mmio = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(imr->mmio)) ++ return PTR_ERR(imr->mmio); ++ ++ /* ...interrupt service routine registration */ ++ imr->irq = ret = platform_get_irq(pdev, 0); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "cannot find IRQ\n"); ++ return ret; ++ } ++ ++ ret = devm_request_irq(&pdev->dev, imr->irq, imr_irq_handler, 0, dev_name(&pdev->dev), imr); ++ if (ret) { ++ dev_err(&pdev->dev, "cannot claim IRQ %d\n", imr->irq); ++ return ret; ++ } ++ ++ imr->clock = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(imr->clock)) { ++ dev_err(&pdev->dev, "cannot get clock\n"); ++ return PTR_ERR(imr->clock); ++ } ++ ++ /* ...create v4l2 device */ ++ ret = v4l2_device_register(&pdev->dev, &imr->v4l2_dev); ++ if (ret) { ++ dev_err(&pdev->dev, "Failed to register v4l2 device\n"); ++ return ret; ++ } ++ ++ /* ...create mem2mem device handle */ ++ imr->m2m_dev = v4l2_m2m_init(&imr_m2m_ops); ++ if (IS_ERR(imr->m2m_dev)) { ++ v4l2_err(&imr->v4l2_dev, "Failed to init mem2mem device\n"); ++ ret = PTR_ERR(imr->m2m_dev); ++ goto device_register_rollback; ++ } ++ ++ strlcpy(imr->video_dev.name, dev_name(&pdev->dev), sizeof(imr->video_dev.name)); ++ imr->video_dev.fops = &imr_fops; ++ imr->video_dev.ioctl_ops = &imr_ioctl_ops; ++ imr->video_dev.minor = -1; ++ imr->video_dev.release = video_device_release_empty; ++ imr->video_dev.lock = &imr->mutex; ++ imr->video_dev.v4l2_dev = &imr->v4l2_dev; ++ imr->video_dev.vfl_dir = VFL_DIR_M2M; ++ ++ ret = video_register_device(&imr->video_dev, VFL_TYPE_GRABBER, -1); ++ if (ret) { ++ v4l2_err(&imr->v4l2_dev, "Failed to register video device\n"); ++ goto m2m_init_rollback; ++ } ++ ++ video_set_drvdata(&imr->video_dev, imr); ++ platform_set_drvdata(pdev, imr); ++ //pm_runtime_enable(&pdev->dev); ++ ++ v4l2_info(&imr->v4l2_dev, "IMR device (pdev: %d) registered as /dev/video%d\n", pdev->id, imr->video_dev.num); ++ ++ return 0; ++ ++m2m_init_rollback: ++ v4l2_m2m_release(imr->m2m_dev); ++ ++device_register_rollback: ++ v4l2_device_unregister(&imr->v4l2_dev); ++ ++ return ret; ++} ++ ++static int imr_remove(struct platform_device *pdev) ++{ ++ struct imr_device *imr = platform_get_drvdata(pdev); ++ ++ //pm_runtime_disable(imr->v4l2_dev.dev); ++ video_unregister_device(&imr->video_dev); ++ v4l2_m2m_release(imr->m2m_dev); ++ v4l2_device_unregister(&imr->v4l2_dev); ++ ++ return 0; ++} ++ ++/******************************************************************************* ++ * Power management ++ ******************************************************************************/ ++ ++#ifdef CONFIG_PM_SLEEP ++ ++/* ...device suspend hook; clock control only - tbd */ ++static int imr_pm_suspend(struct device *dev) ++{ ++ struct imr_device *imr = dev_get_drvdata(dev); ++ ++ WARN_ON(mutex_is_locked(&imr->mutex)); ++ ++ if (imr->refcount == 0) ++ return 0; ++ ++ clk_disable_unprepare(imr->clock); ++ ++ return 0; ++} ++ ++/* ...device resume hook; clock control only */ ++static int imr_pm_resume(struct device *dev) ++{ ++ struct imr_device *imr = dev_get_drvdata(dev); ++ ++ WARN_ON(mutex_is_locked(&imr->mutex)); ++ ++ if (imr->refcount == 0) ++ return 0; ++ ++ clk_prepare_enable(imr->clock); ++ ++ return 0; ++} ++ ++#endif /* CONFIG_PM_SLEEP */ ++ ++/* ...power management callbacks */ ++static const struct dev_pm_ops imr_pm_ops = { ++ SET_SYSTEM_SLEEP_PM_OPS(imr_pm_suspend, imr_pm_resume) ++}; ++ ++/* ...device table */ ++static const struct of_device_id imr_of_match[] = { ++ { .compatible = "renesas,imr-lx4" }, ++ { }, ++}; ++ ++/* ...platform driver interface */ ++static struct platform_driver imr_platform_driver = { ++ .probe = imr_probe, ++ .remove = imr_remove, ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "imr", ++ .pm = &imr_pm_ops, ++ .of_match_table = imr_of_match, ++ }, ++}; ++ ++module_platform_driver(imr_platform_driver); ++ ++MODULE_ALIAS("imr"); ++MODULE_AUTHOR("Cogent Embedded Inc. <sources@cogentembedded.com>"); ++MODULE_DESCRIPTION("Renesas IMR-LX4 Driver"); ++MODULE_LICENSE("GPL"); +diff --git a/include/uapi/linux/rcar-imr.h b/include/uapi/linux/rcar-imr.h +new file mode 100644 +index 0000000..d02082f +--- /dev/null ++++ b/include/uapi/linux/rcar-imr.h +@@ -0,0 +1,98 @@ ++/* ++ * imr.h -- R-Car IMR-LX4 Driver UAPI ++ * ++ * Copyright (C) 2016 Cogent Embedded, Inc. <source@cogentembedded.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++ ++#ifndef RCAR_IMR_USER_H ++#define RCAR_IMR_USER_H ++ ++#include <linux/videodev2.h> ++ ++/******************************************************************************* ++ * Mapping specification descriptor ++ ******************************************************************************/ ++ ++struct imr_map_desc { ++ /* ...mapping types */ ++ u32 type; ++ ++ /* ...total size of the mesh structure */ ++ u32 size; ++ ++ /* ...map-specific user-pointer */ ++ void *data; ++ ++} __attribute__((packed)); ++ ++/* ...regular mesh specification */ ++#define IMR_MAP_MESH (1 << 0) ++ ++/* ...auto-generated source coordinates */ ++#define IMR_MAP_AUTODG (1 << 1) ++ ++/* ...auto-generated destination coordinates */ ++#define IMR_MAP_AUTOSG (1 << 2) ++ ++/* ...luminance correction flag */ ++#define IMR_MAP_LUCE (1 << 3) ++ ++/* ...chromacity correction flag */ ++#define IMR_MAP_CLCE (1 << 4) ++ ++/* ...vertex clockwise-mode order */ ++#define IMR_MAP_TCM (1 << 5) ++ ++/* ...source coordinate decimal point position bit index */ ++#define __IMR_MAP_UVDPOR_SHIFT 8 ++#define __IMR_MAP_UVDPOR(v) (((v) >> __IMR_MAP_UVDPOR_SHIFT) & 0x7) ++#define IMR_MAP_UVDPOR(n) ((n & 0x7) << __IMR_MAP_UVDPOR_SHIFT) ++ ++/* ...destination coordinate sub-pixel mode */ ++#define IMR_MAP_DDP (1 << 11) ++ ++/* ...luminance correction offset decimal point position */ ++#define __IMR_MAP_YLDPO_SHIFT 12 ++#define __IMR_MAP_YLDPO(v) (((v) >> __IMR_MAP_YLDPO_SHIFT) & 0x7) ++#define IMR_MAP_YLDPO(n) ((n & 0x7) << __IMR_MAP_YLDPO_SHIFT) ++ ++/* ...chromacity (U) correction offset decimal point position */ ++#define __IMR_MAP_UBDPO_SHIFT 15 ++#define __IMR_MAP_UBDPO(v) (((v) >> __IMR_MAP_UBDPO_SHIFT) & 0x7) ++#define IMR_MAP_UBDPO(n) ((n & 0x7) << __IMR_MAP_UBDPO_SHIFT) ++ ++/* ...chromacity (V) correction offset decimal point position */ ++#define __IMR_MAP_VRDPO_SHIFT 18 ++#define __IMR_MAP_VRDPO(v) (((v) >> __IMR_MAP_VRDPO_SHIFT) & 0x7) ++#define IMR_MAP_VRDPO(n) ((n & 0x7) << __IMR_MAP_VRDPO_SHIFT) ++ ++/* ...regular mesh specification */ ++struct imr_mesh { ++ /* ...rectangular mesh size */ ++ u16 rows, columns; ++ ++ /* ...mesh parameters */ ++ u16 x0, y0, dx, dy; ++ ++} __attribute__((packed)); ++ ++/* ...VBO descriptor */ ++struct imr_vbo { ++ /* ...number of triangles */ ++ u16 num; ++ ++} __attribute__((packed)); ++ ++ ++/******************************************************************************* ++ * Private IOCTL codes ++ ******************************************************************************/ ++ ++#define VIDIOC_IMR_MESH _IOW('V', BASE_VIDIOC_PRIVATE + 0, struct imr_map_desc) ++ ++#endif /* RCAR_IMR_USER_H */ +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0014-lib-swiotlb-reduce-verbosity.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0014-lib-swiotlb-reduce-verbosity.patch new file mode 100644 index 0000000..6cb5f65 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0014-lib-swiotlb-reduce-verbosity.patch @@ -0,0 +1,40 @@ +From f52105d57c1ec04f8dac9b403232d8b1965a02ca Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Thu, 26 Jan 2017 16:37:50 +0300 +Subject: [PATCH] lib: swiotlb: reduce verbosity + +Signed-off-by: Nikita Yushchenko <nikita.yoush@cogentembedded.com> +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + lib/swiotlb.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/lib/swiotlb.c b/lib/swiotlb.c +index 771234d..b395abc 100644 +--- a/lib/swiotlb.c ++++ b/lib/swiotlb.c +@@ -513,8 +513,10 @@ phys_addr_t swiotlb_tbl_map_single(struct device *hwdev, + + not_found: + spin_unlock_irqrestore(&io_tlb_lock, flags); ++#if 0 + if (printk_ratelimit()) + dev_warn(hwdev, "swiotlb buffer is full (sz: %zd bytes)\n", size); ++#endif + return SWIOTLB_MAP_ERROR; + found: + spin_unlock_irqrestore(&io_tlb_lock, flags); +@@ -714,8 +714,10 @@ swiotlb_full(struct device *dev, size_t size, enum dma_data_direction dir, + * When the mapping is small enough return a static buffer to limit + * the damage, or panic when the transfer is too big. + */ ++#if 0 + dev_err_ratelimited(dev, "DMA: Out of SW-IOMMU space for %zu bytes\n", + size); ++#endif + + if (size <= io_tlb_overflow || !do_panic) + return; +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0015-gpio-max732x-fix-gpio-set.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0015-gpio-max732x-fix-gpio-set.patch new file mode 100644 index 0000000..0195a11 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0015-gpio-max732x-fix-gpio-set.patch @@ -0,0 +1,29 @@ +From 75b9bdbafde96b6af222f96e47d7a4a260ed32df Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Tue, 11 Apr 2017 20:12:56 +0300 +Subject: [PATCH] gpio: max732x: fix gpio set + +gpio set value/direction must 0 or 1, but +gpiolib sets it to random nonzero values + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + drivers/gpio/gpio-max732x.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpio/gpio-max732x.c b/drivers/gpio/gpio-max732x.c +index a9aaf9d..b6fc8c5 100644 +--- a/drivers/gpio/gpio-max732x.c ++++ b/drivers/gpio/gpio-max732x.c +@@ -237,7 +237,7 @@ static void max732x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val) + unsigned base = off & ~0x7; + uint8_t mask = 1u << (off & 0x7); + +- max732x_gpio_set_mask(gc, base, mask, val << (off & 0x7)); ++ max732x_gpio_set_mask(gc, base, mask, (!!val) << (off & 0x7)); + } + + static void max732x_gpio_set_multiple(struct gpio_chip *gc, +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0016-gpio-gpiolib-suppress-gpiod-warning.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0016-gpio-gpiolib-suppress-gpiod-warning.patch new file mode 100644 index 0000000..9a6ae18 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0016-gpio-gpiolib-suppress-gpiod-warning.patch @@ -0,0 +1,29 @@ +From d5f7b238ab2b458876a50521f9c92487f4ba3226 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Thu, 13 Apr 2017 12:18:18 +0300 +Subject: [PATCH] gpio: gpiolib: suppress gpiod warning + +Suppress warning about use gpiod instead gpio deprecated callbacks + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + drivers/gpio/gpiolib.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c +index d407f904..06201ff 100644 +--- a/drivers/gpio/gpiolib.c ++++ b/drivers/gpio/gpiolib.c +@@ -1945,7 +1945,9 @@ void gpiod_set_raw_value(struct gpio_desc *desc, int value) + { + VALIDATE_DESC_VOID(desc); + /* Should be using gpiod_set_value_cansleep() */ ++#if 0 + WARN_ON(desc->gdev->chip->can_sleep); ++#endif + _gpiod_set_raw_value(desc, value); + } + EXPORT_SYMBOL_GPL(gpiod_set_raw_value); +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0017-media-soc_camera-add-legacy-VIN-CSI2.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0017-media-soc_camera-add-legacy-VIN-CSI2.patch new file mode 100644 index 0000000..9a349a0 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0017-media-soc_camera-add-legacy-VIN-CSI2.patch @@ -0,0 +1,5055 @@ +From fd6f489456137d148132010c9da3251ba80f7948 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Sun, 14 May 2017 13:43:24 +0300 +Subject: [PATCH] media: soc_camera: add legacy VIN/CSI2 + +Add legacy/old R-CAR VIN/CSI2 drivers + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi | 348 --- + arch/arm64/boot/dts/renesas/r8a7795.dtsi | 271 --- + arch/arm64/boot/dts/renesas/r8a7796.dtsi | 258 --- + drivers/media/platform/soc_camera/Kconfig | 26 + + drivers/media/platform/soc_camera/Makefile | 2 + + drivers/media/platform/soc_camera/rcar_csi2.c | 708 ++++++ + drivers/media/platform/soc_camera/rcar_vin.c | 3071 +++++++++++++++++++++++++ + include/media/rcar_csi2.h | 66 + + 8 files changed, 3873 insertions(+), 877 deletions(-) + create mode 100644 drivers/media/platform/soc_camera/rcar_csi2.c + create mode 100644 drivers/media/platform/soc_camera/rcar_vin.c + create mode 100644 include/media/rcar_csi2.h + +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi b/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi +index 2bf5911..09e1284 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi +@@ -1927,31 +1927,6 @@ + clocks = <&cpg CPG_MOD 811>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin0csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint= <&csi20vin0>; +- }; +- vin0csi21: endpoint@1 { +- reg = <1>; +- remote-endpoint= <&csi21vin0>; +- }; +- vin0csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint= <&csi40vin0>; +- }; +- }; +- }; + }; + + vin1: video@e6ef1000 { +@@ -1961,31 +1936,6 @@ + clocks = <&cpg CPG_MOD 810>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin1csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint= <&csi20vin1>; +- }; +- vin1csi21: endpoint@1 { +- reg = <1>; +- remote-endpoint= <&csi21vin1>; +- }; +- vin1csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint= <&csi40vin1>; +- }; +- }; +- }; + }; + + vin2: video@e6ef2000 { +@@ -1995,31 +1945,6 @@ + clocks = <&cpg CPG_MOD 809>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin2csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint= <&csi20vin2>; +- }; +- vin2csi21: endpoint@1 { +- reg = <1>; +- remote-endpoint= <&csi21vin2>; +- }; +- vin2csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint= <&csi40vin2>; +- }; +- }; +- }; + }; + + vin3: video@e6ef3000 { +@@ -2029,31 +1954,6 @@ + clocks = <&cpg CPG_MOD 808>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin3csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint= <&csi20vin3>; +- }; +- vin3csi21: endpoint@1 { +- reg = <1>; +- remote-endpoint= <&csi21vin3>; +- }; +- vin3csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint= <&csi40vin3>; +- }; +- }; +- }; + }; + + vin4: video@e6ef4000 { +@@ -2063,31 +1963,6 @@ + clocks = <&cpg CPG_MOD 807>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin4csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint= <&csi20vin4>; +- }; +- vin4csi21: endpoint@1 { +- reg = <1>; +- remote-endpoint= <&csi21vin4>; +- }; +- vin4csi41: endpoint@3 { +- reg = <3>; +- remote-endpoint= <&csi41vin4>; +- }; +- }; +- }; + }; + + vin5: video@e6ef5000 { +@@ -2097,31 +1972,6 @@ + clocks = <&cpg CPG_MOD 806>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin5csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint= <&csi20vin5>; +- }; +- vin5csi21: endpoint@1 { +- reg = <1>; +- remote-endpoint= <&csi21vin5>; +- }; +- vin5csi41: endpoint@3 { +- reg = <3>; +- remote-endpoint= <&csi41vin5>; +- }; +- }; +- }; + }; + + vin6: video@e6ef6000 { +@@ -2131,31 +1981,6 @@ + clocks = <&cpg CPG_MOD 805>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin6csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint= <&csi20vin6>; +- }; +- vin6csi21: endpoint@1 { +- reg = <1>; +- remote-endpoint= <&csi21vin6>; +- }; +- vin6csi41: endpoint@3 { +- reg = <3>; +- remote-endpoint= <&csi41vin6>; +- }; +- }; +- }; + }; + + vin7: video@e6ef7000 { +@@ -2165,31 +1990,6 @@ + clocks = <&cpg CPG_MOD 804>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin7csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint= <&csi20vin7>; +- }; +- vin7csi21: endpoint@1 { +- reg = <1>; +- remote-endpoint= <&csi21vin7>; +- }; +- vin7csi41: endpoint@3 { +- reg = <3>; +- remote-endpoint= <&csi41vin7>; +- }; +- }; +- }; + }; + + csi2_20: csi2@fea80000 { +@@ -2199,51 +1999,6 @@ + clocks = <&cpg CPG_MOD 714>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- csi20vin0: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&vin0csi20>; +- }; +- csi20vin1: endpoint@1 { +- reg = <1>; +- remote-endpoint = <&vin1csi20>; +- }; +- csi20vin2: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&vin2csi20>; +- }; +- csi20vin3: endpoint@3 { +- reg = <3>; +- remote-endpoint = <&vin3csi20>; +- }; +- csi20vin4: endpoint@4 { +- reg = <4>; +- remote-endpoint = <&vin4csi20>; +- }; +- csi20vin5: endpoint@5 { +- reg = <5>; +- remote-endpoint = <&vin5csi20>; +- }; +- csi20vin6: endpoint@6 { +- reg = <6>; +- remote-endpoint = <&vin6csi20>; +- }; +- csi20vin7: endpoint@7 { +- reg = <7>; +- remote-endpoint = <&vin7csi20>; +- }; +- }; +- }; + }; + + csi2_21: csi2@fea90000 { +@@ -2253,51 +2008,6 @@ + clocks = <&cpg CPG_MOD 713>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- csi21vin0: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&vin0csi21>; +- }; +- csi21vin1: endpoint@1 { +- reg = <1>; +- remote-endpoint = <&vin1csi21>; +- }; +- csi21vin2: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&vin2csi21>; +- }; +- csi21vin3: endpoint@3 { +- reg = <3>; +- remote-endpoint = <&vin3csi21>; +- }; +- csi21vin4: endpoint@4 { +- reg = <4>; +- remote-endpoint = <&vin4csi21>; +- }; +- csi21vin5: endpoint@5 { +- reg = <5>; +- remote-endpoint = <&vin5csi21>; +- }; +- csi21vin6: endpoint@6 { +- reg = <6>; +- remote-endpoint = <&vin6csi21>; +- }; +- csi21vin7: endpoint@7 { +- reg = <7>; +- remote-endpoint = <&vin7csi21>; +- }; +- }; +- }; + }; + + csi2_40: csi2@feaa0000 { +@@ -2307,35 +2017,6 @@ + clocks = <&cpg CPG_MOD 716>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- csi40vin0: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&vin0csi40>; +- }; +- csi40vin1: endpoint@1 { +- reg = <1>; +- remote-endpoint = <&vin1csi40>; +- }; +- csi40vin2: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&vin2csi40>; +- }; +- csi40vin3: endpoint@3 { +- reg = <3>; +- remote-endpoint = <&vin3csi40>; +- }; +- }; +- }; + }; + + csi2_41: csi2@feab0000 { +@@ -2345,35 +2026,6 @@ + clocks = <&cpg CPG_MOD 715>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- csi41vin4: endpoint@4 { +- reg = <4>; +- remote-endpoint = <&vin4csi41>; +- }; +- csi41vin5: endpoint@5 { +- reg = <5>; +- remote-endpoint = <&vin5csi41>; +- }; +- csi41vin6: endpoint@6 { +- reg = <6>; +- remote-endpoint = <&vin6csi41>; +- }; +- csi41vin7: endpoint@7 { +- reg = <7>; +- remote-endpoint = <&vin7csi41>; +- }; +- }; +- }; + }; + + sata: sata@ee300000 { +diff --git a/arch/arm64/boot/dts/renesas/r8a7795.dtsi b/arch/arm64/boot/dts/renesas/r8a7795.dtsi +index 94262a1..82ebfd4 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi +@@ -1902,27 +1902,6 @@ + clocks = <&cpg CPG_MOD 811>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin0csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint= <&csi20vin0>; +- }; +- vin0csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint= <&csi40vin0>; +- }; +- }; +- }; + }; + + vin1: video@e6ef1000 { +@@ -1932,27 +1911,6 @@ + clocks = <&cpg CPG_MOD 810>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin1csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint= <&csi20vin1>; +- }; +- vin1csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint= <&csi40vin1>; +- }; +- }; +- }; + }; + + vin2: video@e6ef2000 { +@@ -1962,27 +1920,6 @@ + clocks = <&cpg CPG_MOD 809>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin2csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint= <&csi20vin2>; +- }; +- vin2csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint= <&csi40vin2>; +- }; +- }; +- }; + }; + + vin3: video@e6ef3000 { +@@ -1992,27 +1929,6 @@ + clocks = <&cpg CPG_MOD 808>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin3csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint= <&csi20vin3>; +- }; +- vin3csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint= <&csi40vin3>; +- }; +- }; +- }; + }; + + vin4: video@e6ef4000 { +@@ -2022,27 +1938,6 @@ + clocks = <&cpg CPG_MOD 807>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin4csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint= <&csi20vin4>; +- }; +- vin4csi41: endpoint@3 { +- reg = <3>; +- remote-endpoint= <&csi41vin4>; +- }; +- }; +- }; + }; + + vin5: video@e6ef5000 { +@@ -2052,27 +1947,6 @@ + clocks = <&cpg CPG_MOD 806>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin5csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint= <&csi20vin5>; +- }; +- vin5csi41: endpoint@3 { +- reg = <3>; +- remote-endpoint= <&csi41vin5>; +- }; +- }; +- }; + }; + + vin6: video@e6ef6000 { +@@ -2082,27 +1956,6 @@ + clocks = <&cpg CPG_MOD 805>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin6csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint= <&csi20vin6>; +- }; +- vin6csi41: endpoint@3 { +- reg = <3>; +- remote-endpoint= <&csi41vin6>; +- }; +- }; +- }; + }; + + vin7: video@e6ef7000 { +@@ -2112,27 +1965,6 @@ + clocks = <&cpg CPG_MOD 804>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin7csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint= <&csi20vin7>; +- }; +- vin7csi41: endpoint@3 { +- reg = <3>; +- remote-endpoint= <&csi41vin7>; +- }; +- }; +- }; + }; + + csi2_20: csi2@fea80000 { +@@ -2142,51 +1974,6 @@ + clocks = <&cpg CPG_MOD 714>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- csi20vin0: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&vin0csi20>; +- }; +- csi20vin1: endpoint@1 { +- reg = <1>; +- remote-endpoint = <&vin1csi20>; +- }; +- csi20vin2: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&vin2csi20>; +- }; +- csi20vin3: endpoint@3 { +- reg = <3>; +- remote-endpoint = <&vin3csi20>; +- }; +- csi20vin4: endpoint@4 { +- reg = <4>; +- remote-endpoint = <&vin4csi20>; +- }; +- csi20vin5: endpoint@5 { +- reg = <5>; +- remote-endpoint = <&vin5csi20>; +- }; +- csi20vin6: endpoint@6 { +- reg = <6>; +- remote-endpoint = <&vin6csi20>; +- }; +- csi20vin7: endpoint@7 { +- reg = <7>; +- remote-endpoint = <&vin7csi20>; +- }; +- }; +- }; + }; + + csi2_40: csi2@feaa0000 { +@@ -2196,35 +1983,6 @@ + clocks = <&cpg CPG_MOD 716>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- csi40vin0: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&vin0csi40>; +- }; +- csi40vin1: endpoint@1 { +- reg = <1>; +- remote-endpoint = <&vin1csi40>; +- }; +- csi40vin2: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&vin2csi40>; +- }; +- csi40vin3: endpoint@3 { +- reg = <3>; +- remote-endpoint = <&vin3csi40>; +- }; +- }; +- }; + }; + + csi2_41: csi2@feab0000 { +@@ -2234,35 +1992,6 @@ + clocks = <&cpg CPG_MOD 715>; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- csi41vin4: endpoint@4 { +- reg = <4>; +- remote-endpoint = <&vin4csi41>; +- }; +- csi41vin5: endpoint@5 { +- reg = <5>; +- remote-endpoint = <&vin5csi41>; +- }; +- csi41vin6: endpoint@6 { +- reg = <6>; +- remote-endpoint = <&vin6csi41>; +- }; +- csi41vin7: endpoint@7 { +- reg = <7>; +- remote-endpoint = <&vin7csi41>; +- }; +- }; +- }; + }; + + sata: sata@ee300000 { +diff --git a/arch/arm64/boot/dts/renesas/r8a7796.dtsi b/arch/arm64/boot/dts/renesas/r8a7796.dtsi +index afdd69d..e653814 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7796.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a7796.dtsi +@@ -1592,27 +1592,6 @@ + clocks = <&cpg CPG_MOD 811>; + power-domains = <&sysc R8A7796_PD_ALWAYS_ON>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin0csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint= <&csi20vin0>; +- }; +- vin0csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint= <&csi40vin0>; +- }; +- }; +- }; + }; + + vin1: video@e6ef1000 { +@@ -1622,27 +1601,6 @@ + clocks = <&cpg CPG_MOD 810>; + power-domains = <&sysc R8A7796_PD_ALWAYS_ON>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin1csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint= <&csi20vin1>; +- }; +- vin1csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint= <&csi40vin1>; +- }; +- }; +- }; + }; + + vin2: video@e6ef2000 { +@@ -1652,27 +1610,6 @@ + clocks = <&cpg CPG_MOD 809>; + power-domains = <&sysc R8A7796_PD_ALWAYS_ON>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin2csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint= <&csi20vin2>; +- }; +- vin2csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint= <&csi40vin2>; +- }; +- }; +- }; + }; + + vin3: video@e6ef3000 { +@@ -1682,27 +1619,6 @@ + clocks = <&cpg CPG_MOD 808>; + power-domains = <&sysc R8A7796_PD_ALWAYS_ON>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin3csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint= <&csi20vin3>; +- }; +- vin3csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint= <&csi40vin3>; +- }; +- }; +- }; + }; + + vin4: video@e6ef4000 { +@@ -1712,27 +1628,6 @@ + clocks = <&cpg CPG_MOD 807>; + power-domains = <&sysc R8A7796_PD_ALWAYS_ON>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin4csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint= <&csi20vin4>; +- }; +- vin4csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint= <&csi40vin4>; +- }; +- }; +- }; + }; + + vin5: video@e6ef5000 { +@@ -1742,27 +1637,6 @@ + clocks = <&cpg CPG_MOD 806>; + power-domains = <&sysc R8A7796_PD_ALWAYS_ON>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin5csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint= <&csi20vin5>; +- }; +- vin5csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint= <&csi40vin5>; +- }; +- }; +- }; + }; + + vin6: video@e6ef6000 { +@@ -1772,27 +1646,6 @@ + clocks = <&cpg CPG_MOD 805>; + power-domains = <&sysc R8A7796_PD_ALWAYS_ON>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin6csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint= <&csi20vin6>; +- }; +- vin6csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint= <&csi40vin6>; +- }; +- }; +- }; + }; + + vin7: video@e6ef7000 { +@@ -1802,27 +1655,6 @@ + clocks = <&cpg CPG_MOD 804>; + power-domains = <&sysc R8A7796_PD_ALWAYS_ON>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- vin7csi20: endpoint@0 { +- reg = <0>; +- remote-endpoint= <&csi20vin7>; +- }; +- vin7csi40: endpoint@2 { +- reg = <2>; +- remote-endpoint= <&csi40vin7>; +- }; +- }; +- }; + }; + + csi2_20: csi2@fea80000 { +@@ -1832,51 +1664,6 @@ + clocks = <&cpg CPG_MOD 714>; + power-domains = <&sysc R8A7796_PD_ALWAYS_ON>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- csi20vin0: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&vin0csi20>; +- }; +- csi20vin1: endpoint@1 { +- reg = <1>; +- remote-endpoint = <&vin1csi20>; +- }; +- csi20vin2: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&vin2csi20>; +- }; +- csi20vin3: endpoint@3 { +- reg = <3>; +- remote-endpoint = <&vin3csi20>; +- }; +- csi20vin4: endpoint@4 { +- reg = <4>; +- remote-endpoint = <&vin4csi20>; +- }; +- csi20vin5: endpoint@5 { +- reg = <5>; +- remote-endpoint = <&vin5csi20>; +- }; +- csi20vin6: endpoint@6 { +- reg = <6>; +- remote-endpoint = <&vin6csi20>; +- }; +- csi20vin7: endpoint@7 { +- reg = <7>; +- remote-endpoint = <&vin7csi20>; +- }; +- }; +- }; + }; + + csi2_40: csi2@feaa0000 { +@@ -1886,51 +1673,6 @@ + clocks = <&cpg CPG_MOD 716>; + power-domains = <&sysc R8A7796_PD_ALWAYS_ON>; + status = "disabled"; +- +- ports { +- #address-cells = <1>; +- #size-cells = <0>; +- +- port@1 { +- #address-cells = <1>; +- #size-cells = <0>; +- +- reg = <1>; +- +- csi40vin0: endpoint@0 { +- reg = <0>; +- remote-endpoint = <&vin0csi40>; +- }; +- csi40vin1: endpoint@1 { +- reg = <1>; +- remote-endpoint = <&vin1csi40>; +- }; +- csi40vin2: endpoint@2 { +- reg = <2>; +- remote-endpoint = <&vin2csi40>; +- }; +- csi40vin3: endpoint@3 { +- reg = <3>; +- remote-endpoint = <&vin3csi40>; +- }; +- csi40vin4: endpoint@4 { +- reg = <4>; +- remote-endpoint = <&vin4csi40>; +- }; +- csi40vin5: endpoint@5 { +- reg = <5>; +- remote-endpoint = <&vin5csi40>; +- }; +- csi40vin6: endpoint@6 { +- reg = <6>; +- remote-endpoint = <&vin6csi40>; +- }; +- csi40vin7: endpoint@7 { +- reg = <7>; +- remote-endpoint = <&vin7csi40>; +- }; +- }; +- }; + }; + + vcplf: vcp4@fe910000 { +diff --git a/drivers/media/platform/soc_camera/Kconfig b/drivers/media/platform/soc_camera/Kconfig +index 86d7478..17178ad 100644 +--- a/drivers/media/platform/soc_camera/Kconfig ++++ b/drivers/media/platform/soc_camera/Kconfig +@@ -17,6 +17,32 @@ config SOC_CAMERA_PLATFORM + help + This is a generic SoC camera platform driver, useful for testing + ++config VIDEO_RCAR_VIN_LEGACY ++ tristate "R-Car Video Input (VIN) support" ++ depends on VIDEO_DEV && SOC_CAMERA ++ depends on ARCH_RENESAS || COMPILE_TEST ++ depends on HAS_DMA ++ select VIDEOBUF2_DMA_CONTIG ++ select SOC_CAMERA_SCALE_CROP ++ ---help--- ++ This is a v4l2 driver for the R-Car VIN Interface ++ ++config VIDEO_RCAR_VIN_LEGACY_DEBUG ++ bool "Renesas VIN overflow debug messages" ++ depends on VIDEO_RCAR_VIN_LEGACY ++ ---help--- ++ Enable debug overflow messages on R-Car Video ++ Input driver. ++ If you set to enable, When an overflow occurred, ++ a debug overflow message is output. ++ ++config VIDEO_RCAR_CSI2_LEGACY ++ tristate "R-Car MIPI CSI-2 Interface driver" ++ depends on VIDEO_DEV && SOC_CAMERA && HAVE_CLK ++ depends on ARCH_R8A7795 || ARCH_R8A7796 || COMPILE_TEST ++ ---help--- ++ This is a v4l2 driver for the R-Car CSI-2 Interface ++ + config VIDEO_SH_MOBILE_CEU + tristate "SuperH Mobile CEU Interface driver" + depends on VIDEO_DEV && SOC_CAMERA && HAS_DMA && HAVE_CLK +diff --git a/drivers/media/platform/soc_camera/Makefile b/drivers/media/platform/soc_camera/Makefile +index 7633a0f..8c7ede6 100644 +--- a/drivers/media/platform/soc_camera/Makefile ++++ b/drivers/media/platform/soc_camera/Makefile +@@ -8,3 +8,5 @@ obj-$(CONFIG_SOC_CAMERA_PLATFORM) += soc_camera_platform.o + # soc-camera host drivers have to be linked after camera drivers + obj-$(CONFIG_VIDEO_ATMEL_ISI) += atmel-isi.o + obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o ++obj-$(CONFIG_VIDEO_RCAR_CSI2_LEGACY) += rcar_csi2.o ++obj-$(CONFIG_VIDEO_RCAR_VIN_LEGACY) += rcar_vin.o +diff --git a/drivers/media/platform/soc_camera/rcar_csi2.c b/drivers/media/platform/soc_camera/rcar_csi2.c +new file mode 100644 +index 0000000..05f623468 +--- /dev/null ++++ b/drivers/media/platform/soc_camera/rcar_csi2.c +@@ -0,0 +1,708 @@ ++/* ++ * drivers/media/platform/soc_camera/rcar_csi2.c ++ * This file is the driver for the R-Car MIPI CSI-2 unit. ++ * ++ * Copyright (C) 2015-2016 Renesas Electronics Corporation ++ * ++ * This file is based on the drivers/media/platform/soc_camera/sh_mobile_csi2.c ++ * ++ * Driver for the SH-Mobile MIPI CSI-2 unit ++ * ++ * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include <linux/delay.h> ++#include <linux/interrupt.h> ++#include <linux/err.h> ++#include <linux/i2c.h> ++#include <linux/io.h> ++#include <linux/platform_device.h> ++#include <linux/pm_runtime.h> ++#include <linux/slab.h> ++#include <linux/videodev2.h> ++#include <linux/module.h> ++ ++#include <media/rcar_csi2.h> ++#include <media/soc_camera.h> ++#include <media/v4l2-common.h> ++#include <media/v4l2-dev.h> ++#include <media/v4l2-device.h> ++#include <media/v4l2-mediabus.h> ++#include <media/v4l2-subdev.h> ++ ++#include <media/v4l2-of.h> ++ ++#define DRV_NAME "rcar_csi2" ++#define CONNECT_SLAVE_NAME "adv7482" ++#define VC_MAX_CHANNEL 4 ++ ++#define RCAR_CSI2_TREF 0x00 ++#define RCAR_CSI2_SRST 0x04 ++#define RCAR_CSI2_PHYCNT 0x08 ++#define RCAR_CSI2_CHKSUM 0x0C ++#define RCAR_CSI2_VCDT 0x10 ++ ++#define RCAR_CSI2_VCDT2 0x14 /* Channel Data Type Select */ ++#define RCAR_CSI2_FRDT 0x18 /* Frame Data Type Select */ ++#define RCAR_CSI2_FLD 0x1C /* Field Detection Control */ ++#define RCAR_CSI2_ASTBY 0x20 /* Automatic standby control */ ++#define RCAR_CSI2_LNGDT0 0x28 ++#define RCAR_CSI2_LNGDT1 0x2C ++#define RCAR_CSI2_INTEN 0x30 ++#define RCAR_CSI2_INTCLOSE 0x34 ++#define RCAR_CSI2_INTSTATE 0x38 ++#define RCAR_CSI2_INTERRSTATE 0x3C ++ ++#define RCAR_CSI2_SHPDAT 0x40 ++#define RCAR_CSI2_SHPCNT 0x44 ++ ++#define RCAR_CSI2_LINKCNT 0x48 ++#define RCAR_CSI2_LSWAP 0x4C ++#define RCAR_CSI2_PHTC 0x58 ++#define RCAR_CSI2_PHYPLL 0x68 ++ ++#define RCAR_CSI2_PHEERM 0x74 ++#define RCAR_CSI2_PHCLM 0x78 ++#define RCAR_CSI2_PHDLM 0x7C ++ ++#define RCAR_CSI2_PHYCNT_SHUTDOWNZ (1 << 17) ++#define RCAR_CSI2_PHYCNT_RSTZ (1 << 16) ++#define RCAR_CSI2_PHYCNT_ENABLECLK (1 << 4) ++#define RCAR_CSI2_PHYCNT_ENABLE_3 (1 << 3) ++#define RCAR_CSI2_PHYCNT_ENABLE_2 (1 << 2) ++#define RCAR_CSI2_PHYCNT_ENABLE_1 (1 << 1) ++#define RCAR_CSI2_PHYCNT_ENABLE_0 (1 << 0) ++ ++#define RCAR_CSI2_VCDT_VCDTN_EN (1 << 15) ++#define RCAR_CSI2_VCDT_SEL_VCN (1 << 8) ++#define RCAR_CSI2_VCDT_SEL_DTN_ON (1 << 6) ++#define RCAR_CSI2_VCDT_SEL_DTN (1 << 0) ++ ++#define RCAR_CSI2_LINKCNT_MONITOR_EN (1 << 31) ++#define RCAR_CSI2_LINKCNT_REG_MONI_PACT_EN (1 << 25) ++ ++#define RCAR_CSI2_LSWAP_L3SEL_PLANE0 (0 << 6) ++#define RCAR_CSI2_LSWAP_L3SEL_PLANE1 (1 << 6) ++#define RCAR_CSI2_LSWAP_L3SEL_PLANE2 (2 << 6) ++#define RCAR_CSI2_LSWAP_L3SEL_PLANE3 (3 << 6) ++ ++#define RCAR_CSI2_LSWAP_L2SEL_PLANE0 (0 << 4) ++#define RCAR_CSI2_LSWAP_L2SEL_PLANE1 (1 << 4) ++#define RCAR_CSI2_LSWAP_L2SEL_PLANE2 (2 << 4) ++#define RCAR_CSI2_LSWAP_L2SEL_PLANE3 (3 << 4) ++ ++#define RCAR_CSI2_LSWAP_L1SEL_PLANE0 (0 << 2) ++#define RCAR_CSI2_LSWAP_L1SEL_PLANE1 (1 << 2) ++#define RCAR_CSI2_LSWAP_L1SEL_PLANE2 (2 << 2) ++#define RCAR_CSI2_LSWAP_L1SEL_PLANE3 (3 << 2) ++ ++#define RCAR_CSI2_LSWAP_L0SEL_PLANE0 (0 << 0) ++#define RCAR_CSI2_LSWAP_L0SEL_PLANE1 (1 << 0) ++#define RCAR_CSI2_LSWAP_L0SEL_PLANE2 (2 << 0) ++#define RCAR_CSI2_LSWAP_L0SEL_PLANE3 (3 << 0) ++ ++#define RCAR_CSI2_PHTC_TESTCLR (1 << 0) ++ ++/* interrupt status registers */ ++#define RCAR_CSI2_INTSTATE_EBD_CH1 (1 << 29) ++#define RCAR_CSI2_INTSTATE_LESS_THAN_WC (1 << 28) ++#define RCAR_CSI2_INTSTATE_AFIFO_OF (1 << 27) ++#define RCAR_CSI2_INTSTATE_VD4_START (1 << 26) ++#define RCAR_CSI2_INTSTATE_VD4_END (1 << 25) ++#define RCAR_CSI2_INTSTATE_VD3_START (1 << 24) ++#define RCAR_CSI2_INTSTATE_VD3_END (1 << 23) ++#define RCAR_CSI2_INTSTATE_VD2_START (1 << 22) ++#define RCAR_CSI2_INTSTATE_VD2_END (1 << 21) ++#define RCAR_CSI2_INTSTATE_VD1_START (1 << 20) ++#define RCAR_CSI2_INTSTATE_VD1_END (1 << 19) ++#define RCAR_CSI2_INTSTATE_SHP (1 << 18) ++#define RCAR_CSI2_INTSTATE_FSFE (1 << 17) ++#define RCAR_CSI2_INTSTATE_LNP (1 << 16) ++#define RCAR_CSI2_INTSTATE_CRC_ERR (1 << 15) ++#define RCAR_CSI2_INTSTATE_HD_WC_ZERO (1 << 14) ++#define RCAR_CSI2_INTSTATE_FRM_SEQ_ERR1 (1 << 13) ++#define RCAR_CSI2_INTSTATE_FRM_SEQ_ERR2 (1 << 12) ++#define RCAR_CSI2_INTSTATE_ECC_ERR (1 << 11) ++#define RCAR_CSI2_INTSTATE_ECC_CRCT_ERR (1 << 10) ++#define RCAR_CSI2_INTSTATE_LPDT_START (1 << 9) ++#define RCAR_CSI2_INTSTATE_LPDT_END (1 << 8) ++#define RCAR_CSI2_INTSTATE_ULPS_START (1 << 7) ++#define RCAR_CSI2_INTSTATE_ULPS_END (1 << 6) ++#define RCAR_CSI2_INTSTATE_RESERVED (1 << 5) ++#define RCAR_CSI2_INTSTATE_ERRSOTHS (1 << 4) ++#define RCAR_CSI2_INTSTATE_ERRSOTSYNCCHS (1 << 3) ++#define RCAR_CSI2_INTSTATE_ERRESC (1 << 2) ++#define RCAR_CSI2_INTSTATE_ERRSYNCESC (1 << 1) ++#define RCAR_CSI2_INTSTATE_ERRCONTROL (1 << 0) ++ ++/* monitoring registers of interrupt error status */ ++#define RCAR_CSI2_INTSTATE_ECC_ERR (1 << 11) ++#define RCAR_CSI2_INTSTATE_ECC_CRCT_ERR (1 << 10) ++#define RCAR_CSI2_INTSTATE_LPDT_START (1 << 9) ++#define RCAR_CSI2_INTSTATE_LPDT_END (1 << 8) ++#define RCAR_CSI2_INTSTATE_ULPS_START (1 << 7) ++#define RCAR_CSI2_INTSTATE_ULPS_END (1 << 6) ++#define RCAR_CSI2_INTSTATE_RESERVED (1 << 5) ++#define RCAR_CSI2_INTSTATE_ERRSOTHS (1 << 4) ++#define RCAR_CSI2_INTSTATE_ERRSOTSYNCCHS (1 << 3) ++#define RCAR_CSI2_INTSTATE_ERRESC (1 << 2) ++#define RCAR_CSI2_INTSTATE_ERRSYNCESC (1 << 1) ++#define RCAR_CSI2_INTSTATE_ERRCONTROL (1 << 0) ++ ++enum chip_id { ++ RCAR_GEN3, ++ RCAR_GEN2, ++}; ++ ++enum decoder_input_interface { ++ DECODER_INPUT_INTERFACE_RGB888, ++ DECODER_INPUT_INTERFACE_YCBCR422, ++ DECODER_INPUT_INTERFACE_NONE, ++}; ++ ++/** ++ * struct rcar_csi2_link_config - Describes rcar_csi2 hardware configuration ++ * @input_colorspace: The input colorspace (RGB, YUV444, YUV422) ++ */ ++struct rcar_csi2_link_config { ++ enum decoder_input_interface input_interface; ++ unsigned char lanes; ++ unsigned long vcdt; ++ unsigned long vcdt2; ++}; ++ ++#define INIT_RCAR_CSI2_LINK_CONFIG(m) \ ++{ \ ++ m.input_interface = DECODER_INPUT_INTERFACE_NONE; \ ++ m.lanes = 0; \ ++} ++ ++struct rcar_csi_irq_counter_log { ++ unsigned long crc_err; ++}; ++ ++struct rcar_csi2 { ++ struct v4l2_subdev subdev; ++ struct v4l2_mbus_framefmt *mf; ++ unsigned int irq; ++ unsigned long mipi_flags; ++ void __iomem *base; ++ struct platform_device *pdev; ++ struct rcar_csi2_client_config *client; ++ unsigned long vcdt; ++ unsigned long vcdt2; ++ ++ unsigned int field; ++ unsigned int code; ++ unsigned int lanes; ++ spinlock_t lock; ++}; ++ ++#define RCAR_CSI_80MBPS 0 ++#define RCAR_CSI_90MBPS 1 ++#define RCAR_CSI_100MBPS 2 ++#define RCAR_CSI_110MBPS 3 ++#define RCAR_CSI_120MBPS 4 ++#define RCAR_CSI_130MBPS 5 ++#define RCAR_CSI_140MBPS 6 ++#define RCAR_CSI_150MBPS 7 ++#define RCAR_CSI_160MBPS 8 ++#define RCAR_CSI_170MBPS 9 ++#define RCAR_CSI_180MBPS 10 ++#define RCAR_CSI_190MBPS 11 ++#define RCAR_CSI_205MBPS 12 ++#define RCAR_CSI_220MBPS 13 ++#define RCAR_CSI_235MBPS 14 ++#define RCAR_CSI_250MBPS 15 ++#define RCAR_CSI_275MBPS 16 ++#define RCAR_CSI_300MBPS 17 ++#define RCAR_CSI_325MBPS 18 ++#define RCAR_CSI_350MBPS 19 ++#define RCAR_CSI_400MBPS 20 ++#define RCAR_CSI_450MBPS 21 ++#define RCAR_CSI_500MBPS 22 ++#define RCAR_CSI_550MBPS 23 ++#define RCAR_CSI_600MBPS 24 ++#define RCAR_CSI_650MBPS 25 ++#define RCAR_CSI_700MBPS 26 ++#define RCAR_CSI_750MBPS 27 ++#define RCAR_CSI_800MBPS 28 ++#define RCAR_CSI_850MBPS 29 ++#define RCAR_CSI_900MBPS 30 ++#define RCAR_CSI_950MBPS 31 ++#define RCAR_CSI_1000MBPS 32 ++#define RCAR_CSI_1050MBPS 33 ++#define RCAR_CSI_1100MBPS 34 ++#define RCAR_CSI_1150MBPS 35 ++#define RCAR_CSI_1200MBPS 36 ++#define RCAR_CSI_1250MBPS 37 ++#define RCAR_CSI_1300MBPS 38 ++#define RCAR_CSI_1350MBPS 39 ++#define RCAR_CSI_1400MBPS 40 ++#define RCAR_CSI_1450MBPS 41 ++#define RCAR_CSI_1500MBPS 42 ++ ++static int rcar_csi2_set_phy_freq(struct rcar_csi2 *priv) ++{ ++ const uint32_t const hs_freq_range[43] = { ++ 0x00, 0x10, 0x20, 0x30, 0x01, /* 0-4 */ ++ 0x11, 0x21, 0x31, 0x02, 0x12, /* 5-9 */ ++ 0x22, 0x32, 0x03, 0x13, 0x23, /* 10-14 */ ++ 0x33, 0x04, 0x14, 0x05, 0x15, /* 15-19 */ ++ 0x25, 0x06, 0x16, 0x07, 0x17, /* 20-24 */ ++ 0x08, 0x18, 0x09, 0x19, 0x29, /* 25-29 */ ++ 0x39, 0x0A, 0x1A, 0x2A, 0x3A, /* 30-34 */ ++ 0x0B, 0x1B, 0x2B, 0x3B, 0x0C, /* 35-39 */ ++ 0x1C, 0x2C, 0x3C /* 40-42 */ ++ }; ++ uint32_t bps_per_lane = RCAR_CSI_190MBPS; ++ ++ dev_dbg(&priv->pdev->dev, "Input size (%dx%d%c)\n", ++ priv->mf->width, priv->mf->height, ++ (priv->mf->field == V4L2_FIELD_NONE) ? 'p' : 'i'); ++ ++ switch (priv->lanes) { ++ case 1: ++ bps_per_lane = RCAR_CSI_400MBPS; ++ break; ++ case 4: ++ if (priv->mf->field == V4L2_FIELD_NONE) { ++ if ((priv->mf->width == 1920) && ++ (priv->mf->height == 1080)) ++ bps_per_lane = RCAR_CSI_900MBPS; ++ else if ((priv->mf->width == 1280) && ++ (priv->mf->height == 720)) ++ bps_per_lane = RCAR_CSI_450MBPS; ++ else if ((priv->mf->width == 720) && ++ (priv->mf->height == 480)) ++ bps_per_lane = RCAR_CSI_190MBPS; ++ else if ((priv->mf->width == 720) && ++ (priv->mf->height == 576)) ++ bps_per_lane = RCAR_CSI_190MBPS; ++ else if ((priv->mf->width == 640) && ++ (priv->mf->height == 480)) ++ bps_per_lane = RCAR_CSI_100MBPS; ++ else ++ goto error; ++ } else { ++ if ((priv->mf->width == 1920) && ++ (priv->mf->height == 1080)) ++ bps_per_lane = RCAR_CSI_450MBPS; ++ else ++ goto error; ++ } ++ break; ++ default: ++ dev_err(&priv->pdev->dev, "ERROR: lanes is invalid (%d)\n", ++ priv->lanes); ++ return -EINVAL; ++ } ++ ++ dev_dbg(&priv->pdev->dev, "bps_per_lane (%d)\n", bps_per_lane); ++ ++ iowrite32((hs_freq_range[bps_per_lane] << 16), ++ priv->base + RCAR_CSI2_PHYPLL); ++ return 0; ++ ++error: ++ dev_err(&priv->pdev->dev, "Not support resolution (%dx%d%c)\n", ++ priv->mf->width, priv->mf->height, ++ (priv->mf->field == V4L2_FIELD_NONE) ? 'p' : 'i'); ++ return -EINVAL; ++} ++ ++static irqreturn_t rcar_csi2_irq(int irq, void *data) ++{ ++ struct rcar_csi2 *priv = data; ++ u32 int_status; ++ unsigned int handled = 0; ++ ++ spin_lock(&priv->lock); ++ ++ int_status = ioread32(priv->base + RCAR_CSI2_INTSTATE); ++ if (!int_status) ++ goto done; ++ ++ /* ack interrupts */ ++ iowrite32(int_status, priv->base + RCAR_CSI2_INTSTATE); ++ handled = 1; ++ ++done: ++ spin_unlock(&priv->lock); ++ ++ return IRQ_RETVAL(handled); ++ ++} ++ ++static void rcar_csi2_hwdeinit(struct rcar_csi2 *priv) ++{ ++ iowrite32(0, priv->base + RCAR_CSI2_PHYCNT); ++ ++ /* reset CSI2 hardware */ ++ iowrite32(0x00000001, priv->base + RCAR_CSI2_SRST); ++ udelay(5); ++ iowrite32(0x00000000, priv->base + RCAR_CSI2_SRST); ++} ++ ++static int rcar_csi2_hwinit(struct rcar_csi2 *priv) ++{ ++ int ret; ++ __u32 tmp = 0x10; /* Enable MIPI CSI clock lane */ ++ ++ /* Reflect registers immediately */ ++ iowrite32(0x00000001, priv->base + RCAR_CSI2_TREF); ++ /* reset CSI2 hardware */ ++ iowrite32(0x00000001, priv->base + RCAR_CSI2_SRST); ++ udelay(5); ++ iowrite32(0x00000000, priv->base + RCAR_CSI2_SRST); ++ ++ iowrite32(0x00000000, priv->base + RCAR_CSI2_PHTC); ++ ++ /* setting HS reception frequency */ ++ { ++ switch (priv->lanes) { ++ case 1: ++ /* First field number setting */ ++ iowrite32(0x0001000f, priv->base + RCAR_CSI2_FLD); ++ tmp |= 0x1; ++ break; ++ case 4: ++ /* First field number setting */ ++ iowrite32(0x0002000f, priv->base + RCAR_CSI2_FLD); ++ tmp |= 0xF; ++ break; ++ default: ++ dev_err(&priv->pdev->dev, ++ "ERROR: lanes is invalid (%d)\n", ++ priv->lanes); ++ return -EINVAL; ++ } ++ ++ /* set PHY frequency */ ++ ret = rcar_csi2_set_phy_freq(priv); ++ if (ret < 0) ++ return ret; ++ ++ /* Enable lanes */ ++ iowrite32(tmp, priv->base + RCAR_CSI2_PHYCNT); ++ ++ iowrite32(tmp | RCAR_CSI2_PHYCNT_SHUTDOWNZ, ++ priv->base + RCAR_CSI2_PHYCNT); ++ iowrite32(tmp | (RCAR_CSI2_PHYCNT_SHUTDOWNZ | ++ RCAR_CSI2_PHYCNT_RSTZ), ++ priv->base + RCAR_CSI2_PHYCNT); ++ } ++ ++ iowrite32(0x00000003, priv->base + RCAR_CSI2_CHKSUM); ++ iowrite32(priv->vcdt, priv->base + RCAR_CSI2_VCDT); ++ iowrite32(priv->vcdt2, priv->base + RCAR_CSI2_VCDT2); ++ iowrite32(0x00010000, priv->base + RCAR_CSI2_FRDT); ++ udelay(10); ++ iowrite32(0x83000000, priv->base + RCAR_CSI2_LINKCNT); ++ iowrite32(0x000000e4, priv->base + RCAR_CSI2_LSWAP); ++ ++ dev_dbg(&priv->pdev->dev, "CSI2 VCDT: 0x%x\n", ++ ioread32(priv->base + RCAR_CSI2_VCDT)); ++ dev_dbg(&priv->pdev->dev, "CSI2 VCDT2: 0x%x\n", ++ ioread32(priv->base + RCAR_CSI2_VCDT2)); ++ ++ /* wait until video decoder power off */ ++ msleep(10); ++ { ++ int timeout = 100; ++ ++ /* Read the PHY clock lane monitor register (PHCLM). */ ++ while (!(ioread32(priv->base + RCAR_CSI2_PHCLM) & 0x01) ++ && timeout) { ++ timeout--; ++ } ++ if (timeout == 0) ++ dev_err(&priv->pdev->dev, ++ "Timeout of reading the PHY clock lane\n"); ++ else ++ dev_dbg(&priv->pdev->dev, ++ "Detected the PHY clock lane\n"); ++ ++ timeout = 100; ++ ++ /* Read the PHY data lane monitor register (PHDLM). */ ++ while (!(ioread32(priv->base + RCAR_CSI2_PHDLM) & 0x01) ++ && timeout) { ++ timeout--; ++ } ++ if (timeout == 0) ++ dev_err(&priv->pdev->dev, ++ "Timeout of reading the PHY data lane\n"); ++ else ++ dev_dbg(&priv->pdev->dev, ++ "Detected the PHY data lane\n"); ++ } ++ ++ return 0; ++} ++ ++static int rcar_csi2_s_power(struct v4l2_subdev *sd, int on) ++{ ++ struct rcar_csi2 *priv = container_of(sd, struct rcar_csi2, subdev); ++ struct v4l2_subdev *tmp_sd; ++ struct v4l2_subdev_format fmt = { ++ .which = V4L2_SUBDEV_FORMAT_ACTIVE, ++ }; ++ struct v4l2_mbus_framefmt *mf = &fmt.format; ++ int ret = 0; ++ ++ if (on) { ++ v4l2_device_for_each_subdev(tmp_sd, sd->v4l2_dev) { ++ if (strncmp(tmp_sd->name, CONNECT_SLAVE_NAME, ++ sizeof(CONNECT_SLAVE_NAME) - 1) == 0) { ++ v4l2_subdev_call(tmp_sd, pad, get_fmt, ++ NULL, &fmt); ++ if (ret < 0) ++ return ret; ++ } ++ } ++ priv->mf = mf; ++ pm_runtime_get_sync(&priv->pdev->dev); ++ ret = rcar_csi2_hwinit(priv); ++ if (ret < 0) ++ return ret; ++ } else { ++ rcar_csi2_hwdeinit(priv); ++ pm_runtime_put_sync(&priv->pdev->dev); ++ } ++ ++ return ret; ++} ++ ++static struct v4l2_subdev_core_ops rcar_csi2_subdev_core_ops = { ++ .s_power = rcar_csi2_s_power, ++}; ++ ++static struct v4l2_subdev_ops rcar_csi2_subdev_ops = { ++ .core = &rcar_csi2_subdev_core_ops, ++}; ++ ++#ifdef CONFIG_OF ++static const struct of_device_id rcar_csi2_of_table[] = { ++ { .compatible = "renesas,r8a7796-csi2", .data = (void *)RCAR_GEN3 }, ++ { .compatible = "renesas,r8a7795-csi2", .data = (void *)RCAR_GEN3 }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, rcar_csi2_of_table); ++#endif ++ ++static struct platform_device_id rcar_csi2_id_table[] = { ++ { "r8a7796-csi2", RCAR_GEN3 }, ++ { "r8a7795-csi2", RCAR_GEN3 }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(platform, rcar_csi2_id_table); ++ ++static int rcar_csi2_parse_dt(struct device_node *np, ++ struct rcar_csi2_link_config *config) ++{ ++ struct v4l2_of_endpoint bus_cfg; ++ struct device_node *endpoint; ++ struct device_node *vc_np, *vc_ch; ++ const char *str; ++ char csi_name[9]; ++ int ret; ++ int i, ch; ++ ++ /* Parse the endpoint. */ ++ endpoint = of_graph_get_next_endpoint(np, NULL); ++ if (!endpoint) ++ return -EINVAL; ++ ++ v4l2_of_parse_endpoint(endpoint, &bus_cfg); ++ of_node_put(endpoint); ++ ++ config->lanes = bus_cfg.bus.mipi_csi2.num_data_lanes; ++ ++ ret = of_property_read_string(np, "adi,input-interface", &str); ++ if (ret < 0) ++ return ret; ++ ++ vc_np = of_get_child_by_name(np, "virtual,channel"); ++ ++ config->vcdt = 0; ++ config->vcdt2 = 0; ++ for (i = 0; i < VC_MAX_CHANNEL; i++) { ++ sprintf(csi_name, "csi2_vc%d", i); ++ ++ vc_ch = of_get_child_by_name(vc_np, csi_name); ++ if (!vc_ch) ++ continue; ++ ret = of_property_read_string(vc_ch, "data,type", &str); ++ if (ret < 0) ++ return ret; ++ ret = of_property_read_u32(vc_ch, "receive,vc", &ch); ++ if (ret < 0) ++ return ret; ++ ++ if (i < 2) { ++ if (!strcmp(str, "rgb888")) ++ config->vcdt |= (0x24 << (i * 16)); ++ else if (!strcmp(str, "ycbcr422")) ++ config->vcdt |= (0x1e << (i * 16)); ++ else ++ config->vcdt |= 0; ++ ++ config->vcdt |= (ch << (8 + (i * 16))); ++ config->vcdt |= (RCAR_CSI2_VCDT_VCDTN_EN << (i * 16)) | ++ (RCAR_CSI2_VCDT_SEL_DTN_ON << (i * 16)); ++ } ++ if (i >= 2) { ++ int j = (i - 2); ++ ++ if (!strcmp(str, "rgb888")) ++ config->vcdt2 |= (0x24 << (j * 16)); ++ else if (!strcmp(str, "ycbcr422")) ++ config->vcdt2 |= (0x1e << (j * 16)); ++ else ++ config->vcdt2 |= 0; ++ ++ config->vcdt2 |= (ch << (8 + (j * 16))); ++ config->vcdt2 |= (RCAR_CSI2_VCDT_VCDTN_EN << (j * 16)) | ++ (RCAR_CSI2_VCDT_SEL_DTN_ON << (j * 16)); ++ } ++ } ++ ++ return 0; ++} ++ ++static int rcar_csi2_probe(struct platform_device *pdev) ++{ ++ struct resource *res; ++ unsigned int irq; ++ int ret; ++ struct rcar_csi2 *priv; ++ /* Platform data specify the PHY, lanes, ECC, CRC */ ++ struct rcar_csi2_pdata *pdata; ++ struct rcar_csi2_link_config link_config; ++ ++ dev_dbg(&pdev->dev, "CSI2 probed.\n"); ++ ++ INIT_RCAR_CSI2_LINK_CONFIG(link_config); ++ ++ if (pdev->dev.of_node) { ++ ret = rcar_csi2_parse_dt(pdev->dev.of_node, &link_config); ++ if (ret) ++ return ret; ++ ++ if (link_config.lanes == 4) ++ dev_info(&pdev->dev, ++ "Detected rgb888 in rcar_csi2_parse_dt\n"); ++ else ++ dev_info(&pdev->dev, ++ "Detected YCbCr422 in rcar_csi2_parse_dt\n"); ++ } else { ++ pdata = pdev->dev.platform_data; ++ if (!pdata) ++ return -EINVAL; ++ } ++ ++ priv = devm_kzalloc(&pdev->dev, sizeof(struct rcar_csi2), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ /* Interrupt unused so far */ ++ irq = platform_get_irq(pdev, 0); ++ ++ if (!res || (int)irq <= 0) { ++ dev_err(&pdev->dev, "Not enough CSI2 platform resources.\n"); ++ return -ENODEV; ++ } ++ ++ priv->irq = irq; ++ ++ priv->base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(priv->base)) ++ return PTR_ERR(priv->base); ++ ++ ret = devm_request_irq(&pdev->dev, irq, rcar_csi2_irq, IRQF_SHARED, ++ dev_name(&pdev->dev), priv); ++ if (ret) ++ return ret; ++ ++ priv->pdev = pdev; ++ priv->subdev.owner = THIS_MODULE; ++ priv->subdev.dev = &pdev->dev; ++ priv->lanes = link_config.lanes; ++ priv->vcdt = link_config.vcdt; ++ priv->vcdt2 = link_config.vcdt2; ++ ++ platform_set_drvdata(pdev, &priv->subdev); ++ ++ v4l2_subdev_init(&priv->subdev, &rcar_csi2_subdev_ops); ++ v4l2_set_subdevdata(&priv->subdev, &pdev->dev); ++ ++ snprintf(priv->subdev.name, V4L2_SUBDEV_NAME_SIZE, "rcar_csi2.%s", ++ dev_name(&pdev->dev)); ++ ++ ret = v4l2_async_register_subdev(&priv->subdev); ++ if (ret < 0) ++ return ret; ++ ++ spin_lock_init(&priv->lock); ++ ++ pm_runtime_enable(&pdev->dev); ++ ++ dev_dbg(&pdev->dev, "CSI2 probed.\n"); ++ ++ return 0; ++} ++ ++static int rcar_csi2_remove(struct platform_device *pdev) ++{ ++ struct v4l2_subdev *subdev = platform_get_drvdata(pdev); ++ struct rcar_csi2 *priv = container_of(subdev, struct rcar_csi2, subdev); ++ ++ v4l2_async_unregister_subdev(&priv->subdev); ++ pm_runtime_disable(&pdev->dev); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PM_SLEEP ++static int rcar_csi2_suspend(struct device *dev) ++{ ++ /* Empty function for now */ ++ return 0; ++} ++ ++static int rcar_csi2_resume(struct device *dev) ++{ ++ /* Empty function for now */ ++ return 0; ++} ++ ++static SIMPLE_DEV_PM_OPS(rcar_csi2_pm_ops, ++ rcar_csi2_suspend, rcar_csi2_resume); ++#define DEV_PM_OPS (&rcar_csi2_pm_ops) ++#else ++#define DEV_PM_OPS NULL ++#endif /* CONFIG_PM_SLEEP */ ++ ++static struct platform_driver __refdata rcar_csi2_pdrv = { ++ .remove = rcar_csi2_remove, ++ .probe = rcar_csi2_probe, ++ .driver = { ++ .name = DRV_NAME, ++ .pm = DEV_PM_OPS, ++ .of_match_table = of_match_ptr(rcar_csi2_of_table), ++ }, ++ .id_table = rcar_csi2_id_table, ++}; ++ ++module_platform_driver(rcar_csi2_pdrv); ++ ++MODULE_DESCRIPTION("Renesas R-Car MIPI CSI-2 driver"); ++MODULE_AUTHOR("Koji Matsuoka <koji.matsuoka.xm@renesas.com>"); ++MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS("platform:rcar-csi2"); +diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c +new file mode 100644 +index 0000000..400958b +--- /dev/null ++++ b/drivers/media/platform/soc_camera/rcar_vin.c +@@ -0,0 +1,3071 @@ ++/* ++ * SoC-camera host driver for Renesas R-Car VIN unit ++ * ++ * Copyright (C) 2015-2016 Renesas Electronics Corporation ++ * Copyright (C) 2011-2013 Renesas Solutions Corp. ++ * Copyright (C) 2013 Cogent Embedded, Inc., <source@cogentembedded.com> ++ * ++ * Based on V4L2 Driver for SuperH Mobile CEU interface "sh_mobile_ceu_camera.c" ++ * ++ * Copyright (C) 2008 Magnus Damm ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ */ ++ ++#ifdef CONFIG_VIDEO_RCAR_VIN_LEGACY_DEBUG ++#define DEBUG ++#endif ++ ++#include <linux/delay.h> ++#include <linux/interrupt.h> ++#include <linux/io.h> ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/of.h> ++#include <linux/of_device.h> ++#include <linux/platform_device.h> ++#include <linux/pm_runtime.h> ++#include <linux/slab.h> ++#include <linux/videodev2.h> ++#include <linux/list.h> ++ ++#include <media/soc_camera.h> ++#include <media/drv-intf/soc_mediabus.h> ++#include <media/v4l2-common.h> ++#include <media/v4l2-dev.h> ++#include <media/v4l2-device.h> ++#include <media/v4l2-mediabus.h> ++#include <media/v4l2-of.h> ++#include <media/v4l2-subdev.h> ++#include <media/videobuf2-dma-contig.h> ++ ++#include <media/rcar_csi2.h> ++ ++#include "soc_scale_crop.h" ++ ++#define DRV_NAME "rcar_vin" ++ ++/* Register offsets for R-Car VIN */ ++#define VNMC_REG 0x00 /* Video n Main Control Register */ ++#define VNMS_REG 0x04 /* Video n Module Status Register */ ++#define VNFC_REG 0x08 /* Video n Frame Capture Register */ ++#define VNSLPRC_REG 0x0C /* Video n Start Line Pre-Clip Register */ ++#define VNELPRC_REG 0x10 /* Video n End Line Pre-Clip Register */ ++#define VNSPPRC_REG 0x14 /* Video n Start Pixel Pre-Clip Register */ ++#define VNEPPRC_REG 0x18 /* Video n End Pixel Pre-Clip Register */ ++#define VNSLPOC_REG 0x1C /* Video n Start Line Post-Clip Register */ ++#define VNELPOC_REG 0x20 /* Video n End Line Post-Clip Register */ ++#define VNSPPOC_REG 0x24 /* Video n Start Pixel Post-Clip Register */ ++#define VNEPPOC_REG 0x28 /* Video n End Pixel Post-Clip Register */ ++#define VNIS_REG 0x2C /* Video n Image Stride Register */ ++#define VNMB_REG(m) (0x30 + ((m) << 2)) /* Video n Memory Base m Register */ ++#define VNIE_REG 0x40 /* Video n Interrupt Enable Register */ ++#define VNINTS_REG 0x44 /* Video n Interrupt Status Register */ ++#define VNSI_REG 0x48 /* Video n Scanline Interrupt Register */ ++#define VNMTC_REG 0x4C /* Video n Memory Transfer Control Register */ ++#define VNYS_REG 0x50 /* Video n Y Scale Register */ ++#define VNXS_REG 0x54 /* Video n X Scale Register */ ++#define VNDMR_REG 0x58 /* Video n Data Mode Register */ ++#define VNDMR2_REG 0x5C /* Video n Data Mode Register 2 */ ++#define VNUVAOF_REG 0x60 /* Video n UV Address Offset Register */ ++#define VNC1A_REG 0x80 /* Video n Coefficient Set C1A Register */ ++#define VNC1B_REG 0x84 /* Video n Coefficient Set C1B Register */ ++#define VNC1C_REG 0x88 /* Video n Coefficient Set C1C Register */ ++#define VNC2A_REG 0x90 /* Video n Coefficient Set C2A Register */ ++#define VNC2B_REG 0x94 /* Video n Coefficient Set C2B Register */ ++#define VNC2C_REG 0x98 /* Video n Coefficient Set C2C Register */ ++#define VNC3A_REG 0xA0 /* Video n Coefficient Set C3A Register */ ++#define VNC3B_REG 0xA4 /* Video n Coefficient Set C3B Register */ ++#define VNC3C_REG 0xA8 /* Video n Coefficient Set C3C Register */ ++#define VNC4A_REG 0xB0 /* Video n Coefficient Set C4A Register */ ++#define VNC4B_REG 0xB4 /* Video n Coefficient Set C4B Register */ ++#define VNC4C_REG 0xB8 /* Video n Coefficient Set C4C Register */ ++#define VNC5A_REG 0xC0 /* Video n Coefficient Set C5A Register */ ++#define VNC5B_REG 0xC4 /* Video n Coefficient Set C5B Register */ ++#define VNC5C_REG 0xC8 /* Video n Coefficient Set C5C Register */ ++#define VNC6A_REG 0xD0 /* Video n Coefficient Set C6A Register */ ++#define VNC6B_REG 0xD4 /* Video n Coefficient Set C6B Register */ ++#define VNC6C_REG 0xD8 /* Video n Coefficient Set C6C Register */ ++#define VNC7A_REG 0xE0 /* Video n Coefficient Set C7A Register */ ++#define VNC7B_REG 0xE4 /* Video n Coefficient Set C7B Register */ ++#define VNC7C_REG 0xE8 /* Video n Coefficient Set C7C Register */ ++#define VNC8A_REG 0xF0 /* Video n Coefficient Set C8A Register */ ++#define VNC8B_REG 0xF4 /* Video n Coefficient Set C8B Register */ ++#define VNC8C_REG 0xF8 /* Video n Coefficient Set C8C Register */ ++ ++/* Register bit fields for R-Car VIN */ ++/* Video n Main Control Register bits */ ++#define VNMC_DPINE (1 << 27) ++#define VNMC_SCLE (1 << 26) ++#define VNMC_FOC (1 << 21) ++#define VNMC_YCAL (1 << 19) ++#define VNMC_INF_YUV8_BT656 (0 << 16) ++#define VNMC_INF_YUV8_BT601 (1 << 16) ++#define VNMC_INF_YUV10_BT656 (2 << 16) ++#define VNMC_INF_YUV10_BT601 (3 << 16) ++#define VNMC_INF_YUV16 (5 << 16) ++#define VNMC_INF_RGB888 (6 << 16) ++#define VNMC_INF_MASK (7 << 16) ++#define VNMC_VUP (1 << 10) ++#define VNMC_IM_ODD (0 << 3) ++#define VNMC_IM_ODD_EVEN (1 << 3) ++#define VNMC_IM_EVEN (2 << 3) ++#define VNMC_IM_FULL (3 << 3) ++#define VNMC_BPS (1 << 1) ++#define VNMC_ME (1 << 0) ++ ++/* Video n Module Status Register bits */ ++#define VNMS_FBS_MASK (3 << 3) ++#define VNMS_FBS_SHIFT 3 ++#define VNMS_AV (1 << 1) ++#define VNMS_CA (1 << 0) ++ ++/* Video n Frame Capture Register bits */ ++#define VNFC_C_FRAME (1 << 1) ++#define VNFC_S_FRAME (1 << 0) ++ ++/* Video n Interrupt Enable Register bits */ ++#define VNIE_FIE (1 << 4) ++#define VNIE_EFE (1 << 1) ++#define VNIE_FOE (1 << 0) ++ ++/* Video n Interrupt Status Register bits */ ++#define VNINTS_FIS (1 << 4) ++#define VNINTS_EFS (1 << 1) ++#define VNINTS_FOS (1 << 0) ++ ++/* Video n Data Mode Register bits */ ++#define VNDMR_EXRGB (1 << 8) ++#define VNDMR_BPSM (1 << 4) ++#define VNDMR_DTMD_YCSEP (1 << 1) ++#define VNDMR_DTMD_ARGB (1 << 0) ++#define VNDMR_DTMD_YCSEP_YCBCR420 (3 << 0) ++ ++/* Video n Data Mode Register 2 bits */ ++#define VNDMR2_VPS (1 << 30) ++#define VNDMR2_HPS (1 << 29) ++#define VNDMR2_FTEV (1 << 17) ++#define VNDMR2_VLV(n) ((n & 0xf) << 12) ++ ++/* setting CSI2 on R-Car Gen3*/ ++#define VNCSI_IFMD_REG 0x20 /* Video n CSI2 Interface Mode Register */ ++ ++#define VNCSI_IFMD_DES1 (1 << 26) /* CSI20 */ ++#define VNCSI_IFMD_DES0 (1 << 25) /* H3:CSI40/41, M3:CSI40 */ ++ ++#define VNCSI_IFMD_CSI_CHSEL(n) (n << 0) ++#define VNCSI_IFMD_SEL_NUMBER 5 ++ ++/* UDS */ ++#define VNUDS_CTRL_REG 0x80 /* Scaling Control Registers */ ++#define VNUDS_CTRL_AMD (1 << 30) ++#define VNUDS_CTRL_BC (1 << 20) ++#define VNUDS_CTRL_TDIPC (1 << 1) ++ ++#define VNUDS_SCALE_REG 0x84 /* Scaling Factor Register */ ++#define VNUDS_PASS_BWIDTH_REG 0x90 /* Passband Registers */ ++#define VNUDS_IPC_REG 0x98 /* 2D IPC Setting Register */ ++#define VNUDS_CLIP_SIZE_REG 0xA4 /* UDS Output Size Clipping Register */ ++ ++#define TIMEOUT_MS 100 ++ ++#define RCAR_VIN_HSYNC_ACTIVE_LOW (1 << 0) ++#define RCAR_VIN_VSYNC_ACTIVE_LOW (1 << 1) ++#define RCAR_VIN_BT601 (1 << 2) ++#define RCAR_VIN_BT656 (1 << 3) ++#define RCAR_VIN_CSI2 (1 << 4) ++ ++static int ifmd0_reg_match[VNCSI_IFMD_SEL_NUMBER]; ++static int ifmd4_reg_match[VNCSI_IFMD_SEL_NUMBER]; ++static int ifmd0_init = true; ++static int ifmd4_init = true; ++ ++enum chip_id { ++ RCAR_GEN3, ++ RCAR_M3, ++ RCAR_H3, ++ RCAR_GEN2, ++ RCAR_H1, ++ RCAR_M1, ++ RCAR_E1, ++}; ++ ++enum csi2_ch { ++ RCAR_CSI_CH_NONE = -1, ++ RCAR_CSI40, ++ RCAR_CSI20, ++ RCAR_CSI41, ++ RCAR_CSI21, ++ RCAR_CSI_MAX, ++}; ++ ++enum gen3_vin_ch { ++ RCAR_VIN_CH_NONE = -1, ++ RCAR_VIDEO_0, ++ RCAR_VIDEO_1, ++ RCAR_VIDEO_2, ++ RCAR_VIDEO_3, ++ RCAR_VIDEO_4, ++ RCAR_VIDEO_5, ++ RCAR_VIDEO_6, ++ RCAR_VIDEO_7, ++ RCAR_VIDEO_MAX, ++}; ++ ++enum virtual_ch { ++ RCAR_VIRTUAL_NONE = -1, ++ RCAR_VIRTUAL_CH0, ++ RCAR_VIRTUAL_CH1, ++ RCAR_VIRTUAL_CH2, ++ RCAR_VIRTUAL_CH3, ++ RCAR_VIRTUAL_MAX, ++}; ++ ++struct vin_gen3_virtual_sel { ++ enum csi2_ch csi2_ch; ++ enum virtual_ch vc; ++}; ++ ++struct vin_gen3_ifmd { ++ unsigned int set_reg; ++ struct vin_gen3_virtual_sel v_sel[8]; ++}; ++ ++static const struct vin_gen3_ifmd vin_h3_vc_ifmd[] = { ++ { 0x0000, ++ { ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH1}, ++ } ++ }, ++ { 0x0001, ++ { ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH1}, ++ } ++ }, ++ { 0x0002, ++ { ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH1}, ++ } ++ }, ++ { 0x0003, ++ { ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH2}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH3}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH2}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH3}, ++ } ++ }, ++ { 0x0004, ++ { ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH2}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH3}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH2}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH3}, ++ } ++ }, ++}; ++ ++static const struct vin_gen3_ifmd vin_m3_vc_ifmd[] = { ++ { 0x0000, ++ { ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ } ++ }, ++ { 0x0001, ++ { ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH1}, ++ } ++ }, ++ { 0x0002, ++ { ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ } ++ }, ++ { 0x0003, ++ { ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH2}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH3}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH2}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH3}, ++ } ++ }, ++ { 0x0004, ++ { ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH2}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH3}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH2}, ++ {RCAR_CSI20, RCAR_VIRTUAL_CH3}, ++ } ++ }, ++}; ++ ++enum csi2_fmt { ++ RCAR_CSI_FMT_NONE = -1, ++ RCAR_CSI_RGB888, ++ RCAR_CSI_YCBCR422, ++}; ++ ++struct vin_coeff { ++ unsigned short xs_value; ++ u32 coeff_set[24]; ++}; ++ ++static const struct vin_coeff vin_coeff_set[] = { ++ { 0x0000, { ++ 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00000000, 0x00000000, ++ 0x00000000, 0x00000000, 0x00000000 }, ++ }, ++ { 0x1000, { ++ 0x000fa400, 0x000fa400, 0x09625902, ++ 0x000003f8, 0x00000403, 0x3de0d9f0, ++ 0x001fffed, 0x00000804, 0x3cc1f9c3, ++ 0x001003de, 0x00000c01, 0x3cb34d7f, ++ 0x002003d2, 0x00000c00, 0x3d24a92d, ++ 0x00200bca, 0x00000bff, 0x3df600d2, ++ 0x002013cc, 0x000007ff, 0x3ed70c7e, ++ 0x00100fde, 0x00000000, 0x3f87c036 }, ++ }, ++ { 0x1200, { ++ 0x002ffff1, 0x002ffff1, 0x02a0a9c8, ++ 0x002003e7, 0x001ffffa, 0x000185bc, ++ 0x002007dc, 0x000003ff, 0x3e52859c, ++ 0x00200bd4, 0x00000002, 0x3d53996b, ++ 0x00100fd0, 0x00000403, 0x3d04ad2d, ++ 0x00000bd5, 0x00000403, 0x3d35ace7, ++ 0x3ff003e4, 0x00000801, 0x3dc674a1, ++ 0x3fffe800, 0x00000800, 0x3e76f461 }, ++ }, ++ { 0x1400, { ++ 0x00100be3, 0x00100be3, 0x04d1359a, ++ 0x00000fdb, 0x002003ed, 0x0211fd93, ++ 0x00000fd6, 0x002003f4, 0x0002d97b, ++ 0x000007d6, 0x002ffffb, 0x3e93b956, ++ 0x3ff003da, 0x001003ff, 0x3db49926, ++ 0x3fffefe9, 0x00100001, 0x3d655cee, ++ 0x3fffd400, 0x00000003, 0x3d65f4b6, ++ 0x000fb421, 0x00000402, 0x3dc6547e }, ++ }, ++ { 0x1600, { ++ 0x00000bdd, 0x00000bdd, 0x06519578, ++ 0x3ff007da, 0x00000be3, 0x03c24973, ++ 0x3ff003d9, 0x00000be9, 0x01b30d5f, ++ 0x3ffff7df, 0x001003f1, 0x0003c542, ++ 0x000fdfec, 0x001003f7, 0x3ec4711d, ++ 0x000fc400, 0x002ffffd, 0x3df504f1, ++ 0x001fa81a, 0x002ffc00, 0x3d957cc2, ++ 0x002f8c3c, 0x00100000, 0x3db5c891 }, ++ }, ++ { 0x1800, { ++ 0x3ff003dc, 0x3ff003dc, 0x0791e558, ++ 0x000ff7dd, 0x3ff007de, 0x05328554, ++ 0x000fe7e3, 0x3ff00be2, 0x03232546, ++ 0x000fd7ee, 0x000007e9, 0x0143bd30, ++ 0x001fb800, 0x000007ee, 0x00044511, ++ 0x002fa015, 0x000007f4, 0x3ef4bcee, ++ 0x002f8832, 0x001003f9, 0x3e4514c7, ++ 0x001f7853, 0x001003fd, 0x3de54c9f }, ++ }, ++ { 0x1a00, { ++ 0x000fefe0, 0x000fefe0, 0x08721d3c, ++ 0x001fdbe7, 0x000ffbde, 0x0652a139, ++ 0x001fcbf0, 0x000003df, 0x0463292e, ++ 0x002fb3ff, 0x3ff007e3, 0x0293a91d, ++ 0x002f9c12, 0x3ff00be7, 0x01241905, ++ 0x001f8c29, 0x000007ed, 0x3fe470eb, ++ 0x000f7c46, 0x000007f2, 0x3f04b8ca, ++ 0x3fef7865, 0x000007f6, 0x3e74e4a8 }, ++ }, ++ { 0x1c00, { ++ 0x001fd3e9, 0x001fd3e9, 0x08f23d26, ++ 0x002fbff3, 0x001fe3e4, 0x0712ad23, ++ 0x002fa800, 0x000ff3e0, 0x05631d1b, ++ 0x001f9810, 0x000ffbe1, 0x03b3890d, ++ 0x000f8c23, 0x000003e3, 0x0233e8fa, ++ 0x3fef843b, 0x000003e7, 0x00f430e4, ++ 0x3fbf8456, 0x3ff00bea, 0x00046cc8, ++ 0x3f8f8c72, 0x3ff00bef, 0x3f3490ac }, ++ }, ++ { 0x1e00, { ++ 0x001fbbf4, 0x001fbbf4, 0x09425112, ++ 0x001fa800, 0x002fc7ed, 0x0792b110, ++ 0x000f980e, 0x001fdbe6, 0x0613110a, ++ 0x3fff8c20, 0x001fe7e3, 0x04a368fd, ++ 0x3fcf8c33, 0x000ff7e2, 0x0343b8ed, ++ 0x3f9f8c4a, 0x000fffe3, 0x0203f8da, ++ 0x3f5f9c61, 0x000003e6, 0x00e428c5, ++ 0x3f1fb07b, 0x000003eb, 0x3fe440af }, ++ }, ++ { 0x2000, { ++ 0x000fa400, 0x000fa400, 0x09625902, ++ 0x3fff980c, 0x001fb7f5, 0x0812b0ff, ++ 0x3fdf901c, 0x001fc7ed, 0x06b2fcfa, ++ 0x3faf902d, 0x001fd3e8, 0x055348f1, ++ 0x3f7f983f, 0x001fe3e5, 0x04038ce3, ++ 0x3f3fa454, 0x001fefe3, 0x02e3c8d1, ++ 0x3f0fb86a, 0x001ff7e4, 0x01c3e8c0, ++ 0x3ecfd880, 0x000fffe6, 0x00c404ac }, ++ }, ++ { 0x2200, { ++ 0x3fdf9c0b, 0x3fdf9c0b, 0x09725cf4, ++ 0x3fbf9818, 0x3fffa400, 0x0842a8f1, ++ 0x3f8f9827, 0x000fb3f7, 0x0702f0ec, ++ 0x3f5fa037, 0x000fc3ef, 0x05d330e4, ++ 0x3f2fac49, 0x001fcfea, 0x04a364d9, ++ 0x3effc05c, 0x001fdbe7, 0x038394ca, ++ 0x3ecfdc6f, 0x001fe7e6, 0x0273b0bb, ++ 0x3ea00083, 0x001fefe6, 0x0183c0a9 }, ++ }, ++ { 0x2400, { ++ 0x3f9fa014, 0x3f9fa014, 0x098260e6, ++ 0x3f7f9c23, 0x3fcf9c0a, 0x08629ce5, ++ 0x3f4fa431, 0x3fefa400, 0x0742d8e1, ++ 0x3f1fb440, 0x3fffb3f8, 0x062310d9, ++ 0x3eefc850, 0x000fbbf2, 0x050340d0, ++ 0x3ecfe062, 0x000fcbec, 0x041364c2, ++ 0x3ea00073, 0x001fd3ea, 0x03037cb5, ++ 0x3e902086, 0x001fdfe8, 0x022388a5 }, ++ }, ++ { 0x2600, { ++ 0x3f5fa81e, 0x3f5fa81e, 0x096258da, ++ 0x3f3fac2b, 0x3f8fa412, 0x088290d8, ++ 0x3f0fbc38, 0x3fafa408, 0x0772c8d5, ++ 0x3eefcc47, 0x3fcfa800, 0x0672f4ce, ++ 0x3ecfe456, 0x3fefaffa, 0x05531cc6, ++ 0x3eb00066, 0x3fffbbf3, 0x047334bb, ++ 0x3ea01c77, 0x000fc7ee, 0x039348ae, ++ 0x3ea04486, 0x000fd3eb, 0x02b350a1 }, ++ }, ++ { 0x2800, { ++ 0x3f2fb426, 0x3f2fb426, 0x094250ce, ++ 0x3f0fc032, 0x3f4fac1b, 0x086284cd, ++ 0x3eefd040, 0x3f7fa811, 0x0782acc9, ++ 0x3ecfe84c, 0x3f9fa807, 0x06a2d8c4, ++ 0x3eb0005b, 0x3fbfac00, 0x05b2f4bc, ++ 0x3eb0186a, 0x3fdfb3fa, 0x04c308b4, ++ 0x3eb04077, 0x3fefbbf4, 0x03f31ca8, ++ 0x3ec06884, 0x000fbff2, 0x03031c9e }, ++ }, ++ { 0x2a00, { ++ 0x3f0fc42d, 0x3f0fc42d, 0x090240c4, ++ 0x3eefd439, 0x3f2fb822, 0x08526cc2, ++ 0x3edfe845, 0x3f4fb018, 0x078294bf, ++ 0x3ec00051, 0x3f6fac0f, 0x06b2b4bb, ++ 0x3ec0185f, 0x3f8fac07, 0x05e2ccb4, ++ 0x3ec0386b, 0x3fafac00, 0x0502e8ac, ++ 0x3ed05c77, 0x3fcfb3fb, 0x0432f0a3, ++ 0x3ef08482, 0x3fdfbbf6, 0x0372f898 }, ++ }, ++ { 0x2c00, { ++ 0x3eefdc31, 0x3eefdc31, 0x08e238b8, ++ 0x3edfec3d, 0x3f0fc828, 0x082258b9, ++ 0x3ed00049, 0x3f1fc01e, 0x077278b6, ++ 0x3ed01455, 0x3f3fb815, 0x06c294b2, ++ 0x3ed03460, 0x3f5fb40d, 0x0602acac, ++ 0x3ef0506c, 0x3f7fb006, 0x0542c0a4, ++ 0x3f107476, 0x3f9fb400, 0x0472c89d, ++ 0x3f309c80, 0x3fbfb7fc, 0x03b2cc94 }, ++ }, ++ { 0x2e00, { ++ 0x3eefec37, 0x3eefec37, 0x088220b0, ++ 0x3ee00041, 0x3effdc2d, 0x07f244ae, ++ 0x3ee0144c, 0x3f0fd023, 0x07625cad, ++ 0x3ef02c57, 0x3f1fc81a, 0x06c274a9, ++ 0x3f004861, 0x3f3fbc13, 0x060288a6, ++ 0x3f20686b, 0x3f5fb80c, 0x05529c9e, ++ 0x3f408c74, 0x3f6fb805, 0x04b2ac96, ++ 0x3f80ac7e, 0x3f8fb800, 0x0402ac8e }, ++ }, ++ { 0x3000, { ++ 0x3ef0003a, 0x3ef0003a, 0x084210a6, ++ 0x3ef01045, 0x3effec32, 0x07b228a7, ++ 0x3f00284e, 0x3f0fdc29, 0x073244a4, ++ 0x3f104058, 0x3f0fd420, 0x06a258a2, ++ 0x3f305c62, 0x3f2fc818, 0x0612689d, ++ 0x3f508069, 0x3f3fc011, 0x05728496, ++ 0x3f80a072, 0x3f4fc00a, 0x04d28c90, ++ 0x3fc0c07b, 0x3f6fbc04, 0x04429088 }, ++ }, ++ { 0x3200, { ++ 0x3f00103e, 0x3f00103e, 0x07f1fc9e, ++ 0x3f102447, 0x3f000035, 0x0782149d, ++ 0x3f203c4f, 0x3f0ff02c, 0x07122c9c, ++ 0x3f405458, 0x3f0fe424, 0x06924099, ++ 0x3f607061, 0x3f1fd41d, 0x06024c97, ++ 0x3f909068, 0x3f2fcc16, 0x05726490, ++ 0x3fc0b070, 0x3f3fc80f, 0x04f26c8a, ++ 0x0000d077, 0x3f4fc409, 0x04627484 }, ++ }, ++ { 0x3400, { ++ 0x3f202040, 0x3f202040, 0x07a1e898, ++ 0x3f303449, 0x3f100c38, 0x0741fc98, ++ 0x3f504c50, 0x3f10002f, 0x06e21495, ++ 0x3f706459, 0x3f1ff028, 0x06722492, ++ 0x3fa08060, 0x3f1fe421, 0x05f2348f, ++ 0x3fd09c67, 0x3f1fdc19, 0x05824c89, ++ 0x0000bc6e, 0x3f2fd014, 0x04f25086, ++ 0x0040dc74, 0x3f3fcc0d, 0x04825c7f }, ++ }, ++ { 0x3600, { ++ 0x3f403042, 0x3f403042, 0x0761d890, ++ 0x3f504848, 0x3f301c3b, 0x0701f090, ++ 0x3f805c50, 0x3f200c33, 0x06a2008f, ++ 0x3fa07458, 0x3f10002b, 0x06520c8d, ++ 0x3fd0905e, 0x3f1ff424, 0x05e22089, ++ 0x0000ac65, 0x3f1fe81d, 0x05823483, ++ 0x0030cc6a, 0x3f2fdc18, 0x04f23c81, ++ 0x0080e871, 0x3f2fd412, 0x0482407c }, ++ }, ++ { 0x3800, { ++ 0x3f604043, 0x3f604043, 0x0721c88a, ++ 0x3f80544a, 0x3f502c3c, 0x06d1d88a, ++ 0x3fb06851, 0x3f301c35, 0x0681e889, ++ 0x3fd08456, 0x3f30082f, 0x0611fc88, ++ 0x00009c5d, 0x3f200027, 0x05d20884, ++ 0x0030b863, 0x3f2ff421, 0x05621880, ++ 0x0070d468, 0x3f2fe81b, 0x0502247c, ++ 0x00c0ec6f, 0x3f2fe015, 0x04a22877 }, ++ }, ++ { 0x3a00, { ++ 0x3f904c44, 0x3f904c44, 0x06e1b884, ++ 0x3fb0604a, 0x3f70383e, 0x0691c885, ++ 0x3fe07451, 0x3f502c36, 0x0661d483, ++ 0x00009055, 0x3f401831, 0x0601ec81, ++ 0x0030a85b, 0x3f300c2a, 0x05b1f480, ++ 0x0070c061, 0x3f300024, 0x0562047a, ++ 0x00b0d867, 0x3f3ff41e, 0x05020c77, ++ 0x00f0f46b, 0x3f2fec19, 0x04a21474 }, ++ }, ++ { 0x3c00, { ++ 0x3fb05c43, 0x3fb05c43, 0x06c1b07e, ++ 0x3fe06c4b, 0x3f902c3f, 0x0681c081, ++ 0x0000844f, 0x3f703838, 0x0631cc7d, ++ 0x00309855, 0x3f602433, 0x05d1d47e, ++ 0x0060b459, 0x3f50142e, 0x0581e47b, ++ 0x00a0c85f, 0x3f400828, 0x0531f078, ++ 0x00e0e064, 0x3f300021, 0x0501fc73, ++ 0x00b0fc6a, 0x3f3ff41d, 0x04a20873 }, ++ }, ++ { 0x3e00, { ++ 0x3fe06444, 0x3fe06444, 0x0681a07a, ++ 0x00007849, 0x3fc0503f, 0x0641b07a, ++ 0x0020904d, 0x3fa0403a, 0x05f1c07a, ++ 0x0060a453, 0x3f803034, 0x05c1c878, ++ 0x0090b858, 0x3f70202f, 0x0571d477, ++ 0x00d0d05d, 0x3f501829, 0x0531e073, ++ 0x0110e462, 0x3f500825, 0x04e1e471, ++ 0x01510065, 0x3f40001f, 0x04a1f06d }, ++ }, ++ { 0x4000, { ++ 0x00007044, 0x00007044, 0x06519476, ++ 0x00208448, 0x3fe05c3f, 0x0621a476, ++ 0x0050984d, 0x3fc04c3a, 0x05e1b075, ++ 0x0080ac52, 0x3fa03c35, 0x05a1b875, ++ 0x00c0c056, 0x3f803030, 0x0561c473, ++ 0x0100d45b, 0x3f70202b, 0x0521d46f, ++ 0x0140e860, 0x3f601427, 0x04d1d46e, ++ 0x01810064, 0x3f500822, 0x0491dc6b }, ++ }, ++ { 0x5000, { ++ 0x0110a442, 0x0110a442, 0x0551545e, ++ 0x0140b045, 0x00e0983f, 0x0531585f, ++ 0x0160c047, 0x00c08c3c, 0x0511645e, ++ 0x0190cc4a, 0x00908039, 0x04f1685f, ++ 0x01c0dc4c, 0x00707436, 0x04d1705e, ++ 0x0200e850, 0x00506833, 0x04b1785b, ++ 0x0230f453, 0x00305c30, 0x0491805a, ++ 0x02710056, 0x0010542d, 0x04718059 }, ++ }, ++ { 0x6000, { ++ 0x01c0bc40, 0x01c0bc40, 0x04c13052, ++ 0x01e0c841, 0x01a0b43d, 0x04c13851, ++ 0x0210cc44, 0x0180a83c, 0x04a13453, ++ 0x0230d845, 0x0160a03a, 0x04913c52, ++ 0x0260e047, 0x01409838, 0x04714052, ++ 0x0280ec49, 0x01208c37, 0x04514c50, ++ 0x02b0f44b, 0x01008435, 0x04414c50, ++ 0x02d1004c, 0x00e07c33, 0x0431544f }, ++ }, ++ { 0x7000, { ++ 0x0230c83e, 0x0230c83e, 0x04711c4c, ++ 0x0250d03f, 0x0210c43c, 0x0471204b, ++ 0x0270d840, 0x0200b83c, 0x0451244b, ++ 0x0290dc42, 0x01e0b43a, 0x0441244c, ++ 0x02b0e443, 0x01c0b038, 0x0441284b, ++ 0x02d0ec44, 0x01b0a438, 0x0421304a, ++ 0x02f0f445, 0x0190a036, 0x04213449, ++ 0x0310f847, 0x01709c34, 0x04213848 }, ++ }, ++ { 0x8000, { ++ 0x0280d03d, 0x0280d03d, 0x04310c48, ++ 0x02a0d43e, 0x0270c83c, 0x04311047, ++ 0x02b0dc3e, 0x0250c83a, 0x04311447, ++ 0x02d0e040, 0x0240c03a, 0x04211446, ++ 0x02e0e840, 0x0220bc39, 0x04111847, ++ 0x0300e842, 0x0210b438, 0x04012445, ++ 0x0310f043, 0x0200b037, 0x04012045, ++ 0x0330f444, 0x01e0ac36, 0x03f12445 }, ++ }, ++ { 0xefff, { ++ 0x0340dc3a, 0x0340dc3a, 0x03b0ec40, ++ 0x0340e03a, 0x0330e039, 0x03c0f03e, ++ 0x0350e03b, 0x0330dc39, 0x03c0ec3e, ++ 0x0350e43a, 0x0320dc38, 0x03c0f43e, ++ 0x0360e43b, 0x0320d839, 0x03b0f03e, ++ 0x0360e83b, 0x0310d838, 0x03c0fc3b, ++ 0x0370e83b, 0x0310d439, 0x03a0f83d, ++ 0x0370e83c, 0x0300d438, 0x03b0fc3c }, ++ } ++}; ++ ++enum rcar_vin_state { ++ STOPPED = 0, ++ RUNNING, ++ STOPPING, ++}; ++ ++struct rcar_vin_async_client { ++ struct v4l2_async_subdev *sensor; ++ struct v4l2_async_notifier notifier; ++ struct platform_device *pdev; ++ struct list_head list; /* needed for clean up */ ++}; ++ ++struct soc_of_info { ++ struct soc_camera_async_subdev sasd; ++ struct rcar_vin_async_client sasc; ++ struct v4l2_async_subdev *subdev; ++}; ++ ++struct rcar_vin_priv { ++ void __iomem *base; ++ spinlock_t lock; ++ int sequence; ++ /* State of the VIN module in capturing mode */ ++ enum rcar_vin_state state; ++ struct soc_camera_host ici; ++ struct list_head capture; ++#define MAX_BUFFER_NUM 3 ++ struct vb2_v4l2_buffer *queue_buf[MAX_BUFFER_NUM]; ++ enum v4l2_field field; ++ unsigned int pdata_flags; ++ unsigned int vb_count; ++ unsigned int nr_hw_slots; ++ bool request_to_stop; ++ struct completion capture_stop; ++ enum chip_id chip; ++ unsigned int max_width; ++ unsigned int max_height; ++ unsigned int ratio_h; ++ unsigned int ratio_v; ++ bool error_flag; ++ enum csi2_ch csi_ch; ++ enum csi2_fmt csi_fmt; ++ enum virtual_ch vc; ++ bool csi_sync; ++ ++ struct rcar_vin_async_client *async_client; ++ /* Asynchronous CSI2 linking */ ++ struct v4l2_subdev *csi2_sd; ++ /* Synchronous probing compatibility */ ++ struct platform_device *csi2_pdev; ++ ++ unsigned int index; ++}; ++ ++#define is_continuous_transfer(priv) (priv->vb_count > MAX_BUFFER_NUM) ++ ++struct rcar_vin_buffer { ++ struct vb2_v4l2_buffer vb; ++ struct list_head list; ++}; ++ ++#define to_buf_list(vb2_buffer) (&container_of(vb2_buffer, \ ++ struct rcar_vin_buffer, \ ++ vb)->list) ++ ++struct rcar_vin_cam { ++ /* VIN offsets within the camera output, before the VIN scaler */ ++ unsigned int vin_left; ++ unsigned int vin_top; ++ /* Client output, as seen by the VIN */ ++ unsigned int width; ++ unsigned int height; ++ /* User window from S_FMT */ ++ unsigned int out_width; ++ unsigned int out_height; ++ /* ++ * User window from S_SELECTION / G_SELECTION, produced by client cropping and ++ * scaling, VIN scaling and VIN cropping, mapped back onto the client ++ * input window ++ */ ++ struct v4l2_rect subrect; ++ /* Camera cropping rectangle */ ++ struct v4l2_rect rect; ++ const struct soc_mbus_pixelfmt *extra_fmt; ++}; ++ ++#define VIN_UT_IRQ 0x01 ++ ++static unsigned int vin_debug; ++module_param_named(debug, vin_debug, int, 0600); ++static int overflow_video[RCAR_VIDEO_MAX]; ++module_param_array(overflow_video, int, NULL, 0600); ++ ++#ifdef CONFIG_VIDEO_RCAR_VIN_LEGACY_DEBUG ++#define VIN_IRQ_DEBUG(fmt, args...) \ ++ do { \ ++ if (unlikely(vin_debug & VIN_UT_IRQ)) \ ++ vin_ut_debug_printk(__func__, fmt, ##args); \ ++ } while (0) ++#else ++#define VIN_IRQ_DEBUG(fmt, args...) ++#endif ++ ++void vin_ut_debug_printk(const char *function_name, const char *format, ...) ++{ ++ struct va_format vaf; ++ va_list args; ++ ++ va_start(args, format); ++ vaf.fmt = format; ++ vaf.va = &args; ++ ++ pr_debug("[" DRV_NAME ":%s] %pV", function_name, &vaf); ++ ++ va_end(args); ++} ++ ++static void rcar_vin_cpg_enable_for_ifmd(unsigned int ch, bool enable) ++{ ++ void __iomem *smstpcr8; ++ ++ smstpcr8 = ioremap(0xE6150990, 0x04); ++ ++ if (enable) { ++ if (ch < RCAR_VIDEO_4) ++ iowrite32((ioread32(smstpcr8) & 0xFFFFF7FF), smstpcr8); ++ else ++ iowrite32((ioread32(smstpcr8) & 0xFFFFFF7F), smstpcr8); ++ } else { ++ if (ch < RCAR_VIDEO_4) ++ iowrite32((ioread32(smstpcr8) | 0x00000800), smstpcr8); ++ else ++ iowrite32((ioread32(smstpcr8) | 0x00000080), smstpcr8); ++ } ++ ++ iounmap(smstpcr8); ++} ++ ++static inline int is_scaling(struct rcar_vin_cam *cam) ++{ ++ struct v4l2_rect *cam_subrect = &cam->subrect; ++ ++ if ((cam_subrect->width != cam->out_width) || ++ (cam_subrect->height != cam->out_height)) ++ return 1; ++ ++ return 0; ++} ++ ++/* ++ * .queue_setup() is called to check whether the driver can accept the requested ++ * number of buffers and to fill in plane sizes for the current frame format if ++ * required ++ */ ++static int rcar_vin_videobuf_setup(struct vb2_queue *vq, ++ unsigned int *count, ++ unsigned int *num_planes, ++ unsigned int sizes[], struct device *alloc_devs[]) ++{ ++ struct soc_camera_device *icd = soc_camera_from_vb2q(vq); ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct rcar_vin_priv *priv = ici->priv; ++ struct rcar_vin_cam *cam = icd->host_priv; ++ ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ if ((priv->ratio_h > 0x10000) || (priv->ratio_v > 0x10000)) { ++ dev_err(icd->parent, "Scaling rate parameter error\n"); ++ return -EINVAL; ++ } ++ if (is_scaling(cam) && (cam->out_width % 32)) { ++ dev_err(icd->parent, "Scaling parameter error\n"); ++ return -EINVAL; ++ } ++ if (!is_scaling(cam) && (cam->out_width % 16)) { ++ dev_err(icd->parent, "Image stride parameter error\n"); ++ return -EINVAL; ++ } ++ } ++ ++ if (!vq->num_buffers) ++ priv->sequence = 0; ++ ++ if (!*count) ++ *count = 2; ++ priv->vb_count = *count; ++ ++ /* Number of hardware slots */ ++ if (is_continuous_transfer(priv)) ++ priv->nr_hw_slots = MAX_BUFFER_NUM; ++ else ++ priv->nr_hw_slots = 1; ++ ++ if (*num_planes) ++ return sizes[0] < icd->sizeimage ? -EINVAL : 0; ++ ++ sizes[0] = icd->sizeimage; ++ *num_planes = 1; ++ ++ dev_dbg(icd->parent, "count=%d, size=%u\n", *count, sizes[0]); ++ ++ return 0; ++} ++ ++static int rcar_vin_setup(struct rcar_vin_priv *priv) ++{ ++ struct soc_camera_device *icd = priv->ici.icd; ++ struct rcar_vin_cam *cam = icd->host_priv; ++ u32 vnmc, dmr, interrupts; ++ bool progressive = false, output_is_yuv = false, input_is_yuv = false; ++ ++ switch (priv->field) { ++ case V4L2_FIELD_TOP: ++ vnmc = VNMC_IM_ODD; ++ break; ++ case V4L2_FIELD_BOTTOM: ++ vnmc = VNMC_IM_EVEN; ++ break; ++ case V4L2_FIELD_INTERLACED: ++ case V4L2_FIELD_INTERLACED_TB: ++ vnmc = VNMC_IM_FULL; ++ break; ++ case V4L2_FIELD_INTERLACED_BT: ++ vnmc = VNMC_IM_FULL | VNMC_FOC; ++ break; ++ case V4L2_FIELD_NONE: ++ if (is_continuous_transfer(priv)) { ++ vnmc = VNMC_IM_ODD_EVEN; ++ progressive = true; ++ } else { ++ vnmc = VNMC_IM_ODD; ++ } ++ break; ++ default: ++ vnmc = VNMC_IM_ODD; ++ break; ++ } ++ ++ /* input interface */ ++ switch (icd->current_fmt->code) { ++ case MEDIA_BUS_FMT_YUYV8_1X16: ++ /* BT.601/BT.1358 16bit YCbCr422 */ ++ vnmc |= VNMC_INF_YUV16; ++ input_is_yuv = true; ++ break; ++ case MEDIA_BUS_FMT_YUYV8_2X8: ++ /* BT.656 8bit YCbCr422 or BT.601 8bit YCbCr422 */ ++ vnmc |= priv->pdata_flags & RCAR_VIN_BT656 ? ++ VNMC_INF_YUV8_BT656 : VNMC_INF_YUV8_BT601; ++ input_is_yuv = true; ++ break; ++ case MEDIA_BUS_FMT_RGB888_1X24: ++ vnmc |= VNMC_INF_RGB888; ++ break; ++ case MEDIA_BUS_FMT_YUYV10_2X10: ++ /* BT.656 10bit YCbCr422 or BT.601 10bit YCbCr422 */ ++ vnmc |= priv->pdata_flags & RCAR_VIN_BT656 ? ++ VNMC_INF_YUV10_BT656 : VNMC_INF_YUV10_BT601; ++ input_is_yuv = true; ++ break; ++ default: ++ break; ++ } ++ ++ /* output format */ ++ switch (icd->current_fmt->host_fmt->fourcc) { ++ case V4L2_PIX_FMT_NV12: ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ iowrite32(ALIGN((cam->out_width * cam->out_height), ++ 0x80), priv->base + VNUVAOF_REG); ++ dmr = VNDMR_DTMD_YCSEP_YCBCR420; ++ output_is_yuv = true; ++ } else { ++ dev_warn(icd->parent, "Not support format\n"); ++ return -EINVAL; ++ } ++ break; ++ case V4L2_PIX_FMT_NV16: ++ iowrite32(ALIGN((cam->out_width * cam->out_height), 0x80), ++ priv->base + VNUVAOF_REG); ++ dmr = VNDMR_DTMD_YCSEP; ++ output_is_yuv = true; ++ break; ++ case V4L2_PIX_FMT_YUYV: ++ dmr = VNDMR_BPSM; ++ output_is_yuv = true; ++ break; ++ case V4L2_PIX_FMT_UYVY: ++ dmr = 0; ++ output_is_yuv = true; ++ break; ++ case V4L2_PIX_FMT_ARGB555: ++ dmr = VNDMR_DTMD_ARGB; ++ break; ++ case V4L2_PIX_FMT_RGB565: ++ dmr = 0; ++ break; ++ case V4L2_PIX_FMT_XBGR32: ++ if (priv->chip != RCAR_H3 && priv->chip != RCAR_M3 && ++ priv->chip != RCAR_GEN2 && priv->chip != RCAR_H1 && ++ priv->chip != RCAR_E1) ++ goto e_format; ++ ++ dmr = VNDMR_EXRGB; ++ break; ++ case V4L2_PIX_FMT_ABGR32: ++ if (priv->chip != RCAR_H3 && priv->chip != RCAR_M3) ++ goto e_format; ++ ++ dmr = VNDMR_EXRGB | VNDMR_DTMD_ARGB; ++ break; ++ default: ++ goto e_format; ++ } ++ ++ /* Always update on field change */ ++ vnmc |= VNMC_VUP; ++ ++ /* If input and output use the same colorspace, use bypass mode */ ++ if (input_is_yuv == output_is_yuv) ++ vnmc |= VNMC_BPS; ++ ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ if (priv->pdata_flags & RCAR_VIN_CSI2) ++ vnmc &= ~VNMC_DPINE; ++ else ++ vnmc |= VNMC_DPINE; ++ ++ if ((icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_NV12) ++ && is_scaling(cam)) ++ vnmc |= VNMC_SCLE; ++ } ++ ++ /* progressive or interlaced mode */ ++ interrupts = progressive ? VNIE_FIE : VNIE_EFE; ++ ++ /* Enable Overflow */ ++ if (vin_debug) ++ interrupts |= VNIE_FOE; ++ ++ /* ack interrupts */ ++ iowrite32(interrupts, priv->base + VNINTS_REG); ++ /* enable interrupts */ ++ iowrite32(interrupts, priv->base + VNIE_REG); ++ /* start capturing */ ++ iowrite32(dmr, priv->base + VNDMR_REG); ++ iowrite32(vnmc | VNMC_ME, priv->base + VNMC_REG); ++ ++ return 0; ++ ++e_format: ++ dev_warn(icd->parent, "Invalid fourcc format (0x%x)\n", ++ icd->current_fmt->host_fmt->fourcc); ++ return -EINVAL; ++} ++ ++static void rcar_vin_capture(struct rcar_vin_priv *priv) ++{ ++ if (is_continuous_transfer(priv)) ++ /* Continuous Frame Capture Mode */ ++ iowrite32(VNFC_C_FRAME, priv->base + VNFC_REG); ++ else ++ /* Single Frame Capture Mode */ ++ iowrite32(VNFC_S_FRAME, priv->base + VNFC_REG); ++} ++ ++static void rcar_vin_request_capture_stop(struct rcar_vin_priv *priv) ++{ ++ priv->state = STOPPING; ++ ++ /* set continuous & single transfer off */ ++ iowrite32(0, priv->base + VNFC_REG); ++ /* disable capture (release DMA buffer), reset */ ++ iowrite32(ioread32(priv->base + VNMC_REG) & ~VNMC_ME, ++ priv->base + VNMC_REG); ++ ++ /* update the status if stopped already */ ++ if (!(ioread32(priv->base + VNMS_REG) & VNMS_CA)) ++ priv->state = STOPPED; ++} ++ ++static int rcar_vin_get_free_hw_slot(struct rcar_vin_priv *priv) ++{ ++ int slot; ++ ++ for (slot = 0; slot < priv->nr_hw_slots; slot++) ++ if (priv->queue_buf[slot] == NULL) ++ return slot; ++ ++ return -1; ++} ++ ++static int rcar_vin_hw_ready(struct rcar_vin_priv *priv) ++{ ++ /* Ensure all HW slots are filled */ ++ return rcar_vin_get_free_hw_slot(priv) < 0 ? 1 : 0; ++} ++ ++/* Moves a buffer from the queue to the HW slots */ ++static int rcar_vin_fill_hw_slot(struct rcar_vin_priv *priv) ++{ ++ struct vb2_v4l2_buffer *vbuf; ++ dma_addr_t phys_addr_top; ++ int slot; ++ ++ if (list_empty(&priv->capture)) ++ return 0; ++ ++ /* Find a free HW slot */ ++ slot = rcar_vin_get_free_hw_slot(priv); ++ if (slot < 0) ++ return 0; ++ ++ vbuf = &list_entry(priv->capture.next, ++ struct rcar_vin_buffer, list)->vb; ++ list_del_init(to_buf_list(vbuf)); ++ priv->queue_buf[slot] = vbuf; ++ phys_addr_top = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 0); ++ iowrite32(phys_addr_top, priv->base + VNMB_REG(slot)); ++ ++ return 1; ++} ++ ++static void rcar_vin_videobuf_queue(struct vb2_buffer *vb) ++{ ++ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); ++ struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct rcar_vin_priv *priv = ici->priv; ++ unsigned long size; ++ ++ size = icd->sizeimage; ++ ++ if (vb2_plane_size(vb, 0) < size) { ++ dev_err(icd->parent, "Buffer #%d too small (%lu < %lu)\n", ++ vb->index, vb2_plane_size(vb, 0), size); ++ goto error; ++ } ++ ++ vb2_set_plane_payload(vb, 0, size); ++ ++ dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__, ++ vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); ++ ++ spin_lock_irq(&priv->lock); ++ ++ list_add_tail(to_buf_list(vbuf), &priv->capture); ++ rcar_vin_fill_hw_slot(priv); ++ ++ /* If we weren't running, and have enough buffers, start capturing! */ ++ if (priv->state != RUNNING && rcar_vin_hw_ready(priv)) { ++ if (rcar_vin_setup(priv)) { ++ /* Submit error */ ++ list_del_init(to_buf_list(vbuf)); ++ spin_unlock_irq(&priv->lock); ++ goto error; ++ } ++ priv->request_to_stop = false; ++ init_completion(&priv->capture_stop); ++ priv->state = RUNNING; ++ rcar_vin_capture(priv); ++ } ++ ++ spin_unlock_irq(&priv->lock); ++ ++ return; ++ ++error: ++ vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); ++} ++ ++/* ++ * Wait for capture to stop and all in-flight buffers to be finished with by ++ * the video hardware. This must be called under &priv->lock ++ * ++ */ ++static void rcar_vin_wait_stop_streaming(struct rcar_vin_priv *priv) ++{ ++ while (priv->state != STOPPED) { ++ /* issue stop if running */ ++ if (priv->state == RUNNING) ++ rcar_vin_request_capture_stop(priv); ++ ++ /* wait until capturing has been stopped */ ++ if (priv->state == STOPPING) { ++ priv->request_to_stop = true; ++ spin_unlock_irq(&priv->lock); ++ if (!wait_for_completion_timeout( ++ &priv->capture_stop, ++ msecs_to_jiffies(TIMEOUT_MS))) ++ priv->state = STOPPED; ++ spin_lock_irq(&priv->lock); ++ } ++ } ++} ++ ++static void rcar_vin_stop_streaming(struct vb2_queue *vq) ++{ ++ struct soc_camera_device *icd = soc_camera_from_vb2q(vq); ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct rcar_vin_priv *priv = ici->priv; ++ struct list_head *buf_head, *tmp; ++ int i; ++ ++ spin_lock_irq(&priv->lock); ++ rcar_vin_wait_stop_streaming(priv); ++ ++ for (i = 0; i < MAX_BUFFER_NUM; i++) { ++ if (priv->queue_buf[i]) { ++ vb2_buffer_done(&priv->queue_buf[i]->vb2_buf, ++ VB2_BUF_STATE_ERROR); ++ priv->queue_buf[i] = NULL; ++ } ++ } ++ ++ list_for_each_safe(buf_head, tmp, &priv->capture) { ++ vb2_buffer_done(&list_entry(buf_head, ++ struct rcar_vin_buffer, list)->vb.vb2_buf, ++ VB2_BUF_STATE_ERROR); ++ list_del_init(buf_head); ++ } ++ spin_unlock_irq(&priv->lock); ++} ++ ++static const struct vb2_ops rcar_vin_vb2_ops = { ++ .queue_setup = rcar_vin_videobuf_setup, ++ .buf_queue = rcar_vin_videobuf_queue, ++ .stop_streaming = rcar_vin_stop_streaming, ++ .wait_prepare = vb2_ops_wait_prepare, ++ .wait_finish = vb2_ops_wait_finish, ++}; ++ ++static irqreturn_t rcar_vin_irq(int irq, void *data) ++{ ++ struct rcar_vin_priv *priv = data; ++ u32 int_status; ++ bool can_run = false, hw_stopped; ++ int slot; ++ unsigned int handled = 0; ++ int vin_ovr_cnt = 0; ++ ++ spin_lock(&priv->lock); ++ ++ int_status = ioread32(priv->base + VNINTS_REG); ++ if (!int_status) ++ goto done; ++ ++ /* ack interrupts */ ++ iowrite32(int_status, priv->base + VNINTS_REG); ++ handled = 1; ++ ++ /* overflow occurs */ ++ if (vin_debug && (int_status & VNINTS_FOS)) { ++ vin_ovr_cnt = ++overflow_video[priv->index]; ++ VIN_IRQ_DEBUG("overflow occurrs num[%d] at VIN (%s)\n", ++ vin_ovr_cnt, dev_name(priv->ici.v4l2_dev.dev)); ++ } ++ ++ /* nothing to do if capture status is 'STOPPED' */ ++ if (priv->state == STOPPED) ++ goto done; ++ ++ hw_stopped = !(ioread32(priv->base + VNMS_REG) & VNMS_CA); ++ ++ if (!priv->request_to_stop) { ++ if (is_continuous_transfer(priv)) ++ slot = (ioread32(priv->base + VNMS_REG) & ++ VNMS_FBS_MASK) >> VNMS_FBS_SHIFT; ++ else ++ slot = 0; ++ ++ if (!is_continuous_transfer(priv) || ((priv->state == RUNNING) ++ && !list_empty(&priv->capture))) { ++ priv->queue_buf[slot]->field = priv->field; ++ priv->queue_buf[slot]->sequence = priv->sequence++; ++ priv->queue_buf[slot]->vb2_buf.timestamp = ++ ktime_get_ns(); ++ vb2_buffer_done(&priv->queue_buf[slot]->vb2_buf, ++ VB2_BUF_STATE_DONE); ++ priv->queue_buf[slot] = NULL; ++ ++ can_run = rcar_vin_fill_hw_slot(priv); ++ } ++ ++ if (is_continuous_transfer(priv)) { ++ if (hw_stopped) ++ priv->state = STOPPED; ++ else if (list_empty(&priv->capture) && ++ priv->state == RUNNING) ++ /* ++ * The continuous capturing requires an ++ * explicit stop operation when there is no ++ * buffer to be set into the VnMBm registers. ++ */ ++ rcar_vin_request_capture_stop(priv); ++ } else { ++ if (can_run) ++ rcar_vin_capture(priv); ++ else ++ priv->state = STOPPED; ++ } ++ } else if (hw_stopped) { ++ priv->state = STOPPED; ++ priv->request_to_stop = false; ++ complete(&priv->capture_stop); ++ } ++ ++done: ++ spin_unlock(&priv->lock); ++ ++ return IRQ_RETVAL(handled); ++} ++ ++static struct v4l2_subdev *find_csi2(struct rcar_vin_priv *pcdev) ++{ ++ struct v4l2_subdev *sd; ++ char name[] = "rcar_csi2"; ++ ++ v4l2_device_for_each_subdev(sd, &pcdev->ici.v4l2_dev) { ++ if (!strncmp(name, sd->name, sizeof(name) - 1)) { ++ pcdev->csi2_sd = sd; ++ return sd; ++ } ++ } ++ ++ return NULL; ++} ++ ++static int rcar_vin_add_device(struct soc_camera_device *icd) ++{ ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct rcar_vin_priv *priv = ici->priv; ++ int i; ++ ++ for (i = 0; i < MAX_BUFFER_NUM; i++) ++ priv->queue_buf[i] = NULL; ++ ++ pm_runtime_get_sync(ici->v4l2_dev.dev); ++ ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ struct v4l2_subdev *csi2_sd = find_csi2(priv); ++ int ret; ++ ++ if (csi2_sd) { ++ csi2_sd->grp_id = soc_camera_grp_id(icd); ++ v4l2_set_subdev_hostdata(csi2_sd, icd); ++ ++ ret = v4l2_subdev_call(csi2_sd, core, s_power, 1); ++ priv->csi_sync = true; ++ ++ if (ret < 0 && ret != -EINVAL) ++ priv->csi_sync = false; ++ ++ if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) ++ return ret; ++ } ++ /* ++ * -ENODEV is special: ++ * either csi2_sd == NULL or the CSI-2 driver ++ * has not found this soc-camera device among its clients ++ */ ++ if (csi2_sd && ret == -ENODEV) ++ csi2_sd->grp_id = 0; ++ ++ dev_dbg(icd->parent, ++ "R-Car VIN/CSI-2 driver attached to camera %d\n", ++ icd->devnum); ++ ++ } else ++ dev_dbg(icd->parent, "R-Car VIN driver attached to camera %d\n", ++ icd->devnum); ++ ++ priv->error_flag = false; ++ ++ return 0; ++} ++ ++static void rcar_vin_remove_device(struct soc_camera_device *icd) ++{ ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct rcar_vin_priv *priv = ici->priv; ++ struct vb2_v4l2_buffer *vbuf; ++ struct v4l2_subdev *csi2_sd = find_csi2(priv); ++ int i; ++ ++ /* disable capture, disable interrupts */ ++ iowrite32(ioread32(priv->base + VNMC_REG) & ~VNMC_ME, ++ priv->base + VNMC_REG); ++ iowrite32(0, priv->base + VNIE_REG); ++ ++ priv->state = STOPPED; ++ priv->request_to_stop = false; ++ priv->error_flag = false; ++ ++ /* make sure active buffer is cancelled */ ++ spin_lock_irq(&priv->lock); ++ for (i = 0; i < MAX_BUFFER_NUM; i++) { ++ vbuf = priv->queue_buf[i]; ++ if (vbuf) { ++ list_del_init(to_buf_list(vbuf)); ++ vb2_buffer_done(&vbuf->vb2_buf, VB2_BUF_STATE_ERROR); ++ } ++ } ++ spin_unlock_irq(&priv->lock); ++ ++ pm_runtime_put(ici->v4l2_dev.dev); ++ ++ if ((csi2_sd) && (priv->csi_sync)) ++ v4l2_subdev_call(csi2_sd, core, s_power, 0); ++ ++ dev_dbg(icd->parent, "R-Car VIN driver detached from camera %d\n", ++ icd->devnum); ++} ++ ++struct rcar_vin_uds_regs { ++ unsigned long ctrl; ++ unsigned long scale; ++ unsigned long pass_bwidth; ++ unsigned long clip_size; ++}; ++ ++static unsigned long rcar_vin_get_bwidth(unsigned long ratio) ++{ ++ unsigned long bwidth; ++ unsigned long mant, frac; ++ ++ mant = (ratio & 0xF000) >> 12; ++ frac = ratio & 0x0FFF; ++ if (mant) ++ bwidth = 64 * 4096 * mant / (4096 * mant + frac); ++ else ++ bwidth = 64; ++ ++ return bwidth; ++} ++ ++static unsigned long rcar_vin_compute_ratio(unsigned int input, ++ unsigned int output) ++{ ++ return ((input * 4096 / output) == 0x10000) ? ++ 0xFFFF : (input * 4096 / output); ++} ++ ++int rcar_vin_uds_set(struct rcar_vin_priv *priv, struct rcar_vin_cam *cam) ++{ ++ struct rcar_vin_uds_regs regs; ++ unsigned long ratio_h, ratio_v; ++ unsigned long bwidth_h, bwidth_v; ++ unsigned long ctrl; ++ unsigned long clip_size; ++ struct v4l2_rect *cam_subrect = &cam->subrect; ++ u32 vnmc; ++ ++ ratio_h = rcar_vin_compute_ratio(cam_subrect->width, cam->out_width); ++ ratio_v = rcar_vin_compute_ratio(cam_subrect->height, cam->out_height); ++ ++ priv->ratio_h = ratio_h; ++ priv->ratio_v = ratio_v; ++ ++ bwidth_h = rcar_vin_get_bwidth(ratio_h); ++ bwidth_v = rcar_vin_get_bwidth(ratio_v); ++ ++ ctrl = VNUDS_CTRL_AMD; ++ ++ if (priv->field == V4L2_FIELD_NONE) ++ clip_size = (cam->out_width << 16) | (cam->out_height); ++ else ++ clip_size = (cam->out_width << 16) | (cam->out_height / 2); ++ ++ regs.ctrl = ctrl; ++ regs.scale = (ratio_h << 16) | ratio_v; ++ regs.pass_bwidth = (bwidth_h << 16) | bwidth_v; ++ regs.clip_size = clip_size; ++ ++ vnmc = ioread32(priv->base + VNMC_REG); ++ iowrite32(vnmc | VNMC_SCLE, priv->base + VNMC_REG); ++ iowrite32(regs.ctrl, priv->base + VNUDS_CTRL_REG); ++ iowrite32(regs.scale, priv->base + VNUDS_SCALE_REG); ++ iowrite32(regs.pass_bwidth, priv->base + VNUDS_PASS_BWIDTH_REG); ++ iowrite32(regs.clip_size, priv->base + VNUDS_CLIP_SIZE_REG); ++ ++ return 0; ++} ++ ++static void set_coeff(struct rcar_vin_priv *priv, unsigned short xs) ++{ ++ int i; ++ const struct vin_coeff *p_prev_set = NULL; ++ const struct vin_coeff *p_set = NULL; ++ ++ /* Look for suitable coefficient values */ ++ for (i = 0; i < ARRAY_SIZE(vin_coeff_set); i++) { ++ p_prev_set = p_set; ++ p_set = &vin_coeff_set[i]; ++ ++ if (xs < p_set->xs_value) ++ break; ++ } ++ ++ /* Use previous value if its XS value is closer */ ++ if (p_prev_set && p_set && ++ xs - p_prev_set->xs_value < p_set->xs_value - xs) ++ p_set = p_prev_set; ++ ++ /* Set coefficient registers */ ++ iowrite32(p_set->coeff_set[0], priv->base + VNC1A_REG); ++ iowrite32(p_set->coeff_set[1], priv->base + VNC1B_REG); ++ iowrite32(p_set->coeff_set[2], priv->base + VNC1C_REG); ++ ++ iowrite32(p_set->coeff_set[3], priv->base + VNC2A_REG); ++ iowrite32(p_set->coeff_set[4], priv->base + VNC2B_REG); ++ iowrite32(p_set->coeff_set[5], priv->base + VNC2C_REG); ++ ++ iowrite32(p_set->coeff_set[6], priv->base + VNC3A_REG); ++ iowrite32(p_set->coeff_set[7], priv->base + VNC3B_REG); ++ iowrite32(p_set->coeff_set[8], priv->base + VNC3C_REG); ++ ++ iowrite32(p_set->coeff_set[9], priv->base + VNC4A_REG); ++ iowrite32(p_set->coeff_set[10], priv->base + VNC4B_REG); ++ iowrite32(p_set->coeff_set[11], priv->base + VNC4C_REG); ++ ++ iowrite32(p_set->coeff_set[12], priv->base + VNC5A_REG); ++ iowrite32(p_set->coeff_set[13], priv->base + VNC5B_REG); ++ iowrite32(p_set->coeff_set[14], priv->base + VNC5C_REG); ++ ++ iowrite32(p_set->coeff_set[15], priv->base + VNC6A_REG); ++ iowrite32(p_set->coeff_set[16], priv->base + VNC6B_REG); ++ iowrite32(p_set->coeff_set[17], priv->base + VNC6C_REG); ++ ++ iowrite32(p_set->coeff_set[18], priv->base + VNC7A_REG); ++ iowrite32(p_set->coeff_set[19], priv->base + VNC7B_REG); ++ iowrite32(p_set->coeff_set[20], priv->base + VNC7C_REG); ++ ++ iowrite32(p_set->coeff_set[21], priv->base + VNC8A_REG); ++ iowrite32(p_set->coeff_set[22], priv->base + VNC8B_REG); ++ iowrite32(p_set->coeff_set[23], priv->base + VNC8C_REG); ++} ++ ++/* rect is guaranteed to not exceed the scaled camera rectangle */ ++static int rcar_vin_set_rect(struct soc_camera_device *icd) ++{ ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct rcar_vin_cam *cam = icd->host_priv; ++ struct rcar_vin_priv *priv = ici->priv; ++ unsigned int left_offset, top_offset; ++ unsigned char dsize = 0; ++ struct v4l2_rect *cam_subrect = &cam->subrect; ++ u32 value; ++ int ret = 0; ++ ++ dev_dbg(icd->parent, "Crop %ux%u@%u:%u\n", ++ icd->user_width, icd->user_height, cam->vin_left, cam->vin_top); ++ ++ left_offset = cam->vin_left; ++ top_offset = cam->vin_top; ++ ++ if (icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_XBGR32 && ++ priv->chip == RCAR_E1) ++ dsize = 1; ++ ++ dev_dbg(icd->parent, "Cam %ux%u@%u:%u\n", ++ cam->width, cam->height, cam->vin_left, cam->vin_top); ++ dev_dbg(icd->parent, "Cam subrect %ux%u@%u:%u\n", ++ cam_subrect->width, cam_subrect->height, ++ cam_subrect->left, cam_subrect->top); ++ ++ /* Set Start/End Pixel/Line Pre-Clip */ ++ iowrite32(left_offset << dsize, priv->base + VNSPPRC_REG); ++ iowrite32((left_offset + cam_subrect->width - 1) << dsize, ++ priv->base + VNEPPRC_REG); ++ switch (priv->field) { ++ case V4L2_FIELD_INTERLACED: ++ case V4L2_FIELD_INTERLACED_TB: ++ case V4L2_FIELD_INTERLACED_BT: ++ iowrite32(top_offset / 2, priv->base + VNSLPRC_REG); ++ iowrite32((top_offset + cam_subrect->height) / 2 - 1, ++ priv->base + VNELPRC_REG); ++ break; ++ default: ++ iowrite32(top_offset, priv->base + VNSLPRC_REG); ++ iowrite32(top_offset + cam_subrect->height - 1, ++ priv->base + VNELPRC_REG); ++ break; ++ } ++ ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ if ((icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_NV12) ++ && is_scaling(cam)) { ++ ret = rcar_vin_uds_set(priv, cam); ++ if (ret < 0) ++ return ret; ++ } ++ if (is_scaling(cam) || ++ (icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_NV16) || ++ (icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_NV12)) ++ iowrite32(ALIGN(cam->out_width, 0x20), ++ priv->base + VNIS_REG); ++ else ++ iowrite32(ALIGN(cam->out_width, 0x10), ++ priv->base + VNIS_REG); ++ } else { ++ /* Set scaling coefficient */ ++ value = 0; ++ if (cam_subrect->height != cam->out_height) ++ value = (4096 * cam_subrect->height) / cam->out_height; ++ dev_dbg(icd->parent, "YS Value: %x\n", value); ++ iowrite32(value, priv->base + VNYS_REG); ++ ++ value = 0; ++ if (cam_subrect->width != cam->out_width) ++ value = (4096 * cam_subrect->width) / cam->out_width; ++ ++ /* Horizontal upscaling is up to double size */ ++ if (value < 2048) ++ value = 2048; ++ ++ dev_dbg(icd->parent, "XS Value: %x\n", value); ++ iowrite32(value, priv->base + VNXS_REG); ++ ++ /* Horizontal upscaling is carried out */ ++ /* by scaling down from double size */ ++ if (value < 4096) ++ value *= 2; ++ ++ set_coeff(priv, value); ++ ++ /* Set Start/End Pixel/Line Post-Clip */ ++ iowrite32(0, priv->base + VNSPPOC_REG); ++ iowrite32(0, priv->base + VNSLPOC_REG); ++ iowrite32((cam->out_width - 1) << dsize, ++ priv->base + VNEPPOC_REG); ++ switch (priv->field) { ++ case V4L2_FIELD_INTERLACED: ++ case V4L2_FIELD_INTERLACED_TB: ++ case V4L2_FIELD_INTERLACED_BT: ++ iowrite32(cam->out_height / 2 - 1, ++ priv->base + VNELPOC_REG); ++ break; ++ default: ++ iowrite32(cam->out_height - 1, ++ priv->base + VNELPOC_REG); ++ break; ++ } ++ ++ iowrite32(ALIGN(cam->out_width, 0x10), priv->base + VNIS_REG); ++ } ++ ++ return ret; ++} ++ ++static void capture_stop_preserve(struct rcar_vin_priv *priv, u32 *vnmc) ++{ ++ *vnmc = ioread32(priv->base + VNMC_REG); ++ /* module disable */ ++ iowrite32(*vnmc & ~VNMC_ME, priv->base + VNMC_REG); ++} ++ ++static void capture_restore(struct rcar_vin_priv *priv, u32 vnmc) ++{ ++ unsigned long timeout = jiffies + 10 * HZ; ++ ++ /* ++ * Wait until the end of the current frame. It can take a long time, ++ * but if it has been aborted by a MRST1 reset, it should exit sooner. ++ */ ++ while ((ioread32(priv->base + VNMS_REG) & VNMS_AV) && ++ time_before(jiffies, timeout)) ++ msleep(1); ++ ++ if (time_after(jiffies, timeout)) { ++ dev_err(priv->ici.v4l2_dev.dev, ++ "Timeout waiting for frame end! Interface problem?\n"); ++ return; ++ } ++ ++ iowrite32(vnmc, priv->base + VNMC_REG); ++} ++ ++#define VIN_MBUS_FLAGS (V4L2_MBUS_MASTER | \ ++ V4L2_MBUS_PCLK_SAMPLE_RISING | \ ++ V4L2_MBUS_HSYNC_ACTIVE_HIGH | \ ++ V4L2_MBUS_HSYNC_ACTIVE_LOW | \ ++ V4L2_MBUS_VSYNC_ACTIVE_HIGH | \ ++ V4L2_MBUS_VSYNC_ACTIVE_LOW | \ ++ V4L2_MBUS_DATA_ACTIVE_HIGH) ++ ++static int rcar_vin_set_bus_param(struct soc_camera_device *icd) ++{ ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct rcar_vin_priv *priv = ici->priv; ++ struct v4l2_subdev *sd = soc_camera_to_subdev(icd); ++ struct v4l2_mbus_config cfg; ++ unsigned long common_flags; ++ u32 vnmc; ++ u32 val; ++ int ret; ++ ++ capture_stop_preserve(priv, &vnmc); ++ ++ ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg); ++ if (!ret) { ++ common_flags = soc_mbus_config_compatible(&cfg, VIN_MBUS_FLAGS); ++ if (!common_flags) { ++ dev_warn(icd->parent, ++ "MBUS flags incompatible: camera 0x%x, host 0x%x\n", ++ cfg.flags, VIN_MBUS_FLAGS); ++ return -EINVAL; ++ } ++ } else if (ret != -ENOIOCTLCMD) { ++ return ret; ++ } else { ++ common_flags = VIN_MBUS_FLAGS; ++ } ++ ++ /* Make choises, based on platform preferences */ ++ if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) && ++ (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) { ++ if (priv->pdata_flags & RCAR_VIN_HSYNC_ACTIVE_LOW) ++ common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH; ++ else ++ common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW; ++ } ++ ++ if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) && ++ (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) { ++ if (priv->pdata_flags & RCAR_VIN_VSYNC_ACTIVE_LOW) ++ common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH; ++ else ++ common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW; ++ } ++ ++ cfg.flags = common_flags; ++ ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg); ++ if (ret < 0 && ret != -ENOIOCTLCMD) ++ return ret; ++ ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ if (cfg.type == V4L2_MBUS_CSI2) ++ vnmc &= ~VNMC_DPINE; ++ else ++ vnmc |= VNMC_DPINE; ++ } ++ ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) ++ val = VNDMR2_FTEV; ++ else ++ val = VNDMR2_FTEV | VNDMR2_VLV(1); ++ if (!(common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) ++ val |= VNDMR2_VPS; ++ if (!(common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) ++ val |= VNDMR2_HPS; ++ iowrite32(val, priv->base + VNDMR2_REG); ++ ++ ret = rcar_vin_set_rect(icd); ++ if (ret < 0) ++ return ret; ++ ++ capture_restore(priv, vnmc); ++ ++ return 0; ++} ++ ++static int rcar_vin_try_bus_param(struct soc_camera_device *icd, ++ unsigned char buswidth) ++{ ++ struct v4l2_subdev *sd = soc_camera_to_subdev(icd); ++ struct v4l2_mbus_config cfg; ++ int ret; ++ ++ ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg); ++ if (ret == -ENOIOCTLCMD) ++ return 0; ++ else if (ret) ++ return ret; ++ ++ if (buswidth > 24) ++ return -EINVAL; ++ ++ /* check is there common mbus flags */ ++ ret = soc_mbus_config_compatible(&cfg, VIN_MBUS_FLAGS); ++ if (ret) ++ return 0; ++ ++ dev_warn(icd->parent, ++ "MBUS flags incompatible: camera 0x%x, host 0x%x\n", ++ cfg.flags, VIN_MBUS_FLAGS); ++ ++ return -EINVAL; ++} ++ ++static bool rcar_vin_packing_supported(const struct soc_mbus_pixelfmt *fmt) ++{ ++ return fmt->packing == SOC_MBUS_PACKING_NONE || ++ (fmt->bits_per_sample > 8 && ++ fmt->packing == SOC_MBUS_PACKING_EXTEND16); ++} ++ ++static const struct soc_mbus_pixelfmt rcar_vin_formats[] = { ++ { ++ .fourcc = V4L2_PIX_FMT_NV12, ++ .name = "NV12", ++ .bits_per_sample = 8, ++ .packing = SOC_MBUS_PACKING_1_5X8, ++ .order = SOC_MBUS_ORDER_LE, ++ .layout = SOC_MBUS_LAYOUT_PLANAR_2Y_C, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_NV16, ++ .name = "NV16", ++ .bits_per_sample = 8, ++ .packing = SOC_MBUS_PACKING_2X8_PADHI, ++ .order = SOC_MBUS_ORDER_LE, ++ .layout = SOC_MBUS_LAYOUT_PLANAR_Y_C, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_YUYV, ++ .name = "YUYV", ++ .bits_per_sample = 16, ++ .packing = SOC_MBUS_PACKING_NONE, ++ .order = SOC_MBUS_ORDER_LE, ++ .layout = SOC_MBUS_LAYOUT_PACKED, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_UYVY, ++ .name = "UYVY", ++ .bits_per_sample = 16, ++ .packing = SOC_MBUS_PACKING_NONE, ++ .order = SOC_MBUS_ORDER_LE, ++ .layout = SOC_MBUS_LAYOUT_PACKED, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_RGB565, ++ .name = "RGB565", ++ .bits_per_sample = 16, ++ .packing = SOC_MBUS_PACKING_NONE, ++ .order = SOC_MBUS_ORDER_LE, ++ .layout = SOC_MBUS_LAYOUT_PACKED, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_ARGB555, ++ .name = "ARGB1555", ++ .bits_per_sample = 16, ++ .packing = SOC_MBUS_PACKING_NONE, ++ .order = SOC_MBUS_ORDER_LE, ++ .layout = SOC_MBUS_LAYOUT_PACKED, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_XBGR32, ++ .name = "RGB888", ++ .bits_per_sample = 32, ++ .packing = SOC_MBUS_PACKING_NONE, ++ .order = SOC_MBUS_ORDER_LE, ++ .layout = SOC_MBUS_LAYOUT_PACKED, ++ }, ++ { ++ .fourcc = V4L2_PIX_FMT_ABGR32, ++ .name = "ARGB8888", ++ .bits_per_sample = 32, ++ .packing = SOC_MBUS_PACKING_NONE, ++ .order = SOC_MBUS_ORDER_LE, ++ .layout = SOC_MBUS_LAYOUT_PACKED, ++ }, ++}; ++ ++static int rcar_vin_get_formats(struct soc_camera_device *icd, unsigned int idx, ++ struct soc_camera_format_xlate *xlate) ++{ ++ struct v4l2_subdev *sd = soc_camera_to_subdev(icd); ++ struct device *dev = icd->parent; ++ int ret, k, n; ++ int formats = 0; ++ struct rcar_vin_cam *cam; ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct rcar_vin_priv *priv = ici->priv; ++ struct v4l2_subdev_mbus_code_enum code = { ++ .which = V4L2_SUBDEV_FORMAT_ACTIVE, ++ .index = idx, ++ }; ++ const struct soc_mbus_pixelfmt *fmt; ++ ++ ret = v4l2_subdev_call(sd, pad, enum_mbus_code, NULL, &code); ++ if (ret < 0) ++ return 0; ++ ++ fmt = soc_mbus_get_fmtdesc(code.code); ++ if (!fmt) { ++ dev_warn(dev, "unsupported format code #%u: %d\n", idx, code.code); ++ return 0; ++ } ++ ++ ret = rcar_vin_try_bus_param(icd, fmt->bits_per_sample); ++ if (ret < 0) ++ return 0; ++ ++ if (!icd->host_priv) { ++ struct v4l2_subdev_format fmt = { ++ .which = V4L2_SUBDEV_FORMAT_ACTIVE, ++ }; ++ struct v4l2_mbus_framefmt *mf = &fmt.format; ++ struct v4l2_rect rect; ++ struct device *dev = icd->parent; ++ int shift; ++ ++ ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt); ++ if (ret < 0) ++ return ret; ++ ++ /* Cache current client geometry */ ++ ret = soc_camera_client_g_rect(sd, &rect); ++ if (ret == -ENOIOCTLCMD) { ++ /* Sensor driver doesn't support cropping */ ++ rect.left = 0; ++ rect.top = 0; ++ rect.width = mf->width; ++ rect.height = mf->height; ++ } else if (ret < 0) { ++ return ret; ++ } ++ ++ /* ++ * If sensor proposes too large format then try smaller ones: ++ * 1280x960, 640x480, 320x240 ++ */ ++ for (shift = 0; shift < 3; shift++) { ++ if (mf->width <= priv->max_width && ++ mf->height <= priv->max_height) ++ break; ++ ++ mf->width = 1280 >> shift; ++ mf->height = 960 >> shift; ++ ret = v4l2_device_call_until_err(sd->v4l2_dev, ++ soc_camera_grp_id(icd), ++ pad, set_fmt, NULL, ++ &fmt); ++ if (ret < 0) ++ return ret; ++ } ++ ++ if (shift == 3) { ++ dev_err(dev, ++ "Failed to configure the client below %ux%u\n", ++ mf->width, mf->height); ++ return -EIO; ++ } ++ ++ dev_dbg(dev, "camera fmt %ux%u\n", mf->width, mf->height); ++ ++ cam = kzalloc(sizeof(*cam), GFP_KERNEL); ++ if (!cam) ++ return -ENOMEM; ++ /* ++ * We are called with current camera crop, ++ * initialise subrect with it ++ */ ++ cam->rect = rect; ++ cam->subrect = rect; ++ cam->width = mf->width; ++ cam->height = mf->height; ++ cam->out_width = mf->width; ++ cam->out_height = mf->height; ++ ++ icd->host_priv = cam; ++ } else { ++ cam = icd->host_priv; ++ } ++ ++ /* Beginning of a pass */ ++ if (!idx) ++ cam->extra_fmt = NULL; ++ ++ switch (code.code) { ++ case MEDIA_BUS_FMT_YUYV8_1X16: ++ case MEDIA_BUS_FMT_YUYV8_2X8: ++ case MEDIA_BUS_FMT_YUYV10_2X10: ++ case MEDIA_BUS_FMT_RGB888_1X24: ++ if (cam->extra_fmt) ++ break; ++ ++ /* Add all our formats that can be generated by VIN */ ++ cam->extra_fmt = rcar_vin_formats; ++ ++ n = ARRAY_SIZE(rcar_vin_formats); ++ formats += n; ++ for (k = 0; xlate && k < n; k++, xlate++) { ++ xlate->host_fmt = &rcar_vin_formats[k]; ++ xlate->code = code.code; ++ dev_dbg(dev, "Providing format %s using code %d\n", ++ rcar_vin_formats[k].name, code.code); ++ } ++ break; ++ default: ++ if (!rcar_vin_packing_supported(fmt)) ++ return 0; ++ ++ dev_dbg(dev, "Providing format %s in pass-through mode\n", ++ fmt->name); ++ break; ++ } ++ ++ /* Generic pass-through */ ++ formats++; ++ if (xlate) { ++ xlate->host_fmt = fmt; ++ xlate->code = code.code; ++ xlate++; ++ } ++ ++ return formats; ++} ++ ++static void rcar_vin_put_formats(struct soc_camera_device *icd) ++{ ++ kfree(icd->host_priv); ++ icd->host_priv = NULL; ++} ++ ++static int rcar_vin_set_selection(struct soc_camera_device *icd, ++ struct v4l2_selection *sel) ++{ ++ const struct v4l2_rect *rect = &sel->r; ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct rcar_vin_priv *priv = ici->priv; ++ struct v4l2_selection cam_sel; ++ struct rcar_vin_cam *cam = icd->host_priv; ++ struct v4l2_rect *cam_rect = &cam_sel.r; ++ struct v4l2_subdev *sd = soc_camera_to_subdev(icd); ++ struct device *dev = icd->parent; ++ struct v4l2_subdev_format fmt = { ++ .which = V4L2_SUBDEV_FORMAT_ACTIVE, ++ }; ++ struct v4l2_mbus_framefmt *mf = &fmt.format; ++ u32 vnmc; ++ int ret, i; ++ ++ dev_dbg(dev, "S_SELECTION(%ux%u@%u:%u)\n", rect->width, rect->height, ++ rect->left, rect->top); ++ ++ /* During camera cropping its output window can change too, stop VIN */ ++ capture_stop_preserve(priv, &vnmc); ++ dev_dbg(dev, "VNMC_REG 0x%x\n", vnmc); ++ ++ /* Apply iterative camera S_SELECTION for new input window. */ ++ ret = soc_camera_client_s_selection(sd, sel, &cam_sel, ++ &cam->rect, &cam->subrect); ++ if (ret < 0) ++ return ret; ++ ++ dev_dbg(dev, "camera cropped to %ux%u@%u:%u\n", ++ cam_rect->width, cam_rect->height, ++ cam_rect->left, cam_rect->top); ++ ++ /* On success cam_crop contains current camera crop */ ++ ++ /* Retrieve camera output window */ ++ ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt); ++ if (ret < 0) ++ return ret; ++ ++ if (mf->width > priv->max_width || mf->height > priv->max_height) ++ return -EINVAL; ++ ++ /* Cache camera output window */ ++ cam->width = mf->width; ++ cam->height = mf->height; ++ ++ cam->vin_left = rect->left; ++ cam->vin_top = rect->top; ++ ++ /* Use VIN cropping to crop to the new window. */ ++ ret = rcar_vin_set_rect(icd); ++ if (ret < 0) ++ return ret; ++ ++ dev_dbg(dev, "VIN cropped to %ux%u@%u:%u\n", ++ icd->user_width, icd->user_height, ++ cam->vin_left, cam->vin_top); ++ ++ /* Restore capture */ ++ for (i = 0; i < MAX_BUFFER_NUM; i++) { ++ if (priv->queue_buf[i] && priv->state == STOPPED) { ++ vnmc |= VNMC_ME; ++ break; ++ } ++ } ++ capture_restore(priv, vnmc); ++ ++ /* Even if only camera cropping succeeded */ ++ return ret; ++} ++ ++static int rcar_vin_get_selection(struct soc_camera_device *icd, ++ struct v4l2_selection *sel) ++{ ++ struct rcar_vin_cam *cam = icd->host_priv; ++ ++ sel->r = cam->subrect; ++ ++ return 0; ++} ++ ++/* Similar to set_crop multistage iterative algorithm */ ++static int rcar_vin_set_fmt(struct soc_camera_device *icd, ++ struct v4l2_format *f) ++{ ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct rcar_vin_priv *priv = ici->priv; ++ struct v4l2_subdev *sd = soc_camera_to_subdev(icd); ++ struct rcar_vin_cam *cam = icd->host_priv; ++ struct v4l2_pix_format *pix = &f->fmt.pix; ++ struct v4l2_mbus_framefmt mf; ++ struct device *dev = icd->parent; ++ __u32 pixfmt = pix->pixelformat; ++ const struct soc_camera_format_xlate *xlate; ++ unsigned int vin_sub_width = 0, vin_sub_height = 0; ++ int ret; ++ bool can_scale; ++ enum v4l2_field field; ++ v4l2_std_id std; ++ ++ dev_dbg(dev, "S_FMT(pix=0x%x, %ux%u)\n", ++ pixfmt, pix->width, pix->height); ++ ++ /* At the time of NV16 capture format, the user has to specify */ ++ /* the width of the multiple of 32 for H/W specification. */ ++ if (priv->error_flag == false) ++ priv->error_flag = true; ++ else { ++ if (((pixfmt == V4L2_PIX_FMT_NV16) || ++ (pixfmt == V4L2_PIX_FMT_NV12)) && ++ (pix->width & 0x1F)) { ++ dev_dbg(icd->parent, ++ "specify width of 32 multiple in separate format.\n"); ++ return -EINVAL; ++ } ++ } ++ ++ switch (pix->field) { ++ default: ++ pix->field = V4L2_FIELD_NONE; ++ /* fall-through */ ++ case V4L2_FIELD_NONE: ++ case V4L2_FIELD_TOP: ++ case V4L2_FIELD_BOTTOM: ++ case V4L2_FIELD_INTERLACED_TB: ++ case V4L2_FIELD_INTERLACED_BT: ++ field = pix->field; ++ break; ++ case V4L2_FIELD_INTERLACED: ++ /* Query for standard if not explicitly mentioned _TB/_BT */ ++ ret = v4l2_subdev_call(sd, video, querystd, &std); ++ if (ret == -ENOIOCTLCMD) { ++ field = V4L2_FIELD_NONE; ++ } else if (ret < 0) { ++ return ret; ++ } else { ++ field = std & V4L2_STD_625_50 ? ++ V4L2_FIELD_INTERLACED_TB : ++ V4L2_FIELD_INTERLACED_BT; ++ } ++ break; ++ } ++ ++ xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); ++ if (!xlate) { ++ dev_warn(dev, "Format %x not found\n", pixfmt); ++ return -EINVAL; ++ } ++ /* Calculate client output geometry */ ++ soc_camera_calc_client_output(icd, &cam->rect, &cam->subrect, pix, &mf, ++ 12); ++ mf.field = pix->field; ++ mf.colorspace = pix->colorspace; ++ mf.code = xlate->code; ++ ++ switch (pixfmt) { ++ case V4L2_PIX_FMT_XBGR32: ++ can_scale = priv->chip != RCAR_E1; ++ break; ++ case V4L2_PIX_FMT_ABGR32: ++ case V4L2_PIX_FMT_UYVY: ++ case V4L2_PIX_FMT_YUYV: ++ case V4L2_PIX_FMT_RGB565: ++ case V4L2_PIX_FMT_ARGB555: ++ case V4L2_PIX_FMT_NV16: ++ can_scale = true; ++ break; ++ case V4L2_PIX_FMT_NV12: ++ default: ++ can_scale = false; ++ break; ++ } ++ ++ dev_dbg(dev, "request camera output %ux%u\n", mf.width, mf.height); ++ ++ ret = soc_camera_client_scale(icd, &cam->rect, &cam->subrect, ++ &mf, &vin_sub_width, &vin_sub_height, ++ can_scale, 12); ++ ++ /* Done with the camera. Now see if we can improve the result */ ++ dev_dbg(dev, "Camera %d fmt %ux%u, requested %ux%u\n", ++ ret, mf.width, mf.height, pix->width, pix->height); ++ ++ if (ret == -ENOIOCTLCMD) ++ dev_dbg(dev, "Sensor doesn't support scaling\n"); ++ else if (ret < 0) ++ return ret; ++ ++ if (mf.code != xlate->code) ++ return -EINVAL; ++ ++ /* Prepare VIN crop */ ++ cam->width = mf.width; ++ cam->height = mf.height; ++ ++ /* Use VIN scaling to scale to the requested user window. */ ++ ++ /* We cannot scale up */ ++ if (pix->width > vin_sub_width) ++ vin_sub_width = pix->width; ++ ++ if (pix->height > vin_sub_height) ++ vin_sub_height = pix->height; ++ ++ pix->colorspace = mf.colorspace; ++ ++ if (!can_scale) { ++ pix->width = vin_sub_width; ++ pix->height = vin_sub_height; ++ } ++ ++ /* ++ * We have calculated CFLCR, the actual configuration will be performed ++ * in rcar_vin_set_bus_param() ++ */ ++ ++ dev_dbg(dev, "W: %u : %u, H: %u : %u\n", ++ vin_sub_width, pix->width, vin_sub_height, pix->height); ++ ++ cam->out_width = pix->width; ++ cam->out_height = pix->height; ++ ++ icd->current_fmt = xlate; ++ ++ priv->field = field; ++ ++ return 0; ++} ++ ++static int rcar_vin_try_fmt(struct soc_camera_device *icd, ++ struct v4l2_format *f) ++{ ++ const struct soc_camera_format_xlate *xlate; ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ struct rcar_vin_priv *priv = ici->priv; ++ struct v4l2_pix_format *pix = &f->fmt.pix; ++ struct v4l2_subdev *sd = soc_camera_to_subdev(icd); ++ struct v4l2_subdev_pad_config pad_cfg; ++ struct v4l2_subdev_format format = { ++ .which = V4L2_SUBDEV_FORMAT_TRY, ++ }; ++ struct v4l2_mbus_framefmt *mf = &format.format; ++ __u32 pixfmt = pix->pixelformat; ++ int width, height; ++ int ret; ++ ++ xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); ++ if (!xlate) { ++ xlate = icd->current_fmt; ++ dev_dbg(icd->parent, "Format %x not found, keeping %x\n", ++ pixfmt, xlate->host_fmt->fourcc); ++ pixfmt = xlate->host_fmt->fourcc; ++ pix->pixelformat = pixfmt; ++ pix->colorspace = icd->colorspace; ++ } ++ ++ /* When performing a YCbCr-422 format output, even if it performs */ ++ /* odd number clipping by pixel post clip processing, */ ++ /* it is outputted to a memory per even pixels. */ ++ if ((pixfmt == V4L2_PIX_FMT_NV16) || (pixfmt == V4L2_PIX_FMT_NV12) || ++ (pixfmt == V4L2_PIX_FMT_YUYV) || (pixfmt == V4L2_PIX_FMT_UYVY)) ++ v4l_bound_align_image(&pix->width, 5, priv->max_width, 1, ++ &pix->height, 2, priv->max_height, 0, 0); ++ else ++ v4l_bound_align_image(&pix->width, 5, priv->max_width, 0, ++ &pix->height, 2, priv->max_height, 0, 0); ++ ++ width = pix->width; ++ height = pix->height; ++ ++ /* let soc-camera calculate these values */ ++ pix->bytesperline = 0; ++ pix->sizeimage = 0; ++ ++ /* limit to sensor capabilities */ ++ mf->width = pix->width; ++ mf->height = pix->height; ++ mf->field = pix->field; ++ mf->code = xlate->code; ++ mf->colorspace = pix->colorspace; ++ ++ ret = v4l2_device_call_until_err(sd->v4l2_dev, soc_camera_grp_id(icd), ++ pad, set_fmt, &pad_cfg, &format); ++ if (ret < 0) ++ return ret; ++ ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ /* Adjust max scaling size for Gen3 */ ++ if (pix->width > 4096) ++ pix->width = priv->max_width; ++ if (pix->height > 4096) ++ pix->height = priv->max_height; ++ } else { ++ /* Adjust only if VIN cannot scale */ ++ if (pix->width > mf->width * 2) ++ pix->width = mf->width * 2; ++ if (pix->height > mf->height * 3) ++ pix->height = mf->height * 3; ++ } ++ ++ pix->field = mf->field; ++ pix->colorspace = mf->colorspace; ++ ++ if (pixfmt == V4L2_PIX_FMT_NV16) { ++ /* FIXME: check against rect_max after converting soc-camera */ ++ /* We can scale precisely, need a bigger image from camera */ ++ if (pix->width < width || pix->height < height) { ++ /* ++ * We presume, the sensor behaves sanely, i.e. if ++ * requested a bigger rectangle, it will not return a ++ * smaller one. ++ */ ++ mf->width = priv->max_width; ++ mf->height = priv->max_height; ++ ret = v4l2_device_call_until_err(sd->v4l2_dev, ++ soc_camera_grp_id(icd), ++ pad, set_fmt, &pad_cfg, ++ &format); ++ if (ret < 0) { ++ dev_err(icd->parent, ++ "client try_fmt() = %d\n", ret); ++ return ret; ++ } ++ } ++ /* We will scale exactly */ ++ if (mf->width > width) ++ pix->width = width; ++ if (mf->height > height) ++ pix->height = height; ++ } ++ ++ return ret; ++} ++ ++static unsigned int rcar_vin_poll(struct file *file, poll_table *pt) ++{ ++ struct soc_camera_device *icd = file->private_data; ++ ++ return vb2_poll(&icd->vb2_vidq, file, pt); ++} ++ ++static int rcar_vin_querycap(struct soc_camera_host *ici, ++ struct v4l2_capability *cap) ++{ ++ strlcpy(cap->card, "R_Car_VIN", sizeof(cap->card)); ++ cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; ++ cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; ++ snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s%d", DRV_NAME, ici->nr); ++ ++ return 0; ++} ++ ++static int rcar_vin_init_videobuf2(struct vb2_queue *vq, ++ struct soc_camera_device *icd) ++{ ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ ++ vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; ++ vq->drv_priv = icd; ++ vq->ops = &rcar_vin_vb2_ops; ++ vq->mem_ops = &vb2_dma_contig_memops; ++ vq->buf_struct_size = sizeof(struct rcar_vin_buffer); ++ vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; ++ vq->lock = &ici->host_lock; ++ vq->dev = ici->v4l2_dev.dev; ++ ++ return vb2_queue_init(vq); ++} ++ ++#if 0 ++static int rcar_vin_get_selection(struct soc_camera_device *icd, ++ struct v4l2_selection *sel) ++{ ++ struct v4l2_subdev *sd = soc_camera_to_subdev(icd); ++ struct v4l2_subdev_format fmt = { ++ .which = V4L2_SUBDEV_FORMAT_ACTIVE, ++ }; ++ struct v4l2_mbus_framefmt *mf = &fmt.format; ++ int ret; ++ ++ ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt); ++ if (ret < 0) ++ return ret; ++ ++ if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ sel->r.left = sel->r.top = 0; ++ sel->r.width = mf->width; ++ sel->r.height = mf->height; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int rcar_vin_cropcap(struct soc_camera_device *icd, ++ struct v4l2_cropcap *crop) ++{ ++ struct v4l2_subdev *sd = soc_camera_to_subdev(icd); ++ struct v4l2_subdev_format fmt = { ++ .which = V4L2_SUBDEV_FORMAT_ACTIVE, ++ }; ++ struct v4l2_mbus_framefmt *mf = &fmt.format; ++ int ret; ++ ++ ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt); ++ if (ret < 0) ++ return ret; ++ ++ crop->bounds.left = 0; ++ crop->bounds.top = 0; ++ crop->bounds.width = mf->width; ++ crop->bounds.height = mf->height; ++ ++ /* default cropping rectangle */ ++ crop->defrect = crop->bounds; ++ crop->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ ++ return 0; ++} ++#endif ++ ++static struct soc_camera_host_ops rcar_vin_host_ops = { ++ .owner = THIS_MODULE, ++ .add = rcar_vin_add_device, ++ .remove = rcar_vin_remove_device, ++ .get_formats = rcar_vin_get_formats, ++ .put_formats = rcar_vin_put_formats, ++ .get_selection = rcar_vin_get_selection, ++ .set_selection = rcar_vin_set_selection, ++ .try_fmt = rcar_vin_try_fmt, ++ .set_fmt = rcar_vin_set_fmt, ++ .poll = rcar_vin_poll, ++ .querycap = rcar_vin_querycap, ++ .set_bus_param = rcar_vin_set_bus_param, ++ .init_videobuf2 = rcar_vin_init_videobuf2, ++#if 0 ++ .get_selection = rcar_vin_get_selection, ++ .cropcap = rcar_vin_cropcap, ++#endif ++}; ++ ++#ifdef CONFIG_OF ++static const struct of_device_id rcar_vin_of_table[] = { ++ { .compatible = "renesas,vin-r8a7796", .data = (void *)RCAR_M3 }, ++ { .compatible = "renesas,vin-r8a7795", .data = (void *)RCAR_H3 }, ++ { .compatible = "renesas,vin-r8a7794", .data = (void *)RCAR_GEN2 }, ++ { .compatible = "renesas,vin-r8a7793", .data = (void *)RCAR_GEN2 }, ++ { .compatible = "renesas,vin-r8a7791", .data = (void *)RCAR_GEN2 }, ++ { .compatible = "renesas,vin-r8a7790", .data = (void *)RCAR_GEN2 }, ++ { .compatible = "renesas,vin-r8a7779", .data = (void *)RCAR_H1 }, ++ { .compatible = "renesas,vin-r8a7778", .data = (void *)RCAR_M1 }, ++ { .compatible = "renesas,rcar-gen3-vin", .data = (void *)RCAR_GEN3 }, ++ { .compatible = "renesas,rcar-gen2-vin", .data = (void *)RCAR_GEN2 }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, rcar_vin_of_table); ++#endif ++ ++#define MAP_MAX_NUM 32 ++static DECLARE_BITMAP(device_map, MAP_MAX_NUM); ++static DEFINE_MUTEX(list_lock); ++ ++static int rcar_vin_dyn_pdev(struct soc_camera_desc *sdesc, ++ struct rcar_vin_async_client *sasc) ++{ ++ struct platform_device *pdev; ++ int ret, i; ++ ++ mutex_lock(&list_lock); ++ i = find_first_zero_bit(device_map, MAP_MAX_NUM); ++ if (i < MAP_MAX_NUM) ++ set_bit(i, device_map); ++ mutex_unlock(&list_lock); ++ if (i >= MAP_MAX_NUM) ++ return -ENOMEM; ++ ++ pdev = platform_device_alloc("soc-camera-pdrv", ((2 * i) + 1)); ++ if (!pdev) ++ return -ENOMEM; ++ ++ ret = platform_device_add_data(pdev, sdesc, sizeof(*sdesc)); ++ if (ret < 0) { ++ platform_device_put(pdev); ++ return ret; ++ } ++ ++ sasc->pdev = pdev; ++ ++ return 0; ++} ++ ++static int rcar_vin_async_bound(struct v4l2_async_notifier *notifier, ++ struct v4l2_subdev *sd, ++ struct v4l2_async_subdev *asd) ++{ ++ /* None. */ ++ return 0; ++} ++ ++static void rcar_vin_async_unbind(struct v4l2_async_notifier *notifier, ++ struct v4l2_subdev *sd, ++ struct v4l2_async_subdev *asd) ++{ ++ /* None. */ ++} ++ ++static int rcar_vin_async_probe(struct soc_camera_host *ici, ++ struct soc_camera_device *icd) ++{ ++ struct soc_camera_desc *sdesc = to_soc_camera_desc(icd); ++ struct soc_camera_host_desc *shd = &sdesc->host_desc; ++ struct device *control = NULL; ++ int ret; ++ ++ ret = v4l2_ctrl_handler_init(&icd->ctrl_handler, 16); ++ if (ret < 0) ++ return ret; ++ ++ if (shd->module_name) ++ ret = request_module(shd->module_name); ++ ++ ret = shd->add_device(icd); ++ ++ control = to_soc_camera_control(icd); ++ if (!control || !control->driver || !dev_get_drvdata(control) || ++ !try_module_get(control->driver->owner)) { ++ shd->del_device(icd); ++ ret = -ENODEV; ++ } ++ ++ return ret; ++} ++ ++static int rcar_vin_async_complete(struct v4l2_async_notifier *notifier) ++{ ++ struct rcar_vin_async_client *sasc = container_of(notifier, ++ struct rcar_vin_async_client, notifier); ++ struct soc_camera_device *icd = platform_get_drvdata(sasc->pdev); ++ ++ if (to_soc_camera_control(icd)) { ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ int ret; ++ ++ mutex_lock(&list_lock); ++ ret = rcar_vin_async_probe(ici, icd); ++ mutex_unlock(&list_lock); ++ if (ret < 0) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static struct soc_camera_device *rcar_vin_add_pdev( ++ struct rcar_vin_async_client *sasc) ++{ ++ struct platform_device *pdev = sasc->pdev; ++ int ret; ++ ++ ret = platform_device_add(pdev); ++ ++ if (ret < 0 || !pdev->dev.driver) ++ return NULL; ++ ++ return platform_get_drvdata(pdev); ++} ++ ++static int rcar_vin_soc_of_bind(struct rcar_vin_priv *priv, ++ struct soc_camera_host *ici, ++ struct device_node *ep, ++ struct device_node *remote) ++{ ++ struct soc_camera_device *icd; ++ struct soc_camera_desc sdesc = {.host_desc.bus_id = ici->nr,}; ++ struct rcar_vin_async_client *sasc; ++ struct soc_of_info *info; ++ struct i2c_client *client; ++ char clk_name[V4L2_SUBDEV_NAME_SIZE]; ++ int ret; ++ ++ /* allocate a new subdev and add match info to it */ ++ info = devm_kzalloc(ici->v4l2_dev.dev, sizeof(struct soc_of_info), ++ GFP_KERNEL); ++ if (!info) ++ return -ENOMEM; ++ ++ info->sasd.asd.match.of.node = remote; ++ info->sasd.asd.match_type = V4L2_ASYNC_MATCH_OF; ++ info->subdev = &info->sasd.asd; ++ ++ /* Or shall this be managed by the soc-camera device? */ ++ sasc = &info->sasc; ++ ++ ret = rcar_vin_dyn_pdev(&sdesc, sasc); ++ if (ret < 0) ++ goto eallocpdev; ++ ++ sasc->sensor = &info->sasd.asd; ++ ++ icd = rcar_vin_add_pdev(sasc); ++ if (!icd) { ++ ret = -ENOMEM; ++ goto eaddpdev; ++ } ++ ++ sasc->notifier.subdevs = &info->subdev; ++ sasc->notifier.num_subdevs = 1; ++ sasc->notifier.bound = rcar_vin_async_bound; ++ sasc->notifier.unbind = rcar_vin_async_unbind; ++ sasc->notifier.complete = rcar_vin_async_complete; ++ ++ priv->async_client = sasc; ++ ++ client = of_find_i2c_device_by_node(remote); ++ ++ if (client) ++ snprintf(clk_name, sizeof(clk_name), "%d-%04x", ++ client->adapter->nr, client->addr); ++ else ++ snprintf(clk_name, sizeof(clk_name), "of-%s", ++ of_node_full_name(remote)); ++ ++ ret = v4l2_async_notifier_register(&ici->v4l2_dev, &sasc->notifier); ++ if (!ret) ++ return 0; ++ ++ platform_device_del(sasc->pdev); ++eaddpdev: ++ platform_device_put(sasc->pdev); ++eallocpdev: ++ devm_kfree(ici->v4l2_dev.dev, info); ++ dev_err(ici->v4l2_dev.dev, "group probe failed: %d\n", ret); ++ ++ return ret; ++} ++ ++static int rcar_vin_probe(struct platform_device *pdev) ++{ ++ const struct of_device_id *match = NULL; ++ struct rcar_vin_priv *priv; ++ struct v4l2_of_endpoint ep; ++ struct device_node *np; ++ struct resource *mem; ++ unsigned int pdata_flags; ++ int irq, ret; ++ const char *str; ++ unsigned int i; ++ struct device_node *epn = NULL, *ren = NULL; ++ bool csi_use = false; ++ ++ match = of_match_device(of_match_ptr(rcar_vin_of_table), &pdev->dev); ++ ++ np = of_graph_get_next_endpoint(pdev->dev.of_node, NULL); ++ if (!np) { ++ dev_err(&pdev->dev, "could not find endpoint\n"); ++ return -EINVAL; ++ } ++ ++ for (i = 0; ; i++) { ++ epn = of_graph_get_next_endpoint(pdev->dev.of_node, ++ epn); ++ if (!epn) ++ break; ++ ++ ren = of_graph_get_remote_port(epn); ++ if (!ren) { ++ dev_notice(&pdev->dev, "no remote for %s\n", ++ of_node_full_name(epn)); ++ continue; ++ } ++ ++ /* so we now have a remote node to connect */ ++ dev_dbg(&pdev->dev, "node name:%s\n", ++ of_node_full_name(ren->parent)); ++ ++ if (strcmp(ren->parent->name, "csi2") == 0) ++ csi_use = true; ++ ++ of_node_put(ren); ++ ++ if (i) ++ break; ++ } ++ ++ ret = v4l2_of_parse_endpoint(np, &ep); ++ if (ret) { ++ dev_err(&pdev->dev, "could not parse endpoint\n"); ++ return ret; ++ } ++ ++ if (ep.bus_type == V4L2_MBUS_BT656) ++ pdata_flags = RCAR_VIN_BT656; ++ else if (ep.bus_type == V4L2_MBUS_CSI2) ++ pdata_flags = RCAR_VIN_BT656 | RCAR_VIN_CSI2; ++ else { ++ pdata_flags = 0; ++ if (ep.bus.parallel.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW) ++ pdata_flags |= RCAR_VIN_HSYNC_ACTIVE_LOW; ++ if (ep.bus.parallel.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW) ++ pdata_flags |= RCAR_VIN_VSYNC_ACTIVE_LOW; ++ } ++ ++ of_node_put(np); ++ ++ dev_dbg(&pdev->dev, "pdata_flags = %08x\n", pdata_flags); ++ ++ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (mem == NULL) ++ return -EINVAL; ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq <= 0) ++ return -EINVAL; ++ ++ priv = devm_kzalloc(&pdev->dev, sizeof(struct rcar_vin_priv), ++ GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->base = devm_ioremap_resource(&pdev->dev, mem); ++ if (IS_ERR(priv->base)) ++ return PTR_ERR(priv->base); ++ ++ ret = devm_request_irq(&pdev->dev, irq, rcar_vin_irq, IRQF_SHARED, ++ dev_name(&pdev->dev), priv); ++ if (ret) ++ return ret; ++ ++ priv->ici.priv = priv; ++ priv->ici.v4l2_dev.dev = &pdev->dev; ++ priv->ici.drv_name = dev_name(&pdev->dev); ++ priv->ici.ops = &rcar_vin_host_ops; ++ priv->csi_sync = false; ++ ++ priv->pdata_flags = pdata_flags; ++ if (!match) { ++ priv->ici.nr = pdev->id; ++ priv->chip = pdev->id_entry->driver_data; ++ } else { ++ priv->ici.nr = of_alias_get_id(pdev->dev.of_node, "vin"); ++ priv->chip = (enum chip_id)match->data; ++ } ++ ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ priv->max_width = 4096; ++ priv->max_height = 4096; ++ } else { ++ priv->max_width = 2048; ++ priv->max_height = 2048; ++ } ++ ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ u32 ifmd = 0; ++ bool match_flag = false; ++ const struct vin_gen3_ifmd *gen3_ifmd_table = NULL; ++ int vc, num; ++ ++ num = VNCSI_IFMD_SEL_NUMBER; ++ ++ if (strcmp(dev_name(priv->ici.v4l2_dev.dev), ++ "e6ef0000.video") == 0) ++ priv->index = RCAR_VIDEO_0; ++ else if (strcmp(dev_name(priv->ici.v4l2_dev.dev), ++ "e6ef1000.video") == 0) ++ priv->index = RCAR_VIDEO_1; ++ else if (strcmp(dev_name(priv->ici.v4l2_dev.dev), ++ "e6ef2000.video") == 0) ++ priv->index = RCAR_VIDEO_2; ++ else if (strcmp(dev_name(priv->ici.v4l2_dev.dev), ++ "e6ef3000.video") == 0) ++ priv->index = RCAR_VIDEO_3; ++ else if (strcmp(dev_name(priv->ici.v4l2_dev.dev), ++ "e6ef4000.video") == 0) ++ priv->index = RCAR_VIDEO_4; ++ else if (strcmp(dev_name(priv->ici.v4l2_dev.dev), ++ "e6ef5000.video") == 0) ++ priv->index = RCAR_VIDEO_5; ++ else if (strcmp(dev_name(priv->ici.v4l2_dev.dev), ++ "e6ef6000.video") == 0) ++ priv->index = RCAR_VIDEO_6; ++ else if (strcmp(dev_name(priv->ici.v4l2_dev.dev), ++ "e6ef7000.video") == 0) ++ priv->index = RCAR_VIDEO_7; ++ else ++ priv->index = RCAR_VIN_CH_NONE; ++ ++ ret = of_property_read_string(np, "csi,select", &str); ++ if (ret) { ++ dev_err(&pdev->dev, "could not parse csi,select\n"); ++ return ret; ++ } ++ ++ if (strcmp(str, "csi40") == 0) ++ priv->csi_ch = RCAR_CSI40; ++ else if (strcmp(str, "csi20") == 0) ++ priv->csi_ch = RCAR_CSI20; ++ else if (strcmp(str, "csi41") == 0) ++ priv->csi_ch = RCAR_CSI41; ++ else if (strcmp(str, "csi21") == 0) ++ priv->csi_ch = RCAR_CSI21; ++ else ++ priv->csi_ch = RCAR_CSI_CH_NONE; ++ ++ ret = of_property_read_u32(np, "virtual,channel", &vc); ++ if (ret) { ++ dev_err(&pdev->dev, ++ "could not parse virtual,channel\n"); ++ return ret; ++ } ++ ++ if (vc == 0) ++ priv->vc = RCAR_VIRTUAL_CH0; ++ else if (vc == 1) ++ priv->vc = RCAR_VIRTUAL_CH1; ++ else if (vc == 2) ++ priv->vc = RCAR_VIRTUAL_CH2; ++ else if (vc == 3) ++ priv->vc = RCAR_VIRTUAL_CH3; ++ else ++ priv->vc = RCAR_VIRTUAL_NONE; ++ ++ dev_dbg(&pdev->dev, "csi_ch:%d, vc:%d\n", ++ priv->csi_ch, priv->vc); ++ ++ ifmd = VNCSI_IFMD_DES1 | VNCSI_IFMD_DES0; ++ ++ if (priv->chip == RCAR_H3) ++ gen3_ifmd_table = vin_h3_vc_ifmd; ++ else if (priv->chip == RCAR_M3) ++ gen3_ifmd_table = vin_m3_vc_ifmd; ++ ++ for (i = 0; i < num; i++) { ++ if ((gen3_ifmd_table[i].v_sel[priv->index].csi2_ch ++ == priv->csi_ch) && ++ (gen3_ifmd_table[i].v_sel[priv->index].vc ++ == priv->vc)) { ++ if (priv->index < RCAR_VIDEO_4) { ++ if (ifmd0_init) { ++ ifmd0_reg_match[i] = true; ++ match_flag = true; ++ } else if (ifmd0_reg_match[i]) ++ match_flag = true; ++ } else { ++ if (ifmd4_init) { ++ ifmd4_reg_match[i] = true; ++ match_flag = true; ++ } else if (ifmd4_reg_match[i]) ++ match_flag = true; ++ } ++ } else { ++ if (priv->index < RCAR_VIDEO_4) ++ ifmd0_reg_match[i] = false; ++ else ++ ifmd4_reg_match[i] = false; ++ } ++ } ++ if (priv->index < RCAR_VIDEO_4) ++ ifmd0_init = false; ++ else ++ ifmd4_init = false; ++ ++ if (!match_flag) { ++ dev_err(&pdev->dev, ++ "Not match, virtual channel pattern error.\n"); ++ return -EINVAL; ++ } ++ ++ rcar_vin_cpg_enable_for_ifmd(priv->index, true); ++ ++ if (priv->index < RCAR_VIDEO_4) { ++ void __iomem *ifmd0_mem; ++ ++ for (i = 0; i < num; i++) { ++ if (ifmd0_reg_match[i]) { ++ ifmd |= gen3_ifmd_table[i].set_reg; ++ break; ++ } ++ } ++ ++ ifmd0_mem = ioremap(0xe6ef0000 + VNCSI_IFMD_REG, 0x04); ++ iowrite32(ifmd, ifmd0_mem); ++ iounmap(ifmd0_mem); ++ } else { ++ void __iomem *ifmd4_mem; ++ ++ for (i = 0; i < num; i++) { ++ if (ifmd4_reg_match[i]) { ++ ifmd |= gen3_ifmd_table[i].set_reg; ++ break; ++ } ++ } ++ ++ ifmd4_mem = ioremap(0xe6ef4000 + VNCSI_IFMD_REG, 0x04); ++ iowrite32(ifmd, ifmd4_mem); ++ iounmap(ifmd4_mem); ++ } ++ ++ rcar_vin_cpg_enable_for_ifmd(priv->index, false); ++ } ++ ++ spin_lock_init(&priv->lock); ++ INIT_LIST_HEAD(&priv->capture); ++ ++ priv->state = STOPPED; ++ ++ pm_suspend_ignore_children(&pdev->dev, true); ++ pm_runtime_enable(&pdev->dev); ++ ++ ret = soc_camera_host_register(&priv->ici); ++ if (ret) ++ goto cleanup; ++ ++ if (csi_use) { ++ ret = rcar_vin_soc_of_bind(priv, &priv->ici, epn, ren->parent); ++ if (ret) ++ goto cleanup; ++ } ++ ++ vin_debug = 0; ++ ++ return 0; ++ ++cleanup: ++ pm_runtime_disable(&pdev->dev); ++ ++ return ret; ++} ++ ++static int rcar_vin_remove(struct platform_device *pdev) ++{ ++ struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev); ++ struct rcar_vin_priv *priv = container_of(soc_host, ++ struct rcar_vin_priv, ici); ++ ++ platform_device_del(priv->async_client->pdev); ++ platform_device_put(priv->async_client->pdev); ++ ++ v4l2_async_notifier_unregister(&priv->async_client->notifier); ++ ++ soc_camera_host_unregister(soc_host); ++ pm_runtime_disable(&pdev->dev); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PM_SLEEP ++static int rcar_vin_suspend(struct device *dev) ++{ ++ /* Empty function for now */ ++ return 0; ++} ++ ++static int rcar_vin_resume(struct device *dev) ++{ ++ u32 ifmd = 0; ++ bool match_flag = false; ++ const struct vin_gen3_ifmd *gen3_ifmd_table = NULL; ++ int num; ++ unsigned int i; ++ struct soc_camera_host *soc_host = to_soc_camera_host(dev); ++ struct rcar_vin_priv *priv = container_of(soc_host, ++ struct rcar_vin_priv, ici); ++ num = VNCSI_IFMD_SEL_NUMBER; ++ ifmd0_init = true; ++ ifmd4_init = true; ++ ++ if (priv->chip == RCAR_H3) { ++ ifmd = VNCSI_IFMD_DES1 | VNCSI_IFMD_DES0; ++ gen3_ifmd_table = vin_h3_vc_ifmd; ++ } else if (priv->chip == RCAR_M3) { ++ ifmd = VNCSI_IFMD_DES1; ++ gen3_ifmd_table = vin_m3_vc_ifmd; ++ } ++ ++ for (i = 0; i < num; i++) { ++ if ((gen3_ifmd_table[i].v_sel[priv->index].csi2_ch ++ == priv->csi_ch) && ++ (gen3_ifmd_table[i].v_sel[priv->index].vc ++ == priv->vc)) { ++ if (priv->index < RCAR_VIDEO_4) { ++ if (ifmd0_init) { ++ ifmd0_reg_match[i] = true; ++ match_flag = true; ++ } else if (ifmd0_reg_match[i]) ++ match_flag = true; ++ } else { ++ if (ifmd4_init) { ++ ifmd4_reg_match[i] = true; ++ match_flag = true; ++ } else if (ifmd4_reg_match[i]) ++ match_flag = true; ++ } ++ } else { ++ if (priv->index < RCAR_VIDEO_4) ++ ifmd0_reg_match[i] = false; ++ else ++ ifmd4_reg_match[i] = false; ++ } ++ } ++ if (priv->index < RCAR_VIDEO_4) ++ ifmd0_init = false; ++ else ++ ifmd4_init = false; ++ ++ if (priv->index < RCAR_VIDEO_4) { ++ void __iomem *ifmd0_mem; ++ ++ for (i = 0; i < num; i++) { ++ if (ifmd0_reg_match[i]) { ++ ifmd |= gen3_ifmd_table[i].set_reg; ++ break; ++ } ++ } ++ ++ ifmd0_mem = ioremap(0xe6ef0000 + VNCSI_IFMD_REG, 0x04); ++ iowrite32(ifmd, ifmd0_mem); ++ iounmap(ifmd0_mem); ++ } else { ++ void __iomem *ifmd4_mem; ++ ++ for (i = 0; i < num; i++) { ++ if (ifmd4_reg_match[i]) { ++ ifmd |= gen3_ifmd_table[i].set_reg; ++ break; ++ } ++ } ++ ++ ifmd4_mem = ioremap(0xe6ef4000 + VNCSI_IFMD_REG, 0x04); ++ iowrite32(ifmd, ifmd4_mem); ++ iounmap(ifmd4_mem); ++ } ++ ++ return 0; ++} ++ ++static SIMPLE_DEV_PM_OPS(rcar_vin_pm_ops, ++ rcar_vin_suspend, rcar_vin_resume); ++#define DEV_PM_OPS (&rcar_vin_pm_ops) ++#else ++#define DEV_PM_OPS NULL ++#endif /* CONFIG_PM_SLEEP */ ++ ++static struct platform_driver rcar_vin_driver = { ++ .probe = rcar_vin_probe, ++ .remove = rcar_vin_remove, ++ .driver = { ++ .name = DRV_NAME, ++ .pm = DEV_PM_OPS, ++ .of_match_table = of_match_ptr(rcar_vin_of_table), ++ }, ++}; ++ ++module_platform_driver(rcar_vin_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS("platform:rcar_vin"); ++MODULE_DESCRIPTION("Renesas R-Car VIN camera host driver"); ++MODULE_AUTHOR("Koji Matsuoka <koji.matsuoka.xm@renesas.com>"); +diff --git a/include/media/rcar_csi2.h b/include/media/rcar_csi2.h +new file mode 100644 +index 0000000..1a040fa +--- /dev/null ++++ b/include/media/rcar_csi2.h +@@ -0,0 +1,66 @@ ++/* ++ * include/media/rcar_csi2.h ++ * This file is the driver header ++ * for the Renesas R-Car MIPI CSI-2 unit. ++ * ++ * Copyright (C) 2015 Renesas Electronics Corporation ++ * ++ * This file is based on the include/media/sh_mobile_csi2.h ++ * ++ * Driver header for the SH-Mobile MIPI CSI-2 unit ++ * ++ * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#ifndef RCAR_MIPI_CSI ++#define RCAR_MIPI_CSI ++ ++#include <linux/list.h> ++ ++enum rcar_csi2_phy { ++ RCAR_CSI2_PHY_CSI40, /* CSI0 */ ++ RCAR_CSI2_PHY_CSI20, /* CSI1 */ ++ RCAR_CSI2_PHY_CSI41, /* CSI2 */ ++ RCAR_CSI2_PHY_CSI21, /* CSI3 */ ++}; ++ ++enum rcar_csi2_link { ++ RCAR_CSI2_LINK_CSI40, ++ RCAR_CSI2_LINK_CSI20, ++ RCAR_CSI2_LINK_CSI41, ++ RCAR_CSI2_LINK_CSI21, ++}; ++ ++enum rcar_csi2_type { ++ RCAR_CSI2_CSI4X, ++ RCAR_CSI2_CSI2X, ++}; ++ ++#define RCAR_CSI2_CRC (1 << 0) ++#define RCAR_CSI2_ECC (1 << 1) ++ ++struct platform_device; ++ ++struct rcar_csi2_client_config { ++ enum rcar_csi2_phy phy; ++ enum rcar_csi2_link link; ++ unsigned char lanes; /* bitmask[3:0] */ ++ unsigned char channel; /* 0..3 */ ++ struct platform_device *pdev; /* client platform device */ ++ const char *name; /* async matching: client name */ ++}; ++ ++struct v4l2_device; ++ ++struct rcar_csi2_pdata { ++ enum rcar_csi2_type type; ++ unsigned int flags; ++ struct rcar_csi2_client_config *clients; ++ int num_clients; ++}; ++ ++#endif +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0018-arm64-renesas-r8a7797-Add-Renesas-R8A7797-SoC-suppor.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0018-arm64-renesas-r8a7797-Add-Renesas-R8A7797-SoC-suppor.patch new file mode 100644 index 0000000..02e4e4d --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0018-arm64-renesas-r8a7797-Add-Renesas-R8A7797-SoC-suppor.patch @@ -0,0 +1,5014 @@ +From e8fd03e53c50c67a2aebf19f39a9f14b583f0e2d Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Sun, 14 May 2017 14:48:08 +0300 +Subject: [PATCH] arm64: renesas: r8a7797: Add Renesas R8A7797 SoC support + +This adds Renesas R8A7797 SoC support + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + arch/arm64/Kconfig.platforms | 6 + + arch/arm64/boot/dts/renesas/r8a7797.dtsi | 986 ++++++++++ + drivers/clk/renesas/Kconfig | 1 + + drivers/clk/renesas/Makefile | 1 + + drivers/clk/renesas/r8a7797-cpg-mssr.c | 217 ++ + drivers/clk/renesas/renesas-cpg-mssr.c | 6 + + drivers/clk/renesas/renesas-cpg-mssr.h | 1 + + drivers/gpio/gpio-rcar.c | 6 +- + drivers/gpu/drm/rcar-du/rcar_du_drv.c | 25 + + drivers/gpu/drm/rcar-du/rcar_du_group.c | 12 +- + drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c | 38 +- + drivers/hwspinlock/rcar_hwspinlock.c | 8 +- + drivers/i2c/busses/i2c-rcar.c | 1 + + drivers/iommu/ipmmu-vmsa.c | 7 +- + drivers/media/platform/soc_camera/Kconfig | 2 +- + drivers/media/platform/soc_camera/rcar_csi2.c | 25 +- + drivers/media/platform/soc_camera/rcar_vin.c | 86 +- + drivers/media/platform/vsp1/vsp1_drv.c | 8 + + drivers/media/platform/vsp1/vsp1_lif.c | 13 + + drivers/media/platform/vsp1/vsp1_regs.h | 7 + + drivers/mmc/host/sh_mobile_sdhi.c | 1 + + drivers/net/ethernet/renesas/ravb_main.c | 1 + + drivers/pinctrl/sh-pfc/Kconfig | 5 + + drivers/pinctrl/sh-pfc/Makefile | 1 + + drivers/pinctrl/sh-pfc/core.c | 7 + + drivers/pinctrl/sh-pfc/pfc-r8a7797.c | 2615 +++++++++++++++++++++++++ + drivers/pinctrl/sh-pfc/sh_pfc.h | 12 + + drivers/soc/renesas/Makefile | 3 + + drivers/soc/renesas/r8a7797-sysc.c | 39 + + drivers/soc/renesas/rcar-sysc.c | 3 + + drivers/soc/renesas/rcar-sysc.h | 1 + + drivers/soc/renesas/rcar_ems_ctrl.c | 10 + + drivers/soc/renesas/renesas-soc.c | 8 + + drivers/spi/spi-sh-msiof.c | 4 +- + drivers/thermal/rcar_gen3_thermal.c | 29 + + include/dt-bindings/clock/r8a7797-cpg-mssr.h | 48 + + include/dt-bindings/power/r8a7797-sysc.h | 32 + + 37 files changed, 4247 insertions(+), 28 deletions(-) + create mode 100644 arch/arm64/boot/dts/renesas/r8a7797.dtsi + create mode 100644 drivers/clk/renesas/r8a7797-cpg-mssr.c + create mode 100644 drivers/pinctrl/sh-pfc/pfc-r8a7797.c + create mode 100644 drivers/soc/renesas/r8a7797-sysc.c + create mode 100644 include/dt-bindings/clock/r8a7797-cpg-mssr.h + create mode 100644 include/dt-bindings/power/r8a7797-sysc.h + +diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms +index 7c104ca..9380fc6 100644 +--- a/arch/arm64/Kconfig.platforms ++++ b/arch/arm64/Kconfig.platforms +@@ -160,6 +160,12 @@ config ARCH_R8A7796 + help + This enables support for the Renesas R-Car M3-W SoC. + ++config ARCH_R8A7797 ++ bool "Renesas R-Car V3M SoC Platform" ++ depends on ARCH_RENESAS ++ help ++ This enables support for the Renesas R-Car V3M SoC. ++ + config ARCH_STRATIX10 + bool "Altera's Stratix 10 SoCFPGA Family" + help +diff --git a/arch/arm64/boot/dts/renesas/r8a7797.dtsi b/arch/arm64/boot/dts/renesas/r8a7797.dtsi +new file mode 100644 +index 0000000..c09df87 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7797.dtsi +@@ -0,0 +1,986 @@ ++/* ++ * Device Tree Source for the r8a7797 SoC ++ * ++ * Copyright (C) 2016 - 2017 Renesas Electronics Corp. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include <dt-bindings/clock/r8a7797-cpg-mssr.h> ++#include <dt-bindings/interrupt-controller/arm-gic.h> ++#include <dt-bindings/power/r8a7797-sysc.h> ++ ++/ { ++ compatible = "renesas,r8a7797"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ++ aliases { ++ csi2_40 = &csi2_40; ++ i2c0 = &i2c0; ++ i2c1 = &i2c1; ++ i2c2 = &i2c2; ++ i2c3 = &i2c3; ++ i2c4 = &i2c4; ++ spi1 = &msiof0; ++ spi2 = &msiof1; ++ spi3 = &msiof2; ++ spi4 = &msiof3; ++ vin0 = &vin0; ++ vin1 = &vin1; ++ vin2 = &vin2; ++ vin3 = &vin3; ++ tsc0 = &tsc1; ++ }; ++ ++ psci { ++ compatible = "arm,psci-1.0"; ++ method = "smc"; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ a53_0: cpu@0 { ++ compatible = "arm,cortex-a53", "arm,armv8"; ++ reg = <0x0>; ++ device_type = "cpu"; ++ power-domains = <&sysc R8A7797_PD_CA53_CPU0>; ++ next-level-cache = <&L2_CA53>; ++ enable-method = "psci"; ++ cpu-idle-states = <&CPU_SLEEP_0>; ++ #cooling-cells = <2>; ++ dynamic-power-coefficient = <277>; ++ cooling-min-level = <0>; ++ cooling-max-level = <2>; ++ clocks =<&cpg CPG_CORE R8A7797_CLK_Z2>; ++ operating-points-v2 = <&cluster0_opp_tb0>; ++ /*cpu-supply = <&vdd_dvfs>;*/ ++ }; ++ ++ a53_1: cpu@1 { ++ compatible = "arm,cortex-a53","arm,armv8"; ++ reg = <0x1>; ++ device_type = "cpu"; ++ power-domains = <&sysc R8A7797_PD_CA53_CPU1>; ++ next-level-cache = <&L2_CA53>; ++ enable-method = "psci"; ++ cpu-idle-states = <&CPU_SLEEP_0>; ++ operating-points-v2 = <&cluster0_opp_tb0>; ++ }; ++ ++ idle-states { ++ entry-method = "psci"; ++ ++ CPU_SLEEP_0: cpu-sleep-0 { ++ compatible = "arm,idle-state"; ++ arm,psci-suspend-param = <0x0010000>; ++ local-timer-stop; ++ entry-latency-us = <639>; ++ exit-latency-us = <680>; ++ min-residency-us = <1088>; ++ status = "disabled"; ++ }; ++ }; ++ }; ++ ++ L2_CA53: cache-controller@1 { ++ compatible = "cache"; ++ power-domains = <&sysc R8A7797_PD_CA53_SCU>; ++ cache-unified; ++ cache-level = <2>; ++ }; ++ ++ cluster0_opp_tb0: opp_table0 { ++ compatible = "operating-points-v2"; ++ opp-shared; ++ ++ opp@800000000 { ++ opp-hz = /bits/ 64 <800000000>; ++ opp-microvolt = <850000>; ++ clock-latency-ns = <300000>; ++ }; ++ }; ++ ++ extal_clk: extal { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ /* This value must be overridden by the board */ ++ clock-frequency = <0>; ++ }; ++ ++ extalr_clk: extalr { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ /* This value must be overridden by the board */ ++ clock-frequency = <0>; ++ }; ++ ++ /* External CAN clock - to be overridden by boards that provide it */ ++ can_clk: can { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <0>; ++ }; ++ ++ /* External SCIF clock - to be overridden by boards that provide it */ ++ scif_clk: scif { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <0>; ++ }; ++ ++ /* DU input dot clock - tob be overriden by boards that probide it */ ++ du_dotclkin0: dclkin-0 { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <148500000>; ++ }; ++ ++ soc { ++ compatible = "simple-bus"; ++ interrupt-parent = <&gic>; ++ ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ gic: interrupt-controller@0xf1010000 { ++ compatible = "arm,gic-400"; ++ #interrupt-cells = <3>; ++ #address-cells = <0>; ++ interrupt-controller; ++ reg = <0x0 0xf1010000 0 0x1000>, ++ <0x0 0xf1020000 0 0x20000>, ++ <0x0 0xf1040000 0 0x20000>, ++ <0x0 0xf1060000 0 0x20000>; ++ interrupts = <GIC_PPI 9 ++ (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>; /* PPI9:Virtual maintenance interrupt */ ++/* clocks = <&cpg CPG_MOD 408>; ++ clock-names = "clk"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; */ ++ }; ++ ++ gpio0: gpio@e6050000 { ++ compatible = "renesas,gpio-r8a7797", ++ "renesas,gpio-rcar"; ++ reg = <0 0xe6050000 0 0x50>; ++ interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>; /* SPI4:GPIO.ch0 */ ++ #gpio-cells = <2>; ++ gpio-controller; ++ gpio-ranges = <&pfc 0 0 22>; ++ #interrupt-cells = <2>; ++ interrupt-controller; ++ clocks = <&cpg CPG_MOD 912>; /* RMSTPCR9/bit12:GPIO0 */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ }; ++ ++ gpio1: gpio@e6051000 { ++ compatible = "renesas,gpio-r8a7797", ++ "renesas,gpio-rcar"; ++ reg = <0 0xe6051000 0 0x50>; ++ interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>; /* SPI5:GPIO.ch1 */ ++ #gpio-cells = <2>; ++ gpio-controller; ++ gpio-ranges = <&pfc 0 32 27>; ++ #interrupt-cells = <2>; ++ interrupt-controller; ++ clocks = <&cpg CPG_MOD 911>; /* RMSTPCR9/bit11:GPIO1 */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ }; ++ ++ gpio2: gpio@e6052000 { ++ compatible = "renesas,gpio-r8a7797", ++ "renesas,gpio-rcar"; ++ reg = <0 0xe6052000 0 0x50>; ++ interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>; /* SPI6:GPIO.ch2 */ ++ #gpio-cells = <2>; ++ gpio-controller; ++ gpio-ranges = <&pfc 0 64 17>; ++ #interrupt-cells = <2>; ++ interrupt-controller; ++ clocks = <&cpg CPG_MOD 910>; /* RMSTPCR9/bit10:GPIO2 */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ }; ++ ++ gpio3: gpio@e6053000 { ++ compatible = "renesas,gpio-r8a7797", ++ "renesas,gpio-rcar"; ++ reg = <0 0xe6053000 0 0x50>; ++ interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; /* SPI7:GPIO.ch3 */ ++ #gpio-cells = <2>; ++ gpio-controller; ++ gpio-ranges = <&pfc 0 96 17>; ++ #interrupt-cells = <2>; ++ interrupt-controller; ++ clocks = <&cpg CPG_MOD 909>; /* RMSTPCR9/bit9:GPIO3 */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ }; ++ ++ gpio4: gpio@e6054000 { ++ compatible = "renesas,gpio-r8a7797", ++ "renesas,gpio-rcar"; ++ reg = <0 0xe6054000 0 0x50>; ++ interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>; /* SPI8:GPIO.ch4 */ ++ #gpio-cells = <2>; ++ gpio-controller; ++ gpio-ranges = <&pfc 0 128 6>; ++ #interrupt-cells = <2>; ++ interrupt-controller; ++ clocks = <&cpg CPG_MOD 908>; /* RMSTPCR9/bit8:GPIO4 */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ }; ++ ++ gpio5: gpio@e6055000 { ++ compatible = "renesas,gpio-r8a7797", ++ "renesas,gpio-rcar"; ++ reg = <0 0xe6055000 0 0x50>; ++ interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>; /* SPI9:GPIO.ch5 */ ++ #gpio-cells = <2>; ++ gpio-controller; ++ gpio-ranges = <&pfc 0 160 15>; ++ #interrupt-cells = <2>; ++ interrupt-controller; ++ clocks = <&cpg CPG_MOD 907>; /* RMSTPCR9/bit7:GPIO5 */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ }; ++ ++ pmu_a53 { ++ compatible = "arm,cortex-a53-pmu"; ++ interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>; /* SPI84:AP-System Core.CA53core0 pmu, SPI85:AP-System Core.CA53core1 pmu */ ++ interrupt-affinity = <&a53_0>, ++ <&a53_1>; ++ }; ++ ++ timer { ++ compatible = "arm,armv8-timer"; ++ interrupts = <GIC_PPI 13 ++ (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>, ++ <GIC_PPI 14 ++ (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>, ++ <GIC_PPI 11 ++ (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>, ++ <GIC_PPI 10 ++ (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>; /* PPI13:Secure physical timer, PPI14:Non-secure physical timer, ++ PPI11:Virtual timer, PPI10:Hypervisor timer */ ++ }; ++ ++ wdt0: wdt@e6020000 { ++ compatible = "renesas,r8a7797-wdt", "renesas,rcar-gen3-wdt"; ++ reg = <0 0xe6020000 0 0x0c>; ++ clocks = <&cpg CPG_MOD 402>; /* RMSTPCR4/bit2:RWDT */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ cpg: clock-controller@e6150000 { ++ compatible = "renesas,r8a7797-cpg-mssr"; ++ reg = <0 0xe6150000 0 0x1000>; ++ clocks = <&extal_clk>, <&extalr_clk>; ++ clock-names = "extal", "extalr"; ++ #clock-cells = <2>; ++ #power-domain-cells = <0>; ++ }; ++ ++ csi2_40: csi2@feaa0000 { ++ compatible = "renesas,csi2-r8a7797"; ++ reg = <0 0xfeaa0000 0 0x10000>; ++ interrupts = <GIC_SPI 246 IRQ_TYPE_LEVEL_HIGH>; /* SPI246:CSI2.ch2 */ ++ clocks = <&cpg CPG_MOD 716>; /* RMSTPCR7/bit16:CSI40 */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ sysc: system-controller@e6180000 { ++ compatible = "renesas,r8a7797-sysc"; ++ reg = <0 0xe6180000 0 0x0440>; ++ #power-domain-cells = <1>; ++ }; ++ ++ pfc: pfc@e6060000 { ++ compatible = "renesas,pfc-r8a7797"; ++ reg = <0 0xe6060000 0 0x50c>; ++ }; ++ ++ intc_ex: interrupt-controller@e61c0000 { ++ compatible = "renesas,intc-ex-r8a7797", "renesas,irqc"; ++ #interrupt-cells = <2>; ++ interrupt-controller; ++ reg = <0 0xe61c0000 0 0x200>; ++ interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH ++ GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH ++ GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH ++ GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH ++ GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH ++ GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>; /* SPI1:IRQ1, SPI2:IRQ2, SPI3:IRQ3, SPI18:IRQ4, SPI161:IRQ5 */ ++ clocks = <&cpg CPG_MOD 407>; /* RMSTPCR4/bit7:INTC-EX */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ }; ++ ++ ipmmu_vi: mmu@febd0000 { ++ compatible = "renesas,ipmmu-r8a7797"; ++ reg = <0 0xfebd0000 0 0x1000>; /* IPMMU-VI */ ++ renesas,ipmmu-main = <&ipmmu_mm 11>; ++ #iommu-cells = <1>; ++ status = "disabled"; ++ }; ++ ++ ipmmu_ir: mmu@ff8b0000 { ++ compatible = "renesas,ipmmu-r8a7797"; ++ reg = <0 0xff8b0000 0 0x1000>; /* IPMMU-IR */ ++ renesas,ipmmu-main = <&ipmmu_mm 3>; ++ #iommu-cells = <1>; ++ status = "disabled"; ++ }; ++ ++ ipmmu_rt: mmu@ffc80000 { ++ compatible = "renesas,ipmmu-r8a7797"; ++ reg = <0 0xffc80000 0 0x1000>; /* IPMMU-RT */ ++ renesas,ipmmu-main = <&ipmmu_mm 7>; ++ #iommu-cells = <1>; ++ status = "disabled"; ++ }; ++ ++ ipmmu_ds0: mmu@e6740000 { ++ compatible = "renesas,ipmmu-r8a7797"; ++ reg = <0 0xe6740000 0 0x1000>; /* IPMMU-DS0 */ ++ renesas,ipmmu-main = <&ipmmu_mm 0>; ++ #iommu-cells = <1>; ++ status = "disabled"; ++ }; ++ ++ ipmmu_mm: mmu@e67b0000 { ++ compatible = "renesas,ipmmu-r8a7797"; ++ reg = <0 0xe67b0000 0 0x1000>; /* IPMMU-MM */ ++ interrupts = <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>; /* SPI196:IPMMU, SPI197:IPMMU sec */ ++ #iommu-cells = <1>; ++ status = "disabled"; ++ }; ++ ++ dmac1: dma-controller@e7300000 { ++ compatible = "renesas,dmac-r8a7797", ++ "renesas,rcar-dmac"; ++ reg = <0 0xe7300000 0 0x10000>; ++ interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH ++ GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH ++ GIC_SPI 217 IRQ_TYPE_LEVEL_HIGH ++ GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH ++ GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH ++ GIC_SPI 308 IRQ_TYPE_LEVEL_HIGH ++ GIC_SPI 309 IRQ_TYPE_LEVEL_HIGH ++ GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH ++ GIC_SPI 311 IRQ_TYPE_LEVEL_HIGH>; /* SPI220::SYS-DMAC1 err, ++ SPI216~219:SYS-DMAC1.ch0~SYS-DMAC1.ch3, ++ SPI308~311:SYS-DMAC1.ch4~SYS-DMAC1.ch7 */ ++ interrupt-names = "error", ++ "ch0", "ch1", "ch2", "ch3", ++ "ch4", "ch5", "ch6", "ch7"; ++ clocks = <&cpg CPG_MOD 218>; /* RMSTPCR2/bit18:SYS-DMAC1 */ ++ clock-names = "fck"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ #dma-cells = <1>; ++ dma-channels = <8>; ++ iommus = <&ipmmu_ds0 0>, <&ipmmu_ds0 1>, ++ <&ipmmu_ds0 2>, <&ipmmu_ds0 3>, ++ <&ipmmu_ds0 4>, <&ipmmu_ds0 5>, ++ <&ipmmu_ds0 6>, <&ipmmu_ds0 7>; /* @@ */ ++ }; ++ ++ dmac2: dma-controller@e7310000 { ++ compatible = "renesas,dmac-r8a7797", ++ "renesas,rcar-dmac"; ++ reg = <0 0xe7310000 0 0x10000>; ++ interrupts = <GIC_SPI 307 IRQ_TYPE_LEVEL_HIGH ++ GIC_SPI 312 IRQ_TYPE_LEVEL_HIGH ++ GIC_SPI 313 IRQ_TYPE_LEVEL_HIGH ++ GIC_SPI 314 IRQ_TYPE_LEVEL_HIGH ++ GIC_SPI 315 IRQ_TYPE_LEVEL_HIGH ++ GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH ++ GIC_SPI 317 IRQ_TYPE_LEVEL_HIGH ++ GIC_SPI 318 IRQ_TYPE_LEVEL_HIGH ++ GIC_SPI 319 IRQ_TYPE_LEVEL_HIGH>; /* SPI307::SYS-DMAC2 err, ++ SPI312~319:SYS-DMAC2.ch0~SYS-DMAC1.ch7 */ ++ interrupt-names = "error", ++ "ch0", "ch1", "ch2", "ch3", ++ "ch4", "ch5", "ch6", "ch7"; ++ clocks = <&cpg CPG_MOD 217>; /* RMSTPCR2/bit17:SYS-DMAC2 */ ++ clock-names = "fck"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ #dma-cells = <1>; ++ dma-channels = <8>; ++ iommus = <&ipmmu_ds0 16>, <&ipmmu_ds0 17>, ++ <&ipmmu_ds0 18>, <&ipmmu_ds0 19>, ++ <&ipmmu_ds0 20>, <&ipmmu_ds0 21>, ++ <&ipmmu_ds0 22>, <&ipmmu_ds0 23>; /* @@ */ ++ }; ++ ++ avb: ethernet@e6800000 { ++ compatible = "renesas,etheravb-r8a7797", ++ "renesas,etheravb-rcar-gen3"; ++ reg = <0 0xe6800000 0 0x800>, <0 0xe6a00000 0 0x10000>; ++ interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>; /* SPI39~63:Ethernet AVB.ch0~24 */ ++ /* @@ errreq_avb_p[0]~[3] add (T.B.D) */ ++ interrupt-names = "ch0", "ch1", "ch2", "ch3", ++ "ch4", "ch5", "ch6", "ch7", ++ "ch8", "ch9", "ch10", "ch11", ++ "ch12", "ch13", "ch14", "ch15", ++ "ch16", "ch17", "ch18", "ch19", ++ "ch20", "ch21", "ch22", "ch23", ++ "ch24"; ++ clocks = <&cpg CPG_MOD 812>; /* RMSTPCR8/bit12:EAVB-IF */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ phy-mode = "rgmii-id"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ /* Future ++ canfd: canfd@e66c0000 { ++ compatible = "renesas,r8a7797-canfd", ++ "renesas,rcar-gen3-canfd"; ++ reg = <0 0xe66c0000 0 0x8000>; ++ interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>; ** SPI29:CAN-FD channel, SPI30:CAN-FD global ** ++ clocks = <&cpg CPG_MOD 914>, ++ <&cpg CPG_CORE R8A7797_CLK_CANFD>, ++ <&can_clk>; ** RMSTPCR9/bit14:CAN-FD ** ++ clock-names = "fck", "canfd", "can_clk"; ++ assigned-clocks = <&cpg CPG_CORE R8A7797_CLK_CANFD>; ++ assigned-clock-rates = <40000000>; ++ power-domains = <&cpg>; ++ status = "disabled"; ++ ++ channel0 { ++ status = "disabled"; ++ }; ++ ++ channel1 { ++ status = "disabled"; ++ }; ++ }; */ ++ ++ pwm0: pwm@e6e30000 { ++ compatible = "renesas,pwm-r8a7797", "renesas,pwm-rcar"; ++ reg = <0 0xe6e30000 0 0x10>; ++ #pwm-cells = <2>; ++ clocks = <&cpg CPG_MOD 523>; /* RMSTPCR5/bit23:PWM */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ pwm1: pwm@e6e31000 { ++ compatible = "renesas,pwm-r8a7797", "renesas,pwm-rcar"; ++ reg = <0 0xe6e31000 0 0x10>; ++ #pwm-cells = <2>; ++ clocks = <&cpg CPG_MOD 523>; /* RMSTPCR5/bit23:PWM */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ pwm2: pwm@e6e32000 { ++ compatible = "renesas,pwm-r8a7797", "renesas,pwm-rcar"; ++ reg = <0 0xe6e32000 0 0x10>; ++ #pwm-cells = <2>; ++ clocks = <&cpg CPG_MOD 523>; /* RMSTPCR5/bit23:PWM */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ pwm3: pwm@e6e33000 { ++ compatible = "renesas,pwm-r8a7797", "renesas,pwm-rcar"; ++ reg = <0 0xe6e33000 0 0x10>; ++ #pwm-cells = <2>; ++ clocks = <&cpg CPG_MOD 523>; /* RMSTPCR5/bit23:PWM */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ pwm4: pwm@e6e34000 { ++ compatible = "renesas,pwm-r8a7797", "renesas,pwm-rcar"; ++ reg = <0 0xe6e34000 0 0x10>; ++ #pwm-cells = <2>; ++ clocks = <&cpg CPG_MOD 523>; /* RMSTPCR5/bit23:PWM */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ hscif0: serial@e6540000 { ++ compatible = "renesas,hscif-r8a7797", ++ "renesas,rcar-gen3-hscif", ++ "renesas,hscif"; ++ reg = <0 0xe6540000 0 96>; ++ interrupts = <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>; /* SPI154:HSCIF.ch0 */ ++ clocks = <&cpg CPG_MOD 520>, ++ <&cpg CPG_CORE R8A7797_CLK_S2D1>, ++ <&scif_clk>; /* RMSTPCR5/bit20:HSCIF0 */ ++ clock-names = "fck", "brg_int", "scif_clk"; ++ dmas = <&dmac1 0x31>, <&dmac1 0x30>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ hscif1: serial@e6550000 { ++ compatible = "renesas,hscif-r8a7797", ++ "renesas,rcar-gen3-hscif", ++ "renesas,hscif"; ++ reg = <0 0xe6550000 0 96>; ++ interrupts = <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>; /* SPI155:HSCIF.ch1 */ ++ clocks = <&cpg CPG_MOD 519>, ++ <&cpg CPG_CORE R8A7797_CLK_S2D1>, ++ <&scif_clk>; /* RMSTPCR5/bit19:HSCIF1 */ ++ clock-names = "fck", "brg_int", "scif_clk"; ++ dmas = <&dmac1 0x33>, <&dmac1 0x32>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ hscif2: serial@e6560000 { ++ compatible = "renesas,hscif-r8a7797", ++ "renesas,rcar-gen3-hscif", ++ "renesas,hscif"; ++ reg = <0 0xe6560000 0 96>; ++ interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>; /* SPI144:HSCIF.ch2 */ ++ clocks = <&cpg CPG_MOD 518>, ++ <&cpg CPG_CORE R8A7797_CLK_S2D1>, ++ <&scif_clk>; /* RMSTPCR5/bit18:HSCIF2 */ ++ clock-names = "fck", "brg_int", "scif_clk"; ++ dmas = <&dmac1 0x35>, <&dmac1 0x34>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ hscif3: serial@e66a0000 { ++ compatible = "renesas,hscif-r8a7797", ++ "renesas,rcar-gen3-hscif", ++ "renesas,hscif"; ++ reg = <0 0xe66a0000 0 96>; ++ interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>; /* SPI145:HSCIF.ch3 */ ++ clocks = <&cpg CPG_MOD 517>, ++ <&cpg CPG_CORE R8A7797_CLK_S2D1>, ++ <&scif_clk>; /* RMSTPCR5/bit17:HSCIF3 */ ++ clock-names = "fck", "brg_int", "scif_clk"; ++ dmas = <&dmac1 0x37>, <&dmac1 0x36>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ scif0: serial@e6e60000 { ++ compatible = "renesas,scif-r8a7797", ++ "renesas,rcar-gen3-scif", "renesas,scif"; ++ reg = <0 0xe6e60000 0 64>; ++ interrupts = <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>; /* SPI152:SCIF.ch0 */ ++ clocks = <&cpg CPG_MOD 207>, ++ <&cpg CPG_CORE R8A7797_CLK_S2D1>, ++ <&scif_clk>; /* RMSTPCR2/bit7:SCIF0 */ ++ /*clock-names = "fck", "sck", "brg_int", "scif_clk"; */ ++ clock-names = "fck"; ++ dmas = <&dmac1 0x51>, <&dmac1 0x50>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ scif1: serial@e6e68000 { ++ compatible = "renesas,scif-r8a7797", ++ "renesas,rcar-gen3-scif", "renesas,scif"; ++ reg = <0 0xe6e68000 0 64>; ++ interrupts = <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>; /* SPI153:SCIF.ch1 */ ++ clocks = <&cpg CPG_MOD 206>, ++ <&cpg CPG_CORE R8A7797_CLK_S2D1>, ++ <&scif_clk>; /* RMSTPCR2/bit6:SCIF1 */ ++ clock-names = "fck", "brg_int", "scif_clk"; ++ dmas = <&dmac1 0x53>, <&dmac1 0x52>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ scif3: serial@e6c50000 { ++ compatible = "renesas,scif-r8a7797", ++ "renesas,rcar-gen3-scif", "renesas,scif"; ++ reg = <0 0xe6c50000 0 64>; ++ interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>; /* SPI23:SCIF.ch3 */ ++ clocks = <&cpg CPG_MOD 204>, ++ <&cpg CPG_CORE R8A7797_CLK_S2D1>, ++ <&scif_clk>; /* RMSTPCR2/bit4:SCIF3 */ ++ clock-names = "fck", "brg_int", "scif_clk"; ++ dmas = <&dmac1 0x57>, <&dmac1 0x56>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ scif4: serial@e6c40000 { ++ compatible = "renesas,scif-r8a7797", ++ "renesas,rcar-gen3-scif", "renesas,scif"; ++ reg = <0 0xe6c40000 0 64>; ++ interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>; /* SPI16:SCIF.ch4 */ ++ clocks = <&cpg CPG_MOD 203>, ++ <&cpg CPG_CORE R8A7797_CLK_S2D1>, ++ <&scif_clk>; /* RMSTPCR2/bit3:SCIF4 */ ++ clock-names = "fck", "brg_int", "scif_clk"; ++ dmas = <&dmac1 0x59>, <&dmac1 0x58>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ i2c0: i2c@e6500000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "renesas,i2c-r8a7797"; ++ reg = <0 0xe6500000 0 0x40>; ++ interrupts = <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>; /* SPI287:I2C.ch0 */ ++ clocks = <&cpg CPG_MOD 931>; /* RMSTPCR9/bit31:I2C-IF0 */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ dmas = <&dmac1 0x91>, <&dmac1 0x90>; ++ dma-names = "tx", "rx"; ++ i2c-scl-internal-delay-ns = <6>; ++ status = "disabled"; ++ }; ++ ++ i2c1: i2c@e6508000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "renesas,i2c-r8a7797"; ++ reg = <0 0xe6508000 0 0x40>; ++ interrupts = <GIC_SPI 288 IRQ_TYPE_LEVEL_HIGH>; /* SPI288:I2C.ch1 */ ++ clocks = <&cpg CPG_MOD 930>; /* RMSTPCR9/bit30:I2C-IF1 */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ dmas = <&dmac1 0x93>, <&dmac1 0x92>; ++ dma-names = "tx", "rx"; ++ i2c-scl-internal-delay-ns = <6>; ++ status = "disabled"; ++ }; ++ ++ i2c2: i2c@e6510000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "renesas,i2c-r8a7797"; ++ reg = <0 0xe6510000 0 0x40>; ++ interrupts = <GIC_SPI 286 IRQ_TYPE_LEVEL_HIGH>; /* SPI286:I2C.ch2 */ ++ clocks = <&cpg CPG_MOD 929>; /* RMSTPCR9/bit29:I2C-IF2 */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ dmas = <&dmac1 0x95>, <&dmac1 0x94>; ++ dma-names = "tx", "rx"; ++ i2c-scl-internal-delay-ns = <6>; ++ status = "disabled"; ++ }; ++ ++ i2c3: i2c@e66d0000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "renesas,i2c-r8a7797"; ++ reg = <0 0xe66d0000 0 0x40>; ++ interrupts = <GIC_SPI 290 IRQ_TYPE_LEVEL_HIGH>; /* SPI290:I2C.ch3 */ ++ clocks = <&cpg CPG_MOD 928>; /* RMSTPCR9/bit28:I2C-IF3 */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ dmas = <&dmac1 0x97>, <&dmac1 0x96>; ++ dma-names = "tx", "rx"; ++ i2c-scl-internal-delay-ns = <6>; ++ status = "disabled"; ++ }; ++ ++ i2c4: i2c@e66d8000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "renesas,i2c-r8a7797"; ++ reg = <0 0xe66d8000 0 0x40>; ++ interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>; /* SPI19:I2C.ch4 */ ++ clocks = <&cpg CPG_MOD 927>; /* RMSTPCR9/bit27:I2C-IF4 */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ dmas = <&dmac1 0x99>, <&dmac1 0x98>; ++ dma-names = "tx", "rx"; ++ i2c-scl-internal-delay-ns = <6>; ++ status = "disabled"; ++ }; ++ ++ msiof0: spi@e6e90000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "renesas,msiof-r8a7797"; ++ reg = <0 0xe6e90000 0 0x64>; ++ interrupts = <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>; /* SPI156:MSIOF.ch0 */ ++ clocks = <&cpg CPG_MOD 211>, <&msiof_ref_clk>; /* RMSTPCR2/bit11:MSIOF0, @@ msiof_ref_clk->Eagle.dts */ ++ clock-names = "msiof_clk", "msiof_ref_clk"; ++ dmas = <&dmac1 0x41>, <&dmac1 0x40>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ msiof1: spi@e6ea0000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "renesas,msiof-r8a7797"; ++ reg = <0 0xe6ea0000 0 0x0064>; ++ interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>; /* SPI157:MSIOF.ch1 */ ++ clocks = <&cpg CPG_MOD 210>, <&msiof_ref_clk>; /* RMSTPCR2/bit10:MSIOF1, @@ msiof_ref_clk->Eagle.dts */ ++ clock-names = "msiof_clk", "msiof_ref_clk"; ++ dmas = <&dmac1 0x43>, <&dmac1 0x42>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ msiof2: spi@e6c00000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "renesas,msiof-r8a7797"; ++ reg = <0 0xe6c00000 0 0x0064>; ++ interrupts = <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>; /* SPI158:MSIOF.ch2 */ ++ clocks = <&cpg CPG_MOD 209>, <&msiof_ref_clk>; /* RMSTPCR2/bit9:MSIOF2, @@ msiof_ref_clk->Eagle.dts */ ++ clock-names = "msiof_clk", "msiof_ref_clk"; ++ dmas = <&dmac1 0x45>, <&dmac1 0x44>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ msiof3: spi@e6c10000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "renesas,msiof-r8a7797"; ++ reg = <0 0xe6c10000 0 0x0064>; ++ interrupts = <GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>; /* SPI159:MSIOF.ch3 */ ++ clocks = <&cpg CPG_MOD 208>, <&msiof_ref_clk>; /* RMSTPCR2/bit8:MSIOF3, @@ msiof_ref_clk->Eagle.dts */ ++ clock-names = "msiof_clk", "msiof_ref_clk"; ++ dmas = <&dmac1 0x47>, <&dmac1 0x46>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin0: video@e6ef0000 { ++ compatible = "renesas,vin-r8a7797"; ++ reg = <0 0xe6ef0000 0 0x1000>; ++ interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>; /* SPI188:VIN.ch0 */ ++ clocks = <&cpg CPG_MOD 811>; /* RMSTPCR8/bit11:VIN0 */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin1: video@e6ef1000 { ++ compatible = "renesas,vin-r8a7797"; ++ reg = <0 0xe6ef1000 0 0x1000>; ++ interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>; /* SPI189:VIN.ch1 */ ++ clocks = <&cpg CPG_MOD 810>; /* RMSTPCR8/bit10:VIN1 */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin2: video@e6ef2000 { ++ compatible = "renesas,vin-r8a7797"; ++ reg = <0 0xe6ef2000 0 0x1000>; ++ interrupts = <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>; /* SPI190:VIN.ch2 */ ++ clocks = <&cpg CPG_MOD 809>; /* RMSTPCR8/bit9:VIN2 */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin3: video@e6ef3000 { ++ compatible = "renesas,vin-r8a7797"; ++ reg = <0 0xe6ef3000 0 0x1000>; ++ interrupts = <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>; /* SPI191:VIN.ch3 */ ++ clocks = <&cpg CPG_MOD 808>; /* RMSTPCR8/bit8:VIN3 */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++/* ++ sdhi2: sd@ee140000 { ++ compatible = "renesas,sdhi-r8a7797"; ++ reg = <0 0xee140000 0 0x2000>; ++ interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>; ** SPI165:SDHI.ch0 ** ++ clocks = <&cpg CPG_MOD 314>; ** RMSTPCR3/bit14:SDIF ** ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ renesas,clk-rate = <200000000>; ++ cap-sd-highspeed; ++ sd-uhs-sdr50; ++ sd-uhs-sdr104; ++ renesas,mmc-scc-tapnum = <8>; ++ status = "disabled"; ++ }; ++*/ ++ mmc0: mmc@ee140000 { ++ compatible = "renesas,mmc-r8a7797"; ++ reg = <0 0xee140000 0 0x2000>; ++ interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>; /* SPI165:SDHI.ch0 */ ++ clocks = <&cpg CPG_MOD 314>; /* RMSTPCR3/bit14:SDIF */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ renesas,clk-rate = <200000000>; ++/* cap-sd-highspeed; ++ sd-uhs-sdr104; ++ sd-uhs-sdr50; ++ cap-mmc-highspeed; ++*/ ++ mmc-hs200-1_8v; ++ renesas,mmc-scc-tapnum = <8>; ++ status = "disabled"; ++ }; ++ ++ qos@e67e0000 { ++ compatible = "renesas,qos"; ++ }; ++ ++ vspd0: vsp@fea20000 { ++ compatible = "renesas,vsp2"; ++ reg = <0 0xfea20000 0 0x4000>; ++ ++ interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>; ++ clocks = <&cpg CPG_MOD 623>; /* RMSTPCR6/bit23:VSP(VSPD0) */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ ++ renesas,fcp = <&fcpvd0>; ++ }; ++ ++ fcpvd0: fcp@fea27000 { ++ compatible = "renesas,r8a7797-fcpv", "renesas,fcpv"; ++ reg = <0 0xfea27000 0 0x200>; ++ clocks = <&cpg CPG_MOD 603>; /* RMSTPCR6/bit3:FCPVD0 */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ }; ++ ++ du: display@feb00000 { ++ compatible = "renesas,du-r8a7797"; ++ reg = <0 0xfeb00000 0 0x80000>, ++ <0 0xfeb90000 0 0x14>; /* LDVS */ ++ reg-names = "du", "lvds.0"; ++ interrupts = <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>; /* SPI256:DU.ch0 */ ++ clocks = <&cpg CPG_MOD 724>, ++ <&cpg CPG_MOD 727>, ++ <&dclkin_p0>; ++ clock-names = "du.0", "lvds.0", "dclkin.0"; ++ status = "disabled"; ++ ++ vsps = <&vspd0>; ++ ++ interlaced = <1>; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ du_out_lvds0: endpoint { ++ }; ++ }; ++ }; ++ }; ++ ++ tsc1: thermal@0xe6190000 { ++ compatible = "renesas,thermal-r8a7797"; ++ reg = <0 0xe6190000 0 0x5c>; ++ interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>; /* SPI67~69:Thermal Sensor.ch0~2 */ ++ clocks = <&cpg CPG_MOD 522>; /* RMSTPCR5/bit22:THS/TSC */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ #thermal-sensor-cells = <0>; ++ status = "okay"; ++ }; ++ ++ thermal-zones { ++ emergency { ++ polling-delay = <1000>; ++ on-temperature = <110000>; ++ off-temperature = <95000>; ++ target_cpus = <&a53_1>; ++ status = "disabled"; ++ }; ++ ++ sensor_thermal1: sensor-thermal1 { ++ polling-delay-passive = <250>; ++ polling-delay = <0>; ++ sustainable-power = <6313>; ++ ++ /* sensor ID */ ++ thermal-sensors = <&tsc1>; ++ ++ trips { ++ threshold: trip-point@0 { ++ /* miliCelsius */ ++ temperature = <90000>; ++ hysteresis = <2000>; ++ type = "passive"; ++ }; ++ ++ target: trip-point@1 { ++ /* miliCelsius */ ++ temperature = <100000>; ++ hysteresis = <2000>; ++ type = "passive"; ++ }; ++ ++ sensor1_crit: sensor1-crit { ++ temperature = <120000>; ++ hysteresis = <2000>; ++ type = "critical"; ++ }; ++ }; ++ ++ cooling-maps { ++ map0 { ++ trip = <&target>; ++ cooling-device = <&a53_0 0 2>; ++ contribution = <1024>; ++ }; ++ }; ++ }; ++ }; ++ ++ mfis: mfis@e6260000 { ++ compatible = "renesas,mfis-r8a7797", "renesas,mfis"; ++ reg = <0 0xe6260000 0 0x0200>; ++ interrupts = <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>; /* SPI180:MFIS eicr0 */ ++ interrupt-names = "eicr0"; ++ clocks = <&cpg CPG_MOD 213>; /* RMSTPCR2/bit13:MFIS */ ++ clock-names = "mfis"; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "okay"; ++ }; ++ ++ mfis_lock: mfis-lock { ++ compatible = "renesas,mfis-lock-r8a7797", ++ "renesas,mfis-lock"; ++ reg = <0 0xe62600c0 0 0x0750>; /* @@ transitional 0x20->0x750 */ ++ clocks = <&cpg CPG_MOD 213>; /* RMSTPCR2/bit13:MFIS */ ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "okay"; ++ }; ++ }; ++}; +diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig +index 2586dfa..f86f2bf 100644 +--- a/drivers/clk/renesas/Kconfig ++++ b/drivers/clk/renesas/Kconfig +@@ -4,6 +4,7 @@ config CLK_RENESAS_CPG_MSSR + default y if ARCH_R8A7745 + default y if ARCH_R8A7795 + default y if ARCH_R8A7796 ++ default y if ARCH_R8A7797 + + config CLK_RENESAS_CPG_MSTP + bool +diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile +index 1072f76..c6f0abb 100644 +--- a/drivers/clk/renesas/Makefile ++++ b/drivers/clk/renesas/Makefile +@@ -13,6 +13,7 @@ obj-$(CONFIG_ARCH_R8A7793) += clk-rcar-gen2.o clk-div6.o + obj-$(CONFIG_ARCH_R8A7794) += clk-rcar-gen2.o clk-div6.o + obj-$(CONFIG_ARCH_R8A7795) += r8a7795-cpg-mssr.o rcar-gen3-cpg.o + obj-$(CONFIG_ARCH_R8A7796) += r8a7796-cpg-mssr.o rcar-gen3-cpg.o ++obj-$(CONFIG_ARCH_R8A7797) += r8a7797-cpg-mssr.o rcar-gen3-cpg.o + obj-$(CONFIG_ARCH_SH73A0) += clk-sh73a0.o clk-div6.o + + obj-$(CONFIG_CLK_RENESAS_CPG_MSSR) += renesas-cpg-mssr.o clk-div6.o +diff --git a/drivers/clk/renesas/r8a7797-cpg-mssr.c b/drivers/clk/renesas/r8a7797-cpg-mssr.c +new file mode 100644 +index 0000000..e758685 +--- /dev/null ++++ b/drivers/clk/renesas/r8a7797-cpg-mssr.c +@@ -0,0 +1,217 @@ ++/* ++ * r8a7797 Clock Pulse Generator / Module Standby and Software Reset ++ * ++ * Copyright (C) 2016 Glider bvba ++ * ++ * Based on r8a7795-cpg-mssr.c ++ * ++ * Copyright (C) 2016 Renesas Electronics Corp. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; version 2 of the License. ++ */ ++ ++#include <linux/device.h> ++#include <linux/init.h> ++#include <linux/kernel.h> ++#include <linux/soc/renesas/rcar-rst.h> ++#include <linux/sys_soc.h> ++ ++#include <dt-bindings/clock/r8a7797-cpg-mssr.h> ++ ++#include "renesas-cpg-mssr.h" ++#include "rcar-gen3-cpg.h" ++ ++enum clk_ids { ++ /* Core Clock Outputs exported to DT */ ++ LAST_DT_CORE_CLK = R8A7797_CLK_OSC, ++ ++ /* External Input Clocks */ ++ CLK_EXTAL, ++ CLK_EXTALR, ++ ++ /* Internal Core Clocks */ ++ CLK_MAIN, ++ CLK_PLL0, ++ CLK_PLL1, ++ CLK_PLL3, ++ CLK_PLL1_DIV2, ++ CLK_PLL1_DIV4, ++ CLK_S1, ++ CLK_S2, ++ CLK_RINT, ++ ++ /* Module Clocks */ ++ MOD_CLK_BASE ++}; ++ ++static const struct cpg_core_clk r8a7797_core_clks[] __initconst = { ++ /* External Clock Inputs */ ++ DEF_INPUT("extal", CLK_EXTAL), ++ DEF_INPUT("extalr", CLK_EXTALR), ++ ++ /* Internal Core Clocks */ ++ DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL), ++ DEF_BASE(".pll0", CLK_PLL0, CLK_TYPE_GEN3_PLL0, CLK_MAIN), ++ DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN3_PLL1, CLK_MAIN), ++ DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN3_PLL3, CLK_MAIN), ++ ++ DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1), ++ DEF_FIXED(".pll1_div4", CLK_PLL1_DIV4, CLK_PLL1_DIV2, 2, 1), ++ DEF_FIXED(".s1", CLK_S1, CLK_PLL1_DIV2, 4, 1), ++ DEF_FIXED(".s2", CLK_S2, CLK_PLL1_DIV2, 6, 1), ++ ++ /* Core Clock Outputs */ ++ DEF_BASE("z2", R8A7797_CLK_Z2, CLK_TYPE_GEN3_Z2, CLK_PLL0), ++ DEF_FIXED("ztr", R8A7797_CLK_ZTR, CLK_PLL1_DIV2, 6, 1), ++ DEF_FIXED("ztrd2", R8A7797_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1), ++ DEF_FIXED("zt", R8A7797_CLK_ZT, CLK_PLL1_DIV2, 4, 1), ++ DEF_FIXED("zx", R8A7797_CLK_ZX, CLK_PLL1_DIV2, 3, 1), ++ DEF_FIXED("s1d1", R8A7797_CLK_S1D1, CLK_S1, 1, 1), ++ DEF_FIXED("s1d2", R8A7797_CLK_S1D2, CLK_S1, 2, 1), ++ DEF_FIXED("s1d4", R8A7797_CLK_S1D4, CLK_S1, 4, 1), ++ DEF_FIXED("s2d1", R8A7797_CLK_S2D1, CLK_S2, 1, 1), ++ DEF_FIXED("s2d2", R8A7797_CLK_S2D2, CLK_S2, 2, 1), ++ DEF_FIXED("s2d4", R8A7797_CLK_S2D4, CLK_S2, 4, 1), ++ ++ DEF_GEN3_SD("sd0", R8A7797_CLK_SD0, CLK_PLL1_DIV4, 0x0074), /* FIXME */ ++ ++ DEF_FIXED("cl", R8A7797_CLK_CL, CLK_PLL1_DIV2, 48, 1), ++ DEF_FIXED("cp", R8A7797_CLK_CP, CLK_EXTAL, 2, 1), ++ ++ DEF_FIXED("mso", R8A7797_CLK_MSO, CLK_PLL1_DIV4, 6, 1), ++ DEF_FIXED("canfd", R8A7797_CLK_CANFD, CLK_PLL1_DIV4, 20, 1), ++ DEF_DIV6P1("csi0", R8A7797_CLK_CSI0, CLK_PLL1_DIV4, 0x00c), ++ ++ DEF_FIXED("osc", R8A7797_CLK_OSC, CLK_PLL1_DIV2, (12*1024), 1), ++ DEF_DIV6_RO("r_int", CLK_RINT, CLK_EXTAL, CPG_RCKCR, 32), ++ ++ DEF_BASE("r", R8A7797_CLK_R, CLK_TYPE_GEN3_R, CLK_RINT), ++}; ++ ++static const struct mssr_mod_clk r8a7797_mod_clks[] __initconst = { ++ DEF_MOD("ivcp1e", 127, R8A7797_CLK_S2D1), ++ DEF_MOD("scif4", 203, R8A7797_CLK_S2D4), /* @@ H3=S3D4 */ ++ DEF_MOD("scif3", 204, R8A7797_CLK_S2D4), /* @@ H3=S3D4 */ ++ DEF_MOD("scif1", 206, R8A7797_CLK_S2D4), /* @@ H3=S3D4 */ ++ DEF_MOD("scif0", 207, R8A7797_CLK_S2D4), /* @@ H3=S3D4 */ ++ DEF_MOD("msiof3", 208, R8A7797_CLK_MSO), ++ DEF_MOD("msiof2", 209, R8A7797_CLK_MSO), ++ DEF_MOD("msiof1", 210, R8A7797_CLK_MSO), ++ DEF_MOD("msiof0", 211, R8A7797_CLK_MSO), ++ DEF_MOD("mfis", 213, R8A7797_CLK_S2D2), /* @@ H3=S3D2 */ ++ DEF_MOD("sys-dmac2", 217, R8A7797_CLK_S2D1), /* @@ H3=S3D1 */ ++ DEF_MOD("sys-dmac1", 218, R8A7797_CLK_S2D1), /* @@ H3=S3D1 */ ++ DEF_MOD("sdif", 314, R8A7797_CLK_SD0), ++ DEF_MOD("rwdt0", 402, R8A7797_CLK_R), ++ DEF_MOD("intc-ex", 407, R8A7797_CLK_CP), ++ DEF_MOD("intc-ap", 408, R8A7797_CLK_S2D1), /* @@ H3=S3D1 */ ++ DEF_MOD("hscif3", 517, R8A7797_CLK_S2D1), /* @@ H3=S3D1 */ ++ DEF_MOD("hscif2", 518, R8A7797_CLK_S2D1), /* @@ H3=S3D1 */ ++ DEF_MOD("hscif1", 519, R8A7797_CLK_S2D1), /* @@ H3=S3D1 */ ++ DEF_MOD("hscif0", 520, R8A7797_CLK_S2D1), /* @@ H3=S3D1 */ ++ DEF_MOD("thermal", 522, R8A7797_CLK_CP), ++ DEF_MOD("pwm", 523, R8A7797_CLK_S2D4), ++ DEF_MOD("fcpvd0", 603, R8A7797_CLK_S2D1), ++ DEF_MOD("vspd0", 623, R8A7797_CLK_S2D1), ++ DEF_MOD("csi40", 716, R8A7797_CLK_CSI0), ++ DEF_MOD("du0", 724, R8A7797_CLK_S2D1), ++ DEF_MOD("lvds", 727, R8A7797_CLK_S2D1), ++ DEF_MOD("vin3", 808, R8A7797_CLK_S2D1), ++ DEF_MOD("vin2", 809, R8A7797_CLK_S2D1), ++ DEF_MOD("vin1", 810, R8A7797_CLK_S2D1), ++ DEF_MOD("vin0", 811, R8A7797_CLK_S2D1), ++ DEF_MOD("etheravb", 812, R8A7797_CLK_S2D2), ++ DEF_MOD("isp", 817, R8A7797_CLK_S2D1), /* @@ Unknown Module Clock */ ++ DEF_MOD("gpio5", 907, R8A7797_CLK_CP), ++ DEF_MOD("gpio4", 908, R8A7797_CLK_CP), ++ DEF_MOD("gpio3", 909, R8A7797_CLK_CP), ++ DEF_MOD("gpio2", 910, R8A7797_CLK_CP), ++ DEF_MOD("gpio1", 911, R8A7797_CLK_CP), ++ DEF_MOD("gpio0", 912, R8A7797_CLK_CP), ++ DEF_MOD("can-fd", 914, R8A7797_CLK_S2D2), /* @@ H3=S3D2 */ ++ DEF_MOD("i2c4", 927, R8A7797_CLK_S2D2), ++ DEF_MOD("i2c3", 928, R8A7797_CLK_S2D2), ++ DEF_MOD("i2c2", 929, R8A7797_CLK_S2D2), ++ DEF_MOD("i2c1", 930, R8A7797_CLK_S2D2), ++ DEF_MOD("i2c0", 931, R8A7797_CLK_S2D2), ++}; ++ ++static const unsigned int r8a7797_crit_mod_clks[] __initconst = { ++ MOD_CLK_ID(408), /* INTC-AP (GIC) */ ++}; ++ ++ ++/* ++ * CPG Clock Data ++ */ ++ ++/* ++ * MD EXTAL PLL0 PLL1 PLL3 ++ * 14 13 19 (MHz) ++ *------------------------------------------------- ++ * 0 0 0 16.66 x 1 x192 x192 x96 ++ * 0 0 1 16.66 x 1 x192 x192 x80 ++ * 0 1 0 20 x 1 x160 x160 x80 ++ * 0 1 1 20 x 1 x160 x160 x66 ++ * 1 0 0 27 / 2 x236 x236 x118 ++ * 1 0 1 27 / 2 x236 x236 x98 ++ * 1 1 0 33.33 / 2 x192 x192 x96 ++ * 1 1 1 33.33 / 2 x192 x192 x80 ++ */ ++#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 12) | \ ++ (((md) & BIT(13)) >> 12) | \ ++ (((md) & BIT(19)) >> 19)) ++ ++static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[8] __initconst = { ++ /* EXTAL div PLL1 mult PLL3 mult */ ++ { 1, 192, 96, }, ++ { 1, 192, 80, }, ++ { 1, 160, 80, }, ++ { 1, 160, 66, }, ++ { 2, 236, 118, }, ++ { 2, 236, 98, }, ++ { 2, 192, 96, }, ++ { 2, 192, 80, }, ++}; ++ ++static int __init r8a7797_cpg_mssr_init(struct device *dev) ++{ ++ const struct rcar_gen3_cpg_pll_config *cpg_pll_config; ++ u32 cpg_mode; ++ int error; ++ ++ error = rcar_rst_read_mode_pins(&cpg_mode); ++ if (error) ++ return error; ++ ++ cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)]; ++ if (!cpg_pll_config->extal_div) { ++ dev_err(dev, "Prohibited setting (cpg_mode=0x%x)\n", cpg_mode); ++ return -EINVAL; ++ } ++ ++ return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode); ++} ++ ++const struct cpg_mssr_info r8a7797_cpg_mssr_info __initconst = { ++ /* Core Clocks */ ++ .core_clks = r8a7797_core_clks, ++ .num_core_clks = ARRAY_SIZE(r8a7797_core_clks), ++ .last_dt_core_clk = LAST_DT_CORE_CLK, ++ .num_total_core_clks = MOD_CLK_BASE, ++ ++ /* Module Clocks */ ++ .mod_clks = r8a7797_mod_clks, ++ .num_mod_clks = ARRAY_SIZE(r8a7797_mod_clks), ++ .num_hw_mod_clks = 12 * 32, ++ ++ /* Critical Module Clocks */ ++ .crit_mod_clks = r8a7797_crit_mod_clks, ++ .num_crit_mod_clks = ARRAY_SIZE(r8a7797_crit_mod_clks), ++ ++ /* Callbacks */ ++ .init = r8a7797_cpg_mssr_init, ++ .cpg_clk_register = rcar_gen3_cpg_clk_register, ++}; +diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c +index 494e4e8..e523ab7 100644 +--- a/drivers/clk/renesas/renesas-cpg-mssr.c ++++ b/drivers/clk/renesas/renesas-cpg-mssr.c +@@ -588,6 +588,12 @@ static int __init cpg_mssr_add_clk_domain(struct device *dev, + .data = &r8a7796_cpg_mssr_info, + }, + #endif ++#ifdef CONFIG_ARCH_R8A7797 ++ { ++ .compatible = "renesas,r8a7797-cpg-mssr", ++ .data = &r8a7797_cpg_mssr_info, ++ }, ++#endif + { /* sentinel */ } + }; + +diff --git a/drivers/clk/renesas/renesas-cpg-mssr.h b/drivers/clk/renesas/renesas-cpg-mssr.h +index 148f4f0a..77c27d8 100644 +--- a/drivers/clk/renesas/renesas-cpg-mssr.h ++++ b/drivers/clk/renesas/renesas-cpg-mssr.h +@@ -134,6 +134,7 @@ struct cpg_mssr_info { + extern const struct cpg_mssr_info r8a7745_cpg_mssr_info; + extern const struct cpg_mssr_info r8a7795_cpg_mssr_info; + extern const struct cpg_mssr_info r8a7796_cpg_mssr_info; ++extern const struct cpg_mssr_info r8a7797_cpg_mssr_info; + + + /* +diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c +index f721a89..118e579 100644 +--- a/drivers/gpio/gpio-rcar.c ++++ b/drivers/gpio/gpio-rcar.c +@@ -1,7 +1,7 @@ + /* + * Renesas R-Car GPIO Support + * +- * Copyright (C) 2014 Renesas Electronics Corporation ++ * Copyright (C) 2014-2016 Renesas Electronics Corporation + * Copyright (C) 2013 Magnus Damm + * + * This program is free software; you can redistribute it and/or modify +@@ -579,6 +579,10 @@ struct gpio_rcar_info { + /* Gen3 GPIO is identical to Gen2. */ + .data = &gpio_rcar_info_gen2, + }, { ++ .compatible = "renesas,gpio-r8a7797", ++ /* Gen3 GPIO is identical to Gen2. */ ++ .data = &gpio_rcar_info_gen2, ++ }, { + .compatible = "renesas,gpio-rcar", + .data = &gpio_rcar_info_gen1, + }, { +diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c +index 6295c73..0f9fe44 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c ++++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c +@@ -289,6 +289,30 @@ + {/*sentinel*/} + }; + ++static const struct rcar_du_device_info rcar_du_r8a7797_info = { ++ .gen = 3, ++ .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK ++ | RCAR_DU_FEATURE_EXT_CTRL_REGS ++ | RCAR_DU_FEATURE_VSP1_SOURCE ++ | RCAR_DU_FEATURE_GEN3_REGS, ++ .num_crtcs = 1, ++ .routes = { ++ /* R8A7797 has one RGB output, one LVDS output. */ ++ [RCAR_DU_OUTPUT_DPAD0] = { ++ .possible_crtcs = BIT(0), ++ .encoder_type = DRM_MODE_ENCODER_NONE, ++ .port = 1, ++ }, ++ [RCAR_DU_OUTPUT_LVDS0] = { ++ .possible_crtcs = BIT(0), ++ .encoder_type = DRM_MODE_ENCODER_LVDS, ++ .port = 0, ++ }, ++ }, ++ .num_lvds = 1, ++ .dpll_ch = 0, ++}; ++ + static const struct of_device_id rcar_du_of_table[] = { + { .compatible = "renesas,du-r8a7779", .data = &rcar_du_r8a7779_info }, + { .compatible = "renesas,du-r8a7790", .data = &rcar_du_r8a7790_info }, +@@ -298,6 +322,7 @@ + { .compatible = "renesas,du-r8a7794", .data = &rcar_du_r8a7794_info }, + { .compatible = "renesas,du-r8a7795", .data = &rcar_du_r8a7795_info }, + { .compatible = "renesas,du-r8a7796", .data = &rcar_du_r8a7796_info }, ++ { .compatible = "renesas,du-r8a7797", .data = &rcar_du_r8a7797_info }, + { } + }; + +diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c +index c15611c..95023bd 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_group.c ++++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c +@@ -29,11 +29,17 @@ + + #include <linux/clk.h> + #include <linux/io.h> ++#include <linux/sys_soc.h> + + #include "rcar_du_drv.h" + #include "rcar_du_group.h" + #include "rcar_du_regs.h" + ++static const struct soc_device_attribute r8a7797[] = { ++ { .soc_id = "r8a7797" }, ++ { } ++}; ++ + u32 rcar_du_group_read(struct rcar_du_group *rgrp, u32 reg) + { + return rcar_du_read(rgrp->dev, rgrp->mmio_offset + reg); +@@ -147,8 +153,10 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp) + + /* Apply planes to CRTCs association. */ + mutex_lock(&rgrp->lock); +- rcar_du_group_write(rgrp, DPTSR, (rgrp->dptsr_planes << 16) | +- rgrp->dptsr_planes); ++ if (!soc_device_match(r8a7797)) ++ rcar_du_group_write(rgrp, DPTSR, (rgrp->dptsr_planes << 16) | ++ rgrp->dptsr_planes); ++ + mutex_unlock(&rgrp->lock); + } + +diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c +index ecae864..42eb45c 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c ++++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c +@@ -17,12 +17,18 @@ + #include <linux/of_gpio.h> + #include <linux/platform_device.h> + #include <linux/slab.h> ++#include <linux/sys_soc.h> + + #include "rcar_du_drv.h" + #include "rcar_du_encoder.h" + #include "rcar_du_lvdsenc.h" + #include "rcar_lvds_regs.h" + ++static const struct soc_device_attribute r8a7797[] = { ++ { .soc_id = "r8a7797" }, ++ { } ++}; ++ + struct rcar_du_lvdsenc { + struct rcar_du_device *dev; + +@@ -96,14 +102,25 @@ static void rcar_du_lvdsenc_start_gen3(struct rcar_du_lvdsenc *lvds, + u32 pllcr; + + /* PLL clock configuration */ +- if (freq < 42000) +- pllcr = LVDPLLCR_PLLDIVCNT_42M; +- else if (freq < 85000) +- pllcr = LVDPLLCR_PLLDIVCNT_85M; +- else if (freq < 128000) +- pllcr = LVDPLLCR_PLLDIVCNT_128M; +- else +- pllcr = LVDPLLCR_PLLDIVCNT_148M; ++ if (soc_device_match(r8a7797)) { ++ if (freq < 39000) ++ pllcr = LVDPLLCR_PLLDLYCNT_38M; ++ else if (freq < 61000) ++ pllcr = LVDPLLCR_PLLDLYCNT_60M; ++ else if (freq < 121000) ++ pllcr = LVDPLLCR_PLLDLYCNT_121M; ++ else ++ pllcr = LVDPLLCR_PLLDLYCNT_150M; ++ } else { ++ if (freq < 42000) ++ pllcr = LVDPLLCR_PLLDIVCNT_42M; ++ else if (freq < 85000) ++ pllcr = LVDPLLCR_PLLDIVCNT_85M; ++ else if (freq < 128000) ++ pllcr = LVDPLLCR_PLLDIVCNT_128M; ++ else ++ pllcr = LVDPLLCR_PLLDIVCNT_148M; ++ } + + rcar_lvds_write(lvds, LVDPLLCR, pllcr); + +@@ -123,6 +140,11 @@ static void rcar_du_lvdsenc_start_gen3(struct rcar_du_lvdsenc *lvds, + lvdcr0 |= LVDCR0_PWD; + rcar_lvds_write(lvds, LVDCR0, lvdcr0); + ++ if (soc_device_match(r8a7797)) { ++ lvdcr0 |= LVDCR0_LVEN; ++ rcar_lvds_write(lvds, LVDCR0, lvdcr0); ++ } ++ + usleep_range(100, 150); + + lvdcr0 |= LVDCR0_LVRES; +diff --git a/drivers/hwspinlock/rcar_hwspinlock.c b/drivers/hwspinlock/rcar_hwspinlock.c +index b92db1b..a656c0a 100644 +--- a/drivers/hwspinlock/rcar_hwspinlock.c ++++ b/drivers/hwspinlock/rcar_hwspinlock.c +@@ -21,10 +21,16 @@ + #include <linux/of_address.h> + #include <linux/platform_device.h> + #include <linux/io.h> ++#include <linux/sys_soc.h> + + #include "hwspinlock_internal.h" + +-#define RCAR_HWSPINLOCK_NUM (8) ++static const struct soc_device_attribute r8a7797[] = { ++ { .soc_id = "r8a7797" }, ++ { } ++}; ++ ++#define RCAR_HWSPINLOCK_NUM (soc_device_match(r8a7797) ? 64 : 8) + + static int rcar_hwspinlock_trylock(struct hwspinlock *lock) + { +diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c +index 73ff520..306ba97 100644 +--- a/drivers/i2c/busses/i2c-rcar.c ++++ b/drivers/i2c/busses/i2c-rcar.c +@@ -807,6 +807,7 @@ static u32 rcar_i2c_func(struct i2c_adapter *adap) + { .compatible = "renesas,i2c-r8a7794", .data = (void *)I2C_RCAR_GEN2 }, + { .compatible = "renesas,i2c-r8a7795", .data = (void *)I2C_RCAR_GEN3 }, + { .compatible = "renesas,i2c-r8a7796", .data = (void *)I2C_RCAR_GEN3 }, ++ { .compatible = "renesas,i2c-r8a7797", .data = (void *)I2C_RCAR_GEN3 }, + {}, + }; + MODULE_DEVICE_TABLE(of, rcar_i2c_dt_ids); +diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c +index 2b380ff..b9ef21a 100644 +--- a/drivers/iommu/ipmmu-vmsa.c ++++ b/drivers/iommu/ipmmu-vmsa.c +@@ -1,7 +1,7 @@ + /* + * IPMMU VMSA + * +- * Copyright (C) 2014 Renesas Electronics Corporation ++ * Copyright (C) 2014-2016 Renesas Electronics Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by +@@ -1274,6 +1274,9 @@ static void ipmmu_device_reset(struct ipmmu_vmsa_device *mmu) + .compatible = "renesas,ipmmu-r8a7796", + .data = &ipmmu_features_rcar_gen3, + }, { ++ .compatible = "renesas,ipmmu-r8a7797", ++ .data = &ipmmu_features_rcar_gen3, ++ }, { + /* Terminator */ + }, + }; +@@ -1640,6 +1643,8 @@ static int __init ipmmu_vmsa_iommu_of_setup(struct device_node *np) + ipmmu_vmsa_iommu_of_setup); + IOMMU_OF_DECLARE(ipmmu_r8a7796_iommu_of, "renesas,ipmmu-r8a7796", + ipmmu_vmsa_iommu_of_setup); ++IOMMU_OF_DECLARE(ipmmu_r8a7797_iommu_of, "renesas,ipmmu-r8a7797", ++ ipmmu_vmsa_iommu_of_setup); + #endif + + MODULE_DESCRIPTION("IOMMU API for Renesas VMSA-compatible IPMMU"); +diff --git a/drivers/media/platform/soc_camera/Kconfig b/drivers/media/platform/soc_camera/Kconfig +index 17178ad..5539c5d 100644 +--- a/drivers/media/platform/soc_camera/Kconfig ++++ b/drivers/media/platform/soc_camera/Kconfig +@@ -39,7 +39,7 @@ config VIDEO_RCAR_VIN_LEGACY_DEBUG + config VIDEO_RCAR_CSI2_LEGACY + tristate "R-Car MIPI CSI-2 Interface driver" + depends on VIDEO_DEV && SOC_CAMERA && HAVE_CLK +- depends on ARCH_R8A7795 || ARCH_R8A7796 || COMPILE_TEST ++ depends on ARCH_R8A7795 || ARCH_R8A7796 || ARCH_R8A7797 || COMPILE_TEST + ---help--- + This is a v4l2 driver for the R-Car CSI-2 Interface + +diff --git a/drivers/media/platform/soc_camera/rcar_csi2.c b/drivers/media/platform/soc_camera/rcar_csi2.c +index 851a4ca..1b8a6c6 100644 +--- a/drivers/media/platform/soc_camera/rcar_csi2.c ++++ b/drivers/media/platform/soc_camera/rcar_csi2.c +@@ -25,6 +25,7 @@ + #include <linux/slab.h> + #include <linux/videodev2.h> + #include <linux/module.h> ++#include <linux/sys_soc.h> + + #include <media/rcar_csi2.h> + #include <media/soc_camera.h> +@@ -153,6 +154,11 @@ + #define RCAR_CSI2_INTSTATE_ERRSYNCESC (1 << 1) + #define RCAR_CSI2_INTSTATE_ERRCONTROL (1 << 0) + ++static const struct soc_device_attribute r8a7797[] = { ++ { .soc_id = "r8a7797" }, ++ { } ++}; ++ + enum chip_id { + RCAR_GEN3, + RCAR_GEN2, +@@ -248,6 +254,17 @@ struct rcar_csi2 { + + static int rcar_csi2_set_phy_freq(struct rcar_csi2 *priv) + { ++ const uint32_t const hs_freq_range_v3m[43] = { ++ 0x00, 0x00, 0x20, 0x40, 0x02, /* 80M, 90M, 100M, 110M, 120M */ ++ 0x02, 0x22, 0x42, 0x04, 0x04, /* 130M, 140M, 150M, 160M, 170M */ ++ 0x24, 0x44, 0x44, 0x06, 0x26, /* 180M, 190M, 205M, 220M, 235M */ ++ 0x46, 0x08, 0x28, 0x0a, 0x2a, /* 250M, 270M, 300M, 325M, 350M */ ++ 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, /* 400M, 450M, 500M, 550M, 600M */ ++ 0x10, 0x30, 0x12, 0x32, 0x52, /* 650M, 700M, 750M, 800M, 950M */ ++ 0x72, 0x14, 0x34, 0x52, 0x74, /* 900M, 950M, 1000M, 1050M, 1100M */ ++ 0x16, 0x36, 0x56, 0x76, 0x18, /* 1150M, 1200M, 1250M, 1300M, 1350M */ ++ 0x38, 0x58, 0x38 /* 1400M, 1450M, 1500M */ ++ }; + const uint32_t const hs_freq_range[43] = { + 0x00, 0x10, 0x20, 0x30, 0x01, /* 0-4 */ + 0x11, 0x21, 0x31, 0x02, 0x12, /* 5-9 */ +@@ -304,7 +321,12 @@ static int rcar_csi2_set_phy_freq(struct rcar_csi2 *priv) + + dev_dbg(&priv->pdev->dev, "bps_per_lane (%d)\n", bps_per_lane); + +- iowrite32((hs_freq_range[bps_per_lane] << 16), ++ if (soc_device_match(r8a7797)) ++ iowrite32((hs_freq_range_v3m[bps_per_lane] << 16) | ++ RCAR_CSI2_PHTW_DWEN | RCAR_CSI2_PHTW_CWEN | 0x44, ++ priv->base + RCAR_CSI2_PHTW); ++ else ++ iowrite32(hs_freq_range[bps_per_lane] << 16, + priv->base + RCAR_CSI2_PHYPLL); + return 0; + +@@ -488,6 +509,7 @@ static int rcar_csi2_s_power(struct v4l2_subdev *sd, int on) + + #ifdef CONFIG_OF + static const struct of_device_id rcar_csi2_of_table[] = { ++ { .compatible = "renesas,r8a7797-csi2", .data = (void *)RCAR_GEN3 }, + { .compatible = "renesas,r8a7796-csi2", .data = (void *)RCAR_GEN3 }, + { .compatible = "renesas,r8a7795-csi2", .data = (void *)RCAR_GEN3 }, + { }, +@@ -496,6 +518,7 @@ static int rcar_csi2_s_power(struct v4l2_subdev *sd, int on) + #endif + + static struct platform_device_id rcar_csi2_id_table[] = { ++ { "r8a7797-csi2", RCAR_GEN3 }, + { "r8a7796-csi2", RCAR_GEN3 }, + { "r8a7795-csi2", RCAR_GEN3 }, + {}, +diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c +index 400958b..74fb005 100644 +--- a/drivers/media/platform/soc_camera/rcar_vin.c ++++ b/drivers/media/platform/soc_camera/rcar_vin.c +@@ -154,7 +154,7 @@ + #define VNCSI_IFMD_REG 0x20 /* Video n CSI2 Interface Mode Register */ + + #define VNCSI_IFMD_DES1 (1 << 26) /* CSI20 */ +-#define VNCSI_IFMD_DES0 (1 << 25) /* H3:CSI40/41, M3:CSI40 */ ++#define VNCSI_IFMD_DES0 (1 << 25) /* H3:CSI40/41, M3:CSI40, V3M:CSI40 */ + + #define VNCSI_IFMD_CSI_CHSEL(n) (n << 0) + #define VNCSI_IFMD_SEL_NUMBER 5 +@@ -185,6 +185,7 @@ + + enum chip_id { + RCAR_GEN3, ++ RCAR_V3M, + RCAR_M3, + RCAR_H3, + RCAR_GEN2, +@@ -360,6 +361,49 @@ struct vin_gen3_ifmd { + }, + }; + ++static const struct vin_gen3_ifmd vin_v3_vc_ifmd[] = { ++ { 0x0000, ++ { ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ } ++ }, ++ { 0x0001, ++ { ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ } ++ }, ++ { 0x0002, ++ { ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ } ++ }, ++ { 0x0003, ++ { ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH2}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH3}, ++ } ++ }, ++ { 0x0004, ++ { ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ } ++ }, ++}; ++ + enum csi2_fmt { + RCAR_CSI_FMT_NONE = -1, + RCAR_CSI_RGB888, +@@ -849,7 +893,8 @@ static int rcar_vin_videobuf_setup(struct vb2_queue *vq, + struct rcar_vin_priv *priv = ici->priv; + struct rcar_vin_cam *cam = icd->host_priv; + +- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || ++ priv->chip == RCAR_V3M) { + if ((priv->ratio_h > 0x10000) || (priv->ratio_v > 0x10000)) { + dev_err(icd->parent, "Scaling rate parameter error\n"); + return -EINVAL; +@@ -951,7 +996,8 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) + /* output format */ + switch (icd->current_fmt->host_fmt->fourcc) { + case V4L2_PIX_FMT_NV12: +- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || ++ priv->chip == RCAR_V3M) { + iowrite32(ALIGN((cam->out_width * cam->out_height), + 0x80), priv->base + VNUVAOF_REG); + dmr = VNDMR_DTMD_YCSEP_YCBCR420; +@@ -983,6 +1029,7 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) + break; + case V4L2_PIX_FMT_XBGR32: + if (priv->chip != RCAR_H3 && priv->chip != RCAR_M3 && ++ priv->chip != RCAR_V3M && + priv->chip != RCAR_GEN2 && priv->chip != RCAR_H1 && + priv->chip != RCAR_E1) + goto e_format; +@@ -990,7 +1037,8 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) + dmr = VNDMR_EXRGB; + break; + case V4L2_PIX_FMT_ABGR32: +- if (priv->chip != RCAR_H3 && priv->chip != RCAR_M3) ++ if (priv->chip != RCAR_H3 && priv->chip != RCAR_M3 && ++ priv->chip != RCAR_V3M) + goto e_format; + + dmr = VNDMR_EXRGB | VNDMR_DTMD_ARGB; +@@ -1006,7 +1054,8 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) + if (input_is_yuv == output_is_yuv) + vnmc |= VNMC_BPS; + +- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || ++ priv->chip == RCAR_V3M) { + if (priv->pdata_flags & RCAR_VIN_CSI2) + vnmc &= ~VNMC_DPINE; + else +@@ -1323,7 +1372,8 @@ static int rcar_vin_add_device(struct soc_camera_device *icd) + + pm_runtime_get_sync(ici->v4l2_dev.dev); + +- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || ++ priv->chip == RCAR_V3M) { + struct v4l2_subdev *csi2_sd = find_csi2(priv); + int ret; + +@@ -1569,7 +1619,8 @@ static int rcar_vin_set_rect(struct soc_camera_device *icd) + break; + } + +- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || ++ priv->chip == RCAR_V3M) { + if ((icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_NV12) + && is_scaling(cam)) { + ret = rcar_vin_uds_set(priv, cam); +@@ -1720,14 +1771,16 @@ static int rcar_vin_set_bus_param(struct soc_camera_device *icd) + if (ret < 0 && ret != -ENOIOCTLCMD) + return ret; + +- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || ++ priv->chip == RCAR_V3M) { + if (cfg.type == V4L2_MBUS_CSI2) + vnmc &= ~VNMC_DPINE; + else + vnmc |= VNMC_DPINE; + } + +- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || ++ priv->chip == RCAR_V3M) + val = VNDMR2_FTEV; + else + val = VNDMR2_FTEV | VNDMR2_VLV(1); +@@ -2289,7 +2342,8 @@ static int rcar_vin_try_fmt(struct soc_camera_device *icd, + if (ret < 0) + return ret; + +- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || ++ priv->chip == RCAR_V3M) { + /* Adjust max scaling size for Gen3 */ + if (pix->width > 4096) + pix->width = priv->max_width; +@@ -2454,6 +2508,7 @@ static int rcar_vin_cropcap(struct soc_camera_device *icd, + + #ifdef CONFIG_OF + static const struct of_device_id rcar_vin_of_table[] = { ++ { .compatible = "renesas,vin-r8a7797", .data = (void *)RCAR_V3M }, + { .compatible = "renesas,vin-r8a7796", .data = (void *)RCAR_M3 }, + { .compatible = "renesas,vin-r8a7795", .data = (void *)RCAR_H3 }, + { .compatible = "renesas,vin-r8a7794", .data = (void *)RCAR_GEN2 }, +@@ -2754,7 +2809,8 @@ static int rcar_vin_probe(struct platform_device *pdev) + priv->chip = (enum chip_id)match->data; + } + +- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || ++ priv->chip == RCAR_V3M) { + priv->max_width = 4096; + priv->max_height = 4096; + } else { +@@ -2762,7 +2818,8 @@ static int rcar_vin_probe(struct platform_device *pdev) + priv->max_height = 2048; + } + +- if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3) { ++ if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || ++ priv->chip == RCAR_V3M) { + u32 ifmd = 0; + bool match_flag = false; + const struct vin_gen3_ifmd *gen3_ifmd_table = NULL; +@@ -2841,6 +2898,8 @@ static int rcar_vin_probe(struct platform_device *pdev) + gen3_ifmd_table = vin_h3_vc_ifmd; + else if (priv->chip == RCAR_M3) + gen3_ifmd_table = vin_m3_vc_ifmd; ++ else if (priv->chip == RCAR_V3M) ++ gen3_ifmd_table = vin_v3_vc_ifmd; + + for (i = 0; i < num; i++) { + if ((gen3_ifmd_table[i].v_sel[priv->index].csi2_ch +@@ -2983,6 +3042,9 @@ static int rcar_vin_resume(struct device *dev) + } else if (priv->chip == RCAR_M3) { + ifmd = VNCSI_IFMD_DES1; + gen3_ifmd_table = vin_m3_vc_ifmd; ++ } else if (priv->chip == RCAR_V3M) { ++ ifmd = VNCSI_IFMD_DES1; ++ gen3_ifmd_table = vin_v3_vc_ifmd; + } + + for (i = 0; i < num; i++) { +diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c +index 45bd0f3..50eea8a 100644 +--- a/drivers/media/platform/vsp1/vsp1_drv.c ++++ b/drivers/media/platform/vsp1/vsp1_drv.c +@@ -888,6 +888,14 @@ void vsp1_device_put(struct vsp1_device *vsp1) + .wpf_count = 2, + .num_bru_inputs = 5, + .header_mode = true, ++ }, { ++ .version = VI6_IP_VERSION_MODEL_VSPD_V3M, ++ .gen = 3, ++ .features = VSP1_HAS_BRU | VSP1_HAS_LIF, ++ .rpf_count = 5, ++ .wpf_count = 1, ++ .num_bru_inputs = 5, ++ .header_mode = true, + }, + }; + +diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c +index b442d14..536ee4a 100644 +--- a/drivers/media/platform/vsp1/vsp1_lif.c ++++ b/drivers/media/platform/vsp1/vsp1_lif.c +@@ -13,6 +13,7 @@ + + #include <linux/device.h> + #include <linux/gfp.h> ++#include <linux/sys_soc.h> + + #include <media/v4l2-subdev.h> + +@@ -23,6 +24,11 @@ + #define LIF_MIN_SIZE 2U + #define LIF_MAX_SIZE 8190U + ++static const struct soc_device_attribute r8a7797[] = { ++ { .soc_id = "r8a7797" }, ++ { } ++}; ++ + /* ----------------------------------------------------------------------------- + * Device Access + */ +@@ -142,6 +148,9 @@ static void lif_configure(struct vsp1_entity *entity, + if (params != VSP1_ENTITY_PARAMS_INIT) + return; + ++ if (soc_device_match(r8a7797)) ++ obth = 1500; ++ + format = vsp1_entity_get_pad_format(&lif->entity, lif->entity.config, + LIF_PAD_SOURCE); + +@@ -158,6 +167,10 @@ static void lif_configure(struct vsp1_entity *entity, + (obth << VI6_LIF_CTRL_OBTH_SHIFT) | + (format->code == 0 ? VI6_LIF_CTRL_CFMT : 0) | + VI6_LIF_CTRL_REQSEL | VI6_LIF_CTRL_LIF_EN); ++ ++ if (soc_device_match(r8a7797)) ++ vsp1_lif_write(lif, dl, VI6_LIF_LBA, VI6_LIF_LBA_LBA0 | ++ VI6_LIF_LBA_LBA1); + } + + static const struct vsp1_entity_operations lif_entity_ops = { +diff --git a/drivers/media/platform/vsp1/vsp1_regs.h b/drivers/media/platform/vsp1/vsp1_regs.h +index 885f60b..2d863a7 100644 +--- a/drivers/media/platform/vsp1/vsp1_regs.h ++++ b/drivers/media/platform/vsp1/vsp1_regs.h +@@ -788,6 +788,12 @@ + #define VI6_LIF_CSBTH_LBTH_MASK (0x7ff << 0) + #define VI6_LIF_CSBTH_LBTH_SHIFT 0 + ++ ++#define VI6_LIF_LBA 0x3b0c ++#define VI6_LIF_LBA_LBA0 (1 << 31) ++#define VI6_LIF_LBA_LBA1 (0x600 << 16) ++ ++ + /* ----------------------------------------------------------------------------- + * Security Control Registers + */ +@@ -811,6 +817,7 @@ + #define VI6_IP_VERSION_MODEL_VSPBD_GEN3 (0x15 << 8) + #define VI6_IP_VERSION_MODEL_VSPBC_GEN3 (0x16 << 8) + #define VI6_IP_VERSION_MODEL_VSPD_GEN3 (0x17 << 8) ++#define VI6_IP_VERSION_MODEL_VSPD_V3M (0x18 << 8) + #define VI6_IP_VERSION_MODEL_VSPDL_H3 (0x19 << 8) + #define VI6_IP_VERSION_SOC_MASK (0xff << 0) + #define VI6_IP_VERSION_SOC_H (0x01 << 0) +diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c +index 98c4e11..ee7b188 100644 +--- a/drivers/mmc/host/sh_mobile_sdhi.c ++++ b/drivers/mmc/host/sh_mobile_sdhi.c +@@ -137,6 +137,7 @@ struct sh_mobile_sdhi_of_data { + { .compatible = "renesas,sdhi-r8a7794", .data = &of_rcar_gen2_compatible, }, + { .compatible = "renesas,sdhi-r8a7795", .data = &of_rcar_gen3_compatible, }, + { .compatible = "renesas,sdhi-r8a7796", .data = &of_rcar_gen3_compatible, }, ++ { .compatible = "renesas,sdhi-r8a7797", .data = &of_rcar_gen3_compatible, }, + {}, + }; + MODULE_DEVICE_TABLE(of, sh_mobile_sdhi_of_match); +diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c +index 6c65426..97c52dd 100644 +--- a/drivers/net/ethernet/renesas/ravb_main.c ++++ b/drivers/net/ethernet/renesas/ravb_main.c +@@ -1922,6 +1922,7 @@ static int ravb_mdio_release(struct ravb_private *priv) + { .compatible = "renesas,etheravb-rcar-gen2", .data = (void *)RCAR_GEN2 }, + { .compatible = "renesas,etheravb-r8a7795", .data = (void *)RCAR_GEN3 }, + { .compatible = "renesas,etheravb-r8a7796", .data = (void *)RCAR_GEN3 }, ++ { .compatible = "renesas,etheravb-r8a7797", .data = (void *)RCAR_GEN3 }, + { .compatible = "renesas,etheravb-rcar-gen3", .data = (void *)RCAR_GEN3 }, + { } + }; +diff --git a/drivers/pinctrl/sh-pfc/Kconfig b/drivers/pinctrl/sh-pfc/Kconfig +index 07eca54..002541f 100644 +--- a/drivers/pinctrl/sh-pfc/Kconfig ++++ b/drivers/pinctrl/sh-pfc/Kconfig +@@ -79,6 +79,11 @@ config PINCTRL_PFC_R8A7796 + depends on ARCH_R8A7796 + select PINCTRL_SH_PFC + ++config PINCTRL_PFC_R8A7797 ++ def_bool y ++ depends on ARCH_R8A7797 ++ select PINCTRL_SH_PFC ++ + config PINCTRL_PFC_SH7203 + def_bool y + depends on CPU_SUBTYPE_SH7203 +diff --git a/drivers/pinctrl/sh-pfc/Makefile b/drivers/pinctrl/sh-pfc/Makefile +index 8e08684..10adc18 100644 +--- a/drivers/pinctrl/sh-pfc/Makefile ++++ b/drivers/pinctrl/sh-pfc/Makefile +@@ -13,6 +13,7 @@ obj-$(CONFIG_PINCTRL_PFC_R8A7794) += pfc-r8a7794.o + obj-$(CONFIG_PINCTRL_PFC_R8A7795) += pfc-r8a7795.o + obj-$(CONFIG_PINCTRL_PFC_R8A7795) += pfc-r8a7795-es1.o + obj-$(CONFIG_PINCTRL_PFC_R8A7796) += pfc-r8a7796.o ++obj-$(CONFIG_PINCTRL_PFC_R8A7797) += pfc-r8a7797.o + obj-$(CONFIG_PINCTRL_PFC_SH7203) += pfc-sh7203.o + obj-$(CONFIG_PINCTRL_PFC_SH7264) += pfc-sh7264.o + obj-$(CONFIG_PINCTRL_PFC_SH7269) += pfc-sh7269.o +diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c +index 6399eb1..9bb3665 100644 +--- a/drivers/pinctrl/sh-pfc/core.c ++++ b/drivers/pinctrl/sh-pfc/core.c +@@ -5,6 +5,7 @@ + * + * Copyright (C) 2008 Magnus Damm + * Copyright (C) 2009 - 2012 Paul Mundt ++ * Copyright (C) 2016 Renesas Electronics Corp. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive +@@ -622,6 +623,12 @@ static int sh_pfc_init_ranges(struct sh_pfc *pfc) + .data = &r8a7796_pinmux_info, + }, + #endif ++#ifdef CONFIG_PINCTRL_PFC_R8A7797 ++ { ++ .compatible = "renesas,pfc-r8a7797", ++ .data = &r8a7797_pinmux_info, ++ }, ++#endif + #ifdef CONFIG_PINCTRL_PFC_SH73A0 + { + .compatible = "renesas,pfc-sh73a0", +diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7797.c b/drivers/pinctrl/sh-pfc/pfc-r8a7797.c +new file mode 100644 +index 0000000..a528b44 +--- /dev/null ++++ b/drivers/pinctrl/sh-pfc/pfc-r8a7797.c +@@ -0,0 +1,2615 @@ ++/* ++ * R8A7797 processor support - PFC hardware block. ++ * ++ * Copyright (C) 2016 Renesas Electronics Corp. ++ * ++ * This file is based on the drivers/pinctrl/sh-pfc/pfc-r8a7795.c ++ * ++ * R-Car Gen3 processor support - PFC hardware block. ++ * ++ * Copyright (C) 2015 Renesas Electronics Corporation ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; version 2 of the License. ++ */ ++ ++#include <linux/io.h> ++#include <linux/kernel.h> ++ ++#include "core.h" ++#include "sh_pfc.h" ++ ++#define CPU_ALL_PORT(fn, sfx) \ ++ PORT_GP_CFG_22(0, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \ ++ PORT_GP_CFG_28(1, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \ ++ PORT_GP_CFG_17(2, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \ ++ PORT_GP_CFG_17(3, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \ ++ PORT_GP_CFG_6(4, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \ ++ PORT_GP_CFG_15(5, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH) ++/* ++ * F_() : just information ++ * FM() : macro for FN_xxx / xxx_MARK ++ */ ++ ++/* GPSR0 */ ++#define GPSR0_21 F_(DU_EXODDF_DU_ODDF_DISP_CDE, IP2_23_20) ++#define GPSR0_20 F_(DU_EXVSYNC_DU_VSYNC, IP2_19_16) ++#define GPSR0_19 F_(DU_EXHSYNC_DU_HSYNC, IP2_15_12) ++#define GPSR0_18 F_(DU_DOTCLKOUT, IP2_11_8) ++#define GPSR0_17 F_(DU_DB7, IP2_7_4) ++#define GPSR0_16 F_(DU_DB6, IP2_3_0) ++#define GPSR0_15 F_(DU_DB5, IP1_31_28) ++#define GPSR0_14 F_(DU_DB4, IP1_27_24) ++#define GPSR0_13 F_(DU_DB3, IP1_23_20) ++#define GPSR0_12 F_(DU_DB2, IP1_19_16) ++#define GPSR0_11 F_(DU_DG7, IP1_15_12) ++#define GPSR0_10 F_(DU_DG6, IP1_11_8) ++#define GPSR0_9 F_(DU_DG5, IP1_7_4) ++#define GPSR0_8 F_(DU_DG4, IP1_3_0) ++#define GPSR0_7 F_(DU_DG3, IP0_31_28) ++#define GPSR0_6 F_(DU_DG2, IP0_27_24) ++#define GPSR0_5 F_(DU_DR7, IP0_23_20) ++#define GPSR0_4 F_(DU_DR6, IP0_19_16) ++#define GPSR0_3 F_(DU_DR5, IP0_15_12) ++#define GPSR0_2 F_(DU_DR4, IP0_11_8) ++#define GPSR0_1 F_(DU_DR3, IP0_7_4) ++#define GPSR0_0 F_(DU_DR2, IP0_3_0) ++ ++/* GPSR1 */ ++#define GPSR1_27 F_(DIGRF_CLKOUT, IP8_27_24) ++#define GPSR1_26 F_(DIGRF_CLKIN, IP8_23_20) ++#define GPSR1_25 F_(CANFD_CLK_A, IP8_19_16) ++#define GPSR1_24 F_(CANFD1_RX, IP8_15_12) ++#define GPSR1_23 F_(CANFD1_TX, IP8_11_8) ++#define GPSR1_22 F_(CANFD0_RX_A, IP8_7_4) ++#define GPSR1_21 F_(CANFD0_TX_A, IP8_3_0) ++#define GPSR1_20 F_(AVB0_AVTP_CAPTURE, IP7_31_28) ++#define GPSR1_19 FM(AVB0_AVTP_MATCH) ++#define GPSR1_18 FM(AVB0_LINK) ++#define GPSR1_17 FM(AVB0_PHY_INT) ++#define GPSR1_16 FM(AVB0_MAGIC) ++#define GPSR1_15 FM(AVB0_MDC) ++#define GPSR1_14 FM(AVB0_MDIO) ++#define GPSR1_13 FM(AVB0_TXCREFCLK) ++#define GPSR1_12 FM(AVB0_TD3) ++#define GPSR1_11 FM(AVB0_TD2) ++#define GPSR1_10 FM(AVB0_TD1) ++#define GPSR1_9 FM(AVB0_TD0) ++#define GPSR1_8 FM(AVB0_TXC) ++#define GPSR1_7 FM(AVB0_TX_CTL) ++#define GPSR1_6 FM(AVB0_RD3) ++#define GPSR1_5 FM(AVB0_RD2) ++#define GPSR1_4 FM(AVB0_RD1) ++#define GPSR1_3 FM(AVB0_RD0) ++#define GPSR1_2 FM(AVB0_RXC) ++#define GPSR1_1 FM(AVB0_RX_CTL) ++#define GPSR1_0 F_(IRQ0, IP2_27_24) ++ ++/* GPSR2 */ ++#define GPSR2_16 F_(VI0_FIELD, IP4_31_28) ++#define GPSR2_15 F_(VI0_DATA11, IP4_27_24) ++#define GPSR2_14 F_(VI0_DATA10, IP4_23_20) ++#define GPSR2_13 F_(VI0_DATA9, IP4_19_16) ++#define GPSR2_12 F_(VI0_DATA8, IP4_15_12) ++#define GPSR2_11 F_(VI0_DATA7, IP4_11_8) ++#define GPSR2_10 F_(VI0_DATA6, IP4_7_4) ++#define GPSR2_9 F_(VI0_DATA5, IP4_3_0) ++#define GPSR2_8 F_(VI0_DATA4, IP3_31_28) ++#define GPSR2_7 F_(VI0_DATA3, IP3_27_24) ++#define GPSR2_6 F_(VI0_DATA2, IP3_23_20) ++#define GPSR2_5 F_(VI0_DATA1, IP3_19_16) ++#define GPSR2_4 F_(VI0_DATA0, IP3_15_12) ++#define GPSR2_3 F_(VI0_VSYNC_N, IP3_11_8) ++#define GPSR2_2 F_(VI0_HSYNC_N, IP3_7_4) ++#define GPSR2_1 F_(VI0_CLKENB, IP3_3_0) ++#define GPSR2_0 F_(VI0_CLK, IP2_31_28) ++ ++/* GPSR3 */ ++#define GPSR3_16 F_(VI1_FIELD, IP7_3_0) ++#define GPSR3_15 F_(VI1_DATA11, IP6_31_28) ++#define GPSR3_14 F_(VI1_DATA10, IP6_27_24) ++#define GPSR3_13 F_(VI1_DATA9, IP6_23_20) ++#define GPSR3_12 F_(VI1_DATA8, IP6_19_16) ++#define GPSR3_11 F_(VI1_DATA7, IP6_15_12) ++#define GPSR3_10 F_(VI1_DATA6, IP6_11_8) ++#define GPSR3_9 F_(VI1_DATA5, IP6_7_4) ++#define GPSR3_8 F_(VI1_DATA4, IP6_3_0) ++#define GPSR3_7 F_(VI1_DATA3, IP5_31_28) ++#define GPSR3_6 F_(VI1_DATA2, IP5_27_24) ++#define GPSR3_5 F_(VI1_DATA1, IP5_23_20) ++#define GPSR3_4 F_(VI1_DATA0, IP5_19_16) ++#define GPSR3_3 F_(VI1_VSYNC_N, IP5_15_12) ++#define GPSR3_2 F_(VI1_HSYNC_N, IP5_11_8) ++#define GPSR3_1 F_(VI1_CLKENB, IP5_7_4) ++#define GPSR3_0 F_(VI1_CLK, IP5_3_0) ++ ++/* GPSR4 */ ++#define GPSR4_5 F_(SDA2, IP7_27_24) ++#define GPSR4_4 F_(SCL2, IP7_23_20) ++#define GPSR4_3 F_(SDA1, IP7_19_16) ++#define GPSR4_2 F_(SCL1, IP7_15_12) ++#define GPSR4_1 F_(SDA0, IP7_11_8) ++#define GPSR4_0 F_(SCL0, IP7_7_4) ++ ++/* GPSR5 */ ++#define GPSR5_14 FM(RPC_INT_N) ++#define GPSR5_13 FM(RPC_WP_N) ++#define GPSR5_12 FM(RPC_RESET_N) ++#define GPSR5_11 FM(QSPI1_SSL) ++#define GPSR5_10 FM(QSPI1_IO3) ++#define GPSR5_9 FM(QSPI1_IO2) ++#define GPSR5_8 FM(QSPI1_MISO_IO1) ++#define GPSR5_7 FM(QSPI1_MOSI_IO0) ++#define GPSR5_6 FM(QSPI1_SPCLK) ++#define GPSR5_5 FM(QSPI0_SSL) ++#define GPSR5_4 FM(QSPI0_IO3) ++#define GPSR5_3 FM(QSPI0_IO2) ++#define GPSR5_2 FM(QSPI0_MISO_IO1) ++#define GPSR5_1 FM(QSPI0_MOSI_IO0) ++#define GPSR5_0 FM(QSPI0_SPCLK) ++ ++ ++/* IPSRx */ /* 0 */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 */ /* 7 */ /* 8 */ /* 9 */ /* A */ /* B */ /* C */ /* D */ /* E */ /* F */ ++#define IP0_3_0 FM(DU_DR2) FM(HSCK0) F_(0, 0) FM(A0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP0_7_4 FM(DU_DR3) FM(HRTS0_N) F_(0, 0) FM(A1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP0_11_8 FM(DU_DR4) FM(HCTS0_N) F_(0, 0) FM(A2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP0_15_12 FM(DU_DR5) FM(HTX0) F_(0, 0) FM(A3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP0_19_16 FM(DU_DR6) FM(MSIOF3_RXD) F_(0, 0) FM(A4) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP0_23_20 FM(DU_DR7) FM(MSIOF3_TXD) F_(0, 0) FM(A5) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP0_27_24 FM(DU_DG2) FM(MSIOF3_SS1) F_(0, 0) FM(A6) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP0_31_28 FM(DU_DG3) FM(MSIOF3_SS2) F_(0, 0) FM(A7) FM(PWMFSW0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP1_3_0 FM(DU_DG4) F_(0, 0) F_(0, 0) FM(A8) FM(FSO_CFE_0_N_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP1_7_4 FM(DU_DG5) F_(0, 0) F_(0, 0) FM(A9) FM(FSO_CFE_1_N_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP1_11_8 FM(DU_DG6) F_(0, 0) F_(0, 0) FM(A10) FM(FSO_TOE_N_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP1_15_12 FM(DU_DG7) F_(0, 0) F_(0, 0) FM(A11) FM(IRQ1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP1_19_16 FM(DU_DB2) F_(0, 0) F_(0, 0) FM(A12) FM(IRQ2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP1_23_20 FM(DU_DB3) F_(0, 0) F_(0, 0) FM(A13) FM(FXR_CLKOUT1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP1_27_24 FM(DU_DB4) F_(0, 0) F_(0, 0) FM(A14) FM(FXR_CLKOUT2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP1_31_28 FM(DU_DB5) F_(0, 0) F_(0, 0) FM(A15) FM(FXR_TXENA_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP2_3_0 FM(DU_DB6) F_(0, 0) F_(0, 0) FM(A16) FM(FXR_TXENB_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP2_7_4 FM(DU_DB7) F_(0, 0) F_(0, 0) FM(A17) FM(STPWT_EXTFXR) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP2_11_8 FM(DU_DOTCLKOUT) FM(SCIF_CLK_A) F_(0, 0) FM(A18) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP2_15_12 FM(DU_EXHSYNC_DU_HSYNC) FM(HRX0) F_(0, 0) FM(A19) FM(IRQ3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP2_19_16 FM(DU_EXVSYNC_DU_VSYNC) FM(MSIOF3_SCK) F_(0, 0) FM(A20) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP2_23_20 FM(DU_EXODDF_DU_ODDF_DISP_CDE) FM(MSIOF3_SYNC) F_(0, 0) FM(A21) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP2_27_24 FM(IRQ0) FM(CC5_OSCOUT) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP2_31_28 FM(VI0_CLK) FM(MSIOF2_SCK) FM(SCK3) F_(0, 0) FM(HSCK3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP3_3_0 FM(VI0_CLKENB) FM(MSIOF2_RXD) FM(RX3) FM(RD_WR_N) FM(HCTS3_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP3_7_4 FM(VI0_HSYNC_N) FM(MSIOF2_TXD) FM(TX3) F_(0, 0) FM(HRTS3_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP3_11_8 FM(VI0_VSYNC_N) FM(MSIOF2_SYNC) FM(CTS3_N) F_(0, 0) FM(HTX3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP3_15_12 FM(VI0_DATA0) FM(MSIOF2_SS1) FM(RTS3_N_TANS) F_(0, 0) FM(HRX3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP3_19_16 FM(VI0_DATA1) FM(MSIOF2_SS2) FM(SCK1) F_(0, 0) FM(SPEEDIN_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP3_23_20 FM(VI0_DATA2) FM(AVB0_AVTP_PPS) FM(SDA3_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP3_27_24 FM(VI0_DATA3) FM(HSCK1) FM(SCL3_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP3_31_28 FM(VI0_DATA4) FM(HRTS1_N) FM(RX1_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP4_3_0 FM(VI0_DATA5) FM(HCTS1_N) FM(TX1_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP4_7_4 FM(VI0_DATA6) FM(HTX1) FM(CTS1_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP4_11_8 FM(VI0_DATA7) FM(HRX1) FM(RTS1_N_TANS) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP4_15_12 FM(VI0_DATA8) FM(HSCK2) FM(PWM0_A) FM(A22) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP4_19_16 FM(VI0_DATA9) FM(HCTS2_N) FM(PWM1_A) FM(A23) FM(FSO_CFE_0_N_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP4_23_20 FM(VI0_DATA10) FM(HRTS2_N) FM(PWM2_A) FM(A24) FM(FSO_CFE_1_N_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP4_27_24 FM(VI0_DATA11) FM(HTX2) FM(PWM3_A) FM(A25) FM(FSO_TOE_N_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP4_31_28 FM(VI0_FIELD) FM(HRX2) FM(PWM4_A) FM(CS1_N_A26) FM(FSCLKST2_N_A) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP5_3_0 FM(VI1_CLK) FM(MSIOF1_RXD) F_(0, 0) FM(CS0_N) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP5_7_4 FM(VI1_CLKENB) FM(MSIOF1_TXD) F_(0, 0) FM(D0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP5_11_8 FM(VI1_HSYNC_N) FM(MSIOF1_SCK) F_(0, 0) FM(D1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP5_15_12 FM(VI1_VSYNC_N) FM(MSIOF1_SYNC) F_(0, 0) FM(D2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP5_19_16 FM(VI1_DATA0) FM(MSIOF1_SS1) F_(0, 0) FM(D3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP5_23_20 FM(VI1_DATA1) FM(MSIOF1_SS2) F_(0, 0) FM(D4) FM(MMC_CMD) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP5_27_24 FM(VI1_DATA2) FM(CANFD0_TX_B) F_(0, 0) FM(D5) FM(MMC_D0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP5_31_28 FM(VI1_DATA3) FM(CANFD0_RX_B) F_(0, 0) FM(D6) FM(MMC_D1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP6_3_0 FM(VI1_DATA4) FM(CANFD_CLK_B) F_(0, 0) FM(D7) FM(MMC_D2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP6_7_4 FM(VI1_DATA5) F_(0,0) FM(SCK4) FM(D8) FM(MMC_D3) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP6_11_8 FM(VI1_DATA6) F_(0,0) FM(RX4) FM(D9) FM(MMC_CLK) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP6_15_12 FM(VI1_DATA7) F_(0,0) FM(TX4) FM(D10) FM(MMC_D4) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP6_19_16 FM(VI1_DATA8) F_(0,0) FM(CTS4_N) FM(D11) FM(MMC_D5) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP6_23_20 FM(VI1_DATA9) F_(0,0) FM(RTS4_N_TANS) FM(D12) FM(MMC_D6) FM(SCL3_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP6_27_24 FM(VI1_DATA10) F_(0,0) F_(0, 0) FM(D13) FM(MMC_D7) FM(SDA3_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP6_31_28 FM(VI1_DATA11) FM(SCL4) FM(IRQ4) FM(D14) FM(MMC_WP) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP7_3_0 FM(VI1_FIELD) FM(SDA4) FM(IRQ5) FM(D15) FM(MMC_CD) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP7_7_4 FM(SCL0) FM(DU_DR0) FM(TPU0TO0) FM(CLKOUT) F_(0, 0) FM(MSIOF0_RXD) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP7_11_8 FM(SDA0) FM(DU_DR1) FM(TPU0TO1) FM(BS_N) FM(SCK0) FM(MSIOF0_TXD) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP7_15_12 FM(SCL1) FM(DU_DG0) FM(TPU0TO2) FM(RD_N) FM(CTS0_N) FM(MSIOF0_SCK) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP7_19_16 FM(SDA1) FM(DU_DG1) FM(TPU0TO3) FM(WE0_N) FM(RTS0_N_TANS) FM(MSIOF0_SYNC) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP7_23_20 FM(SCL2) FM(DU_DB0) FM(TCLK1_A) FM(WE1_N) FM(RX0) FM(MSIOF0_SS1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP7_27_24 FM(SDA2) FM(DU_DB1) FM(TCLK2_A) FM(EX_WAIT0) FM(TX0) FM(MSIOF0_SS2) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP7_31_28 FM(AVB0_AVTP_CAPTURE) F_(0, 0) F_(0, 0) F_(0, 0) FM(FSCLKST2_N_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP8_3_0 FM(CANFD0_TX_A) FM(FXR_TXDA) FM(PWM0_B) FM(DU_DISP) FM(FSCLKST2_N_C) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP8_7_4 FM(CANFD0_RX_A) FM(RXDA_EXTFXR) FM(PWM1_B) FM(DU_CDE) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP8_11_8 FM(CANFD1_TX) FM(FXR_TXDB) FM(PWM2_B) FM(TCLK1_B) FM(TX1_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP8_15_12 FM(CANFD1_RX) FM(RXDB_EXTFXR) FM(PWM3_B) FM(TCLK2_B) FM(RX1_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP8_19_16 FM(CANFD_CLK_A) FM(CLK_EXTFXR) FM(PWM4_B) FM(SPEEDIN_B) FM(SCIF_CLK_B) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP8_23_20 FM(DIGRF_CLKIN) FM(DIGRF_CLKEN_IN) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP8_27_24 FM(DIGRF_CLKOUT) FM(DIGRF_CLKEN_OUT) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++#define IP8_31_28 F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) ++ ++#define PINMUX_GPSR \ ++\ ++ GPSR1_27 \ ++ GPSR1_26 \ ++ GPSR1_25 \ ++ GPSR1_24 \ ++ GPSR1_23 \ ++ GPSR1_22 \ ++GPSR0_21 GPSR1_21 \ ++GPSR0_20 GPSR1_20 \ ++GPSR0_19 GPSR1_19 \ ++GPSR0_18 GPSR1_18 \ ++GPSR0_17 GPSR1_17 \ ++GPSR0_16 GPSR1_16 GPSR2_16 GPSR3_16 \ ++GPSR0_15 GPSR1_15 GPSR2_15 GPSR3_15 \ ++GPSR0_14 GPSR1_14 GPSR2_14 GPSR3_14 GPSR5_14 \ ++GPSR0_13 GPSR1_13 GPSR2_13 GPSR3_13 GPSR5_13 \ ++GPSR0_12 GPSR1_12 GPSR2_12 GPSR3_12 GPSR5_12 \ ++GPSR0_11 GPSR1_11 GPSR2_11 GPSR3_11 GPSR5_11 \ ++GPSR0_10 GPSR1_10 GPSR2_10 GPSR3_10 GPSR5_10 \ ++GPSR0_9 GPSR1_9 GPSR2_9 GPSR3_9 GPSR5_9 \ ++GPSR0_8 GPSR1_8 GPSR2_8 GPSR3_8 GPSR5_8 \ ++GPSR0_7 GPSR1_7 GPSR2_7 GPSR3_7 GPSR5_7 \ ++GPSR0_6 GPSR1_6 GPSR2_6 GPSR3_6 GPSR5_6 \ ++GPSR0_5 GPSR1_5 GPSR2_5 GPSR3_5 GPSR4_5 GPSR5_5 \ ++GPSR0_4 GPSR1_4 GPSR2_4 GPSR3_4 GPSR4_4 GPSR5_4 \ ++GPSR0_3 GPSR1_3 GPSR2_3 GPSR3_3 GPSR4_3 GPSR5_3 \ ++GPSR0_2 GPSR1_2 GPSR2_2 GPSR3_2 GPSR4_2 GPSR5_2 \ ++GPSR0_1 GPSR1_1 GPSR2_1 GPSR3_1 GPSR4_1 GPSR5_1 \ ++GPSR0_0 GPSR1_0 GPSR2_0 GPSR3_0 GPSR4_0 GPSR5_0 ++ ++#define PINMUX_IPSR \ ++\ ++FM(IP0_3_0) IP0_3_0 FM(IP1_3_0) IP1_3_0 FM(IP2_3_0) IP2_3_0 FM(IP3_3_0) IP3_3_0 \ ++FM(IP0_7_4) IP0_7_4 FM(IP1_7_4) IP1_7_4 FM(IP2_7_4) IP2_7_4 FM(IP3_7_4) IP3_7_4 \ ++FM(IP0_11_8) IP0_11_8 FM(IP1_11_8) IP1_11_8 FM(IP2_11_8) IP2_11_8 FM(IP3_11_8) IP3_11_8 \ ++FM(IP0_15_12) IP0_15_12 FM(IP1_15_12) IP1_15_12 FM(IP2_15_12) IP2_15_12 FM(IP3_15_12) IP3_15_12 \ ++FM(IP0_19_16) IP0_19_16 FM(IP1_19_16) IP1_19_16 FM(IP2_19_16) IP2_19_16 FM(IP3_19_16) IP3_19_16 \ ++FM(IP0_23_20) IP0_23_20 FM(IP1_23_20) IP1_23_20 FM(IP2_23_20) IP2_23_20 FM(IP3_23_20) IP3_23_20 \ ++FM(IP0_27_24) IP0_27_24 FM(IP1_27_24) IP1_27_24 FM(IP2_27_24) IP2_27_24 FM(IP3_27_24) IP3_27_24 \ ++FM(IP0_31_28) IP0_31_28 FM(IP1_31_28) IP1_31_28 FM(IP2_31_28) IP2_31_28 FM(IP3_31_28) IP3_31_28 \ ++\ ++FM(IP4_3_0) IP4_3_0 FM(IP5_3_0) IP5_3_0 FM(IP6_3_0) IP6_3_0 FM(IP7_3_0) IP7_3_0 \ ++FM(IP4_7_4) IP4_7_4 FM(IP5_7_4) IP5_7_4 FM(IP6_7_4) IP6_7_4 FM(IP7_7_4) IP7_7_4 \ ++FM(IP4_11_8) IP4_11_8 FM(IP5_11_8) IP5_11_8 FM(IP6_11_8) IP6_11_8 FM(IP7_11_8) IP7_11_8 \ ++FM(IP4_15_12) IP4_15_12 FM(IP5_15_12) IP5_15_12 FM(IP6_15_12) IP6_15_12 FM(IP7_15_12) IP7_15_12 \ ++FM(IP4_19_16) IP4_19_16 FM(IP5_19_16) IP5_19_16 FM(IP6_19_16) IP6_19_16 FM(IP7_19_16) IP7_19_16 \ ++FM(IP4_23_20) IP4_23_20 FM(IP5_23_20) IP5_23_20 FM(IP6_23_20) IP6_23_20 FM(IP7_23_20) IP7_23_20 \ ++FM(IP4_27_24) IP4_27_24 FM(IP5_27_24) IP5_27_24 FM(IP6_27_24) IP6_27_24 FM(IP7_27_24) IP7_27_24 \ ++FM(IP4_31_28) IP4_31_28 FM(IP5_31_28) IP5_31_28 FM(IP6_31_28) IP6_31_28 FM(IP7_31_28) IP7_31_28 \ ++\ ++FM(IP8_3_0) IP8_3_0 \ ++FM(IP8_7_4) IP8_7_4 \ ++FM(IP8_11_8) IP8_11_8 \ ++FM(IP8_15_12) IP8_15_12 \ ++FM(IP8_19_16) IP8_19_16 \ ++FM(IP8_23_20) IP8_23_20 \ ++FM(IP8_27_24) IP8_27_24 \ ++FM(IP8_31_28) IP8_31_28 ++ ++/* ++ Set Value = H'0 Set Value = H'1 ++Register Function Pin Function Pin ++------------------------------------------------------------ ++sel_hscif0 HSCIF0_A SCIF_CLK HSCIF0_B SCIF_CLK ++sel_scif1 SCIF1_A RX1 SCIF1_B TX1 ++ SCIF1_A TX1 SCIF1_B RX1 ++sel_canfd0 CANFD0_A CANFD0_TX CANFD0_B CANFD0_TX ++ CANFD0_A CANFD0_RX CANFD0_B CANFD0_RX ++ CANFD0_A CANFD_CLK CANFD0_B CANFD_CLK ++sel_pwm4 PWM4_A PWM4 PWM4_B PWM4 ++sel_pwm3 PWM3_A PWM3 PWM3_B PWM3 ++sel_pwm2 PWM2_A PWM2 PWM2_B PWM2 ++sel_pwm1 PWM1_A PWM1 PWM1_B PWM1 ++sel_pwm0 PWM0_A PWM0 PWM0_B PWM0 ++sel_rfso RFSO_A FSO_CFE_0_N RFSO_B FSO_CFE_0_N ++ RFSO_A FSO_CFE_1_N RFSO_B FSO_CFE_1_N ++ RFSO_A FSO_TOE_N RFSO_B FSO_TOE_N ++sel_rsp RSP_A SPEEDIN RSP_B SPEEDIN ++sel_tmu TMU_A TCLK1 TMU_B TCLK1 ++ TMU_A TCLK2 TMU_B TCLK2 ++*/ ++/* MOD_SEL0 */ /* 0 */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 */ /* 7 */ ++#define MOD_SEL0_10 FM(SEL_HSCIF0_0) FM(SEL_HSCIF0_1) ++#define MOD_SEL0_9 FM(SEL_SCIF1_0) FM(SEL_SCIF1_1) ++#define MOD_SEL0_8 FM(SEL_CANFD0_0) FM(SEL_CANFD0_1) ++#define MOD_SEL0_7 FM(SEL_PWM4_0) FM(SEL_PWM4_1) ++#define MOD_SEL0_6 FM(SEL_PWM3_0) FM(SEL_PWM3_1) ++#define MOD_SEL0_5 FM(SEL_PWM2_0) FM(SEL_PWM2_1) ++#define MOD_SEL0_4 FM(SEL_PWM1_0) FM(SEL_PWM1_1) ++#define MOD_SEL0_3 FM(SEL_PWM0_0) FM(SEL_PWM0_1) ++#define MOD_SEL0_2 FM(SEL_RFSO_0) FM(SEL_RFSO_1) ++#define MOD_SEL0_1 FM(SEL_RSP_0) FM(SEL_RSP_1) ++#define MOD_SEL0_0 FM(SEL_TMU_0) FM(SEL_TMU_1) ++ ++#define PINMUX_MOD_SELS \ ++\ ++MOD_SEL0_10 \ ++MOD_SEL0_9 \ ++MOD_SEL0_8 \ ++MOD_SEL0_7 \ ++MOD_SEL0_6 \ ++MOD_SEL0_5 \ ++MOD_SEL0_4 \ ++MOD_SEL0_3 \ ++MOD_SEL0_2 \ ++MOD_SEL0_1 \ ++MOD_SEL0_0 ++ ++enum { ++ PINMUX_RESERVED = 0, ++ ++ PINMUX_DATA_BEGIN, ++ GP_ALL(DATA), ++ PINMUX_DATA_END, ++ ++#define F_(x, y) ++#define FM(x) FN_##x, ++ PINMUX_FUNCTION_BEGIN, ++ GP_ALL(FN), ++ PINMUX_GPSR ++ PINMUX_IPSR ++ PINMUX_MOD_SELS ++ PINMUX_FUNCTION_END, ++#undef F_ ++#undef FM ++ ++#define F_(x, y) ++#define FM(x) x##_MARK, ++ PINMUX_MARK_BEGIN, ++ PINMUX_GPSR ++ PINMUX_IPSR ++ PINMUX_MOD_SELS ++ PINMUX_MARK_END, ++#undef F_ ++#undef FM ++}; ++ ++static const u16 pinmux_data[] = { ++ PINMUX_DATA_GP_ALL(), ++ ++ PINMUX_SINGLE(AVB0_RX_CTL), ++ PINMUX_SINGLE(AVB0_RXC), ++ PINMUX_SINGLE(AVB0_RD0), ++ PINMUX_SINGLE(AVB0_RD1), ++ PINMUX_SINGLE(AVB0_RD2), ++ PINMUX_SINGLE(AVB0_RD3), ++ PINMUX_SINGLE(AVB0_TX_CTL), ++ PINMUX_SINGLE(AVB0_TXC), ++ PINMUX_SINGLE(AVB0_TD0), ++ PINMUX_SINGLE(AVB0_TD1), ++ PINMUX_SINGLE(AVB0_TD2), ++ PINMUX_SINGLE(AVB0_TD3), ++ PINMUX_SINGLE(AVB0_TXCREFCLK), ++ PINMUX_SINGLE(AVB0_MDIO), ++ PINMUX_SINGLE(AVB0_MDC), ++ PINMUX_SINGLE(AVB0_MAGIC), ++ PINMUX_SINGLE(AVB0_PHY_INT), ++ PINMUX_SINGLE(AVB0_LINK), ++ PINMUX_SINGLE(AVB0_AVTP_MATCH), ++ ++ PINMUX_SINGLE(QSPI0_SPCLK), ++ PINMUX_SINGLE(QSPI0_MOSI_IO0), ++ PINMUX_SINGLE(QSPI0_MISO_IO1), ++ PINMUX_SINGLE(QSPI0_IO2), ++ PINMUX_SINGLE(QSPI0_IO3), ++ PINMUX_SINGLE(QSPI0_SSL), ++ PINMUX_SINGLE(QSPI1_SPCLK), ++ PINMUX_SINGLE(QSPI1_MOSI_IO0), ++ PINMUX_SINGLE(QSPI1_MISO_IO1), ++ PINMUX_SINGLE(QSPI1_IO2), ++ PINMUX_SINGLE(QSPI1_IO3), ++ PINMUX_SINGLE(QSPI1_SSL), ++ PINMUX_SINGLE(RPC_RESET_N), ++ PINMUX_SINGLE(RPC_WP_N), ++ PINMUX_SINGLE(RPC_INT_N), ++ ++ /* IPSR0 */ ++ PINMUX_IPSR_GPSR(IP0_3_0, DU_DR2), ++ PINMUX_IPSR_GPSR(IP0_3_0, HSCK0), ++ PINMUX_IPSR_GPSR(IP0_3_0, A0), ++ ++ PINMUX_IPSR_GPSR(IP0_7_4, DU_DR3), ++ PINMUX_IPSR_GPSR(IP0_7_4, HRTS0_N), ++ PINMUX_IPSR_GPSR(IP0_7_4, A1), ++ ++ PINMUX_IPSR_GPSR(IP0_11_8, DU_DR4), ++ PINMUX_IPSR_GPSR(IP0_11_8, HCTS0_N), ++ PINMUX_IPSR_GPSR(IP0_11_8, A2), ++ ++ PINMUX_IPSR_GPSR(IP0_15_12, DU_DR5), ++ PINMUX_IPSR_GPSR(IP0_15_12, HTX0), ++ PINMUX_IPSR_GPSR(IP0_15_12, A3), ++ ++ PINMUX_IPSR_GPSR(IP0_19_16, DU_DR6), ++ PINMUX_IPSR_GPSR(IP0_19_16, MSIOF3_RXD), ++ PINMUX_IPSR_GPSR(IP0_19_16, A4), ++ ++ PINMUX_IPSR_GPSR(IP0_23_20, DU_DR7), ++ PINMUX_IPSR_GPSR(IP0_23_20, MSIOF3_TXD), ++ PINMUX_IPSR_GPSR(IP0_23_20, A5), ++ ++ PINMUX_IPSR_GPSR(IP0_27_24, DU_DG2), ++ PINMUX_IPSR_GPSR(IP0_27_24, MSIOF3_SS1), ++ PINMUX_IPSR_GPSR(IP0_27_24, A6), ++ ++ PINMUX_IPSR_GPSR(IP0_31_28, DU_DG3), ++ PINMUX_IPSR_GPSR(IP0_31_28, MSIOF3_SS2), ++ PINMUX_IPSR_GPSR(IP0_31_28, A7), ++ PINMUX_IPSR_GPSR(IP0_31_28, PWMFSW0), ++ ++ /* IPSR1 */ ++ PINMUX_IPSR_GPSR(IP1_3_0, DU_DG4), ++ PINMUX_IPSR_GPSR(IP1_3_0, A8), ++ PINMUX_IPSR_MSEL(IP1_3_0, FSO_CFE_0_N_A, SEL_RFSO_0), ++ ++ PINMUX_IPSR_GPSR(IP1_7_4, DU_DG5), ++ PINMUX_IPSR_GPSR(IP1_7_4, A9), ++ PINMUX_IPSR_MSEL(IP1_7_4, FSO_CFE_1_N_A, SEL_RFSO_0), ++ ++ PINMUX_IPSR_GPSR(IP1_11_8, DU_DG6), ++ PINMUX_IPSR_GPSR(IP1_11_8, A10), ++ PINMUX_IPSR_MSEL(IP1_11_8, FSO_TOE_N_A, SEL_RFSO_0), ++ ++ PINMUX_IPSR_GPSR(IP1_15_12, DU_DG7), ++ PINMUX_IPSR_GPSR(IP1_15_12, A11), ++ PINMUX_IPSR_GPSR(IP1_15_12, IRQ1), ++ ++ PINMUX_IPSR_GPSR(IP1_19_16, DU_DB2), ++ PINMUX_IPSR_GPSR(IP1_19_16, A12), ++ PINMUX_IPSR_GPSR(IP1_19_16, IRQ2), ++ ++ PINMUX_IPSR_GPSR(IP1_23_20, DU_DB3), ++ PINMUX_IPSR_GPSR(IP1_23_20, A13), ++ PINMUX_IPSR_GPSR(IP1_23_20, FXR_CLKOUT1), ++ ++ PINMUX_IPSR_GPSR(IP1_27_24, DU_DB4), ++ PINMUX_IPSR_GPSR(IP1_27_24, A14), ++ PINMUX_IPSR_GPSR(IP1_27_24, FXR_CLKOUT2), ++ ++ PINMUX_IPSR_GPSR(IP1_31_28, DU_DB5), ++ PINMUX_IPSR_GPSR(IP1_31_28, A15), ++ PINMUX_IPSR_GPSR(IP1_31_28, FXR_TXENA_N), ++ ++ /* IPSR2 */ ++ PINMUX_IPSR_GPSR(IP2_3_0, DU_DB6), ++ PINMUX_IPSR_GPSR(IP2_3_0, A16), ++ PINMUX_IPSR_GPSR(IP2_3_0, FXR_TXENB_N), ++ ++ PINMUX_IPSR_GPSR(IP2_7_4, DU_DB7), ++ PINMUX_IPSR_GPSR(IP2_7_4, A17), ++ PINMUX_IPSR_GPSR(IP2_7_4, STPWT_EXTFXR), ++ ++ PINMUX_IPSR_GPSR(IP2_11_8, DU_DOTCLKOUT), ++ PINMUX_IPSR_MSEL(IP2_11_8, SCIF_CLK_A, SEL_HSCIF0_0), ++ PINMUX_IPSR_GPSR(IP2_11_8, A18), ++ ++ PINMUX_IPSR_GPSR(IP2_15_12, DU_EXHSYNC_DU_HSYNC), ++ PINMUX_IPSR_GPSR(IP2_15_12, HRX0), ++ PINMUX_IPSR_GPSR(IP2_15_12, A19), ++ PINMUX_IPSR_GPSR(IP2_15_12, IRQ3), ++ ++ PINMUX_IPSR_GPSR(IP2_19_16, DU_EXVSYNC_DU_VSYNC), ++ PINMUX_IPSR_GPSR(IP2_19_16, MSIOF3_SCK), ++ PINMUX_IPSR_GPSR(IP2_19_16, A20), ++ ++ PINMUX_IPSR_GPSR(IP2_23_20, DU_EXODDF_DU_ODDF_DISP_CDE), ++ PINMUX_IPSR_GPSR(IP2_23_20, MSIOF3_SYNC), ++ PINMUX_IPSR_GPSR(IP2_23_20, A21), ++ ++ PINMUX_IPSR_GPSR(IP2_27_24, IRQ0), ++ PINMUX_IPSR_GPSR(IP2_27_24, CC5_OSCOUT), ++ ++ PINMUX_IPSR_GPSR(IP2_31_28, VI0_CLK), ++ PINMUX_IPSR_GPSR(IP2_31_28, MSIOF2_SCK), ++ PINMUX_IPSR_GPSR(IP2_31_28, SCK3), ++ PINMUX_IPSR_GPSR(IP2_31_28, HSCK3), ++ ++ /* IPSR3 */ ++ PINMUX_IPSR_GPSR(IP3_3_0, VI0_CLKENB), ++ PINMUX_IPSR_GPSR(IP3_3_0, MSIOF2_RXD), ++ PINMUX_IPSR_GPSR(IP3_3_0, RX3), ++ PINMUX_IPSR_GPSR(IP3_3_0, RD_WR_N), ++ PINMUX_IPSR_GPSR(IP3_3_0, HCTS3_N), ++ ++ PINMUX_IPSR_GPSR(IP3_7_4, VI0_HSYNC_N), ++ PINMUX_IPSR_GPSR(IP3_7_4, MSIOF2_TXD), ++ PINMUX_IPSR_GPSR(IP3_7_4, TX3), ++ PINMUX_IPSR_GPSR(IP3_7_4, HRTS3_N), ++ ++ PINMUX_IPSR_GPSR(IP3_11_8, VI0_VSYNC_N), ++ PINMUX_IPSR_GPSR(IP3_11_8, MSIOF2_SYNC), ++ PINMUX_IPSR_GPSR(IP3_11_8, CTS3_N), ++ PINMUX_IPSR_GPSR(IP3_11_8, HTX3), ++ ++ PINMUX_IPSR_GPSR(IP3_15_12, VI0_DATA0), ++ PINMUX_IPSR_GPSR(IP3_15_12, MSIOF2_SS1), ++ PINMUX_IPSR_GPSR(IP3_15_12, RTS3_N_TANS), ++ PINMUX_IPSR_GPSR(IP3_15_12, HRX3), ++ ++ PINMUX_IPSR_GPSR(IP3_19_16, VI0_DATA1), ++ PINMUX_IPSR_GPSR(IP3_19_16, MSIOF2_SS2), ++ PINMUX_IPSR_GPSR(IP3_19_16, SCK1), ++ PINMUX_IPSR_MSEL(IP3_19_16, SPEEDIN_A, SEL_RSP_1), ++ ++ PINMUX_IPSR_GPSR(IP3_23_20, VI0_DATA2), ++ PINMUX_IPSR_GPSR(IP3_23_20, AVB0_AVTP_PPS), ++ PINMUX_IPSR_GPSR(IP3_23_20, SDA3_A), ++ ++ PINMUX_IPSR_GPSR(IP3_27_24, VI0_DATA3), ++ PINMUX_IPSR_GPSR(IP3_27_24, HSCK1), ++ PINMUX_IPSR_GPSR(IP3_27_24, SCL3_A), ++ ++ PINMUX_IPSR_GPSR(IP3_31_28, VI0_DATA4), ++ PINMUX_IPSR_GPSR(IP3_31_28, HRTS1_N), ++ PINMUX_IPSR_MSEL(IP3_31_28, RX1_A, SEL_SCIF1_0), ++ ++ /* IPSR4 */ ++ PINMUX_IPSR_GPSR(IP4_3_0, VI0_DATA5), ++ PINMUX_IPSR_GPSR(IP4_3_0, HCTS1_N), ++ PINMUX_IPSR_MSEL(IP4_3_0, TX1_A, SEL_SCIF1_0), ++ ++ PINMUX_IPSR_GPSR(IP4_7_4, VI0_DATA6), ++ PINMUX_IPSR_GPSR(IP4_7_4, HTX1), ++ PINMUX_IPSR_GPSR(IP4_7_4, CTS1_N), ++ ++ PINMUX_IPSR_GPSR(IP4_11_8, VI0_DATA7), ++ PINMUX_IPSR_GPSR(IP4_11_8, HRX1), ++ PINMUX_IPSR_GPSR(IP4_11_8, RTS1_N_TANS), ++ ++ PINMUX_IPSR_GPSR(IP4_15_12, VI0_DATA8), ++ PINMUX_IPSR_GPSR(IP4_15_12, HSCK2), ++ PINMUX_IPSR_MSEL(IP4_15_12, PWM0_A, SEL_PWM0_0), ++ PINMUX_IPSR_GPSR(IP4_15_12, A22), ++ ++ PINMUX_IPSR_GPSR(IP4_19_16, VI0_DATA9), ++ PINMUX_IPSR_GPSR(IP4_19_16, HCTS2_N), ++ PINMUX_IPSR_MSEL(IP4_19_16, PWM1_A, SEL_PWM1_0), ++ PINMUX_IPSR_GPSR(IP4_19_16, A23), ++ PINMUX_IPSR_MSEL(IP4_19_16, FSO_CFE_0_N_B, SEL_RFSO_1), ++ ++ PINMUX_IPSR_GPSR(IP4_23_20, VI0_DATA10), ++ PINMUX_IPSR_GPSR(IP4_23_20, HRTS2_N), ++ PINMUX_IPSR_MSEL(IP4_23_20, PWM2_A, SEL_PWM2_0), ++ PINMUX_IPSR_GPSR(IP4_23_20, A24), ++ PINMUX_IPSR_MSEL(IP4_23_20, FSO_CFE_1_N_B, SEL_RFSO_1), ++ ++ PINMUX_IPSR_GPSR(IP4_27_24, VI0_DATA11), ++ PINMUX_IPSR_GPSR(IP4_27_24, HTX2), ++ PINMUX_IPSR_MSEL(IP4_27_24, PWM3_A, SEL_PWM3_0), ++ PINMUX_IPSR_GPSR(IP4_27_24, A25), ++ PINMUX_IPSR_MSEL(IP4_27_24, FSO_TOE_N_B, SEL_RFSO_1), ++ ++ PINMUX_IPSR_GPSR(IP4_31_28, VI0_FIELD), ++ PINMUX_IPSR_GPSR(IP4_31_28, HRX2), ++ PINMUX_IPSR_MSEL(IP4_31_28, PWM4_A, SEL_PWM4_0), ++ PINMUX_IPSR_GPSR(IP4_31_28, CS1_N_A26), ++ PINMUX_IPSR_GPSR(IP4_31_28, FSCLKST2_N_A), ++ ++ /* IPSR5 */ ++ PINMUX_IPSR_GPSR(IP5_3_0, VI1_CLK), ++ PINMUX_IPSR_GPSR(IP5_3_0, MSIOF1_RXD), ++ PINMUX_IPSR_GPSR(IP5_3_0, CS0_N), ++ ++ PINMUX_IPSR_GPSR(IP5_7_4, VI1_CLKENB), ++ PINMUX_IPSR_GPSR(IP5_7_4, MSIOF1_TXD), ++ PINMUX_IPSR_GPSR(IP5_7_4, D0), ++ ++ PINMUX_IPSR_GPSR(IP5_11_8, VI1_HSYNC_N), ++ PINMUX_IPSR_GPSR(IP5_11_8, MSIOF1_SCK), ++ PINMUX_IPSR_GPSR(IP5_11_8, D1), ++ ++ PINMUX_IPSR_GPSR(IP5_15_12, VI1_VSYNC_N), ++ PINMUX_IPSR_GPSR(IP5_15_12, MSIOF1_SYNC), ++ PINMUX_IPSR_GPSR(IP5_15_12, D2), ++ ++ PINMUX_IPSR_GPSR(IP5_19_16, VI1_DATA0), ++ PINMUX_IPSR_GPSR(IP5_19_16, MSIOF1_SS1), ++ PINMUX_IPSR_GPSR(IP5_19_16, D3), ++ ++ PINMUX_IPSR_GPSR(IP5_23_20, VI1_DATA1), ++ PINMUX_IPSR_GPSR(IP5_23_20, MSIOF1_SS2), ++ PINMUX_IPSR_GPSR(IP5_23_20, D4), ++ PINMUX_IPSR_GPSR(IP5_23_20, MMC_CMD), ++ ++ PINMUX_IPSR_GPSR(IP5_27_24, VI1_DATA2), ++ PINMUX_IPSR_MSEL(IP5_27_24, CANFD0_TX_B, SEL_CANFD0_1), ++ PINMUX_IPSR_GPSR(IP5_27_24, D5), ++ PINMUX_IPSR_GPSR(IP5_27_24, MMC_D0), ++ ++ PINMUX_IPSR_GPSR(IP5_31_28, VI1_DATA3), ++ PINMUX_IPSR_MSEL(IP5_31_28, CANFD0_RX_B, SEL_CANFD0_1), ++ PINMUX_IPSR_GPSR(IP5_31_28, D6), ++ PINMUX_IPSR_GPSR(IP5_31_28, MMC_D1), ++ ++ /* IPSR6 */ ++ PINMUX_IPSR_GPSR(IP6_3_0, VI1_DATA4), ++ PINMUX_IPSR_MSEL(IP6_3_0, CANFD_CLK_B, SEL_CANFD0_1), ++ PINMUX_IPSR_GPSR(IP6_3_0, D7), ++ PINMUX_IPSR_GPSR(IP6_3_0, MMC_D2), ++ ++ PINMUX_IPSR_GPSR(IP6_7_4, VI1_DATA5), ++ PINMUX_IPSR_GPSR(IP6_7_4, SCK4), ++ PINMUX_IPSR_GPSR(IP6_7_4, D8), ++ PINMUX_IPSR_GPSR(IP6_7_4, MMC_D3), ++ ++ PINMUX_IPSR_GPSR(IP6_11_8, VI1_DATA6), ++ PINMUX_IPSR_GPSR(IP6_11_8, RX4), ++ PINMUX_IPSR_GPSR(IP6_11_8, D9), ++ PINMUX_IPSR_GPSR(IP6_11_8, MMC_CLK), ++ ++ PINMUX_IPSR_GPSR(IP6_15_12, VI1_DATA7), ++ PINMUX_IPSR_GPSR(IP6_15_12, TX4), ++ PINMUX_IPSR_GPSR(IP6_15_12, D10), ++ PINMUX_IPSR_GPSR(IP6_15_12, MMC_D4), ++ ++ PINMUX_IPSR_GPSR(IP6_19_16, VI1_DATA8), ++ PINMUX_IPSR_GPSR(IP6_19_16, CTS4_N), ++ PINMUX_IPSR_GPSR(IP6_19_16, D11), ++ PINMUX_IPSR_GPSR(IP6_19_16, MMC_D5), ++ ++ PINMUX_IPSR_GPSR(IP6_23_20, VI1_DATA9), ++ PINMUX_IPSR_GPSR(IP6_23_20, RTS4_N_TANS), ++ PINMUX_IPSR_GPSR(IP6_23_20, D12), ++ PINMUX_IPSR_GPSR(IP6_23_20, MMC_D6), ++ PINMUX_IPSR_GPSR(IP6_23_20, SCL3_B), ++ ++ PINMUX_IPSR_GPSR(IP6_27_24, VI1_DATA10), ++ PINMUX_IPSR_GPSR(IP6_27_24, D13), ++ PINMUX_IPSR_GPSR(IP6_27_24, MMC_D7), ++ PINMUX_IPSR_GPSR(IP6_27_24, SDA3_B), ++ ++ PINMUX_IPSR_GPSR(IP6_31_28, VI1_DATA11), ++ PINMUX_IPSR_GPSR(IP6_31_28, SCL4), ++ PINMUX_IPSR_GPSR(IP6_31_28, IRQ4), ++ PINMUX_IPSR_GPSR(IP6_31_28, D14), ++ PINMUX_IPSR_GPSR(IP6_31_28, MMC_WP), ++ ++ /* IPSR7 */ ++ PINMUX_IPSR_GPSR(IP7_3_0, VI1_FIELD), ++ PINMUX_IPSR_GPSR(IP7_3_0, SDA4), ++ PINMUX_IPSR_GPSR(IP7_3_0, IRQ5), ++ PINMUX_IPSR_GPSR(IP7_3_0, D15), ++ PINMUX_IPSR_GPSR(IP7_3_0, MMC_CD), ++ ++ PINMUX_IPSR_GPSR(IP7_7_4, SCL0), ++ PINMUX_IPSR_GPSR(IP7_7_4, DU_DR0), ++ PINMUX_IPSR_GPSR(IP7_7_4, TPU0TO0), ++ PINMUX_IPSR_GPSR(IP7_7_4, CLKOUT), ++ PINMUX_IPSR_GPSR(IP7_7_4, MSIOF0_RXD), ++ ++ PINMUX_IPSR_GPSR(IP7_11_8, SDA0), ++ PINMUX_IPSR_GPSR(IP7_11_8, DU_DR1), ++ PINMUX_IPSR_GPSR(IP7_11_8, TPU0TO1), ++ PINMUX_IPSR_GPSR(IP7_11_8, BS_N), ++ PINMUX_IPSR_GPSR(IP7_11_8, SCK0), ++ PINMUX_IPSR_GPSR(IP7_11_8, MSIOF0_TXD), ++ ++ PINMUX_IPSR_GPSR(IP7_15_12, SCL1), ++ PINMUX_IPSR_GPSR(IP7_15_12, DU_DG0), ++ PINMUX_IPSR_GPSR(IP7_15_12, TPU0TO2), ++ PINMUX_IPSR_GPSR(IP7_15_12, RD_N), ++ PINMUX_IPSR_GPSR(IP7_15_12, CTS0_N), ++ PINMUX_IPSR_GPSR(IP7_15_12, MSIOF0_SCK), ++ ++ PINMUX_IPSR_GPSR(IP7_19_16, SDA1), ++ PINMUX_IPSR_GPSR(IP7_19_16, DU_DG1), ++ PINMUX_IPSR_GPSR(IP7_19_16, TPU0TO3), ++ PINMUX_IPSR_GPSR(IP7_19_16, WE0_N), ++ PINMUX_IPSR_GPSR(IP7_19_16, RTS0_N_TANS), ++ PINMUX_IPSR_GPSR(IP7_19_16, MSIOF0_SYNC), ++ ++ PINMUX_IPSR_GPSR(IP7_23_20, SCL2), ++ PINMUX_IPSR_GPSR(IP7_23_20, DU_DB0), ++ PINMUX_IPSR_MSEL(IP7_23_20, TCLK1_A, SEL_TMU_0), ++ PINMUX_IPSR_GPSR(IP7_23_20, WE1_N), ++ PINMUX_IPSR_GPSR(IP7_23_20, RX0), ++ PINMUX_IPSR_GPSR(IP7_23_20, MSIOF0_SS1), ++ ++ PINMUX_IPSR_GPSR(IP7_27_24, SDA2), ++ PINMUX_IPSR_GPSR(IP7_27_24, DU_DB1), ++ PINMUX_IPSR_MSEL(IP7_27_24, TCLK2_A, SEL_TMU_0), ++ PINMUX_IPSR_GPSR(IP7_27_24, EX_WAIT0), ++ PINMUX_IPSR_GPSR(IP7_27_24, TX0), ++ PINMUX_IPSR_GPSR(IP7_27_24, MSIOF0_SS2), ++ ++ PINMUX_IPSR_GPSR(IP7_31_28, AVB0_AVTP_CAPTURE), ++ PINMUX_IPSR_GPSR(IP7_31_28, FSCLKST2_N_B), ++ ++ /* IPSR8 */ ++ PINMUX_IPSR_MSEL(IP8_3_0, CANFD0_TX_A, SEL_CANFD0_0), ++ PINMUX_IPSR_GPSR(IP8_3_0, FXR_TXDA), ++ PINMUX_IPSR_MSEL(IP8_3_0, PWM0_B, SEL_PWM0_1), ++ PINMUX_IPSR_GPSR(IP8_3_0, DU_DISP), ++ PINMUX_IPSR_GPSR(IP8_3_0, FSCLKST2_N_C), ++ ++ PINMUX_IPSR_MSEL(IP8_7_4, CANFD0_RX_A, SEL_CANFD0_0), ++ PINMUX_IPSR_GPSR(IP8_7_4, RXDA_EXTFXR), ++ PINMUX_IPSR_MSEL(IP8_7_4, PWM1_B, SEL_PWM1_1), ++ PINMUX_IPSR_GPSR(IP8_7_4, DU_CDE), ++ ++ PINMUX_IPSR_GPSR(IP8_11_8, CANFD1_TX), ++ PINMUX_IPSR_GPSR(IP8_11_8, FXR_TXDB), ++ PINMUX_IPSR_MSEL(IP8_11_8, PWM2_B, SEL_PWM2_1), ++ PINMUX_IPSR_MSEL(IP8_11_8, TCLK1_B, SEL_TMU_1), ++ PINMUX_IPSR_MSEL(IP8_11_8, TX1_B, SEL_SCIF1_1), ++ ++ PINMUX_IPSR_GPSR(IP8_15_12, CANFD1_RX), ++ PINMUX_IPSR_GPSR(IP8_15_12, RXDB_EXTFXR), ++ PINMUX_IPSR_MSEL(IP8_15_12, PWM3_B, SEL_PWM3_1), ++ PINMUX_IPSR_MSEL(IP8_15_12, TCLK2_B, SEL_TMU_1), ++ PINMUX_IPSR_MSEL(IP8_15_12, RX1_B, SEL_SCIF1_1), ++ ++ PINMUX_IPSR_MSEL(IP8_19_16, CANFD_CLK_A, SEL_CANFD0_0), ++ PINMUX_IPSR_GPSR(IP8_19_16, CLK_EXTFXR), ++ PINMUX_IPSR_MSEL(IP8_19_16, PWM4_B, SEL_PWM4_1), ++ PINMUX_IPSR_MSEL(IP8_19_16, SPEEDIN_B, SEL_RSP_0), ++ PINMUX_IPSR_MSEL(IP8_19_16, SCIF_CLK_B, SEL_HSCIF0_1), ++ ++ PINMUX_IPSR_GPSR(IP8_23_20, DIGRF_CLKIN), ++ PINMUX_IPSR_GPSR(IP8_23_20, DIGRF_CLKEN_IN), ++ ++ PINMUX_IPSR_GPSR(IP8_27_24, DIGRF_CLKOUT), ++ PINMUX_IPSR_GPSR(IP8_27_24, DIGRF_CLKEN_OUT), ++}; ++ ++static const struct sh_pfc_pin pinmux_pins[] = { ++ PINMUX_GPIO_GP_ALL(), ++}; ++ ++/* - EtherAVB --------------------------------------------------------------- */ ++static const unsigned int avb0_rx_ctrl_pins[] = { ++ /* AVB0_RX_CTL */ ++ RCAR_GP_PIN(1, 1), ++}; ++static const unsigned int avb0_rx_ctrl_mux[] = { ++ AVB0_RX_CTL_MARK, ++}; ++static const unsigned int avb0_rxc_pins[] = { ++ /* AVB0_RXC */ ++ RCAR_GP_PIN(1, 2), ++}; ++static const unsigned int avb0_rxc_mux[] = { ++ AVB0_RXC_MARK, ++}; ++static const unsigned int avb0_rd0_pins[] = { ++ /* AVB0_RD[0] */ ++ RCAR_GP_PIN(1, 3), ++}; ++static const unsigned int avb0_rd0_mux[] = { ++ AVB0_RD0_MARK, ++}; ++static const unsigned int avb0_rd1_pins[] = { ++ /* AVB0_RD[1] */ ++ RCAR_GP_PIN(1, 4), ++}; ++static const unsigned int avb0_rd1_mux[] = { ++ AVB0_RD1_MARK, ++}; ++static const unsigned int avb0_rd2_pins[] = { ++ /* AVB0_RD[2] */ ++ RCAR_GP_PIN(1, 5), ++}; ++static const unsigned int avb0_rd2_mux[] = { ++ AVB0_RD2_MARK, ++}; ++static const unsigned int avb0_rd3_pins[] = { ++ /* AVB0_RD[3] */ ++ RCAR_GP_PIN(1, 6), ++}; ++static const unsigned int avb0_rd3_mux[] = { ++ AVB0_RD3_MARK, ++}; ++static const unsigned int avb0_rd4_pins[] = { ++ /* AVB0_RD[3:0] */ ++ RCAR_GP_PIN(1, 3), RCAR_GP_PIN(1, 4), ++ RCAR_GP_PIN(1, 5), RCAR_GP_PIN(1, 6), ++}; ++static const unsigned int avb0_rd4_mux[] = { ++ AVB0_RD0_MARK, AVB0_RD1_MARK, ++ AVB0_RD2_MARK, AVB0_RD3_MARK, ++}; ++static const unsigned int avb0_tx_ctrl_pins[] = { ++ /* AVB0_TX_CTL */ ++ RCAR_GP_PIN(1, 7), ++}; ++static const unsigned int avb0_tx_ctrl_mux[] = { ++ AVB0_TX_CTL_MARK, ++}; ++static const unsigned int avb0_txc_pins[] = { ++ /* AVB0_TXC */ ++ RCAR_GP_PIN(1, 8), ++}; ++static const unsigned int avb0_txc_mux[] = { ++ AVB0_TXC_MARK, ++}; ++static const unsigned int avb0_td0_pins[] = { ++ /* AVB0_TD[0] */ ++ RCAR_GP_PIN(1, 9), ++}; ++static const unsigned int avb0_td0_mux[] = { ++ AVB0_TD0_MARK, ++}; ++static const unsigned int avb0_td1_pins[] = { ++ /* AVB0_TD[1] */ ++ RCAR_GP_PIN(1, 10), ++}; ++static const unsigned int avb0_td1_mux[] = { ++ AVB0_TD1_MARK, ++}; ++static const unsigned int avb0_td2_pins[] = { ++ /* AVB0_TD[2] */ ++ RCAR_GP_PIN(1, 11), ++}; ++static const unsigned int avb0_td2_mux[] = { ++ AVB0_TD2_MARK, ++}; ++static const unsigned int avb0_td3_pins[] = { ++ /* AVB0_TD[3] */ ++ RCAR_GP_PIN(1, 12), ++}; ++static const unsigned int avb0_td3_mux[] = { ++ AVB0_TD3_MARK, ++}; ++static const unsigned int avb0_td4_pins[] = { ++ /* AVB0_TD[3:0] */ ++ RCAR_GP_PIN(1, 9), RCAR_GP_PIN(1, 10), ++ RCAR_GP_PIN(1, 11), RCAR_GP_PIN(1, 12), ++}; ++static const unsigned int avb0_td4_mux[] = { ++ AVB0_TD0_MARK, AVB0_TD1_MARK, ++ AVB0_TD2_MARK, AVB0_TD3_MARK, ++}; ++static const unsigned int avb0_txcrefclk_pins[] = { ++ /* AVB0_TXCREFCLK */ ++ RCAR_GP_PIN(1, 13), ++}; ++static const unsigned int avb0_txcrefclk_mux[] = { ++ AVB0_TXCREFCLK_MARK, ++}; ++static const unsigned int avb0_mdio_pins[] = { ++ /* AVB0_MDIO */ ++ RCAR_GP_PIN(1, 14), ++}; ++static const unsigned int avb0_mdio_mux[] = { ++ AVB0_MDIO_MARK, ++}; ++static const unsigned int avb0_mdc_pins[] = { ++ /* AVB0_MDC */ ++ RCAR_GP_PIN(1, 15), ++}; ++static const unsigned int avb0_mdc_mux[] = { ++ AVB0_MDC_MARK, ++}; ++static const unsigned int avb0_magic_pins[] = { ++ /* AVB0_MAGIC */ ++ RCAR_GP_PIN(1, 16), ++}; ++static const unsigned int avb0_magic_mux[] = { ++ AVB0_MAGIC_MARK, ++}; ++static const unsigned int avb0_phy_int_pins[] = { ++ /* AVB0_PHY_INT */ ++ RCAR_GP_PIN(1, 17), ++}; ++static const unsigned int avb0_phy_int_mux[] = { ++ AVB0_PHY_INT_MARK, ++}; ++static const unsigned int avb0_link_pins[] = { ++ /* AVB0_LINK */ ++ RCAR_GP_PIN(1, 18), ++}; ++static const unsigned int avb0_link_mux[] = { ++ AVB0_LINK_MARK, ++}; ++static const unsigned int avb0_avtp_match_pins[] = { ++ /* AVB0_AVTP_MATCH */ ++ RCAR_GP_PIN(1, 19), ++}; ++static const unsigned int avb0_avtp_match_mux[] = { ++ AVB0_AVTP_MATCH_MARK, ++}; ++static const unsigned int avb0_avtp_pps_pins[] = { ++ /* AVB0_AVTP_PPS */ ++ RCAR_GP_PIN(2, 6), ++}; ++static const unsigned int avb0_avtp_pps_mux[] = { ++ AVB0_AVTP_PPS_MARK, ++}; ++static const unsigned int avb0_avtp_capture_pins[] = { ++ /* AVB0_AVTP_CAPTURE */ ++ RCAR_GP_PIN(1, 20), ++}; ++static const unsigned int avb0_avtp_capture_mux[] = { ++ AVB0_AVTP_CAPTURE_MARK, ++}; ++ ++/* - CANFD0 ----------------------------------------------------------------- */ ++static const unsigned int canfd0_data_a_pins[] = { ++ /* TX, RX */ ++ RCAR_GP_PIN(1, 21), RCAR_GP_PIN(1, 22), ++}; ++static const unsigned int canfd0_data_a_mux[] = { ++ CANFD0_TX_A_MARK, CANFD0_RX_A_MARK, ++}; ++static const unsigned int canfd_clk_a_pins[] = { ++ /* CLK */ ++ RCAR_GP_PIN(1, 25), ++}; ++static const unsigned int canfd_clk_a_mux[] = { ++ CANFD_CLK_A_MARK, ++}; ++static const unsigned int canfd0_data_b_pins[] = { ++ /* TX, RX */ ++ RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7), ++}; ++static const unsigned int canfd0_data_b_mux[] = { ++ CANFD0_TX_B_MARK, CANFD0_RX_B_MARK, ++}; ++static const unsigned int canfd_clk_b_pins[] = { ++ /* CLK */ ++ RCAR_GP_PIN(3, 8), ++}; ++static const unsigned int canfd_clk_b_mux[] = { ++ CANFD_CLK_B_MARK, ++}; ++ ++/* - CANFD1 ----------------------------------------------------------------- */ ++static const unsigned int canfd1_data_pins[] = { ++ /* TX, RX */ ++ RCAR_GP_PIN(1, 23), RCAR_GP_PIN(1, 24), ++}; ++static const unsigned int canfd1_data_mux[] = { ++ CANFD1_TX_MARK, CANFD1_RX_MARK, ++}; ++ ++/* - DU --------------------------------------------------------------------- */ ++static const unsigned int du_rgb666_pins[] = { ++ /* R[7:0] */ ++ RCAR_GP_PIN(0, 5), RCAR_GP_PIN(0, 4), RCAR_GP_PIN(0, 3), ++ RCAR_GP_PIN(0, 2), RCAR_GP_PIN(0, 1), RCAR_GP_PIN(0, 0), ++ /* G[7:0] */ ++ RCAR_GP_PIN(0, 11), RCAR_GP_PIN(0, 10), RCAR_GP_PIN(0, 9), ++ RCAR_GP_PIN(0, 8), RCAR_GP_PIN(0, 7), RCAR_GP_PIN(0, 6), ++ /* B[7:0] */ ++ RCAR_GP_PIN(0, 17), RCAR_GP_PIN(0, 16), RCAR_GP_PIN(0, 15), ++ RCAR_GP_PIN(0, 14), RCAR_GP_PIN(0, 13), RCAR_GP_PIN(0, 12), ++}; ++static const unsigned int du_rgb666_mux[] = { ++ DU_DR7_MARK, DU_DR6_MARK, DU_DR5_MARK, DU_DR4_MARK, ++ DU_DR3_MARK, DU_DR2_MARK, ++ DU_DG7_MARK, DU_DG6_MARK, DU_DG5_MARK, DU_DG4_MARK, ++ DU_DG3_MARK, DU_DG2_MARK, ++ DU_DB7_MARK, DU_DB6_MARK, DU_DB5_MARK, DU_DB4_MARK, ++ DU_DB3_MARK, DU_DB2_MARK, ++}; ++static const unsigned int du_clk_out_0_pins[] = { ++ /* CLKOUT0 */ ++ RCAR_GP_PIN(0, 18), ++}; ++static const unsigned int du_clk_out_0_mux[] = { ++ DU_DOTCLKOUT_MARK, ++}; ++static const unsigned int du_clk_out_1_pins[] = { ++ /* CLKOUT1 */ ++ RCAR_GP_PIN(0, 18), /* @@ */ ++}; ++static const unsigned int du_clk_out_1_mux[] = { ++ DU_DOTCLKOUT_MARK, ++}; ++static const unsigned int du_sync_pins[] = { ++ /* EXVSYNC/VSYNC, EXHSYNC/HSYNC */ ++ RCAR_GP_PIN(0, 20), RCAR_GP_PIN(0, 19), ++}; ++static const unsigned int du_sync_mux[] = { ++ DU_EXVSYNC_DU_VSYNC_MARK, DU_EXHSYNC_DU_HSYNC_MARK ++}; ++static const unsigned int du_oddf_pins[] = { ++ /* EXDISP/EXODDF/EXCDE */ ++ RCAR_GP_PIN(0, 21), ++}; ++static const unsigned int du_oddf_mux[] = { ++ DU_EXODDF_DU_ODDF_DISP_CDE_MARK, ++}; ++static const unsigned int du_cde_pins[] = { ++ /* CDE */ ++ RCAR_GP_PIN(1, 22), ++}; ++static const unsigned int du_cde_mux[] = { ++ DU_CDE_MARK, ++}; ++static const unsigned int du_disp_pins[] = { ++ /* DISP */ ++ RCAR_GP_PIN(1, 21), ++}; ++static const unsigned int du_disp_mux[] = { ++ DU_DISP_MARK, ++}; ++ ++/* - HSCIF0 ----------------------------------------------------------------- */ ++static const unsigned int hscif0_data_pins[] = { ++ /* HRX0, HTX0 */ ++ RCAR_GP_PIN(0, 19), RCAR_GP_PIN(0, 3), ++}; ++static const unsigned int hscif0_data_mux[] = { ++ HRX0_MARK, HTX0_MARK, ++}; ++static const unsigned int hscif0_clk_pins[] = { ++ /* HSCK0 */ ++ RCAR_GP_PIN(0, 0), ++}; ++static const unsigned int hscif0_clk_mux[] = { ++ HSCK0_MARK, ++}; ++static const unsigned int hscif0_ctrl_pins[] = { ++ /* HRTS0#, HCTS0# */ ++ RCAR_GP_PIN(0, 1), RCAR_GP_PIN(0, 2), ++}; ++static const unsigned int hscif0_ctrl_mux[] = { ++ HRTS0_N_MARK, HCTS0_N_MARK, ++}; ++ ++/* - HSCIF1 ----------------------------------------------------------------- */ ++static const unsigned int hscif1_data_pins[] = { ++ /* HRX1, HTX1 */ ++ RCAR_GP_PIN(2, 11), RCAR_GP_PIN(2, 10), ++}; ++static const unsigned int hscif1_data_mux[] = { ++ HRX1_MARK, HTX1_MARK, ++}; ++static const unsigned int hscif1_clk_pins[] = { ++ /* HSCK1 */ ++ RCAR_GP_PIN(2, 7), ++}; ++static const unsigned int hscif1_clk_mux[] = { ++ HSCK1_MARK, ++}; ++static const unsigned int hscif1_ctrl_pins[] = { ++ /* HRTS1#, HCTS1# */ ++ RCAR_GP_PIN(2, 8), RCAR_GP_PIN(2, 9), ++}; ++static const unsigned int hscif1_ctrl_mux[] = { ++ HRTS1_N_MARK, HCTS1_N_MARK, ++}; ++ ++/* - HSCIF2 ----------------------------------------------------------------- */ ++static const unsigned int hscif2_data_pins[] = { ++ /* HRX2, HTX2 */ ++ RCAR_GP_PIN(2, 16), RCAR_GP_PIN(2, 15), ++}; ++static const unsigned int hscif2_data_mux[] = { ++ HRX2_MARK, HTX2_MARK, ++}; ++static const unsigned int hscif2_clk_pins[] = { ++ /* HSCK2 */ ++ RCAR_GP_PIN(2, 12), ++}; ++static const unsigned int hscif2_clk_mux[] = { ++ HSCK2_MARK, ++}; ++static const unsigned int hscif2_ctrl_pins[] = { ++ /* HRTS2#, HCTS2# */ ++ RCAR_GP_PIN(2, 14), RCAR_GP_PIN(2, 13), ++}; ++static const unsigned int hscif2_ctrl_mux[] = { ++ HRTS2_N_MARK, HCTS2_N_MARK, ++}; ++ ++/* - HSCIF3 ----------------------------------------------------------------- */ ++static const unsigned int hscif3_data_pins[] = { ++ /* HRX3, HTX3 */ ++ RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 3), ++}; ++static const unsigned int hscif3_data_mux[] = { ++ HRX3_MARK, HTX3_MARK, ++}; ++static const unsigned int hscif3_clk_pins[] = { ++ /* HSCK3 */ ++ RCAR_GP_PIN(2, 0), ++}; ++static const unsigned int hscif3_clk_mux[] = { ++ HSCK3_MARK, ++}; ++static const unsigned int hscif3_ctrl_pins[] = { ++ /* HRTS3#, HCTS3# */ ++ RCAR_GP_PIN(2, 2), RCAR_GP_PIN(2, 1), ++}; ++static const unsigned int hscif3_ctrl_mux[] = { ++ HRTS3_N_MARK, HCTS3_N_MARK, ++}; ++ ++/* - SCIF Clock ------------------------------------------------------------- */ ++static const unsigned int scif_clk_a_pins[] = { ++ /* SCIF_CLK */ ++ RCAR_GP_PIN(0, 18), ++}; ++static const unsigned int scif_clk_a_mux[] = { ++ SCIF_CLK_A_MARK, ++}; ++static const unsigned int scif_clk_b_pins[] = { ++ /* SCIF_CLK */ ++ RCAR_GP_PIN(1, 25), ++}; ++static const unsigned int scif_clk_b_mux[] = { ++ SCIF_CLK_B_MARK, ++}; ++ ++/* - I2C -------------------------------------------------------------------- */ ++static const unsigned int i2c0_pins[] = { ++ /* SDA0, SCL0 */ ++ RCAR_GP_PIN(4, 1), RCAR_GP_PIN(4, 0), ++}; ++static const unsigned int i2c0_mux[] = { ++ SDA0_MARK, SCL0_MARK, ++}; ++static const unsigned int i2c1_pins[] = { ++ /* SDA1, SCL1 */ ++ RCAR_GP_PIN(4, 3), RCAR_GP_PIN(4, 2), ++}; ++static const unsigned int i2c1_mux[] = { ++ SDA1_MARK, SCL1_MARK, ++}; ++static const unsigned int i2c2_pins[] = { ++ /* SDA2, SCL2 */ ++ RCAR_GP_PIN(4, 5), RCAR_GP_PIN(4, 4), ++}; ++static const unsigned int i2c2_mux[] = { ++ SDA2_MARK, SCL2_MARK, ++}; ++static const unsigned int i2c3_pins[] = { ++ /* SDA3_A, SCL3_A */ ++ RCAR_GP_PIN(2, 6), RCAR_GP_PIN(2, 5), ++}; ++static const unsigned int i2c3_mux[] = { ++ SDA3_A_MARK, SCL3_A_MARK, ++}; ++static const unsigned int i2c4_pins[] = { ++ /* SDA4, SCL4 */ ++ RCAR_GP_PIN(3, 16), RCAR_GP_PIN(3, 15), ++}; ++static const unsigned int i2c4_mux[] = { ++ SDA4_MARK, SCL4_MARK, ++}; ++ ++/* - INTC-EX ---------------------------------------------------------------- */ ++static const unsigned int intc_ex_irq0_pins[] = { ++ /* IRQ0 */ ++ RCAR_GP_PIN(1, 0), ++}; ++static const unsigned int intc_ex_irq0_mux[] = { ++ IRQ0_MARK, ++}; ++static const unsigned int intc_ex_irq1_pins[] = { ++ /* IRQ1 */ ++ RCAR_GP_PIN(0, 11), ++}; ++static const unsigned int intc_ex_irq1_mux[] = { ++ IRQ1_MARK, ++}; ++static const unsigned int intc_ex_irq2_pins[] = { ++ /* IRQ2 */ ++ RCAR_GP_PIN(0, 12), ++}; ++static const unsigned int intc_ex_irq2_mux[] = { ++ IRQ2_MARK, ++}; ++static const unsigned int intc_ex_irq3_pins[] = { ++ /* IRQ3 */ ++ RCAR_GP_PIN(0, 19), ++}; ++static const unsigned int intc_ex_irq3_mux[] = { ++ IRQ3_MARK, ++}; ++static const unsigned int intc_ex_irq4_pins[] = { ++ /* IRQ4 */ ++ RCAR_GP_PIN(3, 15), ++}; ++static const unsigned int intc_ex_irq4_mux[] = { ++ IRQ4_MARK, ++}; ++static const unsigned int intc_ex_irq5_pins[] = { ++ /* IRQ5 */ ++ RCAR_GP_PIN(3, 16), ++}; ++static const unsigned int intc_ex_irq5_mux[] = { ++ IRQ5_MARK, ++}; ++ ++/* - MSIOF0 ----------------------------------------------------------------- */ ++static const unsigned int msiof0_clk_pins[] = { ++ /* SCK */ ++ RCAR_GP_PIN(4, 2), ++}; ++static const unsigned int msiof0_clk_mux[] = { ++ MSIOF0_SCK_MARK, ++}; ++static const unsigned int msiof0_sync_pins[] = { ++ /* SYNC */ ++ RCAR_GP_PIN(4, 3), ++}; ++static const unsigned int msiof0_sync_mux[] = { ++ MSIOF0_SYNC_MARK, ++}; ++static const unsigned int msiof0_ss1_pins[] = { ++ /* SS1 */ ++ RCAR_GP_PIN(4, 4), ++}; ++static const unsigned int msiof0_ss1_mux[] = { ++ MSIOF0_SS1_MARK, ++}; ++static const unsigned int msiof0_ss2_pins[] = { ++ /* SS2 */ ++ RCAR_GP_PIN(4, 5), ++}; ++static const unsigned int msiof0_ss2_mux[] = { ++ MSIOF0_SS2_MARK, ++}; ++static const unsigned int msiof0_txd_pins[] = { ++ /* TXD */ ++ RCAR_GP_PIN(4, 1), ++}; ++static const unsigned int msiof0_txd_mux[] = { ++ MSIOF0_TXD_MARK, ++}; ++static const unsigned int msiof0_rxd_pins[] = { ++ /* RXD */ ++ RCAR_GP_PIN(4, 0), ++}; ++static const unsigned int msiof0_rxd_mux[] = { ++ MSIOF0_RXD_MARK, ++}; ++ ++/* - MSIOF1 ----------------------------------------------------------------- */ ++static const unsigned int msiof1_clk_pins[] = { ++ /* SCK */ ++ RCAR_GP_PIN(3, 2), ++}; ++static const unsigned int msiof1_clk_mux[] = { ++ MSIOF1_SCK_MARK, ++}; ++static const unsigned int msiof1_sync_pins[] = { ++ /* SYNC */ ++ RCAR_GP_PIN(3, 3), ++}; ++static const unsigned int msiof1_sync_mux[] = { ++ MSIOF1_SYNC_MARK, ++}; ++static const unsigned int msiof1_ss1_pins[] = { ++ /* SS1 */ ++ RCAR_GP_PIN(3, 4), ++}; ++static const unsigned int msiof1_ss1_mux[] = { ++ MSIOF1_SS1_MARK, ++}; ++static const unsigned int msiof1_ss2_pins[] = { ++ /* SS2 */ ++ RCAR_GP_PIN(3, 5), ++}; ++static const unsigned int msiof1_ss2_mux[] = { ++ MSIOF1_SS2_MARK, ++}; ++static const unsigned int msiof1_txd_pins[] = { ++ /* TXD */ ++ RCAR_GP_PIN(3, 1), ++}; ++static const unsigned int msiof1_txd_mux[] = { ++ MSIOF1_TXD_MARK, ++}; ++static const unsigned int msiof1_rxd_pins[] = { ++ /* RXD */ ++ RCAR_GP_PIN(3, 0), ++}; ++static const unsigned int msiof1_rxd_mux[] = { ++ MSIOF1_RXD_MARK, ++}; ++ ++/* - MSIOF2 ----------------------------------------------------------------- */ ++static const unsigned int msiof2_clk_pins[] = { ++ /* SCK */ ++ RCAR_GP_PIN(2, 0), ++}; ++static const unsigned int msiof2_clk_mux[] = { ++ MSIOF2_SCK_MARK, ++}; ++static const unsigned int msiof2_sync_pins[] = { ++ /* SYNC */ ++ RCAR_GP_PIN(2, 3), ++}; ++static const unsigned int msiof2_sync_mux[] = { ++ MSIOF2_SYNC_MARK, ++}; ++static const unsigned int msiof2_ss1_pins[] = { ++ /* SS1 */ ++ RCAR_GP_PIN(2, 4), ++}; ++static const unsigned int msiof2_ss1_mux[] = { ++ MSIOF2_SS1_MARK, ++}; ++static const unsigned int msiof2_ss2_pins[] = { ++ /* SS2 */ ++ RCAR_GP_PIN(2, 5), ++}; ++static const unsigned int msiof2_ss2_mux[] = { ++ MSIOF2_SS2_MARK, ++}; ++static const unsigned int msiof2_txd_pins[] = { ++ /* TXD */ ++ RCAR_GP_PIN(2, 2), ++}; ++static const unsigned int msiof2_txd_mux[] = { ++ MSIOF2_TXD_MARK, ++}; ++static const unsigned int msiof2_rxd_pins[] = { ++ /* RXD */ ++ RCAR_GP_PIN(2, 1), ++}; ++static const unsigned int msiof2_rxd_mux[] = { ++ MSIOF2_RXD_MARK, ++}; ++ ++/* - MSIOF3 ----------------------------------------------------------------- */ ++static const unsigned int msiof3_clk_pins[] = { ++ /* SCK */ ++ RCAR_GP_PIN(0, 20), ++}; ++static const unsigned int msiof3_clk_mux[] = { ++ MSIOF3_SCK_MARK, ++}; ++static const unsigned int msiof3_sync_pins[] = { ++ /* SYNC */ ++ RCAR_GP_PIN(0, 21), ++}; ++static const unsigned int msiof3_sync_mux[] = { ++ MSIOF3_SYNC_MARK, ++}; ++static const unsigned int msiof3_ss1_pins[] = { ++ /* SS1 */ ++ RCAR_GP_PIN(0, 6), ++}; ++static const unsigned int msiof3_ss1_mux[] = { ++ MSIOF3_SS1_MARK, ++}; ++static const unsigned int msiof3_ss2_pins[] = { ++ /* SS2 */ ++ RCAR_GP_PIN(0, 7), ++}; ++static const unsigned int msiof3_ss2_mux[] = { ++ MSIOF3_SS2_MARK, ++}; ++static const unsigned int msiof3_txd_pins[] = { ++ /* TXD */ ++ RCAR_GP_PIN(0, 5), ++}; ++static const unsigned int msiof3_txd_mux[] = { ++ MSIOF3_TXD_MARK, ++}; ++static const unsigned int msiof3_rxd_pins[] = { ++ /* RXD */ ++ RCAR_GP_PIN(0, 4), ++}; ++static const unsigned int msiof3_rxd_mux[] = { ++ MSIOF3_RXD_MARK, ++}; ++ ++/* - PWM0 ------------------------------------------------------------------- */ ++static const unsigned int pwm0_a_pins[] = { ++ /* PWM0 */ ++ RCAR_GP_PIN(2, 12), ++}; ++static const unsigned int pwm0_a_mux[] = { ++ PWM0_A_MARK, ++}; ++static const unsigned int pwm0_b_pins[] = { ++ /* PWM0 */ ++ RCAR_GP_PIN(1, 21), ++}; ++static const unsigned int pwm0_b_mux[] = { ++ PWM0_B_MARK, ++}; ++ ++/* - PWM1 ------------------------------------------------------------------- */ ++static const unsigned int pwm1_a_pins[] = { ++ /* PWM1 */ ++ RCAR_GP_PIN(2, 13), ++}; ++static const unsigned int pwm1_a_mux[] = { ++ PWM1_A_MARK, ++}; ++static const unsigned int pwm1_b_pins[] = { ++ /* PWM */ ++ RCAR_GP_PIN(1, 22), ++}; ++static const unsigned int pwm1_b_mux[] = { ++ PWM1_B_MARK, ++}; ++ ++/* - PWM2 ------------------------------------------------------------------- */ ++static const unsigned int pwm2_a_pins[] = { ++ /* PWM2 */ ++ RCAR_GP_PIN(2, 14), ++}; ++static const unsigned int pwm2_a_mux[] = { ++ PWM2_A_MARK, ++}; ++static const unsigned int pwm2_b_pins[] = { ++ /* PWM2 */ ++ RCAR_GP_PIN(1, 23), ++}; ++static const unsigned int pwm2_b_mux[] = { ++ PWM2_B_MARK, ++}; ++ ++/* - PWM3 ------------------------------------------------------------------- */ ++static const unsigned int pwm3_a_pins[] = { ++ /* PWM3 */ ++ RCAR_GP_PIN(2, 15), ++}; ++static const unsigned int pwm3_a_mux[] = { ++ PWM3_A_MARK, ++}; ++static const unsigned int pwm3_b_pins[] = { ++ /* PWM3 */ ++ RCAR_GP_PIN(1, 24), ++}; ++static const unsigned int pwm3_b_mux[] = { ++ PWM3_B_MARK, ++}; ++ ++/* - PWM4 ------------------------------------------------------------------- */ ++static const unsigned int pwm4_a_pins[] = { ++ /* PWM4 */ ++ RCAR_GP_PIN(2, 16), ++}; ++static const unsigned int pwm4_a_mux[] = { ++ PWM4_A_MARK, ++}; ++static const unsigned int pwm4_b_pins[] = { ++ /* PWM4 */ ++ RCAR_GP_PIN(1, 25), ++}; ++static const unsigned int pwm4_b_mux[] = { ++ PWM4_B_MARK, ++}; ++/* - SCIF0 ------------------------------------------------------------------ */ ++static const unsigned int scif0_data_pins[] = { ++ /* RX, TX */ ++ RCAR_GP_PIN(4, 4), RCAR_GP_PIN(4, 5), ++}; ++static const unsigned int scif0_data_mux[] = { ++ RX0_MARK, TX0_MARK, ++}; ++static const unsigned int scif0_clk_pins[] = { ++ /* SCK */ ++ RCAR_GP_PIN(4, 1), ++}; ++static const unsigned int scif0_clk_mux[] = { ++ SCK0_MARK, ++}; ++#if 0 ++static const unsigned int scif0_ctrl_pins[] = { ++ /* RTS, CTS */ ++ RCAR_GP_PIN(4, 3), RCAR_GP_PIN(4, 2), ++}; ++static const unsigned int scif0_ctrl_mux[] = { ++ RTS0_N_TANS_MARK, CTS0_N_MARK, ++}; ++#endif ++/* - SCIF1 ------------------------------------------------------------------ */ ++static const unsigned int scif1_data_a_pins[] = { ++ /* RX, TX */ ++ RCAR_GP_PIN(2, 8), RCAR_GP_PIN(2, 9), ++}; ++static const unsigned int scif1_data_a_mux[] = { ++ RX1_A_MARK, TX1_A_MARK, ++}; ++static const unsigned int scif1_clk_pins[] = { ++ /* SCK */ ++ RCAR_GP_PIN(2, 5), ++}; ++static const unsigned int scif1_clk_mux[] = { ++ SCK1_MARK, ++}; ++static const unsigned int scif1_ctrl_pins[] = { ++ /* RTS, CTS */ ++ RCAR_GP_PIN(2, 11), RCAR_GP_PIN(2, 10), ++}; ++static const unsigned int scif1_ctrl_mux[] = { ++ RTS1_N_TANS_MARK, CTS1_N_MARK, ++}; ++static const unsigned int scif1_data_b_pins[] = { ++ /* RX, TX */ ++ RCAR_GP_PIN(1, 24), RCAR_GP_PIN(1, 23), ++}; ++static const unsigned int scif1_data_b_mux[] = { ++ RX1_B_MARK, TX1_B_MARK, ++}; ++ ++/* - SCIF3 ------------------------------------------------------------------ */ ++static const unsigned int scif3_data_pins[] = { ++ /* RX, TX */ ++ RCAR_GP_PIN(2, 1), RCAR_GP_PIN(2, 2), ++}; ++static const unsigned int scif3_data_mux[] = { ++ RX3_MARK, TX3_MARK, ++}; ++static const unsigned int scif3_clk_pins[] = { ++ /* SCK */ ++ RCAR_GP_PIN(2, 0), ++}; ++static const unsigned int scif3_clk_mux[] = { ++ SCK3_MARK, ++}; ++static const unsigned int scif3_ctrl_pins[] = { ++ /* RTS, CTS */ ++ RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 3), ++}; ++static const unsigned int scif3_ctrl_mux[] = { ++ RTS3_N_TANS_MARK, CTS3_N_MARK, ++}; ++ ++/* - SCIF4 ------------------------------------------------------------------ */ ++static const unsigned int scif4_data_pins[] = { ++ /* RX, TX */ ++ RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 11), ++}; ++static const unsigned int scif4_data_mux[] = { ++ RX4_MARK, TX4_MARK, ++}; ++static const unsigned int scif4_clk_pins[] = { ++ /* SCK */ ++ RCAR_GP_PIN(3, 9), ++}; ++static const unsigned int scif4_clk_mux[] = { ++ SCK4_MARK, ++}; ++static const unsigned int scif4_ctrl_pins[] = { ++ /* RTS, CTS */ ++ RCAR_GP_PIN(3, 13), RCAR_GP_PIN(3, 12), ++}; ++static const unsigned int scif4_ctrl_mux[] = { ++ RTS4_N_TANS_MARK, CTS4_N_MARK, ++}; ++ ++/* - MMC -------------------------------------------------------------------- */ ++static const unsigned int mmc_data1_pins[] = { ++ /* D0 */ ++ RCAR_GP_PIN(3, 6), ++}; ++static const unsigned int mmc_data1_mux[] = { ++ MMC_D0_MARK, ++}; ++static const unsigned int mmc_data4_pins[] = { ++ /* D[0:3] */ ++ RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7), ++ RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9), ++}; ++static const unsigned int mmc_data4_mux[] = { ++ MMC_D0_MARK, MMC_D1_MARK, ++ MMC_D2_MARK, MMC_D3_MARK, ++}; ++static const unsigned int mmc_data8_pins[] = { ++ /* D[0:7] */ ++ RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7), ++ RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9), ++ RCAR_GP_PIN(3, 11), RCAR_GP_PIN(3, 12), ++ RCAR_GP_PIN(3, 13), RCAR_GP_PIN(3, 14), ++}; ++static const unsigned int mmc_data8_mux[] = { ++ MMC_D0_MARK, MMC_D1_MARK, ++ MMC_D2_MARK, MMC_D3_MARK, ++ MMC_D4_MARK, MMC_D5_MARK, ++ MMC_D6_MARK, MMC_D7_MARK, ++}; ++static const unsigned int mmc_ctrl_pins[] = { ++ /* CLK, CMD */ ++ RCAR_GP_PIN(3,10), RCAR_GP_PIN(3, 5), ++}; ++static const unsigned int mmc_ctrl_mux[] = { ++ MMC_CLK_MARK, MMC_CMD_MARK, ++}; ++static const unsigned int mmc_cd_pins[] = { ++ /* CD */ ++ RCAR_GP_PIN(3, 16), ++}; ++static const unsigned int mmc_cd_mux[] = { ++ MMC_CD_MARK, ++}; ++static const unsigned int mmc_wp_pins[] = { ++ /* WP */ ++ RCAR_GP_PIN(3, 15), ++}; ++static const unsigned int mmc_wp_mux[] = { ++ MMC_WP_MARK, ++}; ++ ++/* - TMU -------------------------------------------------------------------- */ ++static const unsigned int tmu_tclk1_a_pins[] = { ++ /* TCLK1 */ ++ RCAR_GP_PIN(4, 4), ++}; ++static const unsigned int tmu_tclk1_a_mux[] = { ++ TCLK1_A_MARK, ++}; ++static const unsigned int tmu_tclk1_b_pins[] = { ++ /* TCLK1 */ ++ RCAR_GP_PIN(1, 23), ++}; ++static const unsigned int tmu_tclk1_b_mux[] = { ++ TCLK1_B_MARK, ++}; ++static const unsigned int tmu_tclk2_a_pins[] = { ++ /* TCLK2 */ ++ RCAR_GP_PIN(4, 5), ++}; ++static const unsigned int tmu_tclk2_a_mux[] = { ++ TCLK2_A_MARK, ++}; ++static const unsigned int tmu_tclk2_b_pins[] = { ++ /* TCLK2 */ ++ RCAR_GP_PIN(1, 24), ++}; ++static const unsigned int tmu_tclk2_b_mux[] = { ++ TCLK2_B_MARK, ++}; ++ ++/* - VIN0 ------------------------------------------------------------------- */ ++static const unsigned int vin0_data8_pins[] = { ++ RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 5), ++ RCAR_GP_PIN(2, 6), RCAR_GP_PIN(2, 7), ++ RCAR_GP_PIN(2, 8), RCAR_GP_PIN(2, 9), ++ RCAR_GP_PIN(2, 10), RCAR_GP_PIN(2, 11), ++}; ++static const unsigned int vin0_data8_mux[] = { ++ VI0_DATA0_MARK, VI0_DATA1_MARK, ++ VI0_DATA2_MARK, VI0_DATA3_MARK, ++ VI0_DATA4_MARK, VI0_DATA5_MARK, ++ VI0_DATA6_MARK, VI0_DATA7_MARK, ++}; ++static const unsigned int vin0_data10_pins[] = { ++ RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 5), ++ RCAR_GP_PIN(2, 6), RCAR_GP_PIN(2, 7), ++ RCAR_GP_PIN(2, 8), RCAR_GP_PIN(2, 9), ++ RCAR_GP_PIN(2, 10), RCAR_GP_PIN(2, 11), ++ RCAR_GP_PIN(2, 12), RCAR_GP_PIN(2, 13), ++}; ++static const unsigned int vin0_data10_mux[] = { ++ VI0_DATA0_MARK, VI0_DATA1_MARK, ++ VI0_DATA2_MARK, VI0_DATA3_MARK, ++ VI0_DATA4_MARK, VI0_DATA5_MARK, ++ VI0_DATA6_MARK, VI0_DATA7_MARK, ++ VI0_DATA8_MARK, VI0_DATA9_MARK, ++}; ++static const unsigned int vin0_data12_pins[] = { ++ RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 5), ++ RCAR_GP_PIN(2, 6), RCAR_GP_PIN(2, 7), ++ RCAR_GP_PIN(2, 8), RCAR_GP_PIN(2, 9), ++ RCAR_GP_PIN(2, 10), RCAR_GP_PIN(2, 11), ++ RCAR_GP_PIN(2, 12), RCAR_GP_PIN(2, 13), ++ RCAR_GP_PIN(2, 14), RCAR_GP_PIN(2, 15), ++}; ++static const unsigned int vin0_data12_mux[] = { ++ VI0_DATA0_MARK, VI0_DATA1_MARK, ++ VI0_DATA2_MARK, VI0_DATA3_MARK, ++ VI0_DATA4_MARK, VI0_DATA5_MARK, ++ VI0_DATA6_MARK, VI0_DATA7_MARK, ++ VI0_DATA8_MARK, VI0_DATA9_MARK, ++ VI0_DATA10_MARK, VI0_DATA11_MARK, ++}; ++static const unsigned int vin0_sync_pins[] = { ++ /* VSYNC_N, HSYNC_N */ ++ RCAR_GP_PIN(2, 3), RCAR_GP_PIN(2, 2), ++}; ++static const unsigned int vin0_sync_mux[] = { ++ VI0_HSYNC_N_MARK, VI0_VSYNC_N_MARK, ++}; ++static const unsigned int vin0_field_pins[] = { ++ /* FIELD */ ++ RCAR_GP_PIN(2, 16), ++}; ++static const unsigned int vin0_field_mux[] = { ++ VI0_FIELD_MARK, ++}; ++static const unsigned int vin0_clkenb_pins[] = { ++ /* CLKENB */ ++ RCAR_GP_PIN(2, 1), ++}; ++static const unsigned int vin0_clkenb_mux[] = { ++ VI0_CLKENB_MARK, ++}; ++static const unsigned int vin0_clk_pins[] = { ++ /* CLK */ ++ RCAR_GP_PIN(2, 0), ++}; ++static const unsigned int vin0_clk_mux[] = { ++ VI0_CLK_MARK, ++}; ++/* - VIN1 ------------------------------------------------------------------- */ ++static const unsigned int vin1_data8_pins[] = { ++ RCAR_GP_PIN(3, 4), RCAR_GP_PIN(3, 5), ++ RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7), ++ RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9), ++ RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 11), ++}; ++static const unsigned int vin1_data8_mux[] = { ++ VI1_DATA0_MARK, VI1_DATA1_MARK, ++ VI1_DATA2_MARK, VI1_DATA3_MARK, ++ VI1_DATA4_MARK, VI1_DATA5_MARK, ++ VI1_DATA6_MARK, VI1_DATA7_MARK, ++}; ++static const unsigned int vin1_data10_pins[] = { ++ RCAR_GP_PIN(3, 4), RCAR_GP_PIN(3, 5), ++ RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7), ++ RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9), ++ RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 11), ++ RCAR_GP_PIN(3, 12), RCAR_GP_PIN(3, 13), ++}; ++static const unsigned int vin1_data10_mux[] = { ++ VI1_DATA0_MARK, VI1_DATA1_MARK, ++ VI1_DATA2_MARK, VI1_DATA3_MARK, ++ VI1_DATA4_MARK, VI1_DATA5_MARK, ++ VI1_DATA6_MARK, VI1_DATA7_MARK, ++ VI1_DATA8_MARK, VI1_DATA9_MARK, ++}; ++static const unsigned int vin1_data12_pins[] = { ++ RCAR_GP_PIN(3, 4), RCAR_GP_PIN(3, 5), ++ RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7), ++ RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9), ++ RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 11), ++ RCAR_GP_PIN(3, 12), RCAR_GP_PIN(3, 13), ++ RCAR_GP_PIN(3, 14), RCAR_GP_PIN(3, 15), ++}; ++static const unsigned int vin1_data12_mux[] = { ++ VI1_DATA0_MARK, VI1_DATA1_MARK, ++ VI1_DATA2_MARK, VI1_DATA3_MARK, ++ VI1_DATA4_MARK, VI1_DATA5_MARK, ++ VI1_DATA6_MARK, VI1_DATA7_MARK, ++ VI1_DATA8_MARK, VI1_DATA9_MARK, ++ VI1_DATA10_MARK, VI1_DATA11_MARK, ++}; ++static const unsigned int vin1_sync_pins[] = { ++ /* VSYNC_N, HSYNC_N */ ++ RCAR_GP_PIN(3, 3), RCAR_GP_PIN(3, 2), ++}; ++static const unsigned int vin1_sync_mux[] = { ++ VI1_HSYNC_N_MARK, VI1_VSYNC_N_MARK, ++}; ++static const unsigned int vin1_field_pins[] = { ++ RCAR_GP_PIN(3, 16), ++}; ++static const unsigned int vin1_field_mux[] = { ++ /* FIELD */ ++ VI1_FIELD_MARK, ++}; ++static const unsigned int vin1_clkenb_pins[] = { ++ RCAR_GP_PIN(3, 1), ++}; ++static const unsigned int vin1_clkenb_mux[] = { ++ /* CLKENB */ ++ VI1_CLKENB_MARK, ++}; ++static const unsigned int vin1_clk_pins[] = { ++ RCAR_GP_PIN(3, 0), ++}; ++static const unsigned int vin1_clk_mux[] = { ++ /* CLK */ ++ VI1_CLK_MARK, ++}; ++ ++static const struct sh_pfc_pin_group pinmux_groups[] = { ++ SH_PFC_PIN_GROUP(avb0_rx_ctrl), ++ SH_PFC_PIN_GROUP(avb0_rxc), ++ SH_PFC_PIN_GROUP(avb0_rd0), ++ SH_PFC_PIN_GROUP(avb0_rd1), ++ SH_PFC_PIN_GROUP(avb0_rd2), ++ SH_PFC_PIN_GROUP(avb0_rd3), ++ SH_PFC_PIN_GROUP(avb0_rd4), ++ SH_PFC_PIN_GROUP(avb0_tx_ctrl), ++ SH_PFC_PIN_GROUP(avb0_txc), ++ SH_PFC_PIN_GROUP(avb0_td0), ++ SH_PFC_PIN_GROUP(avb0_td1), ++ SH_PFC_PIN_GROUP(avb0_td2), ++ SH_PFC_PIN_GROUP(avb0_td3), ++ SH_PFC_PIN_GROUP(avb0_td4), ++ SH_PFC_PIN_GROUP(avb0_txcrefclk), ++ SH_PFC_PIN_GROUP(avb0_mdio), ++ SH_PFC_PIN_GROUP(avb0_mdc), ++ SH_PFC_PIN_GROUP(avb0_magic), ++ SH_PFC_PIN_GROUP(avb0_phy_int), ++ SH_PFC_PIN_GROUP(avb0_link), ++ SH_PFC_PIN_GROUP(avb0_avtp_match), ++ SH_PFC_PIN_GROUP(avb0_avtp_pps), ++ SH_PFC_PIN_GROUP(avb0_avtp_capture), ++ SH_PFC_PIN_GROUP(canfd0_data_a), ++ SH_PFC_PIN_GROUP(canfd_clk_a), ++ SH_PFC_PIN_GROUP(canfd0_data_b), ++ SH_PFC_PIN_GROUP(canfd_clk_b), ++ SH_PFC_PIN_GROUP(canfd1_data), ++ SH_PFC_PIN_GROUP(du_rgb666), ++ SH_PFC_PIN_GROUP(du_clk_out_0), ++ SH_PFC_PIN_GROUP(du_clk_out_1), ++ SH_PFC_PIN_GROUP(du_sync), ++ SH_PFC_PIN_GROUP(du_oddf), ++ SH_PFC_PIN_GROUP(du_cde), ++ SH_PFC_PIN_GROUP(du_disp), ++ SH_PFC_PIN_GROUP(hscif0_data), ++ SH_PFC_PIN_GROUP(hscif0_clk), ++ SH_PFC_PIN_GROUP(hscif0_ctrl), ++ SH_PFC_PIN_GROUP(hscif1_data), ++ SH_PFC_PIN_GROUP(hscif1_clk), ++ SH_PFC_PIN_GROUP(hscif1_ctrl), ++ SH_PFC_PIN_GROUP(hscif2_data), ++ SH_PFC_PIN_GROUP(hscif2_clk), ++ SH_PFC_PIN_GROUP(hscif2_ctrl), ++ SH_PFC_PIN_GROUP(hscif3_data), ++ SH_PFC_PIN_GROUP(hscif3_clk), ++ SH_PFC_PIN_GROUP(hscif3_ctrl), ++ SH_PFC_PIN_GROUP(scif_clk_a), ++ SH_PFC_PIN_GROUP(scif_clk_b), ++ SH_PFC_PIN_GROUP(i2c0), ++ SH_PFC_PIN_GROUP(i2c1), ++ SH_PFC_PIN_GROUP(i2c2), ++ SH_PFC_PIN_GROUP(i2c3), ++ SH_PFC_PIN_GROUP(i2c4), ++ SH_PFC_PIN_GROUP(intc_ex_irq0), ++ SH_PFC_PIN_GROUP(intc_ex_irq1), ++ SH_PFC_PIN_GROUP(intc_ex_irq2), ++ SH_PFC_PIN_GROUP(intc_ex_irq3), ++ SH_PFC_PIN_GROUP(intc_ex_irq4), ++ SH_PFC_PIN_GROUP(intc_ex_irq5), ++ SH_PFC_PIN_GROUP(msiof0_clk), ++ SH_PFC_PIN_GROUP(msiof0_sync), ++ SH_PFC_PIN_GROUP(msiof0_ss1), ++ SH_PFC_PIN_GROUP(msiof0_ss2), ++ SH_PFC_PIN_GROUP(msiof0_txd), ++ SH_PFC_PIN_GROUP(msiof0_rxd), ++ SH_PFC_PIN_GROUP(msiof1_clk), ++ SH_PFC_PIN_GROUP(msiof1_sync), ++ SH_PFC_PIN_GROUP(msiof1_ss1), ++ SH_PFC_PIN_GROUP(msiof1_ss2), ++ SH_PFC_PIN_GROUP(msiof1_txd), ++ SH_PFC_PIN_GROUP(msiof1_rxd), ++ SH_PFC_PIN_GROUP(msiof2_clk), ++ SH_PFC_PIN_GROUP(msiof2_sync), ++ SH_PFC_PIN_GROUP(msiof2_ss1), ++ SH_PFC_PIN_GROUP(msiof2_ss2), ++ SH_PFC_PIN_GROUP(msiof2_txd), ++ SH_PFC_PIN_GROUP(msiof2_rxd), ++ SH_PFC_PIN_GROUP(msiof3_clk), ++ SH_PFC_PIN_GROUP(msiof3_sync), ++ SH_PFC_PIN_GROUP(msiof3_ss1), ++ SH_PFC_PIN_GROUP(msiof3_ss2), ++ SH_PFC_PIN_GROUP(msiof3_txd), ++ SH_PFC_PIN_GROUP(msiof3_rxd), ++ SH_PFC_PIN_GROUP(pwm0_a), ++ SH_PFC_PIN_GROUP(pwm0_b), ++ SH_PFC_PIN_GROUP(pwm1_a), ++ SH_PFC_PIN_GROUP(pwm1_b), ++ SH_PFC_PIN_GROUP(pwm2_a), ++ SH_PFC_PIN_GROUP(pwm2_b), ++ SH_PFC_PIN_GROUP(pwm3_a), ++ SH_PFC_PIN_GROUP(pwm3_b), ++ SH_PFC_PIN_GROUP(pwm4_a), ++ SH_PFC_PIN_GROUP(pwm4_b), ++ SH_PFC_PIN_GROUP(scif0_data), ++ //SH_PFC_PIN_GROUP(scif0_clk), ++ //SH_PFC_PIN_GROUP(scif0_ctrl), ++ SH_PFC_PIN_GROUP(scif1_data_a), ++ SH_PFC_PIN_GROUP(scif1_clk), ++ SH_PFC_PIN_GROUP(scif1_ctrl), ++ SH_PFC_PIN_GROUP(scif1_data_b), ++ SH_PFC_PIN_GROUP(scif3_data), ++ SH_PFC_PIN_GROUP(scif3_clk), ++ SH_PFC_PIN_GROUP(scif3_ctrl), ++ SH_PFC_PIN_GROUP(scif4_data), ++ SH_PFC_PIN_GROUP(scif4_clk), ++ SH_PFC_PIN_GROUP(scif4_ctrl), ++ SH_PFC_PIN_GROUP(mmc_data1), ++ SH_PFC_PIN_GROUP(mmc_data4), ++ SH_PFC_PIN_GROUP(mmc_data8), ++ SH_PFC_PIN_GROUP(mmc_ctrl), ++ SH_PFC_PIN_GROUP(mmc_cd), ++ SH_PFC_PIN_GROUP(mmc_wp), ++ SH_PFC_PIN_GROUP(tmu_tclk1_a), ++ SH_PFC_PIN_GROUP(tmu_tclk1_b), ++ SH_PFC_PIN_GROUP(tmu_tclk2_a), ++ SH_PFC_PIN_GROUP(tmu_tclk2_b), ++ SH_PFC_PIN_GROUP(vin0_data8), ++ SH_PFC_PIN_GROUP(vin0_data10), ++ SH_PFC_PIN_GROUP(vin0_data12), ++ SH_PFC_PIN_GROUP(vin0_sync), ++ SH_PFC_PIN_GROUP(vin0_field), ++ SH_PFC_PIN_GROUP(vin0_clkenb), ++ SH_PFC_PIN_GROUP(vin0_clk), ++ SH_PFC_PIN_GROUP(vin1_data8), ++ SH_PFC_PIN_GROUP(vin1_data10), ++ SH_PFC_PIN_GROUP(vin1_data12), ++ SH_PFC_PIN_GROUP(vin1_sync), ++ SH_PFC_PIN_GROUP(vin1_field), ++ SH_PFC_PIN_GROUP(vin1_clkenb), ++ SH_PFC_PIN_GROUP(vin1_clk), ++}; ++ ++static const char * const avb0_groups[] = { ++ "avb0_rx_ctrl", ++ "avb0_rxc", ++ "avb0_rd1", ++ "avb0_rd4", ++ "avb0_tx_ctrl", ++ "avb0_txc", ++ "avb0_td1", ++ "avb0_td4", ++ "avb0_txcrefclk", ++ "avb0_mdio", ++ "avb0_mdc", ++ "avb0_magic", ++ "avb0_phy_int", ++ "avb0_link", ++ "avb0_avtp_match", ++ "avb0_avtp_pps", ++ "avb0_avtp_capture", ++}; ++ ++static const char * const canfd0_groups[] = { ++ "canfd0_data_a", ++ "canfd0_clk_a", ++ "canfd0_data_b", ++ "canfd0_clk_b", ++}; ++ ++static const char * const canfd1_groups[] = { ++ "canfd1_data", ++}; ++ ++static const char * const du_groups[] = { ++ "du_rgb666", ++ "du_clk_out_0", ++ "du_clk_out_1", ++ "du_sync", ++ "du_oddf", ++ "du_cde", ++ "du_disp", ++}; ++ ++static const char * const hscif0_groups[] = { ++ "hscif0_data", ++ "hscif0_clk", ++ "hscif0_ctrl", ++}; ++ ++static const char * const hscif1_groups[] = { ++ "hscif1_data", ++ "hscif1_clk", ++ "hscif1_ctrl", ++}; ++ ++static const char * const hscif2_groups[] = { ++ "hscif2_data", ++ "hscif2_clk", ++ "hscif2_ctrl", ++}; ++ ++static const char * const hscif3_groups[] = { ++ "hscif3_data", ++ "hscif3_clk", ++ "hscif3_ctrl", ++}; ++ ++static const char * const scif_clk_groups[] = { ++ "scif_clk_a", ++ "scif_clk_b", ++}; ++ ++static const char * const i2c0_groups[] = { ++ "i2c0", ++}; ++ ++static const char * const i2c1_groups[] = { ++ "i2c1", ++}; ++ ++static const char * const i2c2_groups[] = { ++ "i2c2", ++}; ++ ++static const char * const i2c3_groups[] = { ++ "i2c3", ++}; ++ ++static const char * const i2c4_groups[] = { ++ "i2c4", ++}; ++ ++static const char * const intc_ex_groups[] = { ++ "intc_ex_irq0", ++ "intc_ex_irq1", ++ "intc_ex_irq2", ++ "intc_ex_irq3", ++ "intc_ex_irq4", ++ "intc_ex_irq5", ++}; ++ ++static const char * const msiof0_groups[] = { ++ "msiof0_clk", ++ "msiof0_sync", ++ "msiof0_ss1", ++ "msiof0_ss2", ++ "msiof0_txd", ++ "msiof0_rxd", ++}; ++ ++static const char * const msiof1_groups[] = { ++ "msiof1_clk", ++ "msiof1_sync", ++ "msiof1_ss1", ++ "msiof1_ss2", ++ "msiof1_txd", ++ "msiof1_rxd", ++}; ++ ++static const char * const msiof2_groups[] = { ++ "msiof2_clk", ++ "msiof2_sync", ++ "msiof2_ss1", ++ "msiof2_ss2", ++ "msiof2_txd", ++ "msiof2_rxd", ++}; ++ ++static const char * const msiof3_groups[] = { ++ "msiof3_clk", ++ "msiof3_sync", ++ "msiof3_ss1", ++ "msiof3_ss2", ++ "msiof3_txd", ++ "msiof3_rxd", ++}; ++ ++static const char * const pwm0_groups[] = { ++ "pwm0_a", ++ "pwm0_b", ++}; ++ ++static const char * const pwm1_groups[] = { ++ "pwm1_a", ++ "pwm1_b", ++}; ++ ++static const char * const pwm2_groups[] = { ++ "pwm2_a", ++ "pwm2_b", ++}; ++ ++static const char * const pwm3_groups[] = { ++ "pwm3_a", ++ "pwm3_b", ++}; ++ ++static const char * const pwm4_groups[] = { ++ "pwm4_a", ++ "pwm4_b", ++}; ++ ++static const char * const scif0_groups[] = { ++ "scif0_data", ++// "scif0_clk", ++// "scif0_ctl", ++}; ++ ++static const char * const scif1_groups[] = { ++ "scif1_data_a", ++ "scif1_clk", ++ "scif1_ctl", ++ "scif1_data_b", ++}; ++ ++static const char * const scif3_groups[] = { ++ "scif3_data", ++ "scif3_clk", ++ "scif3_ctl", ++}; ++ ++static const char * const scif4_groups[] = { ++ "scif4_data", ++ "scif4_clk", ++ "scif4_ctl", ++}; ++ ++static const char * const mmc_groups[] = { ++ "mmc_data1", ++ "mmc_data4", ++ "mmc_data8", ++ "mmc_ctrl", ++ "mmc_cd", ++ "mmc_wp", ++}; ++ ++static const char * const tmu_groups[] = { ++ "tmu_tclk1_a", ++ "tmu_tclk1_b", ++ "tmu_tclk2_a", ++ "tmu_tclk2_b", ++}; ++ ++static const char * const vin0_groups[] = { ++ "vin0_data8", ++ "vin0_data10", ++ "vin0_data12", ++ "vin0_sync", ++ "vin0_field", ++ "vin0_clkenb", ++ "vin0_clk", ++}; ++ ++static const char * const vin1_groups[] = { ++ "vin1_data8", ++ "vin1_data10", ++ "vin1_data12", ++ "vin1_sync", ++ "vin1_field", ++ "vin1_clkenb", ++ "vin1_clk", ++}; ++ ++#define POCCTRL0 0x380 ++#define POCCTRL1 0x384 ++#define PIN2POCCTRL0_SHIFT(a) ({ \ ++ int _gp = (a) >> 5; \ ++ int _bit = (a) & 0x1f; \ ++ ((_gp == 3) && (_bit < 12)) ? _bit : \ ++ ((_gp == 4) && (_bit < 18)) ? _bit + 12 : -1; \ ++}) ++ ++#if 0 ++static int r8a7797_get_io_voltage(struct sh_pfc *pfc, unsigned int pin) ++{ ++ void __iomem *reg; ++ u32 data, mask; ++ int shift; ++ ++ /* Bits in POCCTRL0 are numbered in opposite order to pins */ ++ shift = PIN2POCCTRL0_SHIFT(pin); ++ ++ if (WARN(shift < 0, "invalid pin %#x", pin)) ++ return -EINVAL; ++ ++ reg = pfc->windows->virt + POCCTRL0; ++ data = ioread32(reg); ++ ++ mask = 0x1 << shift; ++ ++ return (data & mask) ? 3300 : 1800; ++} ++ ++static int r8a7797_set_io_voltage(struct sh_pfc *pfc, unsigned int pin, u16 mV) ++{ ++ void __iomem *reg; ++ u32 data, mask; ++ int shift; ++ ++ /* Bits in POCCTRL0 are numbered in opposite order to pins */ ++ shift = PIN2POCCTRL0_SHIFT(pin); ++ ++ if (WARN(shift < 0, "invalid pin %#x", pin)) ++ return -EINVAL; ++ ++ if (mV != 1800 && mV != 3300) ++ return -EINVAL; ++ ++ reg = pfc->windows->virt + POCCTRL0; ++ data = ioread32(reg); ++ ++ mask = 0x1 << shift; ++ ++ if (mV == 3300) ++ data |= mask; ++ else ++ data &= ~mask; ++ ++ ++ iowrite32(~data, pfc->windows->virt + ++ (pfc->info->unlock_reg - pfc->windows->phys)); ++ iowrite32(data, reg); ++ ++ return 0; ++} ++#endif ++ ++static const struct sh_pfc_function pinmux_functions[] = { ++ SH_PFC_FUNCTION(avb0), ++ SH_PFC_FUNCTION(canfd0), ++ SH_PFC_FUNCTION(canfd1), ++ SH_PFC_FUNCTION(du), ++ SH_PFC_FUNCTION(hscif0), ++ SH_PFC_FUNCTION(hscif1), ++ SH_PFC_FUNCTION(hscif2), ++ SH_PFC_FUNCTION(hscif3), ++ SH_PFC_FUNCTION(scif_clk), ++ SH_PFC_FUNCTION(i2c0), ++ SH_PFC_FUNCTION(i2c1), ++ SH_PFC_FUNCTION(i2c2), ++ SH_PFC_FUNCTION(i2c3), ++ SH_PFC_FUNCTION(i2c4), ++ SH_PFC_FUNCTION(intc_ex), ++ SH_PFC_FUNCTION(msiof0), ++ SH_PFC_FUNCTION(msiof1), ++ SH_PFC_FUNCTION(msiof2), ++ SH_PFC_FUNCTION(msiof3), ++ SH_PFC_FUNCTION(pwm0), ++ SH_PFC_FUNCTION(pwm1), ++ SH_PFC_FUNCTION(pwm2), ++ SH_PFC_FUNCTION(pwm3), ++ SH_PFC_FUNCTION(pwm4), ++ SH_PFC_FUNCTION(scif0), ++ SH_PFC_FUNCTION(scif1), ++ SH_PFC_FUNCTION(scif3), ++ SH_PFC_FUNCTION(scif4), ++ SH_PFC_FUNCTION(mmc), ++ SH_PFC_FUNCTION(tmu), ++ SH_PFC_FUNCTION(vin0), ++ SH_PFC_FUNCTION(vin1), ++}; ++ ++static const struct pinmux_cfg_reg pinmux_config_regs[] = { ++#define F_(x, y) FN_##y ++#define FM(x) FN_##x ++ { PINMUX_CFG_REG("GPSR0", 0xe6060100, 32, 1) { ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ GP_0_21_FN, GPSR0_21, ++ GP_0_20_FN, GPSR0_20, ++ GP_0_19_FN, GPSR0_19, ++ GP_0_18_FN, GPSR0_18, ++ GP_0_17_FN, GPSR0_17, ++ GP_0_16_FN, GPSR0_16, ++ GP_0_15_FN, GPSR0_15, ++ GP_0_14_FN, GPSR0_14, ++ GP_0_13_FN, GPSR0_13, ++ GP_0_12_FN, GPSR0_12, ++ GP_0_11_FN, GPSR0_11, ++ GP_0_10_FN, GPSR0_10, ++ GP_0_9_FN, GPSR0_9, ++ GP_0_8_FN, GPSR0_8, ++ GP_0_7_FN, GPSR0_7, ++ GP_0_6_FN, GPSR0_6, ++ GP_0_5_FN, GPSR0_5, ++ GP_0_4_FN, GPSR0_4, ++ GP_0_3_FN, GPSR0_3, ++ GP_0_2_FN, GPSR0_2, ++ GP_0_1_FN, GPSR0_1, ++ GP_0_0_FN, GPSR0_0, } ++ }, ++ { PINMUX_CFG_REG("GPSR1", 0xe6060104, 32, 1) { ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ GP_1_27_FN, GPSR1_27, ++ GP_1_26_FN, GPSR1_26, ++ GP_1_25_FN, GPSR1_25, ++ GP_1_24_FN, GPSR1_24, ++ GP_1_23_FN, GPSR1_23, ++ GP_1_22_FN, GPSR1_22, ++ GP_1_21_FN, GPSR1_21, ++ GP_1_20_FN, GPSR1_20, ++ GP_1_19_FN, GPSR1_19, ++ GP_1_18_FN, GPSR1_18, ++ GP_1_17_FN, GPSR1_17, ++ GP_1_16_FN, GPSR1_16, ++ GP_1_15_FN, GPSR1_15, ++ GP_1_14_FN, GPSR1_14, ++ GP_1_13_FN, GPSR1_13, ++ GP_1_12_FN, GPSR1_12, ++ GP_1_11_FN, GPSR1_11, ++ GP_1_10_FN, GPSR1_10, ++ GP_1_9_FN, GPSR1_9, ++ GP_1_8_FN, GPSR1_8, ++ GP_1_7_FN, GPSR1_7, ++ GP_1_6_FN, GPSR1_6, ++ GP_1_5_FN, GPSR1_5, ++ GP_1_4_FN, GPSR1_4, ++ GP_1_3_FN, GPSR1_3, ++ GP_1_2_FN, GPSR1_2, ++ GP_1_1_FN, GPSR1_1, ++ GP_1_0_FN, GPSR1_0, } ++ }, ++ { PINMUX_CFG_REG("GPSR2", 0xe6060108, 32, 1) { ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ GP_2_16_FN, GPSR2_16, ++ GP_2_15_FN, GPSR2_15, ++ GP_2_14_FN, GPSR2_14, ++ GP_2_13_FN, GPSR2_13, ++ GP_2_12_FN, GPSR2_12, ++ GP_2_11_FN, GPSR2_11, ++ GP_2_10_FN, GPSR2_10, ++ GP_2_9_FN, GPSR2_9, ++ GP_2_8_FN, GPSR2_8, ++ GP_2_7_FN, GPSR2_7, ++ GP_2_6_FN, GPSR2_6, ++ GP_2_5_FN, GPSR2_5, ++ GP_2_4_FN, GPSR2_4, ++ GP_2_3_FN, GPSR2_3, ++ GP_2_2_FN, GPSR2_2, ++ GP_2_1_FN, GPSR2_1, ++ GP_2_0_FN, GPSR2_0, } ++ }, ++ { PINMUX_CFG_REG("GPSR3", 0xe606010c, 32, 1) { ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ GP_3_16_FN, GPSR3_16, ++ GP_3_15_FN, GPSR3_15, ++ GP_3_14_FN, GPSR3_14, ++ GP_3_13_FN, GPSR3_13, ++ GP_3_12_FN, GPSR3_12, ++ GP_3_11_FN, GPSR3_11, ++ GP_3_10_FN, GPSR3_10, ++ GP_3_9_FN, GPSR3_9, ++ GP_3_8_FN, GPSR3_8, ++ GP_3_7_FN, GPSR3_7, ++ GP_3_6_FN, GPSR3_6, ++ GP_3_5_FN, GPSR3_5, ++ GP_3_4_FN, GPSR3_4, ++ GP_3_3_FN, GPSR3_3, ++ GP_3_2_FN, GPSR3_2, ++ GP_3_1_FN, GPSR3_1, ++ GP_3_0_FN, GPSR3_0, } ++ }, ++ { PINMUX_CFG_REG("GPSR4", 0xe6060110, 32, 1) { ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ GP_4_5_FN, GPSR4_5, ++ GP_4_4_FN, GPSR4_4, ++ GP_4_3_FN, GPSR4_3, ++ GP_4_2_FN, GPSR4_2, ++ GP_4_1_FN, GPSR4_1, ++ GP_4_0_FN, GPSR4_0, } ++ }, ++ { PINMUX_CFG_REG("GPSR5", 0xe6060114, 32, 1) { ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ GP_5_14_FN, GPSR5_14, ++ GP_5_13_FN, GPSR5_13, ++ GP_5_12_FN, GPSR5_12, ++ GP_5_11_FN, GPSR5_11, ++ GP_5_10_FN, GPSR5_10, ++ GP_5_9_FN, GPSR5_9, ++ GP_5_8_FN, GPSR5_8, ++ GP_5_7_FN, GPSR5_7, ++ GP_5_6_FN, GPSR5_6, ++ GP_5_5_FN, GPSR5_5, ++ GP_5_4_FN, GPSR5_4, ++ GP_5_3_FN, GPSR5_3, ++ GP_5_2_FN, GPSR5_2, ++ GP_5_1_FN, GPSR5_1, ++ GP_5_0_FN, GPSR5_0, } ++ }, ++#undef F_ ++#undef FM ++ ++#define F_(x, y) x, ++#define FM(x) FN_##x, ++ { PINMUX_CFG_REG("IPSR0", 0xe6060200, 32, 4) { ++ IP0_31_28 ++ IP0_27_24 ++ IP0_23_20 ++ IP0_19_16 ++ IP0_15_12 ++ IP0_11_8 ++ IP0_7_4 ++ IP0_3_0 } ++ }, ++ { PINMUX_CFG_REG("IPSR1", 0xe6060204, 32, 4) { ++ IP1_31_28 ++ IP1_27_24 ++ IP1_23_20 ++ IP1_19_16 ++ IP1_15_12 ++ IP1_11_8 ++ IP1_7_4 ++ IP1_3_0 } ++ }, ++ { PINMUX_CFG_REG("IPSR2", 0xe6060208, 32, 4) { ++ IP2_31_28 ++ IP2_27_24 ++ IP2_23_20 ++ IP2_19_16 ++ IP2_15_12 ++ IP2_11_8 ++ IP2_7_4 ++ IP2_3_0 } ++ }, ++ { PINMUX_CFG_REG("IPSR3", 0xe606020c, 32, 4) { ++ IP3_31_28 ++ IP3_27_24 ++ IP3_23_20 ++ IP3_19_16 ++ IP3_15_12 ++ IP3_11_8 ++ IP3_7_4 ++ IP3_3_0 } ++ }, ++ { PINMUX_CFG_REG("IPSR4", 0xe6060210, 32, 4) { ++ IP4_31_28 ++ IP4_27_24 ++ IP4_23_20 ++ IP4_19_16 ++ IP4_15_12 ++ IP4_11_8 ++ IP4_7_4 ++ IP4_3_0 } ++ }, ++ { PINMUX_CFG_REG("IPSR5", 0xe6060214, 32, 4) { ++ IP5_31_28 ++ IP5_27_24 ++ IP5_23_20 ++ IP5_19_16 ++ IP5_15_12 ++ IP5_11_8 ++ IP5_7_4 ++ IP5_3_0 } ++ }, ++ { PINMUX_CFG_REG("IPSR6", 0xe6060218, 32, 4) { ++ IP6_31_28 ++ IP6_27_24 ++ IP6_23_20 ++ IP6_19_16 ++ IP6_15_12 ++ IP6_11_8 ++ IP6_7_4 ++ IP6_3_0 } ++ }, ++ { PINMUX_CFG_REG("IPSR7", 0xe606021c, 32, 4) { ++ IP7_31_28 ++ IP7_27_24 ++ IP7_23_20 ++ IP7_19_16 ++ IP7_15_12 ++ IP7_11_8 ++ IP7_7_4 ++ IP7_3_0 } ++ }, ++ { PINMUX_CFG_REG("IPSR8", 0xe6060220, 32, 4) { ++ IP8_31_28 ++ IP8_27_24 ++ IP8_23_20 ++ IP8_19_16 ++ IP8_15_12 ++ IP8_11_8 ++ IP8_7_4 ++ IP8_3_0 } ++ }, ++#undef F_ ++#undef FM ++ ++#define F_(x, y) x, ++#define FM(x) FN_##x, ++ { PINMUX_CFG_REG_VAR("MOD_SEL0", 0xe6060500, 32, ++ 4, 4, 4, 4, 1, ++ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) { ++ /* RESERVED 31, 30, 29, 28 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ /* RESERVED 27, 26, 25, 24 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ /* RESERVED 23, 22, 21, 20 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ /* RESERVED 19, 18, 17, 16 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ /* RESERVED 15, 14, 13, 12 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, /* RESERVED 11 */ ++ MOD_SEL0_10 ++ MOD_SEL0_9 ++ MOD_SEL0_8 ++ MOD_SEL0_7 ++ MOD_SEL0_6 ++ MOD_SEL0_5 ++ MOD_SEL0_4 ++ MOD_SEL0_3 ++ MOD_SEL0_2 ++ MOD_SEL0_1 ++ MOD_SEL0_0 } ++ }, ++ { }, ++}; ++ ++static const struct sh_pfc_soc_operations pinmux_ops = { ++#if 0 ++ .get_io_voltage = r8a7797_get_io_voltage, ++ .set_io_voltage = r8a7797_set_io_voltage, ++#endif ++}; ++ ++const struct sh_pfc_soc_info r8a7797_pinmux_info = { ++ .name = "r8a77970_pfc", ++ .ops = &pinmux_ops, ++ .unlock_reg = 0xe6060000, /* PMMR */ ++ ++ .function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END }, ++ ++ .pins = pinmux_pins, ++ .nr_pins = ARRAY_SIZE(pinmux_pins), ++ .groups = pinmux_groups, ++ .nr_groups = ARRAY_SIZE(pinmux_groups), ++ .functions = pinmux_functions, ++ .nr_functions = ARRAY_SIZE(pinmux_functions), ++ ++ .cfg_regs = pinmux_config_regs, ++ ++ .pinmux_data = pinmux_data, ++ .pinmux_data_size = ARRAY_SIZE(pinmux_data), ++}; +diff --git a/drivers/pinctrl/sh-pfc/sh_pfc.h b/drivers/pinctrl/sh-pfc/sh_pfc.h +index c6a1855..a673a00 100644 +--- a/drivers/pinctrl/sh-pfc/sh_pfc.h ++++ b/drivers/pinctrl/sh-pfc/sh_pfc.h +@@ -269,6 +269,7 @@ struct sh_pfc_soc_info { + extern const struct sh_pfc_soc_info r8a7795_pinmux_info; + extern const struct sh_pfc_soc_info r8a7795_es1_pinmux_info; + extern const struct sh_pfc_soc_info r8a7796_pinmux_info; ++extern const struct sh_pfc_soc_info r8a7797_pinmux_info; + extern const struct sh_pfc_soc_info sh7203_pinmux_info; + extern const struct sh_pfc_soc_info sh7264_pinmux_info; + extern const struct sh_pfc_soc_info sh7269_pinmux_info; +@@ -374,6 +375,11 @@ struct sh_pfc_soc_info { + PORT_GP_CFG_1(bank, 3, fn, sfx, cfg) + #define PORT_GP_4(bank, fn, sfx) PORT_GP_CFG_4(bank, fn, sfx, 0) + ++#define PORT_GP_CFG_6(bank, fn, sfx, cfg) \ ++ PORT_GP_CFG_4(bank, fn, sfx, cfg), \ ++ PORT_GP_CFG_1(bank, 4, fn, sfx, cfg), PORT_GP_CFG_1(bank, 5, fn, sfx, cfg) ++#define PORT_GP_6(bank, fn, sfx) PORT_GP_CFG_6(bank, fn, sfx, 0) ++ + #define PORT_GP_CFG_8(bank, fn, sfx, cfg) \ + PORT_GP_CFG_4(bank, fn, sfx, cfg), \ + PORT_GP_CFG_1(bank, 4, fn, sfx, cfg), \ +@@ -420,6 +426,12 @@ struct sh_pfc_soc_info { + PORT_GP_CFG_1(bank, 17, fn, sfx, cfg) + #define PORT_GP_18(bank, fn, sfx) PORT_GP_CFG_18(bank, fn, sfx, 0) + ++#define PORT_GP_CFG_22(bank, fn, sfx, cfg) \ ++ PORT_GP_CFG_18(bank, fn, sfx, cfg), \ ++ PORT_GP_CFG_1(bank, 18, fn, sfx, cfg), PORT_GP_CFG_1(bank, 19, fn, sfx, cfg), \ ++ PORT_GP_CFG_1(bank, 20, fn, sfx, cfg), PORT_GP_CFG_1(bank, 21, fn, sfx, cfg) ++#define PORT_GP_22(bank, fn, sfx) PORT_GP_CFG_22(bank, fn, sfx, 0) ++ + #define PORT_GP_CFG_23(bank, fn, sfx, cfg) \ + PORT_GP_CFG_18(bank, fn, sfx, cfg), \ + PORT_GP_CFG_1(bank, 18, fn, sfx, cfg), \ +diff --git a/drivers/soc/renesas/Makefile b/drivers/soc/renesas/Makefile +index 504fb05..df143fe 100644 +--- a/drivers/soc/renesas/Makefile ++++ b/drivers/soc/renesas/Makefile +@@ -16,11 +16,14 @@ obj-$(CONFIG_ARCH_R8A7793) += rcar-sysc.o r8a7791-sysc.o + obj-$(CONFIG_ARCH_R8A7794) += rcar-sysc.o r8a7794-sysc.o + obj-$(CONFIG_ARCH_R8A7795) += rcar-sysc.o r8a7795-sysc.o + obj-$(CONFIG_ARCH_R8A7796) += rcar-sysc.o r8a7796-sysc.o ++obj-$(CONFIG_ARCH_R8A7797) += rcar-sysc.o r8a7797-sysc.o + + obj-$(CONFIG_ARCH_R8A7795) += rcar-avs.o + obj-$(CONFIG_ARCH_R8A7796) += rcar-avs.o ++obj-$(CONFIG_ARCH_R8A7797) += rcar-avs.o + # EMS for R-Car Gen3 + obj-$(CONFIG_ARCH_R8A7795) += rcar_ems_ctrl.o + obj-$(CONFIG_ARCH_R8A7796) += rcar_ems_ctrl.o ++obj-$(CONFIG_ARCH_R8A7797) += rcar_ems_ctrl.o + + obj-$(CONFIG_RCAR_DDR_BACKUP) += s2ram_ddr_backup.o +diff --git a/drivers/soc/renesas/r8a7797-sysc.c b/drivers/soc/renesas/r8a7797-sysc.c +new file mode 100644 +index 0000000..b71bdedb +--- /dev/null ++++ b/drivers/soc/renesas/r8a7797-sysc.c +@@ -0,0 +1,39 @@ ++/* ++ * Renesas R-Car V3M System Controller ++ * ++ * Copyright (C) 2016 Glider bvba ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; version 2 of the License. ++ */ ++ ++#include <linux/bug.h> ++#include <linux/kernel.h> ++ ++#include <dt-bindings/power/r8a7797-sysc.h> ++ ++#include "rcar-sysc.h" ++ ++static const struct rcar_sysc_area r8a7797_areas[] __initconst = { ++ { "always-on", 0, 0, R8A7797_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, ++ { "ca53-scu", 0x140, 0, R8A7797_PD_CA53_SCU, R8A7797_PD_ALWAYS_ON, ++ PD_SCU }, ++ { "ca53-cpu0", 0x200, 0, R8A7797_PD_CA53_CPU0, R8A7797_PD_CA53_SCU, ++ PD_CPU_NOCR }, ++ { "ca53-cpu1", 0x200, 1, R8A7797_PD_CA53_CPU1, R8A7797_PD_CA53_SCU, ++ PD_CPU_NOCR }, ++ { "cr7", 0x240, 0, R8A7797_PD_CR7, R8A7797_PD_ALWAYS_ON }, ++ { "a3ir", 0x180, 0, R8A7797_PD_A3IR, R8A7797_PD_ALWAYS_ON }, ++ { "a2ir0", 0x400, 0, R8A7797_PD_A2IR0, R8A7797_PD_ALWAYS_ON }, ++ { "a2ir1", 0x400, 1, R8A7797_PD_A2IR1, R8A7797_PD_A2IR0 }, ++ { "a2ir2", 0x400, 2, R8A7797_PD_A2IR2, R8A7797_PD_A2IR0 }, ++ { "a2ir3", 0x400, 3, R8A7797_PD_A2IR3, R8A7797_PD_A2IR0 }, ++ { "a2sc0", 0x400, 4, R8A7797_PD_A2SC0, R8A7797_PD_ALWAYS_ON }, ++ { "a2sc1", 0x400, 5, R8A7797_PD_A2SC1, R8A7797_PD_A2SC0 }, ++}; ++ ++const struct rcar_sysc_info r8a7797_sysc_info __initconst = { ++ .areas = r8a7797_areas, ++ .num_areas = ARRAY_SIZE(r8a7797_areas), ++}; +diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c +index 042500a..e6165b6 100644 +--- a/drivers/soc/renesas/rcar-sysc.c ++++ b/drivers/soc/renesas/rcar-sysc.c +@@ -320,6 +320,9 @@ static void __init rcar_sysc_pd_setup(struct rcar_sysc_pd *pd) + #ifdef CONFIG_ARCH_R8A7796 + { .compatible = "renesas,r8a7796-sysc", .data = &r8a7796_sysc_info }, + #endif ++#ifdef CONFIG_ARCH_R8A7797 ++ { .compatible = "renesas,r8a7797-sysc", .data = &r8a7797_sysc_info }, ++#endif + { /* sentinel */ } + }; + +diff --git a/drivers/soc/renesas/rcar-sysc.h b/drivers/soc/renesas/rcar-sysc.h +index f6e842e..e7980d5 100644 +--- a/drivers/soc/renesas/rcar-sysc.h ++++ b/drivers/soc/renesas/rcar-sysc.h +@@ -59,4 +59,5 @@ struct rcar_sysc_info { + extern const struct rcar_sysc_info r8a7794_sysc_info; + extern const struct rcar_sysc_info r8a7795_sysc_info; + extern const struct rcar_sysc_info r8a7796_sysc_info; ++extern const struct rcar_sysc_info r8a7797_sysc_info; + #endif /* __SOC_RENESAS_RCAR_SYSC_H__ */ +diff --git a/drivers/soc/renesas/rcar_ems_ctrl.c b/drivers/soc/renesas/rcar_ems_ctrl.c +index ca9af73..388c570 100644 +--- a/drivers/soc/renesas/rcar_ems_ctrl.c ++++ b/drivers/soc/renesas/rcar_ems_ctrl.c +@@ -24,11 +24,17 @@ + #include <linux/pm_runtime.h> + #include <linux/spinlock.h> + #include <linux/thermal.h> ++#include <linux/sys_soc.h> + + #include <linux/soc/renesas/rcar_ems_ctrl.h> + + #define EMS_THERMAL_ZONE_MAX 10 + ++static const struct soc_device_attribute r8a7797[] = { ++ { .soc_id = "r8a7797" }, ++ { } ++}; ++ + static void rcar_ems_monitor(struct work_struct *ws); + static DECLARE_DELAYED_WORK(rcar_ems_monitor_work, rcar_ems_monitor); + +@@ -268,6 +274,10 @@ static int __init rcar_ems_cpu_shutdown_init(void) + + for_each_online_cpu(cpu) { + tmp_node = of_get_cpu_node(cpu, NULL); ++ if (soc_device_match(r8a7797)) { ++ if (!of_device_is_compatible(tmp_node, "arm,cortex-a53")) ++ continue; ++ } + if (!of_device_is_compatible(tmp_node, "arm,cortex-a57")) + continue; + for (i = 0; i < total_target_cpu; i++) { +diff --git a/drivers/soc/renesas/renesas-soc.c b/drivers/soc/renesas/renesas-soc.c +index 5cab1b5..9d6fdb0 100644 +--- a/drivers/soc/renesas/renesas-soc.c ++++ b/drivers/soc/renesas/renesas-soc.c +@@ -134,6 +134,11 @@ struct renesas_soc { + .id = 0x52, + }; + ++static const struct renesas_soc soc_rcar_v3m __initconst __maybe_unused = { ++ .family = &fam_rcar_gen3, ++ .id = 0x54, ++}; ++ + static const struct renesas_soc soc_shmobile_ag5 __initconst __maybe_unused = { + .family = &fam_shmobile, + .id = 0x37, +@@ -183,6 +188,9 @@ struct renesas_soc { + #ifdef CONFIG_ARCH_R8A7796 + { .compatible = "renesas,r8a7796", .data = &soc_rcar_m3_w }, + #endif ++#ifdef CONFIG_ARCH_R8A7797 ++ { .compatible = "renesas,r8a7797", .data = &soc_rcar_v3m }, ++#endif + #ifdef CONFIG_ARCH_SH73A0 + { .compatible = "renesas,sh73a0", .data = &soc_shmobile_ag5 }, + #endif +diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c +index 996869e..3281dc7 100644 +--- a/drivers/spi/spi-sh-msiof.c ++++ b/drivers/spi/spi-sh-msiof.c +@@ -215,7 +215,8 @@ static int msiof_rcar_is_gen3(struct device *dev) + struct device_node *node = dev->of_node; + + return of_device_is_compatible(node, "renesas,msiof-r8a7795") || +- of_device_is_compatible(node, "renesas,msiof-r8a7796"); ++ of_device_is_compatible(node, "renesas,msiof-r8a7796") || ++ of_device_is_compatible(node, "renesas,msiof-r8a7797"); + } + + static u32 sh_msiof_read(struct sh_msiof_spi_priv *p, int reg_offs) +@@ -1188,6 +1189,7 @@ static int sh_msiof_transfer_one(struct spi_master *master, + { .compatible = "renesas,msiof-r8a7794", .data = &r8a779x_data }, + { .compatible = "renesas,msiof-r8a7795", .data = &r8a779x_data }, + { .compatible = "renesas,msiof-r8a7796", .data = &r8a779x_data }, ++ { .compatible = "renesas,msiof-r8a7797", .data = &r8a779x_data }, + {}, + }; + MODULE_DEVICE_TABLE(of, sh_msiof_match); +diff --git a/drivers/thermal/rcar_gen3_thermal.c b/drivers/thermal/rcar_gen3_thermal.c +index 39763c7..07b1a2e 100644 +--- a/drivers/thermal/rcar_gen3_thermal.c ++++ b/drivers/thermal/rcar_gen3_thermal.c +@@ -385,6 +385,30 @@ static int rcar_gen3_r8a7795_thermal_init(struct rcar_thermal_priv *priv) + return 0; + } + ++/* @@ transitional */ ++static int rcar_gen3_r8a7797_thermal_init(struct rcar_thermal_priv *priv) ++{ ++#if 0 ++ unsigned long flags; ++ unsigned long reg_val; ++ ++ spin_lock_irqsave(&priv->lock, flags); ++ rcar_thermal_write(priv, REG_GEN3_THCTR, 0x0); ++ udelay(1000); ++ rcar_thermal_write(priv, REG_GEN3_IRQCTL, 0x3F); ++ rcar_thermal_write(priv, REG_GEN3_IRQEN, ++ IRQ_TEMP1_BIT | IRQ_TEMPD2_BIT); ++ rcar_thermal_write(priv, REG_GEN3_THCTR, CTCTL | THCNTSEN(BIT_LEN_12)); ++ reg_val = rcar_thermal_read(priv, REG_GEN3_THCTR); ++ reg_val &= ~CTCTL; ++ reg_val |= THSST; ++ rcar_thermal_write(priv, REG_GEN3_THCTR, reg_val); ++ ++ spin_unlock_irqrestore(&priv->lock, flags); ++#endif ++ return 0; ++} ++ + /* + * Interrupt + */ +@@ -466,9 +490,14 @@ static int rcar_gen3_thermal_remove(struct platform_device *pdev) + .thermal_init = rcar_gen3_r8a7796_thermal_init, + }; + ++static const struct rcar_thermal_data r8a7797_data = { ++ .thermal_init = rcar_gen3_r8a7797_thermal_init, ++}; ++ + static const struct of_device_id rcar_thermal_dt_ids[] = { + { .compatible = "renesas,thermal-r8a7795", .data = &r8a7795_data}, + { .compatible = "renesas,thermal-r8a7796", .data = &r8a7796_data}, ++ { .compatible = "renesas,thermal-r8a7797", .data = &r8a7797_data}, + {}, + }; + MODULE_DEVICE_TABLE(of, rcar_thermal_dt_ids); +diff --git a/include/dt-bindings/clock/r8a7797-cpg-mssr.h b/include/dt-bindings/clock/r8a7797-cpg-mssr.h +new file mode 100644 +index 0000000..ae6b3af +--- /dev/null ++++ b/include/dt-bindings/clock/r8a7797-cpg-mssr.h +@@ -0,0 +1,48 @@ ++/* ++ * Copyright (C) 2016 Renesas Electronics Corp. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++#ifndef __DT_BINDINGS_CLOCK_R8A7797_CPG_MSSR_H__ ++#define __DT_BINDINGS_CLOCK_R8A7797_CPG_MSSR_H__ ++ ++#include <dt-bindings/clock/renesas-cpg-mssr.h> ++ ++/* r8a7797 CPG Core Clocks */ ++#define R8A7797_CLK_Z2 0 ++#define R8A7797_CLK_ZR 1 ++#define R8A7797_CLK_ZTR 2 ++#define R8A7797_CLK_ZTRD2 3 ++#define R8A7797_CLK_ZT 4 ++#define R8A7797_CLK_ZX 5 ++#define R8A7797_CLK_S1D1 6 ++#define R8A7797_CLK_S1D2 7 ++#define R8A7797_CLK_S1D4 8 ++#define R8A7797_CLK_S2D1 9 ++#define R8A7797_CLK_S2D2 10 ++#define R8A7797_CLK_S2D4 11 ++#define R8A7797_CLK_LB 12 ++#define R8A7797_CLK_CL 13 ++#define R8A7797_CLK_ZB3 14 ++#define R8A7797_CLK_ZB3D2 15 ++#define R8A7797_CLK_DDR 16 ++#define R8A7797_CLK_CR 17 ++#define R8A7797_CLK_CRD2 18 ++#define R8A7797_CLK_SD0H 19 ++#define R8A7797_CLK_SD0 20 ++#define R8A7797_CLK_RPC 21 ++#define R8A7797_CLK_RPCD2 22 ++#define R8A7797_CLK_MSO 23 ++#define R8A7797_CLK_CANFD 24 ++#define R8A7797_CLK_CSI0 25 ++#define R8A7797_CLK_CSIREF 26 ++#define R8A7797_CLK_FRAY 27 ++#define R8A7797_CLK_CP 28 ++#define R8A7797_CLK_CPEX 29 ++#define R8A7797_CLK_R 30 ++#define R8A7797_CLK_OSC 31 ++ ++#endif /* __DT_BINDINGS_CLOCK_R8A7797_CPG_MSSR_H__ */ +diff --git a/include/dt-bindings/power/r8a7797-sysc.h b/include/dt-bindings/power/r8a7797-sysc.h +new file mode 100644 +index 0000000..5aef212 +--- /dev/null ++++ b/include/dt-bindings/power/r8a7797-sysc.h +@@ -0,0 +1,32 @@ ++/* ++ * Copyright (C) 2016 Glider bvba ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; version 2 of the License. ++ */ ++#ifndef __DT_BINDINGS_POWER_R8A7797_SYSC_H__ ++#define __DT_BINDINGS_POWER_R8A7797_SYSC_H__ ++ ++/* ++ * These power domain indices match the numbers of the interrupt bits ++ * representing the power areas in the various Interrupt Registers ++ * (e.g. SYSCISR, Interrupt Status Register) ++ */ ++ ++#define R8A7797_PD_CA53_CPU0 5 ++#define R8A7797_PD_CA53_CPU1 6 ++#define R8A7797_PD_CR7 13 ++#define R8A7797_PD_CA53_SCU 21 ++#define R8A7797_PD_A2IR0 23 ++#define R8A7797_PD_A3IR 24 ++#define R8A7797_PD_A2IR1 27 ++#define R8A7797_PD_A2IR2 28 ++#define R8A7797_PD_A2IR3 29 ++#define R8A7797_PD_A2SC0 30 ++#define R8A7797_PD_A2SC1 31 ++ ++/* Always-on power area */ ++#define R8A7797_PD_ALWAYS_ON 32 ++ ++#endif /* __DT_BINDINGS_POWER_R8A7797_SYSC_H__ */ +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0019-Revert-media-v4l2-async-remove-unneeded-.registered_.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0019-Revert-media-v4l2-async-remove-unneeded-.registered_.patch new file mode 100644 index 0000000..72c22f5 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0019-Revert-media-v4l2-async-remove-unneeded-.registered_.patch @@ -0,0 +1,54 @@ +From 050637736af144f4bfb096f5f47120c477349732 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Sun, 14 May 2017 15:23:57 +0300 +Subject: [PATCH] Revert "[media] v4l2-async: remove unneeded .registered_async + callback" + +This reverts commit a53d2f299dc83340c695e153363a2f21641d5f58. +--- + drivers/media/v4l2-core/v4l2-async.c | 7 +++++++ + include/media/v4l2-subdev.h | 3 +++ + 2 files changed, 10 insertions(+) + +diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c +index 5bada20..a4b224d 100644 +--- a/drivers/media/v4l2-core/v4l2-async.c ++++ b/drivers/media/v4l2-core/v4l2-async.c +@@ -119,6 +119,13 @@ static int v4l2_async_test_notify(struct v4l2_async_notifier *notifier, + return ret; + } + ++ ret = v4l2_subdev_call(sd, core, registered_async); ++ if (ret < 0 && ret != -ENOIOCTLCMD) { ++ if (notifier->unbind) ++ notifier->unbind(notifier, sd, asd); ++ return ret; ++ } ++ + if (list_empty(¬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..7b08da4 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0022-ASoC-Modify-check-condition-of-multiple-bindings-of-.patch @@ -0,0 +1,42 @@ +From 2fc4f16b075264fae016ea3db1f1f81d30cb0ab6 Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +Date: Tue, 13 Dec 2016 18:08:39 +0300 +Subject: [PATCH 102/104] ASoC: Modify check condition of multiple bindings of + components + +https://patchwork.kernel.org/patch/7385501/ +...and some more hacks to bind one component (with several DAIs) +to more than one sound card. + +Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +--- + sound/soc/soc-core.c | 6 ++++-- + 2 files changed, 4 insertions(+), 14 deletions(-) + +diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c +index 16369ca..899d013 100644 +--- a/sound/soc/soc-core.c ++++ b/sound/soc/soc-core.c +@@ -1373,7 +1373,8 @@ static int soc_probe_component(struct snd_soc_card *card, + return 0; + + if (component->card) { +- if (component->card != card) { ++ if (component->card != card && ++ component->registered_as_component) { + dev_err(component->dev, + "Trying to bind component to card \"%s\" but is already bound to card \"%s\"\n", + card->name, component->card->name); +@@ -3049,7 +3050,8 @@ int snd_soc_register_component(struct device *dev, + goto err_free; + + cmpnt->ignore_pmdown_time = true; +- cmpnt->registered_as_component = true; ++ if (num_dai == 1) ++ cmpnt->registered_as_component = true; + + ret = snd_soc_register_dais(cmpnt, dai_drv, num_dai, true); + if (ret < 0) { +-- +1.7.10.4 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0023-ASoC-add-dummy-Si468x-driver.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0023-ASoC-add-dummy-Si468x-driver.patch new file mode 100644 index 0000000..fa27dc1 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0023-ASoC-add-dummy-Si468x-driver.patch @@ -0,0 +1,123 @@ +From 8829efb30ecbecde33a266ddaed25a74cebbbaf2 Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +Date: Tue, 13 Dec 2016 18:07:13 +0300 +Subject: [PATCH 103/104] ASoC: add dummy Si468x driver + + +Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +--- + sound/soc/codecs/Kconfig | 3 +++ + sound/soc/codecs/Makefile | 2 ++ + sound/soc/codecs/si468x.c | 66 +++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 71 insertions(+) + create mode 100644 sound/soc/codecs/si468x.c + +diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig +index 4d82a58..264fe79 100644 +--- a/sound/soc/codecs/Kconfig ++++ b/sound/soc/codecs/Kconfig +@@ -588,6 +588,9 @@ config SND_SOC_PCM3168A_SPI + select SND_SOC_PCM3168A + select REGMAP_SPI + ++config SND_SOC_SI468X ++ tristate "Dummy sound driver for Si468x radio" ++ + config SND_SOC_PCM5102A + tristate + +diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile +index 0f548fd3..71a6c2f 100644 +--- a/sound/soc/codecs/Makefile ++++ b/sound/soc/codecs/Makefile +@@ -116,6 +116,7 @@ snd-soc-sigmadsp-objs := sigmadsp.o + snd-soc-sigmadsp-i2c-objs := sigmadsp-i2c.o + snd-soc-sigmadsp-regmap-objs := sigmadsp-regmap.o + snd-soc-si476x-objs := si476x.o ++snd-soc-si468x-objs := si468x.o + snd-soc-sirf-audio-codec-objs := sirf-audio-codec.o + snd-soc-sn95031-objs := sn95031.o + snd-soc-spdif-tx-objs := spdif_transmitter.o +@@ -328,6 +329,7 @@ obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o + obj-$(CONFIG_SND_SOC_SIGMADSP_I2C) += snd-soc-sigmadsp-i2c.o + obj-$(CONFIG_SND_SOC_SIGMADSP_REGMAP) += snd-soc-sigmadsp-regmap.o + obj-$(CONFIG_SND_SOC_SI476X) += snd-soc-si476x.o ++obj-$(CONFIG_SND_SOC_SI468X) += snd-soc-si468x.o + obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o + obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif-rx.o snd-soc-spdif-tx.o + obj-$(CONFIG_SND_SOC_SSM2518) += snd-soc-ssm2518.o +diff --git a/sound/soc/codecs/si468x.c b/sound/soc/codecs/si468x.c +new file mode 100644 +index 0000000..18b099f +--- /dev/null ++++ b/sound/soc/codecs/si468x.c +@@ -0,0 +1,66 @@ ++/* ++ * Dummy sound driver for Si468x DAB/FM/AM chips ++ * Copyright 2016 Andrey Gusakov <andrey.gusakov@cogentembedded.com> ++ * ++ * Based on: Driver for the DFBM-CS320 bluetooth module ++ * Copyright 2011 Lars-Peter Clausen <lars@metafoo.de> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ * ++ */ ++ ++#include <linux/init.h> ++#include <linux/module.h> ++#include <linux/platform_device.h> ++ ++#include <sound/soc.h> ++ ++static struct snd_soc_dai_driver si468x_dai = { ++ .name = "si468x-pcm", ++ .capture = { ++ .channels_min = 2, ++ .channels_max = 2, ++ .rates = SNDRV_PCM_RATE_48000, ++ .formats = SNDRV_PCM_FMTBIT_S16_LE, ++ }, ++}; ++ ++static struct snd_soc_codec_driver soc_codec_dev_si468x; ++ ++static int si468x_probe(struct platform_device *pdev) ++{ ++ return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_si468x, ++ &si468x_dai, 1); ++} ++ ++static int si468x_remove(struct platform_device *pdev) ++{ ++ snd_soc_unregister_codec(&pdev->dev); ++ ++ return 0; ++} ++ ++static const struct of_device_id si468x_of_match[] = { ++ { .compatible = "si,si468x-pcm", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, si468x_of_match); ++ ++static struct platform_driver si468x_driver = { ++ .driver = { ++ .name = "si468x", ++ .of_match_table = si468x_of_match, ++ .owner = THIS_MODULE, ++ }, ++ .probe = si468x_probe, ++ .remove = si468x_remove, ++}; ++ ++module_platform_driver(si468x_driver); ++ ++MODULE_AUTHOR("Andrey Gusakov <andrey.gusakov@cogentembedded.com>"); ++MODULE_DESCRIPTION("ASoC Si468x radio chip driver"); ++MODULE_LICENSE("GPL"); +-- +1.7.10.4 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0030-Gen3-LVDS-cameras.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0030-Gen3-LVDS-cameras.patch new file mode 100644 index 0000000..f927db2 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0030-Gen3-LVDS-cameras.patch @@ -0,0 +1,6491 @@ +From 7a6b0c38e5e1502f309b89b16fad8c70645e1221 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Sun, 14 May 2017 15:20:01 +0300 +Subject: [PATCH] Gen3: LVDS cameras + +This add Gen3 LVDS cameras support: +- deserializers: MAX9286, TI964, TI953, TI960 +- cameras: 10635, ov490+ov10640, ov495+OV2775 + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + drivers/media/i2c/soc_camera/Kconfig | 47 + + drivers/media/i2c/soc_camera/Makefile | 7 + + drivers/media/i2c/soc_camera/max9286_max9271.c | 562 +++++++++++ + drivers/media/i2c/soc_camera/max9286_max9271.h | 196 ++++ + drivers/media/i2c/soc_camera/ov10635.c | 751 ++++++++++++++ + drivers/media/i2c/soc_camera/ov10635.h | 1139 ++++++++++++++++++++++ + drivers/media/i2c/soc_camera/ov10635_debug.h | 54 + + drivers/media/i2c/soc_camera/ov106xx.c | 95 ++ + drivers/media/i2c/soc_camera/ov490_ov10640.c | 963 ++++++++++++++++++ + drivers/media/i2c/soc_camera/ov490_ov10640.h | 33 + + drivers/media/i2c/soc_camera/ov495_ov2775.c | 670 +++++++++++++ + drivers/media/i2c/soc_camera/ov495_ov2775.h | 18 + + drivers/media/i2c/soc_camera/ti954_ti9x3.c | 414 ++++++++ + drivers/media/i2c/soc_camera/ti964_ti9x3.c | 382 ++++++++ + drivers/media/i2c/soc_camera/ti9x4_ti9x3.h | 108 ++ + drivers/media/platform/soc_camera/rcar_csi2.c | 253 +++-- + drivers/media/platform/soc_camera/rcar_vin.c | 159 ++- + drivers/media/platform/soc_camera/soc_camera.c | 17 +- + drivers/media/platform/soc_camera/soc_mediabus.c | 16 + + include/media/drv-intf/soc_mediabus.h | 3 + + include/media/soc_camera.h | 1 + + 21 files changed, 5781 insertions(+), 107 deletions(-) + create mode 100644 drivers/media/i2c/soc_camera/max9286_max9271.c + create mode 100644 drivers/media/i2c/soc_camera/max9286_max9271.h + create mode 100644 drivers/media/i2c/soc_camera/ov10635.c + create mode 100644 drivers/media/i2c/soc_camera/ov10635.h + create mode 100644 drivers/media/i2c/soc_camera/ov10635_debug.h + create mode 100644 drivers/media/i2c/soc_camera/ov106xx.c + create mode 100644 drivers/media/i2c/soc_camera/ov490_ov10640.c + create mode 100644 drivers/media/i2c/soc_camera/ov490_ov10640.h + create mode 100644 drivers/media/i2c/soc_camera/ov495_ov2775.c + create mode 100644 drivers/media/i2c/soc_camera/ov495_ov2775.h + create mode 100644 drivers/media/i2c/soc_camera/ti954_ti9x3.c + create mode 100644 drivers/media/i2c/soc_camera/ti964_ti9x3.c + create mode 100644 drivers/media/i2c/soc_camera/ti9x4_ti9x3.h + +diff --git a/drivers/media/i2c/soc_camera/Kconfig b/drivers/media/i2c/soc_camera/Kconfig +index 7704bcf..82da59f 100644 +--- a/drivers/media/i2c/soc_camera/Kconfig ++++ b/drivers/media/i2c/soc_camera/Kconfig +@@ -6,6 +6,53 @@ config SOC_CAMERA_IMX074 + help + This driver supports IMX074 cameras from Sony + ++config SOC_CAMERA_MAX9286_MAX9271 ++ tristate "max9286-max9271 GMSL support" ++ depends on SOC_CAMERA && I2C ++ help ++ This is a MAXIM max9286-max9271 GMSL driver ++ ++config SOC_CAMERA_OV106XX ++ tristate "ov106xx camera support" ++ depends on SOC_CAMERA && SOC_CAMERA_MAX9286_MAX9271 && I2C ++ help ++ This is a runtime detected OmniVision ov10635 or ov490-ov10640 ++ or ov495-ov2775 sensors camera driver ++ ++if !SOC_CAMERA_OV106XX ++ ++config SOC_CAMERA_OV10635 ++ tristate "ov10635 camera support" ++ depends on SOC_CAMERA && SOC_CAMERA_MAX9286_MAX9271 && I2C ++ help ++ This is an OmniVision ov10635 sensor camera driver ++ ++config SOC_CAMERA_OV490_OV10640 ++ tristate "ov490-ov10640 camera support" ++ depends on SOC_CAMERA && SOC_CAMERA_MAX9286_MAX9271 && I2C ++ help ++ This is an OmniVision ov490-ov10640 sensor camera driver ++ ++config SOC_CAMERA_OV495_OV2775 ++ tristate "ov495-ov2775 camera support" ++ depends on SOC_CAMERA && I2C ++ help ++ This is an OmniVision ov495-ov2775 sensor camera driver ++ ++endif ++ ++config SOC_CAMERA_TI964_TI9X3 ++ tristate "ti964-ti9x3 FPDLinkIII support" ++ depends on SOC_CAMERA && I2C ++ help ++ This is an Texas Instruments ti964-ti9X3 FPDLinkIII driver ++ ++config SOC_CAMERA_TI954_TI9X3 ++ tristate "ti954-ti9X3 FPDLinkIII support" ++ depends on SOC_CAMERA && I2C ++ help ++ This is an Texas Instruments ti954-ti9X3 FPDLinkIII driver ++ + config SOC_CAMERA_MT9M001 + tristate "mt9m001 support" + depends on SOC_CAMERA && I2C +diff --git a/drivers/media/i2c/soc_camera/Makefile b/drivers/media/i2c/soc_camera/Makefile +index 6f994f9..7d4c1ab 100644 +--- a/drivers/media/i2c/soc_camera/Makefile ++++ b/drivers/media/i2c/soc_camera/Makefile +@@ -1,8 +1,15 @@ + obj-$(CONFIG_SOC_CAMERA_IMX074) += imx074.o ++obj-$(CONFIG_SOC_CAMERA_MAX9286_MAX9271) += max9286_max9271.o ++obj-$(CONFIG_SOC_CAMERA_TI964_TI9X3) += ti964_ti9x3.o ++obj-$(CONFIG_SOC_CAMERA_TI954_TI9X3) += ti954_ti9x3.o + obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o + obj-$(CONFIG_SOC_CAMERA_MT9T031) += mt9t031.o + obj-$(CONFIG_SOC_CAMERA_MT9T112) += mt9t112.o + obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o ++obj-$(CONFIG_SOC_CAMERA_OV10635) += ov10635.o ++obj-$(CONFIG_SOC_CAMERA_OV490_OV10640) += ov490_ov10640.o ++obj-$(CONFIG_SOC_CAMERA_OV495_OV2775) += ov495_ov2775.o ++obj-$(CONFIG_SOC_CAMERA_OV106XX) += ov106xx.o + obj-$(CONFIG_SOC_CAMERA_OV2640) += ov2640.o + obj-$(CONFIG_SOC_CAMERA_OV5642) += ov5642.o + obj-$(CONFIG_SOC_CAMERA_OV6650) += ov6650.o +diff --git a/drivers/media/i2c/soc_camera/max9286_max9271.c b/drivers/media/i2c/soc_camera/max9286_max9271.c +new file mode 100644 +index 0000000..1261e45 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/max9286_max9271.c +@@ -0,0 +1,562 @@ ++/* ++ * MAXIM max9286-max9271 GMSL driver ++ * ++ * Copyright (C) 2015-2017 Cogent Embedded, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ */ ++ ++#include <linux/delay.h> ++#include <linux/i2c.h> ++#include <linux/module.h> ++#include <linux/of_gpio.h> ++#include <linux/videodev2.h> ++#include <linux/notifier.h> ++ ++#include <media/v4l2-common.h> ++#include <media/v4l2-device.h> ++#include <media/v4l2-of.h> ++#include <media/v4l2-subdev.h> ++ ++#include "max9286_max9271.h" ++ ++#define MAXIM_I2C_I2C_SPEED_837KHZ (0x7 << 2) /* 837kbps */ ++#define MAXIM_I2C_I2C_SPEED_533KHZ (0x6 << 2) /* 533kbps */ ++#define MAXIM_I2C_I2C_SPEED_339KHZ (0x5 << 2) /* 339 kbps */ ++#define MAXIM_I2C_I2C_SPEED_173KHZ (0x4 << 2) /* 174kbps */ ++#define MAXIM_I2C_I2C_SPEED_105KHZ (0x3 << 2) /* 105 kbps */ ++#define MAXIM_I2C_I2C_SPEED_085KHZ (0x2 << 2) /* 84.7 kbps */ ++#define MAXIM_I2C_I2C_SPEED_028KHZ (0x1 << 2) /* 28.3 kbps */ ++#define MAXIM_I2C_I2C_SPEED MAXIM_I2C_I2C_SPEED_339KHZ ++ ++struct max9286_max9271_priv { ++ struct v4l2_subdev sd[4]; ++ struct device_node *sd_of_node[4]; ++ int des_addr; ++ int des_quirk_addr; /* second MAX9286 on the same I2C bus */ ++ int links; ++ int links_mask; ++ int lanes; ++ int csi_rate; ++ const char *fsync_mode; ++ int fsync_period; ++ char pclk_rising_edge; ++ int gpio_resetb; ++ int active_low_resetb; ++ int timeout; ++ atomic_t use_count; ++ u32 csi2_outord; ++ struct i2c_client *client; ++ int max9271_addr_map[4]; ++}; ++ ++static int force_conf_link; ++ ++static __init int max9286_max9271_force_conf_link(char *str) ++{ ++ /* force configuration link */ ++ /* used only if robust firmware flashing required (f.e. recovery) */ ++ force_conf_link = 1; ++ return 0; ++} ++early_param("force_conf_link", max9286_max9271_force_conf_link); ++ ++static void max9286_max9271_preinit(struct i2c_client *client, int addr) ++{ ++ client->addr = addr; /* MAX9286-CAMx I2C */ ++ reg8_write(client, 0x0a, 0x00); /* disable reverse control for all cams */ ++ reg8_write(client, 0x00, 0x00); /* disable all GMSL links [0:3] */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++} ++ ++static void max9286_max9271_postinit(struct i2c_client *client, int addr) ++{ ++ struct max9286_max9271_priv *priv = i2c_get_clientdata(client); ++ ++ client->addr = addr; /* MAX9286 I2C */ ++ reg8_write(client, 0x0a, 0x00); /* disable reverse control for all cams */ ++ reg8_write(client, 0x00, 0xe0 | priv->links_mask); /* enable GMSL link for CAMs */ ++ reg8_write(client, 0x0b, priv->csi2_outord); /* CSI2 output order */ ++ reg8_write(client, 0x15, 0x9b); /* enable CSI output, VC is set accordingly to Link number, BIT7 magic must be set */ ++ reg8_write(client, 0x1b, priv->links_mask); /* enable equalizer for CAMs */ ++ usleep_range(5000, 5500); /* wait 2ms after any change of reverse channel settings */ ++ ++ /* wait for sensor firmware up (f.e. ov490) if we did sensor reset */ ++ if (priv->gpio_resetb >= 1 && priv->gpio_resetb <= 5) ++ mdelay(300); ++} ++ ++static int max9286_max9271_reverse_channel_setup(struct i2c_client *client, int idx) ++{ ++ struct max9286_max9271_priv *priv = i2c_get_clientdata(client); ++ u8 val = 0; ++ int timeout = priv->timeout; ++ int ret = 0; ++ ++ /* Reverse channel enable */ ++ client->addr = priv->des_addr; /* MAX9286-CAMx I2C */ ++ reg8_write(client, 0x3f, 0x4f); /* enable custom reverse channel & first pulse length */ ++ reg8_write(client, 0x34, 0xa2 | MAXIM_I2C_I2C_SPEED); /* enable artificial ACKs, I2C speed set */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ reg8_write(client, 0x00, 0xe0 | BIT(idx)); /* enable GMSL link for CAMx */ ++ reg8_write(client, 0x0a, 0x11 << idx); /* enable reverse control for CAMx */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ ++ for (;;) { ++ client->addr = priv->des_addr; /* MAX9286-CAMx I2C */ ++ reg8_write(client, 0x3b, 0x1e); /* first pulse length rise time changed from 300ns to 200ns, amplitude 100mV */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ ++ client->addr = 0x40; /* MAX9271-CAMx I2C */ ++ reg8_write(client, 0x08, 0x1); /* reverse channel receiver high threshold enable */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ ++ client->addr = priv->des_addr; /* MAX9286-CAMx I2C */ ++ reg8_write(client, 0x3b, 0x19); /* reverse channel increase amplitude 170mV to compensate high threshold enabled */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ ++ client->addr = 0x40; /* MAX9271-CAMx I2C */ ++ reg8_write(client, 0x04, 0x43); /* wake-up, enable reverse_control/conf_link */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ ++ client->addr = 0x40; /* MAX9271-CAMx I2C */ ++ reg8_read(client, 0x1e, &val); /* read max9271 ID */ ++ if (val == MAX9271_ID || --timeout == 0) ++ break; ++ ++ /* Check if already initialized (after reboot/reset ?) */ ++ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C */ ++ reg8_read(client, 0x1e, &val); /* read max9271 ID */ ++ if (val == MAX9271_ID) { ++ reg8_write(client, 0x04, 0x43); /* enable reverse_control/conf_link */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ ret = -EADDRINUSE; ++ break; ++ } ++ } ++ ++ if (!timeout) { ++ ret = -ETIMEDOUT; ++ goto out; ++ } ++ ++ priv->links_mask |= BIT(idx); ++ priv->csi2_outord &= ~(0x3 << (idx * 2)); ++ priv->csi2_outord |= ((hweight8(priv->links_mask) - 1) << (idx * 2)); ++ ++out: ++ dev_info(&client->dev, "link%d MAX9271 %sat 0x%x %s\n", idx, ++ ret == -EADDRINUSE ? "already " : "", priv->max9271_addr_map[idx], ++ ret == -ETIMEDOUT ? "not found: timeout GMSL link establish" : ""); ++ ++ return ret; ++} ++ ++static void max9286_max9271_initial_setup(struct i2c_client *client) ++{ ++ struct max9286_max9271_priv *priv = i2c_get_clientdata(client); ++ ++ /* Initial setup */ ++ client->addr = priv->des_addr; /* MAX9286-CAMx I2C */ ++ reg8_write(client, 0x15, 0x13); /* disable CSI output, VC is set accordingly to Link number */ ++ reg8_write(client, 0x69, 0x0f); /* mask CSI forwarding from all links */ ++ switch (priv->lanes) { ++ case 1: ++ reg8_write(client, 0x12, 0x33); /* enable CSI-2 Lane D0, DBL mode, YUV422 8-bit*/ ++ break; ++ case 2: ++ reg8_write(client, 0x12, 0x73); /* enable CSI-2 Lanes D0,D1, DBL mode, YUV422 8-bit*/ ++ break; ++ case 3: ++ reg8_write(client, 0x12, 0xd3); /* enable CSI-2 Lanes D0-D2, DBL mode, YUV422 8-bit*/ ++ break; ++ case 4: ++ reg8_write(client, 0x12, 0xf3); /* enable CSI-2 Lanes D0-D3, DBL mode, YUV422 8-bit*/ ++ break; ++ default: ++ dev_err(&client->dev, "CSI2 lanes number is invalid (%d)\n", priv->lanes); ++ } ++ ++ if (strcmp(priv->fsync_mode, "manual") == 0) { ++ reg8_write(client, 0x06, priv->fsync_period & 0xff); ++ reg8_write(client, 0x07, (priv->fsync_period >> 8) & 0xff); ++ reg8_write(client, 0x08, priv->fsync_period >> 16); ++ reg8_write(client, 0x01, 0x00); /* manual: FRAMESYNC set manually via [0x06:0x08] regs */ ++ } else if (strcmp(priv->fsync_mode, "automatic") == 0) { ++ reg8_write(client, 0x01, 0x02); /* automatic: FRAMESYNC taken from the slowest Link */ ++ } else if (strcmp(priv->fsync_mode, "semi-automatic") == 0) { ++ reg8_write(client, 0x01, 0x01); /* semi-automatic: FRAMESYNC taken from the slowest Link */ ++ } else if (strcmp(priv->fsync_mode, "external") == 0) { ++ reg8_write(client, 0x01, 0xc0); /* ECU (aka MCU) based FrameSync using GPI-to-GPO */ ++ } ++ ++ reg8_write(client, 0x63, 0); /* disable overlap window */ ++ reg8_write(client, 0x64, 0); ++ reg8_write(client, 0x0c, 0x89); /* enable HS/VS encoding, use D14/15 for HS/VS, invert VS */ ++} ++ ++static void max9286_max9271_gmsl_link_setup(struct i2c_client *client, int idx) ++{ ++ struct max9286_max9271_priv *priv = i2c_get_clientdata(client); ++ ++ /* GMSL setup */ ++ client->addr = 0x40; /* MAX9271-CAMx I2C */ ++ reg8_write(client, 0x0d, 0x22 | MAXIM_I2C_I2C_SPEED); /* disable artificial ACK, I2C speed set */ ++ reg8_write(client, 0x07, 0x84 | (priv->pclk_rising_edge ? 0 : 0x10)); /* RAW/YUV, PCLK edge, HS/VS encoding enabled */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x02, 0xff); /* spread spectrum +-4%, pclk range automatic, Gbps automatic */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ ++ client->addr = priv->des_addr; /* MAX9286-CAMx I2C */ ++ reg8_write(client, 0x34, 0x22 | MAXIM_I2C_I2C_SPEED); /* disable artificial ACK, I2C speed set */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ ++ /* I2C translator setup */ ++ client->addr = 0x40; /* MAX9271-CAMx I2C */ ++// reg8_write(client, 0x09, maxim_map[2][idx] << 1); /* SENSOR I2C translated - must be set by sensor driver */ ++// reg8_write(client, 0x0A, 0x30 << 1); /* SENSOR I2C native - must be set by sensor driver */ ++ reg8_write(client, 0x0B, BROADCAST << 1); /* broadcast I2C */ ++ reg8_write(client, 0x0C, priv->max9271_addr_map[idx] << 1); /* MAX9271-CAMx I2C new */ ++ /* I2C addresse change */ ++ reg8_write(client, 0x01, priv->des_addr << 1); /* MAX9286 I2C */ ++ reg8_write(client, 0x00, priv->max9271_addr_map[idx] << 1); /* MAX9271-CAM0 I2C new */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ /* put MAX9271 in configuration link state */ ++ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C new */ ++ reg8_write(client, 0x04, 0x43); /* enable reverse_control/conf_link */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++#ifdef MAXIM_DUMP ++ client->addr = priv->des_addr; /* MAX9286-CAMx I2C */ ++ maxim_max927x_dump_regs(client); ++ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C new */ ++ maxim_max927x_dump_regs(client); ++#endif ++ if (priv->gpio_resetb >= 1 && priv->gpio_resetb <= 5) { ++ /* get out from sensor reset */ ++ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C new */ ++ reg8_write(client, 0x0f, (0xfe & ~BIT(priv->gpio_resetb)) | ++ (priv->active_low_resetb ? 0 : BIT(priv->gpio_resetb))); /* set GPIOn value to reset */ ++ reg8_write(client, 0x0e, 0x42 | BIT(priv->gpio_resetb)); /* set GPIOn direction output */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x0f, (0xfe & ~BIT(priv->gpio_resetb)) | ++ (priv->active_low_resetb ? BIT(priv->gpio_resetb) : 0)); /* set GPIOn value to un-reset */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ } ++} ++ ++static int max9286_max9271_initialize(struct i2c_client *client) ++{ ++ struct max9286_max9271_priv *priv = i2c_get_clientdata(client); ++ int idx, ret; ++ ++ dev_info(&client->dev, "LINKs=%d, LANES=%d, FSYNC mode=%s, FSYNC period=%d, PCLK edge=%s\n", ++ priv->links, priv->lanes, priv->fsync_mode, priv->fsync_period, ++ priv->pclk_rising_edge ? "rising" : "falling"); ++ ++ if (priv->des_quirk_addr) ++ max9286_max9271_preinit(client, priv->des_quirk_addr); ++ ++ max9286_max9271_preinit(client, priv->des_addr); ++ max9286_max9271_initial_setup(client); ++ ++ for (idx = 0; idx < priv->links; idx++) { ++ ret = max9286_max9271_reverse_channel_setup(client, idx); ++ if (ret) ++ continue; ++ max9286_max9271_gmsl_link_setup(client, idx); ++ } ++ ++ max9286_max9271_postinit(client, priv->des_addr); ++ ++ client->addr = priv->des_addr; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int max9286_max9271_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct max9286_max9271_priv *priv = v4l2_get_subdevdata(sd); ++ struct i2c_client *client = priv->client; ++ int ret; ++ u8 val = 0; ++ ++ ret = reg8_read(client, (u8)reg->reg, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u8); ++ ++ return 0; ++} ++ ++static int max9286_max9271_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct max9286_max9271_priv *priv = v4l2_get_subdevdata(sd); ++ struct i2c_client *client = priv->client; ++ ++ return reg8_write(client, (u8)reg->reg, (u8)reg->val); ++} ++#endif ++ ++static int max9286_max9271_s_power(struct v4l2_subdev *sd, int on) ++{ ++ struct max9286_max9271_priv *priv = v4l2_get_subdevdata(sd); ++ struct i2c_client *client = priv->client; ++ ++ if (on) { ++ if (atomic_inc_return(&priv->use_count) == 1) ++ reg8_write(client, 0x69, priv->links_mask ^ 0x0f); /* unmask CSI forwarding from detected links */ ++ } else { ++ if (atomic_dec_return(&priv->use_count) == 0) ++ reg8_write(client, 0x69, 0x0f); /* mask CSI forwarding from all links */ ++ } ++ ++ return 0; ++} ++ ++static int max9286_max9271_registered_async(struct v4l2_subdev *sd) ++{ ++ struct max9286_max9271_priv *priv = v4l2_get_subdevdata(sd); ++ struct i2c_client *client = priv->client; ++ int idx, tmp_addr; ++ ++ /* switch to GMSL serial_link for streaming video */ ++ tmp_addr = client->addr; ++ idx = sd->grp_id; ++ ++ client->addr = priv->des_addr; /* MAX9286 I2C */ ++ reg8_write(client, 0x0a, 0x11 << idx); /* enable reverse/forward control for CAMx */ ++ ++ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx */ ++ reg8_write(client, 0x04, force_conf_link ? 0x43 : 0x83); /* enable reverse_control/serial_link */ ++ usleep_range(2000, 2500); /* wait 2ms after changing reverse_control */ ++ ++ client->addr = priv->des_addr; /* MAX9286 I2C */ ++ reg8_write(client, 0x0a, (priv->links_mask << 4) | priv->links_mask); /* enable reverse/forward control for all CAMs */ ++ ++ client->addr = tmp_addr; ++ ++ return 0; ++} ++ ++static struct v4l2_subdev_core_ops max9286_max9271_subdev_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = max9286_max9271_g_register, ++ .s_register = max9286_max9271_s_register, ++#endif ++ .s_power = max9286_max9271_s_power, ++ .registered_async = max9286_max9271_registered_async, ++}; ++ ++static struct v4l2_subdev_ops max9286_max9271_subdev_ops = { ++ .core = &max9286_max9271_subdev_core_ops, ++}; ++ ++static int max9286_max9271_parse_dt(struct i2c_client *client) ++{ ++ struct max9286_max9271_priv *priv = i2c_get_clientdata(client); ++ struct device_node *np = client->dev.of_node; ++ struct device_node *endpoint = NULL; ++ struct property *prop; ++ int err, pwen, i; ++ int sensor_delay, gpio0 = 1, gpio1 = 1; ++ char fsync_mode_default[20] = "manual"; /* manual, automatic, semi-automatic, external */ ++ u8 val = 0; ++ ++ if (of_property_read_u32(np, "maxim,links", &priv->links)) ++ priv->links = 4; ++ ++ if (of_property_read_u32(np, "maxim,lanes", &priv->lanes)) ++ priv->lanes = 4; ++ ++ pwen = of_get_gpio(np, 0); ++ if (pwen > 0) { ++ err = gpio_request_one(pwen, GPIOF_OUT_INIT_HIGH, dev_name(&client->dev)); ++ if (err) ++ dev_err(&client->dev, "cannot request PWEN gpio %d: %d\n", pwen, err); ++ else ++ mdelay(250); ++ } ++ ++ reg8_read(client, 0x1e, &val); /* read max9286 ID */ ++ if (val != MAX9286_ID) { ++ prop = of_find_property(np, "reg", NULL); ++ if (prop) ++ of_remove_property(np, prop); ++ return -ENODEV; ++ } ++ ++ if (!of_property_read_u32(np, "maxim,gpio0", &gpio0) || ++ !of_property_read_u32(np, "maxim,gpio1", &gpio1)) ++ reg8_write(client, 0x0f, 0x08 | (gpio1 << 1) | gpio0); ++ ++ if (of_property_read_u32(np, "maxim,resetb-gpio", &priv->gpio_resetb)) { ++ priv->gpio_resetb = -1; ++ } else { ++ if (of_property_read_bool(np, "maxim,resetb-active-high")) ++ priv->active_low_resetb = false; ++ else ++ priv->active_low_resetb = true; ++ } ++ ++ if (!of_property_read_u32(np, "maxim,sensor_delay", &sensor_delay)) ++ mdelay(sensor_delay); ++ ++ if (of_property_read_string(np, "maxim,fsync-mode", &priv->fsync_mode)) ++ priv->fsync_mode = fsync_mode_default; ++ ++ if (of_property_read_u32(np, "maxim,fsync-period", &priv->fsync_period)) ++ priv->fsync_period = 3200000; /* 96MHz/30fps */ ++ priv->pclk_rising_edge = true; ++ if (of_property_read_bool(np, "maxim,pclk-falling-edge")) ++ priv->pclk_rising_edge = false; ++ if (of_property_read_u32(np, "maxim,timeout", &priv->timeout)) ++ priv->timeout = 100; ++ if (of_property_read_u32(np, "maxim,i2c-quirk", &priv->des_quirk_addr)) ++ priv->des_quirk_addr = 0; ++ ++ for (i = 0; i < priv->links; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; ++ ++ of_node_put(endpoint); ++ ++ if (of_property_read_u32(endpoint, "max9271-addr", &priv->max9271_addr_map[i])) { ++ dev_err(&client->dev, "max9271-addr not set\n"); ++ return -EINVAL; ++ } ++ ++ priv->sd_of_node[i] = endpoint; ++ } ++ ++ return 0; ++} ++ ++static void max9286_max9271_setup_remote_endpoint(struct i2c_client *client) ++{ ++ struct max9286_max9271_priv *priv = i2c_get_clientdata(client); ++ struct device_node *np = client->dev.of_node; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ int i; ++ struct property *csi_rate_prop, *dvp_order_prop; ++ ++ for (i = 0; ; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; ++ ++ of_node_put(endpoint); ++ ++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); ++ if (!rendpoint) ++ continue; ++ ++ csi_rate_prop = of_find_property(endpoint, "csi-rate", NULL); ++ if (csi_rate_prop) { ++ /* CSI2_RATE = PCLK*sizeof(YUV8)*links/lanes */ ++ priv->csi_rate = cpu_to_be32(100 * 8 * hweight8(priv->links_mask) / priv->lanes); ++ csi_rate_prop->value = &priv->csi_rate; ++ of_update_property(rendpoint, csi_rate_prop); ++ } ++ ++ dvp_order_prop = of_find_property(endpoint, "dvp-order", NULL); ++ if (dvp_order_prop) ++ of_update_property(rendpoint, dvp_order_prop); ++ } ++} ++ ++static int max9286_max9271_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct max9286_max9271_priv *priv; ++ int err, i; ++ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ i2c_set_clientdata(client, priv); ++ priv->des_addr = client->addr; ++ priv->client = client; ++ atomic_set(&priv->use_count, 0); ++ priv->csi2_outord = 0xff; ++ ++ err = max9286_max9271_parse_dt(client); ++ if (err) ++ goto out; ++ ++ err = max9286_max9271_initialize(client); ++ if (err < 0) ++ goto out; ++ ++ max9286_max9271_setup_remote_endpoint(client); ++ ++ for (i = 0; i < 4; i++) { ++ v4l2_subdev_init(&priv->sd[i], &max9286_max9271_subdev_ops); ++ priv->sd[i].owner = client->dev.driver->owner; ++ priv->sd[i].dev = &client->dev; ++ priv->sd[i].grp_id = i; ++ v4l2_set_subdevdata(&priv->sd[i], priv); ++ priv->sd[i].of_node = priv->sd_of_node[i]; ++ ++ snprintf(priv->sd[i].name, V4L2_SUBDEV_NAME_SIZE, "%s.%d %d-%04x", ++ client->dev.driver->name, i, i2c_adapter_id(client->adapter), ++ client->addr); ++ ++ err = v4l2_async_register_subdev(&priv->sd[i]); ++ if (err < 0) ++ goto out; ++ } ++ ++out: ++ return err; ++} ++ ++static int max9286_max9271_remove(struct i2c_client *client) ++{ ++ struct max9286_max9271_priv *priv = i2c_get_clientdata(client); ++ int i; ++ ++ for (i = 0; i < 4; i++) { ++ v4l2_async_unregister_subdev(&priv->sd[i]); ++ v4l2_device_unregister_subdev(&priv->sd[i]); ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id max9286_max9271_dt_ids[] = { ++ { .compatible = "maxim,max9286-max9271" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, max9286_max9271_dt_ids); ++ ++static const struct i2c_device_id max9286_max9271_id[] = { ++ { "max9286_max9271", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, max9286_max9271_id); ++ ++static struct i2c_driver max9286_max9271_i2c_driver = { ++ .driver = { ++ .name = "max9286_max9271", ++ .of_match_table = of_match_ptr(max9286_max9271_dt_ids), ++ }, ++ .probe = max9286_max9271_probe, ++ .remove = max9286_max9271_remove, ++ .id_table = max9286_max9271_id, ++}; ++ ++module_i2c_driver(max9286_max9271_i2c_driver); ++ ++MODULE_DESCRIPTION("GMSL driver for MAX9286-MAX9271"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/i2c/soc_camera/max9286_max9271.h b/drivers/media/i2c/soc_camera/max9286_max9271.h +new file mode 100644 +index 0000000..87c040b +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/max9286_max9271.h +@@ -0,0 +1,196 @@ ++/* ++ * MAXIM max9286-max9271 GMSL driver include file ++ * ++ * Copyright (C) 2015-2017 Cogent Embedded, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ */ ++ ++#ifndef _MAX9286_MAX9271_H ++#define _MAX9286_MAX9271_H ++ ++//#define DEBUG ++#ifdef DEBUG ++//#define WRITE_VERIFY ++#define MAXIM_DUMP ++#undef dev_dbg ++#define dev_dbg dev_info ++#endif ++ ++#define REG8_NUM_RETRIES 1 /* number of read/write retries */ ++#define REG16_NUM_RETRIES 10 /* number of read/write retries */ ++#define MAX9271_ID 0x9 ++#define MAX9286_ID 0x40 ++#define BROADCAST 0x6f ++ ++static inline int reg8_read(struct i2c_client *client, u8 reg, u8 *val) ++{ ++ int ret, retries; ++ ++ for (retries = REG8_NUM_RETRIES; retries; retries--) { ++ ret = i2c_smbus_read_byte_data(client, reg); ++ if (!(ret < 0)) ++ break; ++ } ++ ++ if (ret < 0) { ++ dev_dbg(&client->dev, ++ "read fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } else { ++ *val = ret; ++ } ++ ++ return ret < 0 ? ret : 0; ++} ++ ++static inline int reg8_write(struct i2c_client *client, u8 reg, u8 val) ++{ ++ int ret, retries; ++ ++ for (retries = REG8_NUM_RETRIES; retries; retries--) { ++ ret = i2c_smbus_write_byte_data(client, reg, val); ++ if (!(ret < 0)) ++ break; ++ } ++ ++ if (ret < 0) { ++ dev_dbg(&client->dev, ++ "write fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } else { ++#ifdef WRITE_VERIFY ++ u8 val2; ++ reg8_read(client, reg, &val2); ++ if (val != val2) ++ dev_err(&client->dev, ++ "write verify mismatch: chip 0x%x reg=0x%x " ++ "0x%x->0x%x\n", client->addr, reg, val, val2); ++#endif ++ } ++ ++ return ret < 0 ? ret : 0; ++} ++ ++static inline int reg16_read(struct i2c_client *client, u16 reg, u8 *val) ++{ ++ int ret, retries; ++ u8 buf[2] = {reg >> 8, reg & 0xff}; ++ ++ for (retries = REG16_NUM_RETRIES; retries; retries--) { ++ ret = i2c_master_send(client, buf, 2); ++ if (ret == 2) { ++ ret = i2c_master_recv(client, buf, 1); ++ if (ret == 1) ++ break; ++ } ++ } ++ ++ if (ret < 0) { ++ dev_dbg(&client->dev, ++ "read fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } else { ++ *val = buf[0]; ++ } ++ ++ return ret < 0 ? ret : 0; ++} ++ ++static inline int reg16_write(struct i2c_client *client, u16 reg, u8 val) ++{ ++ int ret, retries; ++ u8 buf[3] = {reg >> 8, reg & 0xff, val}; ++ ++ for (retries = REG16_NUM_RETRIES; retries; retries--) { ++ ret = i2c_master_send(client, buf, 3); ++ if (ret == 3) ++ break; ++ } ++ ++ if (ret < 0) { ++ dev_dbg(&client->dev, ++ "write fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } else { ++#ifdef WRITE_VERIFY ++ u8 val2; ++ reg16_read(client, reg, &val2); ++ if (val != val2) ++ dev_err(&client->dev, ++ "write verify mismatch: chip 0x%x reg=0x%x " ++ "0x%x->0x%x\n", client->addr, reg, val, val2); ++#endif ++ } ++ ++ return ret < 0 ? ret : 0; ++} ++ ++#ifdef MAXIM_DUMP ++static void maxim_ovsensor_dump_regs(struct i2c_client *client) ++{ ++ int ret, i; ++ u8 val = 0; ++ u16 regs[] = {0x300a, 0x300b, 0x300c}; ++ ++ dev_dbg(&client->dev, "dump regs 0x%x\n", client->addr); ++ ++ for (i = 0; i < sizeof(regs) / 2; i++) { ++ ret = reg16_read(client, regs[i], &val); ++ if (ret < 0) ++ dev_err(&client->dev, ++ "read fail: chip 0x%x register 0x%02x: %d\n", ++ client->addr, regs[i], ret); ++ printk("0x%02x -> 0x%x\n", regs[i], val); ++ } ++} ++ ++static void maxim_ov10635_dump_format_regs(struct i2c_client *client) ++{ ++ int ret, i; ++ u8 val; ++ u16 regs[] = {0x3003, 0x3004, 0x4300, ++ 0x4605, 0x3621, 0x3702, 0x3703, 0x3704, ++ 0x3802, 0x3803, 0x3806, 0x3807, 0x3808, 0x3809, 0x380a, ++ 0x380b, 0x380c, 0x380d, 0x380e, 0x380f, ++ 0x4606, 0x4607, 0x460a, 0x460b, ++ 0xc488, 0xc489, 0xc48a, 0xc48b, ++ 0xc4cc, 0xc4cd, 0xc4ce, 0xc4cf, 0xc512, 0xc513, ++ 0xc518, 0xc519, 0xc51a, 0xc51b, ++ }; ++ ++ dev_dbg(&client->dev, "dump regs 0x%x\n", client->addr); ++ ++ for (i = 0; i < sizeof(regs) / 2; i++) { ++ ret = reg16_read(client, regs[i], &val); ++ if (ret < 0) ++ dev_err(&client->dev, ++ "read fail: chip 0x%x register 0x%02x: %d\n", ++ client->addr, regs[i], ret); ++ printk("0x%02x -> 0x%x\n", regs[i], val); ++ } ++} ++ ++static void maxim_max927x_dump_regs(struct i2c_client *client) ++{ ++ int ret; ++ u8 reg; ++ ++ dev_dbg(&client->dev, "dump regs 0x%x\n", client->addr); ++ ++ for (reg = 0; reg < 0x20; reg++) { ++ ret = i2c_smbus_read_byte_data(client, reg); ++ if (ret < 0) ++ dev_err(&client->dev, ++ "read fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ printk("0x%02x ", ret); ++ if (((reg + 1) % 0x10) == 0) ++ printk("\n"); ++ } ++} ++#endif /* MAXIM_DUMP */ ++#endif /* _MAX9286_MAX9271_H */ +diff --git a/drivers/media/i2c/soc_camera/ov10635.c b/drivers/media/i2c/soc_camera/ov10635.c +new file mode 100644 +index 0000000..fd72396 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov10635.c +@@ -0,0 +1,751 @@ ++/* ++ * OmniVision ov10635 sensor camera driver ++ * ++ * Copyright (C) 2015-2017 Cogent Embedded, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ */ ++ ++#include <linux/delay.h> ++#include <linux/init.h> ++#include <linux/i2c.h> ++#include <linux/module.h> ++#include <linux/videodev2.h> ++ ++#include <media/soc_camera.h> ++#include <media/v4l2-common.h> ++#include <media/v4l2-ctrls.h> ++#include <media/v4l2-of.h> ++ ++#include "max9286_max9271.h" ++#include "ov10635.h" ++ ++#define OV10635_I2C_ADDR 0x30 ++ ++#define OV10635_PID 0x300a ++#define OV10635_VER 0x300b ++#define OV10635_VERSION_REG 0xa635 ++#define OV10635_VERSION(pid, ver) (((pid) << 8) | ((ver) & 0xff)) ++ ++struct ov10635_priv { ++ struct v4l2_subdev sd; ++ struct v4l2_ctrl_handler hdl; ++ struct media_pad pad; ++ struct v4l2_rect rect; ++ int subsampling; ++ int fps_denominator; ++ int init_complete; ++ u8 id[6]; ++ int dvp_order; ++ /* serializers */ ++ int max9286_addr; ++ int max9271_addr; ++ int ti964_addr; ++ int ti954_addr; ++ int ti9x3_addr; ++ int port; ++ int gpio_resetb; ++ int gpio_fsin; ++}; ++ ++static inline struct ov10635_priv *to_ov10635(const struct i2c_client *client) ++{ ++ return container_of(i2c_get_clientdata(client), struct ov10635_priv, sd); ++} ++ ++static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) ++{ ++ return &container_of(ctrl->handler, struct ov10635_priv, hdl)->sd; ++} ++ ++static void ov10635_s_port(struct i2c_client *client, int fwd_en) ++{ ++ struct ov10635_priv *priv = to_ov10635(client); ++ int tmp_addr; ++ ++ if (priv->max9286_addr) { ++ tmp_addr = client->addr; ++ client->addr = priv->max9286_addr; /* Deserializer I2C address */ ++ reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ ++ client->addr = tmp_addr; ++ }; ++} ++ ++static int ov10635_set_regs(struct i2c_client *client, ++ const struct ov10635_reg *regs, int nr_regs) ++{ ++ int i; ++ ++ for (i = 0; i < nr_regs; i++) { ++ if (reg16_write(client, regs[i].reg, regs[i].val)) { ++ usleep_range(100, 150); /* wait 100ns */ ++ reg16_write(client, regs[i].reg, regs[i].val); ++ } ++ } ++ ++ return 0; ++} ++ ++static int ov10635_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ return 0; ++} ++ ++static int ov10635_set_window(struct v4l2_subdev *sd, int subsampling) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10635_priv *priv = to_ov10635(client); ++ ++ /* disable clocks */ ++ reg16_write(client, 0x302e, 0x00); ++ reg16_write(client, 0x301b, 0xff); ++ reg16_write(client, 0x301c, 0xff); ++ reg16_write(client, 0x301a, 0xff); ++ ++ /* setup resolution */ ++ reg16_write(client, 0x3808, priv->rect.width >> 8); ++ reg16_write(client, 0x3809, priv->rect.width & 0xff); ++ reg16_write(client, 0x380a, priv->rect.height >> 8); ++ reg16_write(client, 0x380b, priv->rect.height & 0xff); ++ ++ /* enable/disable subsampling */ ++ reg16_write(client, 0x5005, subsampling ? 0x89 : 0x08); ++ reg16_write(client, 0x3007, subsampling ? 0x02 : 0x01); ++ reg16_write(client, 0x4004, subsampling ? 0x02 : 0x04); ++ ++#if 0 /* This is implemented in VIN via SOC_CAMERA layer, hence skip */ ++ /* horiz crop start */ ++ reg16_write(client, 0x3800, priv->rect.left >> 8); ++ reg16_write(client, 0x3801, priv->rect.left & 0xff); ++ /* horiz crop end */ ++ reg16_write(client, 0x3804, (priv->rect.left + priv->rect.width + 1) >> 8); ++ reg16_write(client, 0x3805, (priv->rect.left + priv->rect.width + 1) & 0xff); ++ /* vert crop start */ ++ reg16_write(client, 0x3802, priv->rect.top >> 8); ++ reg16_write(client, 0x3803, priv->rect.top & 0xff); ++ /* vert crop end */ ++ reg16_write(client, 0x3806, (priv->rect.top + priv->rect.height + 1) >> 8); ++ reg16_write(client, 0x3807, (priv->rect.top + priv->rect.height + 1) & 0xff); ++#endif ++ /* enable clocks */ ++ reg16_write(client, 0x301b, 0xf0); ++ reg16_write(client, 0x301c, 0xf0); ++ reg16_write(client, 0x301a, 0xf0); ++ reg16_write(client, 0x302e, 0x01); ++ ++ return 0; ++}; ++ ++static int ov10635_get_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10635_priv *priv = to_ov10635(client); ++ ++ if (format->pad) ++ return -EINVAL; ++ ++ mf->width = priv->rect.width; ++ mf->height = priv->rect.height; ++ mf->code = MEDIA_BUS_FMT_YUYV8_2X8; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static int ov10635_set_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ ++ mf->code = MEDIA_BUS_FMT_YUYV8_2X8; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ if (format->which == V4L2_SUBDEV_FORMAT_TRY) ++ cfg->try_fmt = *mf; ++ ++ return 0; ++} ++ ++static int ov10635_enum_mbus_code(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ if (code->pad || code->index > 0) ++ return -EINVAL; ++ ++ code->code = MEDIA_BUS_FMT_YUYV8_2X8; ++ ++ return 0; ++} ++ ++static int ov10635_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10635_priv *priv = to_ov10635(client); ++ ++ memcpy(edid->edid, priv->id, 6); ++ ++ edid->edid[6] = 0xff; ++ edid->edid[7] = client->addr; ++ edid->edid[8] = OV10635_VERSION_REG >> 8; ++ edid->edid[9] = OV10635_VERSION_REG & 0xff; ++ ++ return 0; ++} ++ ++static int ov10635_set_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct v4l2_rect *rect = &sel->r; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10635_priv *priv = to_ov10635(client); ++ int subsampling = 0; ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || ++ sel->target != V4L2_SEL_TGT_CROP) ++ return -EINVAL; ++ ++ rect->left = ALIGN(rect->left, 2); ++ rect->top = ALIGN(rect->top, 2); ++ rect->width = ALIGN(rect->width, 2); ++ rect->height = ALIGN(rect->height, 2); ++ ++ if ((rect->left + rect->width > OV10635_MAX_WIDTH) || ++ (rect->top + rect->height > OV10635_MAX_HEIGHT)) ++ *rect = priv->rect; ++ ++ if (rect->width == OV10635_MAX_WIDTH / 2 && ++ rect->height == OV10635_MAX_HEIGHT / 2) ++ subsampling = 1; ++ ++ priv->rect.left = rect->left; ++ priv->rect.top = rect->top; ++ priv->rect.width = rect->width; ++ priv->rect.height = rect->height; ++ ++ /* change window only for subsampling, crop is done by VIN */ ++ if (subsampling != priv->subsampling) { ++ ov10635_set_window(sd, subsampling); ++ priv->subsampling = subsampling; ++ } ++ ++ return 0; ++} ++ ++static int ov10635_get_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10635_priv *priv = to_ov10635(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) ++ return -EINVAL; ++ ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = OV10635_MAX_WIDTH; ++ sel->r.height = OV10635_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = OV10635_MAX_WIDTH; ++ sel->r.height = OV10635_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP: ++ sel->r = priv->rect; ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int ov10635_g_mbus_config(struct v4l2_subdev *sd, ++ struct v4l2_mbus_config *cfg) ++{ ++ cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | ++ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; ++ cfg->type = V4L2_MBUS_CSI2; ++ ++ return 0; ++} ++ ++static int ov10635_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10635_priv *priv = to_ov10635(client); ++ struct v4l2_captureparm *cp = &parms->parm.capture; ++ ++ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ ++ memset(cp, 0, sizeof(struct v4l2_captureparm)); ++ cp->capability = V4L2_CAP_TIMEPERFRAME; ++ cp->timeperframe.numerator = 1; ++ cp->timeperframe.denominator = priv->fps_denominator; ++ ++ return 0; ++} ++ ++static int ov10635_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10635_priv *priv = to_ov10635(client); ++ struct v4l2_captureparm *cp = &parms->parm.capture; ++ int ret = 0; ++ ++ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ if (cp->extendedmode != 0) ++ return -EINVAL; ++ ++ if (priv->fps_denominator != cp->timeperframe.denominator) { ++ switch (cp->timeperframe.denominator) { ++ case 5: ++ ret = ov10635_set_regs(client, ov10635_regs_5fps, ++ ARRAY_SIZE(ov10635_regs_5fps)); ++ break; ++ case 10: ++ ret = ov10635_set_regs(client, ov10635_regs_10fps, ++ ARRAY_SIZE(ov10635_regs_10fps)); ++ break; ++ case 15: ++ ret = ov10635_set_regs(client, ov10635_regs_15fps, ++ ARRAY_SIZE(ov10635_regs_15fps)); ++ break; ++ case 30: ++ ret = ov10635_set_regs(client, ov10635_regs_30fps, ++ ARRAY_SIZE(ov10635_regs_30fps)); ++ break; ++ default: ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ priv->fps_denominator = cp->timeperframe.denominator; ++ } ++ ++out: ++ return ret; ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int ov10635_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ int ret; ++ u8 val = 0; ++ ++ ret = reg16_read(client, (u16)reg->reg, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u16); ++ ++ return 0; ++} ++ ++static int ov10635_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ return reg16_write(client, (u16)reg->reg, (u8)reg->val); ++} ++#endif ++ ++static struct v4l2_subdev_core_ops ov10635_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = ov10635_g_register, ++ .s_register = ov10635_s_register, ++#endif ++}; ++ ++static int ov10635_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct v4l2_subdev *sd = to_sd(ctrl); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10635_priv *priv = to_ov10635(client); ++ int ret = -EINVAL; ++ u8 val = 0; ++ ++ if (!priv->init_complete) ++ return 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_BRIGHTNESS: ++ /* AEC/AGC target */ ++ ret = reg16_write(client, 0xc46a, ctrl->val); ++ break; ++ case V4L2_CID_CONTRAST: ++ udelay(100); ++ ret = ov10635_set_regs(client, &ov10635_regs_contrast[ctrl->val][0], 18); ++ break; ++ case V4L2_CID_SATURATION: ++ ret = reg16_write(client, 0xc316, ctrl->val); ++ break; ++ case V4L2_CID_HUE: ++ /* CMX ? */ ++ ret = 0; ++ break; ++ case V4L2_CID_GAMMA: ++ ret = reg16_write(client, 0xc4be, ctrl->val >> 8); ++ ret |= reg16_write(client, 0xc4bf, ctrl->val & 0xff); ++ break; ++ case V4L2_CID_AUTOGAIN: ++ /* automatic gain/exposure */ ++ ret = reg16_write(client, 0x56d0, !ctrl->val); ++ break; ++ case V4L2_CID_GAIN: ++ /* manual gain */ ++ ret = reg16_write(client, 0x3504, 0); ++ ret |= reg16_write(client, 0x56d1, ctrl->val >> 8); ++ ret |= reg16_write(client, 0x56d2, ctrl->val & 0xff); ++ ret |= reg16_write(client, 0x3504, 1); /* validate gain */ ++ break; ++ case V4L2_CID_EXPOSURE: ++ /* manual exposure */ ++ ret = reg16_write(client, 0x3504, 0); ++ ret |= reg16_write(client, 0x56d5, ctrl->val >> 8); ++ ret |= reg16_write(client, 0x56d6, ctrl->val & 0xff); ++ ret |= reg16_write(client, 0x3504, 1); /* validate exposure */ ++ break; ++ case V4L2_CID_HFLIP: ++ ret = reg16_read(client, 0x381d, &val); ++ if (ret < 0) ++ goto out; ++ if (ctrl->val) ++ val |= 0x3; ++ else ++ val &= ~0x3; ++ ret = reg16_write(client, 0x381d, val); ++ break; ++ case V4L2_CID_VFLIP: ++ ret = reg16_read(client, 0x381c, &val); ++ if (ctrl->val) ++ val |= 0xc0; ++ else ++ val &= ~0xc0; ++ ret = reg16_write(client, 0x381c, val); ++ break; ++ } ++ ++out: ++ return ret; ++} ++ ++static const struct v4l2_ctrl_ops ov10635_ctrl_ops = { ++ .s_ctrl = ov10635_s_ctrl, ++}; ++ ++static struct v4l2_subdev_video_ops ov10635_video_ops = { ++ .s_stream = ov10635_s_stream, ++ .g_mbus_config = ov10635_g_mbus_config, ++ .g_parm = ov10635_g_parm, ++ .s_parm = ov10635_s_parm, ++}; ++ ++static const struct v4l2_subdev_pad_ops ov10635_subdev_pad_ops = { ++ .get_edid = ov10635_get_edid, ++ .enum_mbus_code = ov10635_enum_mbus_code, ++ .get_selection = ov10635_get_selection, ++ .set_selection = ov10635_set_selection, ++ .get_fmt = ov10635_get_fmt, ++ .set_fmt = ov10635_set_fmt, ++}; ++ ++static struct v4l2_subdev_ops ov10635_subdev_ops = { ++ .core = &ov10635_core_ops, ++ .video = &ov10635_video_ops, ++ .pad = &ov10635_subdev_pad_ops, ++}; ++ ++static void ov10635_otp_id_read(struct i2c_client *client) ++{ ++ struct ov10635_priv *priv = to_ov10635(client); ++ int i; ++ ++ /* read camera id from OTP memory */ ++ reg16_write(client, 0x3d10, 1); ++ ++ usleep_range(15000, 16000); /* wait 15ms */ ++ ++ for (i = 0; i < 6; i++) ++ reg16_read(client, 0x3d00 + i, &priv->id[i]); ++} ++ ++static ssize_t ov10635_otp_id_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(to_i2c_client(dev)); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10635_priv *priv = to_ov10635(client); ++ ++ return snprintf(buf, 32, "%02x:%02x:%02x:%02x:%02x:%02x\n", ++ priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++} ++ ++static DEVICE_ATTR(otp_id_ov10635, S_IRUGO, ov10635_otp_id_show, NULL); ++ ++static int ov10635_initialize(struct i2c_client *client) ++{ ++ struct ov10635_priv *priv = to_ov10635(client); ++ u8 pid = 0, ver = 0; ++ int ret = 0; ++ ++ ov10635_s_port(client, 1); ++ ++ /* check and show product ID and manufacturer ID */ ++ reg16_read(client, OV10635_PID, &pid); ++ reg16_read(client, OV10635_VER, &ver); ++ ++ if (OV10635_VERSION(pid, ver) != OV10635_VERSION_REG) { ++ dev_dbg(&client->dev, "Product ID error %x:%x\n", pid, ver); ++ ret = -ENODEV; ++ goto out; ++ } ++ ++ /* s/w reset sensor */ ++ reg16_write(client, 0x103, 0x1); ++ udelay(100); ++ /* Program wizard registers */ ++ ov10635_set_regs(client, ov10635_regs_wizard, ARRAY_SIZE(ov10635_regs_wizard)); ++ /* Set DVP bit swap */ ++ reg16_write(client, 0x4709, priv->dvp_order << 4); ++ /* Read OTP IDs */ ++ ov10635_otp_id_read(client); ++ ++ dev_info(&client->dev, "ov10635 Product ID %x Manufacturer ID %x OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, ver, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++ ++out: ++ ov10635_s_port(client, 0); ++ ++ return ret; ++} ++ ++static int ov10635_parse_dt(struct device_node *np, struct ov10635_priv *priv) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); ++ int i; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ int tmp_addr = 0; ++ ++ for (i = 0; ; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; ++ ++ of_node_put(endpoint); ++ ++ of_property_read_u32(endpoint, "dvp-order", &priv->dvp_order); ++ ++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); ++ if (!rendpoint) ++ continue; ++ ++ if (!of_property_read_u32(rendpoint, "max9271-addr", &priv->max9271_addr) && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->max9286_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ ++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti964-ti9x3") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti964_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ ++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti954-ti9x3") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti954_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ } ++ ++ if (!priv->max9286_addr && !priv->ti964_addr && !priv->ti954_addr) { ++ dev_err(&client->dev, "deserializer does not present\n"); ++ return -EINVAL; ++ } ++ ++ ov10635_s_port(client, 1); ++ ++ /* setup I2C translator address */ ++ tmp_addr = client->addr; ++ if (priv->max9286_addr) { ++ client->addr = priv->max9271_addr; /* Serializer I2C address */ ++ ++ reg8_write(client, 0x09, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x0A, OV10635_I2C_ADDR << 1); /* Sensor native I2C address */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ }; ++ ++ if (priv->ti964_addr) { ++ client->addr = priv->ti964_addr; /* Deserializer I2C address */ ++ ++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x5d, OV10635_I2C_ADDR << 1); /* Sensor native I2C address */ ++ ++ reg8_write(client, 0x6e, 0xa9); /* GPIO0 - resetb, GPIO1 - fsin */ ++ udelay(100); ++ } ++ ++ if (priv->ti954_addr) { ++ client->addr = priv->ti954_addr; /* Deserializer I2C address */ ++ ++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x5d, OV10635_I2C_ADDR << 1); /* Sensor native I2C address */ ++ ++ reg8_write(client, 0x6e, 0xa9); /* GPIO0 - resetb, GPIO1 - fsin */ ++ udelay(100); ++ } ++ client->addr = tmp_addr; ++ ++ return 0; ++} ++ ++static int ov10635_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct ov10635_priv *priv; ++ int ret; ++ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ v4l2_i2c_subdev_init(&priv->sd, client, &ov10635_subdev_ops); ++ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; ++ priv->rect.left = 0; ++ priv->rect.top = 0; ++ priv->rect.width = OV10635_MAX_WIDTH; ++ priv->rect.height = OV10635_MAX_HEIGHT; ++ priv->fps_denominator = 30; ++ ++ v4l2_ctrl_handler_init(&priv->hdl, 4); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_BRIGHTNESS, 0, 0xff, 1, 0x30); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_CONTRAST, 0, 4, 1, 2); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_SATURATION, 0, 0xff, 1, 0xff); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_HUE, 0, 255, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_GAMMA, 0, 0xffff, 1, 0x233); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_AUTOGAIN, 0, 1, 1, 1); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_GAIN, 0, 0x3ff, 1, 0x10); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_EXPOSURE, 0, 0xffff, 1, 0x80); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ priv->sd.ctrl_handler = &priv->hdl; ++ ++ ret = priv->hdl.error; ++ if (ret) ++ goto cleanup; ++ ++ v4l2_ctrl_handler_setup(&priv->hdl); ++ ++ priv->pad.flags = MEDIA_PAD_FL_SOURCE; ++ priv->sd.entity.flags |= MEDIA_ENT_F_CAM_SENSOR; ++ ret = media_entity_pads_init(&priv->sd.entity, 1, &priv->pad); ++ if (ret < 0) ++ goto cleanup; ++ ++ ret = ov10635_parse_dt(client->dev.of_node, priv); ++ if (ret) ++ goto cleanup; ++ ++ ret = ov10635_initialize(client); ++ if (ret < 0) ++ goto cleanup; ++ ++ ret = v4l2_async_register_subdev(&priv->sd); ++ if (ret) ++ goto cleanup; ++ ++ if (device_create_file(&client->dev, &dev_attr_otp_id_ov10635) != 0) { ++ dev_err(&client->dev, "sysfs otp_id entry creation failed\n"); ++ goto cleanup; ++ } ++ ++ priv->init_complete = 1; ++ ++ return 0; ++ ++cleanup: ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++#ifdef CONFIG_SOC_CAMERA_OV10635 ++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", ++ client->addr, client->adapter->name); ++#endif ++ return ret; ++} ++ ++static int ov10635_remove(struct i2c_client *client) ++{ ++ struct ov10635_priv *priv = i2c_get_clientdata(client); ++ ++ device_remove_file(&client->dev, &dev_attr_otp_id_ov10635); ++ v4l2_async_unregister_subdev(&priv->sd); ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_SOC_CAMERA_OV10635 ++static const struct i2c_device_id ov10635_id[] = { ++ { "ov10635", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, ov10635_id); ++ ++static const struct of_device_id ov10635_of_ids[] = { ++ { .compatible = "ovti,ov10635", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ov10635_of_ids); ++ ++static struct i2c_driver ov10635_i2c_driver = { ++ .driver = { ++ .name = "ov10635", ++ .of_match_table = ov10635_of_ids, ++ }, ++ .probe = ov10635_probe, ++ .remove = ov10635_remove, ++ .id_table = ov10635_id, ++}; ++ ++module_i2c_driver(ov10635_i2c_driver); ++ ++MODULE_DESCRIPTION("SoC Camera driver for OV10635"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); ++#endif +diff --git a/drivers/media/i2c/soc_camera/ov10635.h b/drivers/media/i2c/soc_camera/ov10635.h +new file mode 100644 +index 0000000..66cc490 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov10635.h +@@ -0,0 +1,1139 @@ ++/* ++ * OmniVision ov10635 sensor camera wizard 1280x800@30/UYVY/BT601/8bit ++ * ++ * Copyright (C) 2015-2017 Cogent Embedded, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ */ ++ ++//#define OV10635_DISPLAY_PATTERN ++ ++#define OV10635_SENSOR_WIDTH 1312 ++#define OV10635_SENSOR_HEIGHT 814 ++ ++#define OV10635_MAX_WIDTH 1280 ++#define OV10635_MAX_HEIGHT 800 ++ ++//#define OV10635_PCLK_96MHZ ++#define OV10635_PCLK_88MHZ ++ ++#if defined(OV10635_PCLK_96MHZ) ++/* VTS=PCLK/FPS/HTS/2 (=96MHz/30/1600/2) */ ++ #define OV10635_HTS 1600 ++ #define OV10635_VTS 1000 /* fps=30 */ ++#elif defined(OV10635_PCLK_88MHZ) ++/* VTS=PCLK/FPS/HTS/2 (=88MHz/1572/30/2) */ ++ #define OV10635_HTS 1572 ++ #define OV10635_VTS 933 /* fps=29.9998 */ ++#else ++ #error PCLK not defined ++#endif ++ ++struct ov10635_reg { ++ u16 reg; ++ u8 val; ++}; ++ ++static const struct ov10635_reg ov10635_regs_wizard[] = { ++//{0x0103, 0x01}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x301B, 0xFF}, ++{0x301C, 0xFF}, ++{0x301A, 0xFF}, ++{0x3011, 0x42}, ++{0x6900, 0x0C}, ++{0x6901, 0x19}, ++{0x3503, 0x10}, ++{0x3025, 0x03}, ++#if defined(OV10635_PCLK_96MHZ) ++{0x3003, 0x20}, ++{0x3004, 0x21}, ++#elif defined(OV10635_PCLK_88MHZ) ++{0x3003, 0x16}, ++{0x3004, 0x30}, ++#endif ++{0x3005, 0x40}, ++{0x3006, 0x91}, ++{0x3600, 0x74}, ++{0x3601, 0x2B}, ++{0x3612, 0x00}, ++{0x3611, 0x67}, ++{0x3633, 0xCA}, ++{0x3602, 0xAF}, ++{0x3603, 0x04}, ++{0x3630, 0x28}, ++{0x3631, 0x16}, ++{0x3714, 0x10}, ++{0x371D, 0x01}, ++{0x4300, 0x3A}, ++{0x3007, 0x01}, ++{0x3024, 0x03}, ++{0x3020, 0x0A}, ++{0x3702, 0x0D}, ++{0x3703, 0x20}, ++{0x3704, 0x15}, ++{0x3709, 0xA8}, ++{0x370C, 0xC7}, ++{0x370D, 0x80}, ++{0x3712, 0x00}, ++{0x3713, 0x20}, ++{0x3715, 0x04}, ++{0x381D, 0x40}, ++{0x381C, 0x00}, ++{0x3822, 0x50}, ++{0x3824, 0x10}, ++{0x3815, 0x8C}, ++{0x3804, 0x05}, ++{0x3805, 0x1F}, ++{0x3800, 0x00}, ++{0x3801, 0x00}, ++{0x3806, 0x03}, ++{0x3807, 0x28}, ++{0x3802, 0x00}, ++{0x3803, 0x07}, ++{0x3808, 0x05}, ++{0x3809, 0x00}, ++{0x380A, 0x03}, ++{0x380B, 0x20}, ++{0x380C, OV10635_HTS >> 8}, ++{0x380D, OV10635_HTS & 0xff}, ++{0x380E, OV10635_VTS >> 8}, ++{0x380F, OV10635_VTS & 0xff}, ++{0x3813, 0x02}, ++{0x3811, 0x08}, ++{0x381F, 0x0C}, ++{0x3819, 0x04}, ++{0x3804, 0x01}, ++{0x3805, 0x00}, ++{0x3828, 0x03}, ++{0x3829, 0x10}, ++{0x382A, 0x10}, ++{0x3621, 0x63}, ++{0x5005, 0x08}, ++{0x56D5, 0x00}, ++{0x56D6, 0x80}, ++{0x56D7, 0x00}, ++{0x56D8, 0x00}, ++{0x56D9, 0x00}, ++{0x56DA, 0x80}, ++{0x56DB, 0x00}, ++{0x56DC, 0x00}, ++{0x56E8, 0x00}, ++{0x56E9, 0x7F}, ++{0x56EA, 0x00}, ++{0x56EB, 0x7F}, ++{0x5100, 0x00}, ++{0x5101, 0x80}, ++{0x5102, 0x00}, ++{0x5103, 0x80}, ++{0x5104, 0x00}, ++{0x5105, 0x80}, ++{0x5106, 0x00}, ++{0x5107, 0x80}, ++{0x5108, 0x00}, ++{0x5109, 0x00}, ++{0x510A, 0x00}, ++{0x510B, 0x00}, ++{0x510C, 0x00}, ++{0x510D, 0x00}, ++{0x510E, 0x00}, ++{0x510F, 0x00}, ++{0x5110, 0x00}, ++{0x5111, 0x80}, ++{0x5112, 0x00}, ++{0x5113, 0x80}, ++{0x5114, 0x00}, ++{0x5115, 0x80}, ++{0x5116, 0x00}, ++{0x5117, 0x80}, ++{0x5118, 0x00}, ++{0x5119, 0x00}, ++{0x511A, 0x00}, ++{0x511B, 0x00}, ++{0x511C, 0x00}, ++{0x511D, 0x00}, ++{0x511E, 0x00}, ++{0x511F, 0x00}, ++{0x56D0, 0x00}, ++{0x5006, 0x04}, ++{0x5608, 0x05}, ++{0x52D7, 0x06}, ++{0x528D, 0x08}, ++{0x5293, 0x12}, ++{0x52D3, 0x12}, ++{0x5288, 0x06}, ++{0x5289, 0x20}, ++{0x52C8, 0x06}, ++{0x52C9, 0x20}, ++{0x52CD, 0x04}, ++{0x5381, 0x00}, ++{0x5382, 0xFF}, ++{0x5589, 0x76}, ++{0x558A, 0x47}, ++{0x558B, 0xEF}, ++{0x558C, 0xC9}, ++{0x558D, 0x49}, ++{0x558E, 0x30}, ++{0x558F, 0x67}, ++{0x5590, 0x3F}, ++{0x5591, 0xF0}, ++{0x5592, 0x10}, ++{0x55A2, 0x6D}, ++{0x55A3, 0x55}, ++{0x55A4, 0xC3}, ++{0x55A5, 0xB5}, ++{0x55A6, 0x43}, ++{0x55A7, 0x38}, ++{0x55A8, 0x5F}, ++{0x55A9, 0x4B}, ++{0x55AA, 0xF0}, ++{0x55AB, 0x10}, ++{0x5581, 0x52}, ++{0x5300, 0x01}, ++{0x5301, 0x00}, ++{0x5302, 0x00}, ++{0x5303, 0x0E}, ++{0x5304, 0x00}, ++{0x5305, 0x0E}, ++{0x5306, 0x00}, ++{0x5307, 0x36}, ++{0x5308, 0x00}, ++{0x5309, 0xD9}, ++{0x530A, 0x00}, ++{0x530B, 0x0F}, ++{0x530C, 0x00}, ++{0x530D, 0x2C}, ++{0x530E, 0x00}, ++{0x530F, 0x59}, ++{0x5310, 0x00}, ++{0x5311, 0x7B}, ++{0x5312, 0x00}, ++{0x5313, 0x22}, ++{0x5314, 0x00}, ++{0x5315, 0xD5}, ++{0x5316, 0x00}, ++{0x5317, 0x13}, ++{0x5318, 0x00}, ++{0x5319, 0x18}, ++{0x531A, 0x00}, ++{0x531B, 0x26}, ++{0x531C, 0x00}, ++{0x531D, 0xDC}, ++{0x531E, 0x00}, ++{0x531F, 0x02}, ++{0x5320, 0x00}, ++{0x5321, 0x24}, ++{0x5322, 0x00}, ++{0x5323, 0x56}, ++{0x5324, 0x00}, ++{0x5325, 0x85}, ++{0x5326, 0x00}, ++{0x5327, 0x20}, ++{0x5609, 0x01}, ++{0x560A, 0x40}, ++{0x560B, 0x01}, ++{0x560C, 0x40}, ++{0x560D, 0x00}, ++{0x560E, 0xFA}, ++{0x560F, 0x00}, ++{0x5610, 0xFA}, ++{0x5611, 0x02}, ++{0x5612, 0x80}, ++{0x5613, 0x02}, ++{0x5614, 0x80}, ++{0x5615, 0x01}, ++{0x5616, 0x2C}, ++{0x5617, 0x01}, ++{0x5618, 0x2C}, ++{0x563B, 0x01}, ++{0x563C, 0x01}, ++{0x563D, 0x01}, ++{0x563E, 0x01}, ++{0x563F, 0x03}, ++{0x5640, 0x03}, ++{0x5641, 0x03}, ++{0x5642, 0x05}, ++{0x5643, 0x09}, ++{0x5644, 0x05}, ++{0x5645, 0x05}, ++{0x5646, 0x05}, ++{0x5647, 0x05}, ++{0x5651, 0x00}, ++{0x5652, 0x80}, ++{0x521A, 0x01}, ++{0x521B, 0x03}, ++{0x521C, 0x06}, ++{0x521D, 0x0A}, ++{0x521E, 0x0E}, ++{0x521F, 0x12}, ++{0x5220, 0x16}, ++{0x5223, 0x02}, ++{0x5225, 0x04}, ++{0x5227, 0x08}, ++{0x5229, 0x0C}, ++{0x522B, 0x12}, ++{0x522D, 0x18}, ++{0x522F, 0x1E}, ++{0x5241, 0x04}, ++{0x5242, 0x01}, ++{0x5243, 0x03}, ++{0x5244, 0x06}, ++{0x5245, 0x0A}, ++{0x5246, 0x0E}, ++{0x5247, 0x12}, ++{0x5248, 0x16}, ++{0x524A, 0x03}, ++{0x524C, 0x04}, ++{0x524E, 0x08}, ++{0x5250, 0x0C}, ++{0x5252, 0x12}, ++{0x5254, 0x18}, ++{0x5256, 0x1E}, ++{0x4606, (2*OV10635_HTS) >> 8}, /* fifo_line_length = 2*hts */ ++{0x4607, (2*OV10635_HTS) & 0xff}, ++{0x460a, (2*(OV10635_HTS-OV10635_MAX_WIDTH)) >> 8}, /* fifo_hsync_start = 2*(hts - xres) */ ++{0x460b, (2*(OV10635_HTS-OV10635_MAX_WIDTH)) & 0xff }, ++{0x460C, 0x00}, ++{0x4620, 0x0E}, ++#if 0 ++{0x4700, 0x02}, // BT656: mode is acceptable but artefact lines on left/bottom due to BT656 SAV/EAV are parsed as image data ++#else ++{0x4700, 0x04}, // BT601: 0x08 is also accaptable as HS/VS mode ++#endif ++{0x4701, 0x00}, ++{0x4702, 0x01}, ++{0x4004, 0x04}, ++{0x4005, 0x18}, ++{0x4001, 0x06}, ++{0x4050, 0x22}, ++{0x4051, 0x24}, ++{0x4052, 0x02}, ++{0x4057, 0x9C}, ++{0x405A, 0x00}, ++{0x4202, 0x02}, ++{0x3023, 0x10}, ++{0x0100, 0x01}, ++{0x0100, 0x01}, ++{0x6F10, 0x07}, ++{0x6F11, 0x82}, ++{0x6F12, 0x04}, ++{0x6F13, 0x00}, ++{0xD000, 0x19}, ++{0xD001, 0xA0}, ++{0xD002, 0x00}, ++{0xD003, 0x01}, ++{0xD004, 0xA9}, ++{0xD005, 0xAD}, ++{0xD006, 0x10}, ++{0xD007, 0x40}, ++{0xD008, 0x44}, ++{0xD009, 0x00}, ++{0xD00A, 0x68}, ++{0xD00B, 0x00}, ++{0xD00C, 0x15}, ++{0xD00D, 0x00}, ++{0xD00E, 0x00}, ++{0xD00F, 0x00}, ++{0xD040, 0x9C}, ++{0xD041, 0x21}, ++{0xD042, 0xFF}, ++{0xD043, 0xF8}, ++{0xD044, 0xD4}, ++{0xD045, 0x01}, ++{0xD046, 0x48}, ++{0xD047, 0x00}, ++{0xD048, 0xD4}, ++{0xD049, 0x01}, ++{0xD04A, 0x50}, ++{0xD04B, 0x04}, ++{0xD04C, 0x18}, ++{0xD04D, 0x60}, ++{0xD04E, 0x00}, ++{0xD04F, 0x01}, ++{0xD050, 0xA8}, ++{0xD051, 0x63}, ++{0xD052, 0x02}, ++{0xD053, 0xA4}, ++{0xD054, 0x85}, ++{0xD055, 0x43}, ++{0xD056, 0x00}, ++{0xD057, 0x00}, ++{0xD058, 0x18}, ++{0xD059, 0x60}, ++{0xD05A, 0x00}, ++{0xD05B, 0x01}, ++{0xD05C, 0xA8}, ++{0xD05D, 0x63}, ++{0xD05E, 0x03}, ++{0xD05F, 0xF0}, ++{0xD060, 0x98}, ++{0xD061, 0xA3}, ++{0xD062, 0x00}, ++{0xD063, 0x00}, ++{0xD064, 0x8C}, ++{0xD065, 0x6A}, ++{0xD066, 0x00}, ++{0xD067, 0x6E}, ++{0xD068, 0xE5}, ++{0xD069, 0x85}, ++{0xD06A, 0x18}, ++{0xD06B, 0x00}, ++{0xD06C, 0x10}, ++{0xD06D, 0x00}, ++{0xD06E, 0x00}, ++{0xD06F, 0x10}, ++{0xD070, 0x9C}, ++{0xD071, 0x80}, ++{0xD072, 0x00}, ++{0xD073, 0x03}, ++{0xD074, 0x18}, ++{0xD075, 0x60}, ++{0xD076, 0x00}, ++{0xD077, 0x01}, ++{0xD078, 0xA8}, ++{0xD079, 0x63}, ++{0xD07A, 0x07}, ++{0xD07B, 0x80}, ++{0xD07C, 0x07}, ++{0xD07D, 0xFF}, ++{0xD07E, 0xF9}, ++{0xD07F, 0x03}, ++{0xD080, 0x8C}, ++{0xD081, 0x63}, ++{0xD082, 0x00}, ++{0xD083, 0x00}, ++{0xD084, 0xA5}, ++{0xD085, 0x6B}, ++{0xD086, 0x00}, ++{0xD087, 0xFF}, ++{0xD088, 0x18}, ++{0xD089, 0x80}, ++{0xD08A, 0x00}, ++{0xD08B, 0x01}, ++{0xD08C, 0xA8}, ++{0xD08D, 0x84}, ++{0xD08E, 0x01}, ++{0xD08F, 0x04}, ++{0xD090, 0xE1}, ++{0xD091, 0x6B}, ++{0xD092, 0x58}, ++{0xD093, 0x00}, ++{0xD094, 0x94}, ++{0xD095, 0x6A}, ++{0xD096, 0x00}, ++{0xD097, 0x70}, ++{0xD098, 0xE1}, ++{0xD099, 0x6B}, ++{0xD09A, 0x20}, ++{0xD09B, 0x00}, ++{0xD09C, 0x95}, ++{0xD09D, 0x6B}, ++{0xD09E, 0x00}, ++{0xD09F, 0x00}, ++{0xD0A0, 0xE4}, ++{0xD0A1, 0x8B}, ++{0xD0A2, 0x18}, ++{0xD0A3, 0x00}, ++{0xD0A4, 0x0C}, ++{0xD0A5, 0x00}, ++{0xD0A6, 0x00}, ++{0xD0A7, 0x23}, ++{0xD0A8, 0x15}, ++{0xD0A9, 0x00}, ++{0xD0AA, 0x00}, ++{0xD0AB, 0x00}, ++{0xD0AC, 0x18}, ++{0xD0AD, 0x60}, ++{0xD0AE, 0x80}, ++{0xD0AF, 0x06}, ++{0xD0B0, 0xA8}, ++{0xD0B1, 0x83}, ++{0xD0B2, 0x40}, ++{0xD0B3, 0x08}, ++{0xD0B4, 0xA8}, ++{0xD0B5, 0xE3}, ++{0xD0B6, 0x38}, ++{0xD0B7, 0x2A}, ++{0xD0B8, 0xA8}, ++{0xD0B9, 0xC3}, ++{0xD0BA, 0x40}, ++{0xD0BB, 0x09}, ++{0xD0BC, 0xA8}, ++{0xD0BD, 0xA3}, ++{0xD0BE, 0x38}, ++{0xD0BF, 0x29}, ++{0xD0C0, 0x8C}, ++{0xD0C1, 0x65}, ++{0xD0C2, 0x00}, ++{0xD0C3, 0x00}, ++{0xD0C4, 0xD8}, ++{0xD0C5, 0x04}, ++{0xD0C6, 0x18}, ++{0xD0C7, 0x00}, ++{0xD0C8, 0x8C}, ++{0xD0C9, 0x67}, ++{0xD0CA, 0x00}, ++{0xD0CB, 0x00}, ++{0xD0CC, 0xD8}, ++{0xD0CD, 0x06}, ++{0xD0CE, 0x18}, ++{0xD0CF, 0x00}, ++{0xD0D0, 0x18}, ++{0xD0D1, 0x60}, ++{0xD0D2, 0x80}, ++{0xD0D3, 0x06}, ++{0xD0D4, 0xA8}, ++{0xD0D5, 0xE3}, ++{0xD0D6, 0x67}, ++{0xD0D7, 0x02}, ++{0xD0D8, 0xA9}, ++{0xD0D9, 0x03}, ++{0xD0DA, 0x67}, ++{0xD0DB, 0x03}, ++{0xD0DC, 0xA8}, ++{0xD0DD, 0xC3}, ++{0xD0DE, 0x3D}, ++{0xD0DF, 0x05}, ++{0xD0E0, 0x8C}, ++{0xD0E1, 0x66}, ++{0xD0E2, 0x00}, ++{0xD0E3, 0x00}, ++{0xD0E4, 0xB8}, ++{0xD0E5, 0x63}, ++{0xD0E6, 0x00}, ++{0xD0E7, 0x18}, ++{0xD0E8, 0xB8}, ++{0xD0E9, 0x63}, ++{0xD0EA, 0x00}, ++{0xD0EB, 0x98}, ++{0xD0EC, 0xBC}, ++{0xD0ED, 0x03}, ++{0xD0EE, 0x00}, ++{0xD0EF, 0x00}, ++{0xD0F0, 0x10}, ++{0xD0F1, 0x00}, ++{0xD0F2, 0x00}, ++{0xD0F3, 0x16}, ++{0xD0F4, 0xB8}, ++{0xD0F5, 0x83}, ++{0xD0F6, 0x00}, ++{0xD0F7, 0x19}, ++{0xD0F8, 0x8C}, ++{0xD0F9, 0x67}, ++{0xD0FA, 0x00}, ++{0xD0FB, 0x00}, ++{0xD0FC, 0xB8}, ++{0xD0FD, 0xA4}, ++{0xD0FE, 0x00}, ++{0xD0FF, 0x98}, ++{0xD100, 0xB8}, ++{0xD101, 0x83}, ++{0xD102, 0x00}, ++{0xD103, 0x08}, ++{0xD104, 0x8C}, ++{0xD105, 0x68}, ++{0xD106, 0x00}, ++{0xD107, 0x00}, ++{0xD108, 0xE0}, ++{0xD109, 0x63}, ++{0xD10A, 0x20}, ++{0xD10B, 0x04}, ++{0xD10C, 0xE0}, ++{0xD10D, 0x65}, ++{0xD10E, 0x18}, ++{0xD10F, 0x00}, ++{0xD110, 0xA4}, ++{0xD111, 0x83}, ++{0xD112, 0xFF}, ++{0xD113, 0xFF}, ++{0xD114, 0xB8}, ++{0xD115, 0x64}, ++{0xD116, 0x00}, ++{0xD117, 0x48}, ++{0xD118, 0xD8}, ++{0xD119, 0x07}, ++{0xD11A, 0x18}, ++{0xD11B, 0x00}, ++{0xD11C, 0xD8}, ++{0xD11D, 0x08}, ++{0xD11E, 0x20}, ++{0xD11F, 0x00}, ++{0xD120, 0x9C}, ++{0xD121, 0x60}, ++{0xD122, 0x00}, ++{0xD123, 0x00}, ++{0xD124, 0xD8}, ++{0xD125, 0x06}, ++{0xD126, 0x18}, ++{0xD127, 0x00}, ++{0xD128, 0x00}, ++{0xD129, 0x00}, ++{0xD12A, 0x00}, ++{0xD12B, 0x08}, ++{0xD12C, 0x15}, ++{0xD12D, 0x00}, ++{0xD12E, 0x00}, ++{0xD12F, 0x00}, ++{0xD130, 0x8C}, ++{0xD131, 0x6A}, ++{0xD132, 0x00}, ++{0xD133, 0x76}, ++{0xD134, 0xBC}, ++{0xD135, 0x23}, ++{0xD136, 0x00}, ++{0xD137, 0x00}, ++{0xD138, 0x13}, ++{0xD139, 0xFF}, ++{0xD13A, 0xFF}, ++{0xD13B, 0xE6}, ++{0xD13C, 0x18}, ++{0xD13D, 0x60}, ++{0xD13E, 0x80}, ++{0xD13F, 0x06}, ++{0xD140, 0x03}, ++{0xD141, 0xFF}, ++{0xD142, 0xFF}, ++{0xD143, 0xDD}, ++{0xD144, 0xA8}, ++{0xD145, 0x83}, ++{0xD146, 0x40}, ++{0xD147, 0x08}, ++{0xD148, 0x85}, ++{0xD149, 0x21}, ++{0xD14A, 0x00}, ++{0xD14B, 0x00}, ++{0xD14C, 0x85}, ++{0xD14D, 0x41}, ++{0xD14E, 0x00}, ++{0xD14F, 0x04}, ++{0xD150, 0x44}, ++{0xD151, 0x00}, ++{0xD152, 0x48}, ++{0xD153, 0x00}, ++{0xD154, 0x9C}, ++{0xD155, 0x21}, ++{0xD156, 0x00}, ++{0xD157, 0x08}, ++{0x6F0E, 0x03}, ++{0x6F0F, 0x00}, ++{0x460E, 0x08}, ++{0x460F, 0x01}, ++{0x4610, 0x00}, ++{0x4611, 0x01}, ++{0x4612, 0x00}, ++{0x4613, 0x01}, ++{0x4605, 0x08}, // 8bit ++//{0x4709, 0x10}, // swap data bits order [9:0] -> [0:9] ++{0x4608, 0x00}, ++{0x4609, 0x08}, ++{0x6804, 0x00}, ++{0x6805, 0x06}, ++{0x6806, 0x00}, ++{0x5120, 0x00}, ++{0x3510, 0x00}, ++{0x3504, 0x00}, ++{0x6800, 0x00}, ++{0x6F0D, 0x01}, ++{0x4708, 0x01}, // PCLK rising edge ++{0x5000, 0xFF}, ++{0x5001, 0xBF}, ++{0x5002, 0x7E}, ++#ifdef OV10635_DISPLAY_PATTERN ++{0x503d, 0x80}, ++#else ++{0x503D, 0x00}, ++#endif ++{0xC450, 0x01}, /* AA mode */ ++{0xC452, 0x04}, ++{0xC453, 0x00}, ++{0xC454, 0x00}, ++{0xC455, 0x01}, ++{0xC456, 0x01}, ++{0xC457, 0x00}, ++{0xC458, 0x00}, ++{0xC459, 0x00}, ++{0xC45B, 0x00}, ++{0xC45C, 0x01}, ++{0xC45D, 0x00}, ++{0xC45E, 0x00}, ++{0xC45F, 0x00}, ++{0xC460, 0x00}, ++{0xC461, 0x01}, ++{0xC462, 0x01}, ++{0xC464, 0x03}, ++{0xC465, 0x00}, ++{0xC466, 0x8A}, ++{0xC467, 0x00}, ++{0xC468, 0x86}, ++{0xC469, 0x00}, ++{0xC46A, 0x30}, ++{0xC46B, 0x50}, ++{0xC46C, 0x30}, ++{0xC46D, 0x28}, ++{0xC46E, 0x60}, ++{0xC46F, 0x40}, ++{0xC47C, 0x01}, ++{0xC47D, 0x38}, ++{0xC47E, 0x00}, ++{0xC47F, 0x00}, ++{0xC480, 0x00}, ++{0xC481, 0xFF}, ++{0xC482, 0x00}, ++{0xC483, 0x40}, ++{0xC484, 0x00}, ++{0xC485, 0x18}, ++{0xC486, 0x00}, ++{0xC487, 0x18}, ++{0xC488, (OV10635_VTS-8)*16 >> 8}, ++{0xC489, (OV10635_VTS-8)*16 & 0xff}, ++{0xC48A, (OV10635_VTS-8)*16 >> 8}, ++{0xC48B, (OV10635_VTS-8)*16 & 0xff}, ++{0xC48C, 0x00}, ++{0xC48D, 0x04}, ++{0xC48E, 0x00}, ++{0xC48F, 0x04}, ++{0xC490, 0x03}, ++{0xC492, 0x20}, ++{0xC493, 0x08}, ++{0xC498, 0x02}, ++{0xC499, 0x00}, ++{0xC49A, 0x02}, ++{0xC49B, 0x00}, ++{0xC49C, 0x02}, ++{0xC49D, 0x00}, ++{0xC49E, 0x02}, ++{0xC49F, 0x60}, ++{0xC4A0, 0x03}, ++{0xC4A1, 0x00}, ++{0xC4A2, 0x04}, ++{0xC4A3, 0x00}, ++{0xC4A4, 0x00}, ++{0xC4A5, 0x10}, ++{0xC4A6, 0x00}, ++{0xC4A7, 0x40}, ++{0xC4A8, 0x00}, ++{0xC4A9, 0x80}, ++{0xC4AA, 0x0D}, ++{0xC4AB, 0x00}, ++{0xC4AC, 0x0F}, ++{0xC4AD, 0xC0}, ++{0xC4B4, 0x01}, ++{0xC4B5, 0x01}, ++{0xC4B6, 0x00}, ++{0xC4B7, 0x01}, ++{0xC4B8, 0x00}, ++{0xC4B9, 0x01}, ++{0xC4BA, 0x01}, ++{0xC4BB, 0x00}, ++{0xC4BC, 0x01}, ++{0xC4BD, 0x60}, ++{0xC4BE, 0x02}, ++{0xC4BF, 0x33}, ++{0xC4C8, 0x03}, ++{0xC4C9, 0xD0}, ++{0xC4CA, 0x0E}, ++{0xC4CB, 0x00}, ++{0xC4CC, 0x0E}, ++{0xC4CD, 0x51}, ++{0xC4CE, 0x0E}, ++{0xC4CF, 0x51}, ++{0xC4D0, 0x04}, ++{0xC4D1, 0x80}, ++{0xC4E0, 0x04}, ++{0xC4E1, 0x02}, ++{0xC4E2, 0x01}, ++{0xC4E4, 0x10}, ++{0xC4E5, 0x20}, ++{0xC4E6, 0x30}, ++{0xC4E7, 0x40}, ++{0xC4E8, 0x50}, ++{0xC4E9, 0x60}, ++{0xC4EA, 0x70}, ++{0xC4EB, 0x80}, ++{0xC4EC, 0x90}, ++{0xC4ED, 0xA0}, ++{0xC4EE, 0xB0}, ++{0xC4EF, 0xC0}, ++{0xC4F0, 0xD0}, ++{0xC4F1, 0xE0}, ++{0xC4F2, 0xF0}, ++{0xC4F3, 0x80}, ++{0xC4F4, 0x00}, ++{0xC4F5, 0x20}, ++{0xC4F6, 0x02}, ++{0xC4F7, 0x00}, ++{0xC4F8, 0x00}, ++{0xC4F9, 0x00}, ++{0xC4FA, 0x00}, ++{0xC4FB, 0x01}, ++{0xC4FC, 0x01}, ++{0xC4FD, 0x00}, ++{0xC4FE, 0x04}, ++{0xC4FF, 0x02}, ++{0xC500, 0x48}, ++{0xC501, 0x74}, ++{0xC502, 0x58}, ++{0xC503, 0x80}, ++{0xC504, 0x05}, ++{0xC505, 0x80}, ++{0xC506, 0x03}, ++{0xC507, 0x80}, ++{0xC508, 0x01}, ++{0xC509, 0xC0}, ++{0xC50A, 0x01}, ++{0xC50B, 0xA0}, ++{0xC50C, 0x01}, ++{0xC50D, 0x2C}, ++{0xC50E, 0x01}, ++{0xC50F, 0x0A}, ++{0xC510, 0x00}, ++{0xC511, 0x00}, ++{0xC512, 0xE5}, ++{0xC513, 0x14}, ++{0xC514, 0x04}, ++{0xC515, 0x00}, ++{0xC518, OV10635_VTS >> 8}, ++{0xC519, OV10635_VTS & 0xff}, ++{0xC51A, OV10635_HTS >> 8}, ++{0xC51B, OV10635_HTS & 0xff}, ++{0xC2E0, 0x00}, ++{0xC2E1, 0x51}, ++{0xC2E2, 0x00}, ++{0xC2E3, 0xD6}, ++{0xC2E4, 0x01}, ++{0xC2E5, 0x5E}, ++{0xC2E9, 0x01}, ++{0xC2EA, 0x7A}, ++{0xC2EB, 0x90}, ++{0xC2ED, 0x00}, ++{0xC2EE, 0x7A}, ++{0xC2EF, 0x64}, ++{0xC308, 0x00}, ++{0xC309, 0x00}, ++{0xC30A, 0x00}, ++{0xC30C, 0x00}, ++{0xC30D, 0x01}, ++{0xC30E, 0x00}, ++{0xC30F, 0x00}, ++{0xC310, 0x01}, ++{0xC311, 0x60}, ++{0xC312, 0xFF}, ++{0xC313, 0x08}, ++{0xC314, 0x01}, ++{0xC315, 0x00}, /* min saturation gain */ ++{0xC316, 0xFF}, /* max saturation gain */ ++{0xC317, 0x0B}, ++{0xC318, 0x00}, ++{0xC319, 0x0C}, ++{0xC31A, 0x00}, ++{0xC31B, 0xE0}, ++{0xC31C, 0x00}, ++{0xC31D, 0x14}, ++{0xC31E, 0x00}, ++{0xC31F, 0xC5}, ++{0xC320, 0xFF}, ++{0xC321, 0x4B}, ++{0xC322, 0xFF}, ++{0xC323, 0xF0}, ++{0xC324, 0xFF}, ++{0xC325, 0xE8}, ++{0xC326, 0x00}, ++{0xC327, 0x46}, ++{0xC328, 0xFF}, ++{0xC329, 0xD2}, ++{0xC32A, 0xFF}, ++{0xC32B, 0xE4}, ++{0xC32C, 0xFF}, ++{0xC32D, 0xBB}, ++{0xC32E, 0x00}, ++{0xC32F, 0x61}, ++{0xC330, 0xFF}, ++{0xC331, 0xF9}, ++{0xC332, 0x00}, ++{0xC333, 0xD9}, ++{0xC334, 0x00}, ++{0xC335, 0x2E}, ++{0xC336, 0x00}, ++{0xC337, 0xB1}, ++{0xC338, 0xFF}, ++{0xC339, 0x64}, ++{0xC33A, 0xFF}, ++{0xC33B, 0xEB}, ++{0xC33C, 0xFF}, ++{0xC33D, 0xE8}, ++{0xC33E, 0x00}, ++{0xC33F, 0x48}, ++{0xC340, 0xFF}, ++{0xC341, 0xD0}, ++{0xC342, 0xFF}, ++{0xC343, 0xED}, ++{0xC344, 0xFF}, ++{0xC345, 0xAD}, ++{0xC346, 0x00}, ++{0xC347, 0x66}, ++{0xC348, 0x01}, ++{0xC349, 0x00}, ++{0x6700, 0x04}, ++{0x6701, 0x7B}, ++{0x6702, 0xFD}, ++{0x6703, 0xF9}, ++{0x6704, 0x3D}, ++{0x6705, 0x71}, ++{0x6706, 0x78}, ++{0x6708, 0x05}, ++{0x6F06, 0x6F}, ++{0x6F07, 0x00}, ++{0x6F0A, 0x6F}, ++{0x6F0B, 0x00}, ++{0x6F00, 0x03}, ++{0xC34C, 0x01}, ++{0xC34D, 0x00}, ++{0xC34E, 0x46}, ++{0xC34F, 0x55}, ++{0xC350, 0x00}, ++{0xC351, 0x40}, ++{0xC352, 0x00}, ++{0xC353, 0xFF}, ++{0xC354, 0x04}, ++{0xC355, 0x08}, ++{0xC356, 0x01}, ++{0xC357, 0xEF}, ++{0xC358, 0x30}, ++{0xC359, 0x01}, ++{0xC35A, 0x64}, ++{0xC35B, 0x46}, ++{0xC35C, 0x00}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0xC261, 0x01}, ++{0x301B, 0xF0}, ++{0x301C, 0xF0}, ++{0x301A, 0xF0}, ++{0x6F00, 0xC3}, ++{0xC46A, 0x30}, ++{0xC46D, 0x20}, ++{0xC464, 0x84}, ++{0xC465, 0x00}, ++{0x6F00, 0x03}, ++{0x6F00, 0x43}, ++{0x381C, 0x00}, ++{0x381D, 0x40}, ++{0xC454, 0x01}, ++{0x6F00, 0xC3}, ++{0xC454, 0x00}, ++{0xC4B1, 0x02}, ++{0xC4B2, 0x01}, ++{0xC4B3, 0x03}, ++{0x6F00, 0x03}, ++{0x6F00, 0x43}, ++/* enable FSIN (FRAMESYNC input) functionality */ ++{0x3832, 0x00}, ++{0x3833, 0x10}, ++{0x3834, 0x00}, ++{0x3835, 0x10}, ++{0x302E, 0x01}, ++}; ++ ++static const struct ov10635_reg ov10635_regs_30fps[] = { ++/* disable clocks */ ++{0x301b, 0xff}, ++{0x301c, 0xff}, ++{0x301a, 0xff}, ++/* clk = 24Mhz/2*32/2(1+1)=96Mhz, 30fps */ ++{0x3003, 0x20}, ++{0x3004, 0x21}, ++/* enable clocks */ ++{0x301b, 0xf0}, ++{0x301c, 0xf0}, ++{0x301a, 0xf0}, ++}; ++ ++static const struct ov10635_reg ov10635_regs_15fps[] = { ++/* disable clocks */ ++{0x301b, 0xff}, ++{0x301c, 0xff}, ++{0x301a, 0xff}, ++/* clk = 24Mhz/2*32/2(1+3)=48Mhz, 15fps */ ++{0x3003, 0x20}, ++{0x3004, 0x23}, ++/* enable clocks */ ++{0x301b, 0xf0}, ++{0x301c, 0xf0}, ++{0x301a, 0xf0}, ++}; ++ ++static const struct ov10635_reg ov10635_regs_10fps[] = { ++/* disable clocks */ ++{0x301b, 0xff}, ++{0x301c, 0xff}, ++{0x301a, 0xff}, ++/* clk = 24Mhz/2*32/2(1+5)=32Mhz, 10fps */ ++{0x3003, 0x20}, ++{0x3004, 0x25}, ++/* enable clocks */ ++{0x301b, 0xf0}, ++{0x301c, 0xf0}, ++{0x301a, 0xf0}, ++}; ++ ++static const struct ov10635_reg ov10635_regs_5fps[] = { ++/* disable clocks */ ++{0x301b, 0xff}, ++{0x301c, 0xff}, ++{0x301a, 0xff}, ++/* clk = 24Mhz/4*32/2(1+5)=96Mhz, 5fps */ ++{0x3003, 0x20}, ++{0x3004, 0x45}, ++/* enable clocks */ ++{0x301b, 0xf0}, ++{0x301c, 0xf0}, ++{0x301a, 0xf0}, ++}; ++ ++static const struct ov10635_reg ov10635_regs_contrast[5][18] = { ++{ ++ {0x6f00, 0xc3}, ++ {0xc4e4, 0x20}, ++ {0xc4e5, 0x40}, ++ {0xc4e6, 0x60}, ++ {0xc4e7, 0x80}, ++ {0xc4e8, 0xa0}, ++ {0xc4e9, 0xb4}, ++ {0xc4ea, 0xc0}, ++ {0xc4eb, 0xcb}, ++ {0xc4ec, 0xd5}, ++ {0xc4ed, 0xde}, ++ {0xc4ee, 0xe6}, ++ {0xc4ef, 0xed}, ++ {0xc4f0, 0xf3}, ++ {0xc4f1, 0xf8}, ++ {0xc4f2, 0xfc}, ++ {0x6f00, 0x03}, ++ {0x6f00, 0x43}, ++}, { ++ {0x6f00, 0xc3}, ++ {0xc4e4, 0x18}, ++ {0xc4e5, 0x30}, ++ {0xc4e6, 0x48}, ++ {0xc4e7, 0x60}, ++ {0xc4e8, 0x78}, ++ {0xc4e9, 0x90}, ++ {0xc4ea, 0xa4}, ++ {0xc4eb, 0xb4}, ++ {0xc4ec, 0xc2}, ++ {0xc4ed, 0xcf}, ++ {0xc4ee, 0xdb}, ++ {0xc4ef, 0xe5}, ++ {0xc4f0, 0xee}, ++ {0xc4f1, 0xf6}, ++ {0xc4f2, 0xfc}, ++ {0x6f00, 0x03}, ++ {0x6f00, 0x43}, ++}, { ++ {0x6f00, 0xc3}, ++ {0xc4e4, 0x10}, ++ {0xc4e5, 0x20}, ++ {0xc4e6, 0x30}, ++ {0xc4e7, 0x40}, ++ {0xc4e8, 0x50}, ++ {0xc4e9, 0x60}, ++ {0xc4ea, 0x70}, ++ {0xc4eb, 0x80}, ++ {0xc4ec, 0x90}, ++ {0xc4ed, 0xa0}, ++ {0xc4ee, 0xb0}, ++ {0xc4ef, 0xc0}, ++ {0xc4f0, 0xd0}, ++ {0xc4f1, 0xe0}, ++ {0xc4f2, 0xf0}, ++ {0x6f00, 0x03}, ++ {0x6f00, 0x43}, ++}, { ++ {0x6f00, 0xc3}, ++ {0xc4e4, 0x0c}, ++ {0xc4e5, 0x18}, ++ {0xc4e6, 0x24}, ++ {0xc4e7, 0x30}, ++ {0xc4e8, 0x3c}, ++ {0xc4e9, 0x48}, ++ {0xc4ea, 0x54}, ++ {0xc4eb, 0x62}, ++ {0xc4ec, 0x72}, ++ {0xc4ed, 0x84}, ++ {0xc4ee, 0x94}, ++ {0xc4ef, 0xa6}, ++ {0xc4f0, 0xb9}, ++ {0xc4f1, 0xcd}, ++ {0xc4f2, 0xe2}, ++ {0x6f00, 0x03}, ++ {0x6f00, 0x43}, ++}, { ++ {0x6f00, 0xc3}, ++ {0xc4e4, 0x06}, ++ {0xc4e5, 0x0d}, ++ {0xc4e6, 0x15}, ++ {0xc4e7, 0x1e}, ++ {0xc4e8, 0x28}, ++ {0xc4e9, 0x32}, ++ {0xc4ea, 0x3c}, ++ {0xc4eb, 0x48}, ++ {0xc4ec, 0x56}, ++ {0xc4ed, 0x66}, ++ {0xc4ee, 0x78}, ++ {0xc4ef, 0x8c}, ++ {0xc4f0, 0xa2}, ++ {0xc4f1, 0xba}, ++ {0xc4f2, 0xd4}, ++ {0x6f00, 0x03}, ++ {0x6f00, 0x43}, ++} ++}; +diff --git a/drivers/media/i2c/soc_camera/ov10635_debug.h b/drivers/media/i2c/soc_camera/ov10635_debug.h +new file mode 100644 +index 0000000..4c3515a +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov10635_debug.h +@@ -0,0 +1,54 @@ ++ ++#if 0 ++{0x4700, 0x02}, // BT656 ++{0x381d, 0x40}, // mirror off ++{0x381c, 0x00}, // flip off ++{0x4300, 0x3a}, // YUV: UYVY ++{0x4708, 0x00}, // PCLK rising edge ++ ++// clk = 24Mhz/3*22/2= 88Mhz ++{0x3003, 0x16}, ++{0x3004, 0x30}, ++#endif ++ ++#define WIDTH 1280 ++#define HEIGHT 720 ++ ++// DVP frame size ++{0x3808, WIDTH >> 8}, ++{0x3809, WIDTH & 0xff}, ++{0x380a, HEIGHT >> 8}, ++{0x380b, HEIGHT & 0xff}, ++ ++{0x3802, ((814 - HEIGHT)/2) >> 8}, // vert crop start ++{0x3803, ((814 - HEIGHT)/2) & 0xff}, ++{0x3806, ((814 - HEIGHT)/2 + HEIGHT + 1) >> 8}, // vert crop end ++{0x3807, ((814 - HEIGHT)/2 + HEIGHT + 1) & 0xff}, ++ ++#if 0 ++#define HTS 0x6f6 // got from above table 1782 ++#define VTS (0x2ec+80) // got from above table 748 + 80 ++ ++{0x380c, HTS >> 8}, // hts ++{0x380d, HTS & 0xff}, ++{0x380e, VTS >> 8}, // vts ++{0x380f, VTS & 0xff}, ++ ++// fifo ++{0x4606, (2*HTS) >> 8}, // fifo_line_length = 2*hts ++{0x4607, (2*HTS) & 0xff}, ++{0x460a, (2*(HTS-1280)) >> 8}, // fifo_hsync_start = 2*(hts - xres) ++{0x460b, (2*(HTS-1280)) & 0xff }, ++ ++// exposure ++{0xC488, (VTS-8)*16 >> 8}, ++{0xC489, (VTS-8)*16 & 0xff}, ++{0xC48A, (VTS-8)*16 >> 8}, ++{0xC48B, (VTS-8)*16 & 0xff}, ++ ++// vts/hts ++{0xC518, VTS >> 8}, ++{0xC519, VTS & 0xff}, ++{0xC51A, HTS >> 8}, ++{0xC51B, HTS & 0xff}, ++#endif +diff --git a/drivers/media/i2c/soc_camera/ov106xx.c b/drivers/media/i2c/soc_camera/ov106xx.c +new file mode 100644 +index 0000000..0079bb2 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov106xx.c +@@ -0,0 +1,95 @@ ++/* ++ * OmniVision ov10635/ov490-ov10640/ov495-ov2775 sensor camera driver ++ * ++ * Copyright (C) 2016-2017 Cogent Embedded, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ */ ++ ++#include "ov10635.c" ++#include "ov490_ov10640.c" ++#include "ov495_ov2775.c" ++ ++static enum { ++ ID_OV10635, ++ ID_OV490_OV10640, ++ ID_OV495_OV2775, ++} chip_id; ++ ++static int ov106xx_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ int ret; ++ chip_id = -EINVAL; ++ ++ ret = ov10635_probe(client, did); ++ if (!ret) { ++ chip_id = ID_OV10635; ++ goto out; ++ } ++ ++ ret = ov490_probe(client, did); ++ if (!ret) { ++ chip_id = ID_OV490_OV10640; ++ goto out; ++ } ++ ++ ret = ov495_probe(client, did); ++ if (!ret) { ++ chip_id = ID_OV495_OV2775; ++ goto out; ++ } ++ ++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", ++ client->addr, client->adapter->name); ++out: ++ return ret; ++} ++ ++static int ov106xx_remove(struct i2c_client *client) ++{ ++ switch (chip_id) { ++ case ID_OV10635: ++ ov10635_remove(client); ++ break; ++ case ID_OV490_OV10640: ++ ov490_remove(client); ++ break; ++ case ID_OV495_OV2775: ++ ov495_remove(client); ++ break; ++ }; ++ ++ return 0; ++} ++ ++static const struct i2c_device_id ov106xx_id[] = { ++ { "ov106xx", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, ov106xx_id); ++ ++static const struct of_device_id ov106xx_of_ids[] = { ++ { .compatible = "ovti,ov106xx", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ov106xx_of_ids); ++ ++static struct i2c_driver ov106xx_i2c_driver = { ++ .driver = { ++ .name = "ov106xx", ++ .of_match_table = ov106xx_of_ids, ++ }, ++ .probe = ov106xx_probe, ++ .remove = ov106xx_remove, ++ .id_table = ov106xx_id, ++}; ++ ++module_i2c_driver(ov106xx_i2c_driver); ++ ++MODULE_DESCRIPTION("SoC Camera driver for OV10635 or OV490/OV10640 or OV495/OV2775"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/i2c/soc_camera/ov490_ov10640.c b/drivers/media/i2c/soc_camera/ov490_ov10640.c +new file mode 100644 +index 0000000..dfd410a +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov490_ov10640.c +@@ -0,0 +1,963 @@ ++/* ++ * OmniVision ov490-ov10640 sensor camera driver ++ * ++ * Copyright (C) 2016-2017 Cogent Embedded, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ */ ++ ++#include <linux/delay.h> ++#include <linux/init.h> ++#include <linux/i2c.h> ++#include <linux/module.h> ++#include <linux/videodev2.h> ++ ++#include <media/soc_camera.h> ++#include <media/v4l2-common.h> ++#include <media/v4l2-ctrls.h> ++#include <media/v4l2-of.h> ++ ++#include "max9286_max9271.h" ++#include "ov490_ov10640.h" ++ ++#define OV490_I2C_ADDR 0x24 ++ ++#define OV490_PID 0x300a ++#define OV490_VER 0x300b ++#define OV490_VERSION_REG 0x0490 ++#define OV490_VERSION(pid, ver) (((pid) << 8) | ((ver) & 0xff)) ++#define OV490_REV 0x0007 ++ ++#define OV490_ISP_HSIZE_LOW 0x60 ++#define OV490_ISP_HSIZE_HIGH 0x61 ++#define OV490_ISP_VSIZE_LOW 0x62 ++#define OV490_ISP_VSIZE_HIGH 0x63 ++ ++struct ov490_priv { ++ struct v4l2_subdev sd; ++ struct v4l2_ctrl_handler hdl; ++ struct media_pad pad; ++ struct v4l2_rect rect; ++ int max_width; ++ int max_height; ++ char is_fixed_sensor; ++ int init_complete; ++ u8 id[6]; ++ int exposure; ++ int gain; ++ int autogain; ++ int dvp_order; ++ /* serializers */ ++ int max9286_addr; ++ int max9271_addr; ++ int ti964_addr; ++ int ti954_addr; ++ int ti9x3_addr; ++ int port; ++ int gpio_resetb; ++ int gpio_fsin; ++ ++}; ++ ++static int force_conf_link; ++ ++static __init int ov490_force_conf_link(char *str) ++{ ++ /* force configuration link */ ++ /* used only if robust firmware flashing required (f.e. recovery) */ ++ force_conf_link = 1; ++ return 0; ++} ++early_param("force_conf_link", ov490_force_conf_link); ++ ++static inline struct ov490_priv *to_ov490(const struct i2c_client *client) ++{ ++ return container_of(i2c_get_clientdata(client), struct ov490_priv, sd); ++} ++ ++static void ov490_s_port(struct i2c_client *client, int fwd_en) ++{ ++ struct ov490_priv *priv = to_ov490(client); ++ int tmp_addr; ++ ++ if (priv->max9286_addr) { ++ tmp_addr = client->addr; ++ client->addr = priv->max9286_addr; /* Deserializer I2C address */ ++ reg8_write(client, 0x0a, fwd_en ? 0x11 << priv->port : 0); /* Enable/disable reverse/forward control for this port */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ client->addr = tmp_addr; ++ }; ++} ++ ++static int ov490_set_regs(struct i2c_client *client, ++ const struct ov490_reg *regs, int nr_regs) ++{ ++ int i; ++ ++ for (i = 0; i < nr_regs; i++) { ++ if (reg16_write(client, regs[i].reg, regs[i].val)) { ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, regs[i].reg, regs[i].val); ++ } ++ } ++ ++ return 0; ++} ++ ++static int ov490_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ return 0; ++} ++ ++static int ov490_get_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov490_priv *priv = to_ov490(client); ++ ++ if (format->pad) ++ return -EINVAL; ++ ++ mf->width = priv->rect.width; ++ mf->height = priv->rect.height; ++ mf->code = MEDIA_BUS_FMT_YUYV8_2X8; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static int ov490_set_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ ++ mf->code = MEDIA_BUS_FMT_YUYV8_2X8; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ if (format->which == V4L2_SUBDEV_FORMAT_TRY) ++ cfg->try_fmt = *mf; ++ ++ return 0; ++} ++ ++static int ov490_enum_mbus_code(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ if (code->pad || code->index > 0) ++ return -EINVAL; ++ ++ code->code = MEDIA_BUS_FMT_YUYV8_2X8; ++ ++ return 0; ++} ++ ++static int ov490_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov490_priv *priv = to_ov490(client); ++ ++ memcpy(edid->edid, priv->id, 6); ++ ++ edid->edid[6] = 0xff; ++ edid->edid[7] = client->addr; ++ edid->edid[8] = OV490_VERSION_REG >> 8; ++ edid->edid[9] = OV490_VERSION_REG & 0xff; ++ ++ return 0; ++} ++ ++static int ov490_set_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct v4l2_rect *rect = &sel->r; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov490_priv *priv = to_ov490(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || ++ sel->target != V4L2_SEL_TGT_CROP) ++ return -EINVAL; ++ ++ rect->left = ALIGN(rect->left, 2); ++ rect->top = ALIGN(rect->top, 2); ++ rect->width = ALIGN(rect->width, 2); ++ rect->height = ALIGN(rect->height, 2); ++ ++ if ((rect->left + rect->width > priv->max_width) || ++ (rect->top + rect->height > priv->max_height)) ++ *rect = priv->rect; ++ ++ priv->rect.left = rect->left; ++ priv->rect.top = rect->top; ++ priv->rect.width = rect->width; ++ priv->rect.height = rect->height; ++ ++ return 0; ++} ++ ++static int ov490_get_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov490_priv *priv = to_ov490(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) ++ return -EINVAL; ++ ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = priv->max_width; ++ sel->r.height = priv->max_height; ++ return 0; ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = priv->max_width; ++ sel->r.height = priv->max_height; ++ return 0; ++ case V4L2_SEL_TGT_CROP: ++ sel->r = priv->rect; ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int ov490_g_mbus_config(struct v4l2_subdev *sd, ++ struct v4l2_mbus_config *cfg) ++{ ++ cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | ++ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; ++ cfg->type = V4L2_MBUS_CSI2; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int ov490_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ int ret; ++ u8 val = 0; ++ ++ ret = reg16_read(client, (u16)reg->reg, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u16); ++ ++ return 0; ++} ++ ++static int ov490_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ int ret; ++ ++ ret = reg16_write(client, (u16)reg->reg, (u8)reg->val); ++ if ((u8)reg->reg == 0xFFFD) ++ usleep_range(100, 150); /* wait 100 us */ ++ if ((u8)reg->reg == 0xFFFE) ++ usleep_range(100, 150); /* wait 100 us */ ++ return ret; ++} ++#endif ++ ++static struct v4l2_subdev_core_ops ov490_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = ov490_g_register, ++ .s_register = ov490_s_register, ++#endif ++}; ++ ++static int ov490_s_gamma(int a, int ref) ++{ ++ if ((a + ref) > 0xff) ++ return 0xff; ++ ++ if ((a + ref) < 0) ++ return 0; ++ ++ return a + ref; ++} ++ ++static int ov490_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct v4l2_subdev *sd = to_sd(ctrl); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov490_priv *priv = to_ov490(client); ++ int ret = -EINVAL; ++ ++ if (!priv->init_complete) ++ return 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_BRIGHTNESS: ++ /* SDE (rough) brightness */ ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x00); ++ ret |= reg16_write(client, 0x5001, ctrl->val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xf1); ++ break; ++ case V4L2_CID_CONTRAST: ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, ctrl->val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xfd); ++ break; ++ case V4L2_CID_SATURATION: ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, ctrl->val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xf3); ++ break; ++ case V4L2_CID_HUE: ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, ctrl->val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xf5); ++ break; ++ case V4L2_CID_GAMMA: ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, ov490_s_gamma(ctrl->val, 0x12)); ++ ret |= reg16_write(client, 0x5001, ov490_s_gamma(ctrl->val, 0x20)); ++ ret |= reg16_write(client, 0x5002, ov490_s_gamma(ctrl->val, 0x3b)); ++ ret |= reg16_write(client, 0x5003, ov490_s_gamma(ctrl->val, 0x5d)); ++ ret |= reg16_write(client, 0x5004, ov490_s_gamma(ctrl->val, 0x6a)); ++ ret |= reg16_write(client, 0x5005, ov490_s_gamma(ctrl->val, 0x76)); ++ ret |= reg16_write(client, 0x5006, ov490_s_gamma(ctrl->val, 0x81)); ++ ret |= reg16_write(client, 0x5007, ov490_s_gamma(ctrl->val, 0x8b)); ++ ret |= reg16_write(client, 0x5008, ov490_s_gamma(ctrl->val, 0x96)); ++ ret |= reg16_write(client, 0x5009, ov490_s_gamma(ctrl->val, 0x9e)); ++ ret |= reg16_write(client, 0x500a, ov490_s_gamma(ctrl->val, 0xae)); ++ ret |= reg16_write(client, 0x500b, ov490_s_gamma(ctrl->val, 0xbc)); ++ ret |= reg16_write(client, 0x500c, ov490_s_gamma(ctrl->val, 0xcf)); ++ ret |= reg16_write(client, 0x500d, ov490_s_gamma(ctrl->val, 0xde)); ++ ret |= reg16_write(client, 0x500e, ov490_s_gamma(ctrl->val, 0xec)); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xf9); ++ break; ++ case V4L2_CID_SHARPNESS: ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, ctrl->val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xfb); ++ break; ++ case V4L2_CID_AUTOGAIN: ++ case V4L2_CID_GAIN: ++ case V4L2_CID_EXPOSURE: ++ if (ctrl->id == V4L2_CID_AUTOGAIN) ++ priv->autogain = ctrl->val; ++ if (ctrl->id == V4L2_CID_GAIN) ++ priv->gain = ctrl->val; ++ if (ctrl->id == V4L2_CID_EXPOSURE) ++ priv->exposure = ctrl->val; ++ ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, !priv->autogain); ++ ret |= reg16_write(client, 0x5001, priv->exposure >> 8); ++ ret |= reg16_write(client, 0x5002, priv->exposure & 0xff); ++ ret |= reg16_write(client, 0x5003, priv->exposure >> 8); ++ ret |= reg16_write(client, 0x5004, priv->exposure & 0xff); ++ ret |= reg16_write(client, 0x5005, priv->exposure >> 8); ++ ret |= reg16_write(client, 0x5006, priv->exposure & 0xff); ++ ret |= reg16_write(client, 0x5007, priv->gain >> 8); ++ ret |= reg16_write(client, 0x5008, priv->gain & 0xff); ++ ret |= reg16_write(client, 0x5009, priv->gain >> 8); ++ ret |= reg16_write(client, 0x500a, priv->gain & 0xff); ++ ret |= reg16_write(client, 0x500b, priv->gain >> 8); ++ ret |= reg16_write(client, 0x500c, priv->gain & 0xff); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xea); ++ break; ++ case V4L2_CID_HFLIP: ++#if 1 ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, ctrl->val); ++ ret |= reg16_write(client, 0x5001, 0x00); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xdc); ++#else ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x01); // read 0x3128 ++ ret |= reg16_write(client, 0x5001, 0x31); ++ ret |= reg16_write(client, 0x5002, 0x28); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_read(client, 0x5000, &val); ++ val &= ~(0x1 << 0); ++ val |= (ctrl->val << 0); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x00); // write 0x3128 ++ ret |= reg16_write(client, 0x5001, 0x31); ++ ret |= reg16_write(client, 0x5002, 0x28); ++ ret |= reg16_write(client, 0x5003, val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x01); // read 0x3291 ++ ret |= reg16_write(client, 0x5001, 0x32); ++ ret |= reg16_write(client, 0x5002, 0x91); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_read(client, 0x5000, &val); ++ val &= ~(0x1 << 1); ++ val |= (ctrl->val << 1); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x00); // write 0x3291 ++ ret |= reg16_write(client, 0x5001, 0x32); ++ ret |= reg16_write(client, 0x5002, 0x91); ++ ret |= reg16_write(client, 0x5003, val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x01); // read 0x3090 ++ ret |= reg16_write(client, 0x5001, 0x30); ++ ret |= reg16_write(client, 0x5002, 0x90); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_read(client, 0x5000, &val); ++ val &= ~(0x1 << 2); ++ val |= (ctrl->val << 2); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x00); // write 0x3090 ++ ret |= reg16_write(client, 0x5001, 0x30); ++ ret |= reg16_write(client, 0x5002, 0x90); ++ ret |= reg16_write(client, 0x5003, val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++#endif ++ break; ++ case V4L2_CID_VFLIP: ++#if 1 ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, ctrl->val); ++ ret |= reg16_write(client, 0x5001, 0x01); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xdc); ++#else ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x01); // read 0x3128 ++ ret |= reg16_write(client, 0x5001, 0x31); ++ ret |= reg16_write(client, 0x5002, 0x28); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_read(client, 0x5000, &val); ++ val &= ~(0x1 << 1); ++ val |= (ctrl->val << 1); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x00); // write 0x3128 ++ ret |= reg16_write(client, 0x5001, 0x31); ++ ret |= reg16_write(client, 0x5002, 0x28); ++ ret |= reg16_write(client, 0x5003, val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x01); // read 0x3291 ++ ret |= reg16_write(client, 0x5001, 0x32); ++ ret |= reg16_write(client, 0x5002, 0x91); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_read(client, 0x5000, &val); ++ val &= ~(0x1 << 2); ++ val |= (ctrl->val << 2); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x00); // write 0x3291 ++ ret |= reg16_write(client, 0x5001, 0x32); ++ ret |= reg16_write(client, 0x5002, 0x91); ++ ret |= reg16_write(client, 0x5003, val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x01); // read 0x3090 ++ ret |= reg16_write(client, 0x5001, 0x30); ++ ret |= reg16_write(client, 0x5002, 0x90); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_read(client, 0x5000, &val); ++ val &= ~(0x1 << 3); ++ val |= (ctrl->val << 3); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x00); // write 0x3090 ++ ret |= reg16_write(client, 0x5001, 0x30); ++ ret |= reg16_write(client, 0x5002, 0x90); ++ ret |= reg16_write(client, 0x5003, val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++#endif ++ break; ++ } ++ ++ return ret; ++} ++ ++static const struct v4l2_ctrl_ops ov490_ctrl_ops = { ++ .s_ctrl = ov490_s_ctrl, ++}; ++ ++static struct v4l2_subdev_video_ops ov490_video_ops = { ++ .s_stream = ov490_s_stream, ++ .g_mbus_config = ov490_g_mbus_config, ++}; ++ ++static const struct v4l2_subdev_pad_ops ov490_subdev_pad_ops = { ++ .get_edid = ov490_get_edid, ++ .enum_mbus_code = ov490_enum_mbus_code, ++ .get_selection = ov490_get_selection, ++ .set_selection = ov490_set_selection, ++ .get_fmt = ov490_get_fmt, ++ .set_fmt = ov490_set_fmt, ++}; ++ ++static struct v4l2_subdev_ops ov490_subdev_ops = { ++ .core = &ov490_core_ops, ++ .video = &ov490_video_ops, ++ .pad = &ov490_subdev_pad_ops, ++}; ++ ++static void ov490_otp_id_read(struct i2c_client *client) ++{ ++ struct ov490_priv *priv = to_ov490(client); ++ int i; ++ ++#if 0 ++ /* read camera id from ov490 OTP memory */ ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x28); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0xE084, 0x40); /* manual mode, bank#0 */ ++ reg16_write(client, 0xE081, 1); /* start OTP read */ ++ ++ usleep_range(25000, 26000); /* wait 25 ms */ ++ ++ for (i = 0; i < 6; i++) ++ reg16_read(client, 0xe000 + i + 4, &priv->id[i]); ++#else ++ /* read camera id from ov10640 OTP memory */ ++ reg16_write(client, 0xFFFD, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x5000, 0x00); /* write 0x349C -> 1 */ ++ reg16_write(client, 0x5001, 0x34); ++ reg16_write(client, 0x5002, 0x9C); ++ reg16_write(client, 0x5003, 1); ++ reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x00C0, 0xc1); ++ ++ usleep_range(25000, 25500); /* wait 25 ms */ ++ ++ for (i = 0; i < 6; i++) { ++ reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x5000, 0x01); /* read (0x349E + i) */ ++ reg16_write(client, 0x5001, 0x34); ++ reg16_write(client, 0x5002, 0x9e + i + 6); /* first 6 bytes are equal on all ov10640 */ ++ reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x00C0, 0xc1); ++ reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(1000, 1500); /* wait 1 ms */ ++ reg16_read(client, 0x5000, &priv->id[i]); ++ } ++#endif ++} ++ ++static ssize_t ov490_otp_id_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(to_i2c_client(dev)); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov490_priv *priv = to_ov490(client); ++ ++ return snprintf(buf, 32, "%02x:%02x:%02x:%02x:%02x:%02x\n", ++ priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++} ++ ++static DEVICE_ATTR(otp_id_ov490, S_IRUGO, ov490_otp_id_show, NULL); ++ ++static int ov490_initialize(struct i2c_client *client) ++{ ++ struct ov490_priv *priv = to_ov490(client); ++ u8 val = 0; ++ u8 pid = 0, ver = 0, rev = 0; ++ int ret = 0; ++ ++ if (priv->is_fixed_sensor) { ++ dev_info(&client->dev, "ov490/ov10640 fixed-sensor res %dx%d\n", priv->max_width, priv->max_height); ++ return 0; ++ } ++ ++ ov490_s_port(client, 1); ++ ++ /* check and show product ID and manufacturer ID */ ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_read(client, OV490_PID, &pid); ++ reg16_read(client, OV490_VER, &ver); ++ reg16_read(client, OV490_REV, &rev); ++ ++ if (OV490_VERSION(pid, ver) != OV490_VERSION_REG) { ++ dev_dbg(&client->dev, "Product ID error %x:%x\n", pid, ver); ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ if (unlikely(force_conf_link)) ++ goto out; ++ ++ /* read resolution used by current firmware */ ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x82); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_read(client, OV490_ISP_HSIZE_HIGH, &val); ++ priv->max_width = val; ++ reg16_read(client, OV490_ISP_HSIZE_LOW, &val); ++ priv->max_width = (priv->max_width << 8) | val; ++ reg16_read(client, OV490_ISP_VSIZE_HIGH, &val); ++ priv->max_height = val; ++ reg16_read(client, OV490_ISP_VSIZE_LOW, &val); ++ priv->max_height = (priv->max_height << 8) | val; ++ /* Program wizard registers */ ++ ov490_set_regs(client, ov490_regs_wizard, ARRAY_SIZE(ov490_regs_wizard)); ++ /* Set DVP bit swap */ ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x28); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x6009, priv->dvp_order << 4); ++ /* Read OTP IDs */ ++ ov490_otp_id_read(client); ++ ++out: ++ dev_info(&client->dev, "ov490/ov10640 Product ID %x Manufacturer ID %x, rev 1%x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, ver, 0xa + rev, priv->max_width, priv->max_height, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++err: ++ ov490_s_port(client, 0); ++ ++ return ret; ++} ++ ++static int ov490_parse_dt(struct device_node *np, struct ov490_priv *priv) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); ++ int err, i; ++ const char *fixed_sensor; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ int tmp_addr = 0; ++ ++ for (i = 0; ; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; ++ ++ of_node_put(endpoint); ++ ++ of_property_read_u32(endpoint, "dvp-order", &priv->dvp_order); ++ ++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); ++ if (!rendpoint) ++ continue; ++ ++ if (!of_property_read_u32(rendpoint, "max9271-addr", &priv->max9271_addr) && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->max9286_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ ++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti964-ti9x3") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti964_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ ++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti954-ti9x3") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti954_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ } ++ ++ if (!priv->max9286_addr && !priv->ti964_addr && !priv->ti954_addr) { ++ dev_err(&client->dev, "deserializer does not present\n"); ++ return -EINVAL; ++ } ++ ++ ov490_s_port(client, 1); ++ ++ /* setup I2C translator address */ ++ tmp_addr = client->addr; ++ if (priv->max9286_addr) { ++ client->addr = priv->max9271_addr; /* Serializer I2C address */ ++ ++ reg8_write(client, 0x09, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x0A, OV490_I2C_ADDR << 1); /* Sensor native I2C address */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ }; ++ if (priv->ti964_addr) { ++ client->addr = priv->ti964_addr; /* Deserializer I2C address */ ++ ++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x5d, OV490_I2C_ADDR << 1); /* Sensor native I2C address */ ++ ++ reg8_write(client, 0x6e, 0x9a); /* GPIO0 - fsin, GPIO1 - resetb */ ++ /* TODO: why too long? move logic to workqueue? */ ++ mdelay(350); /* time needed to boot all sensor IPs */ ++ } ++ if (priv->ti954_addr) { ++ client->addr = priv->ti954_addr; /* Deserializer I2C address */ ++ ++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x5d, OV490_I2C_ADDR << 1); /* Sensor native I2C address */ ++ ++ reg8_write(client, 0x6e, 0x9a); /* GPIO0 - fsin, GPIO1 - resetb */ ++ /* TODO: why too long? move logic to workqueue? */ ++ mdelay(350); /* time needed to boot all sensor IPs */ ++ } ++ client->addr = tmp_addr; ++ ++ err = of_property_read_string(np, "maxim,fixed-sensor", &fixed_sensor); ++ if (err) ++ return 0; ++ ++ if (strcmp(fixed_sensor, "ov490") == 0) { ++ err = of_property_read_u32(np, "maxim,width", &priv->max_width); ++ if (err) { ++ dev_err(&client->dev, "maxim,width must be set for fixed-sensor\n"); ++ goto out; ++ } ++ ++ err = of_property_read_u32(np, "maxim,height", &priv->max_height); ++ if (err) { ++ dev_err(&client->dev, "maxim,height must be set for fixed-sensor\n"); ++ goto out; ++ } ++ ++ priv->is_fixed_sensor = true; ++ } ++ ++out: ++ return err; ++} ++ ++static int ov490_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct ov490_priv *priv; ++ int ret; ++ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ v4l2_i2c_subdev_init(&priv->sd, client, &ov490_subdev_ops); ++ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; ++ ++ priv->exposure = 0x100; ++ priv->gain = 0x100; ++ priv->autogain = 1; ++ v4l2_ctrl_handler_init(&priv->hdl, 4); ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_BRIGHTNESS, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_CONTRAST, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_SATURATION, 0, 7, 1, 2); ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_HUE, 0, 23, 1, 12); ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_GAMMA, -128, 128, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_SHARPNESS, 0, 10, 1, 3); ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_AUTOGAIN, 0, 1, 1, priv->autogain); ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_GAIN, 0, 0xffff, 1, priv->gain); ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_EXPOSURE, 0, 0xffff, 1, priv->exposure); ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 1); ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ priv->sd.ctrl_handler = &priv->hdl; ++ ++ ret = priv->hdl.error; ++ if (ret) ++ goto cleanup; ++ ++ v4l2_ctrl_handler_setup(&priv->hdl); ++ ++ priv->pad.flags = MEDIA_PAD_FL_SOURCE; ++ priv->sd.entity.flags |= MEDIA_ENT_F_CAM_SENSOR; ++ ret = media_entity_pads_init(&priv->sd.entity, 1, &priv->pad); ++ if (ret < 0) ++ goto cleanup; ++ ++ ret = ov490_parse_dt(client->dev.of_node, priv); ++ if (ret) ++ goto cleanup; ++ ++ ret = ov490_initialize(client); ++ if (ret < 0) ++ goto cleanup; ++ ++ priv->rect.left = 0; ++ priv->rect.top = 0; ++ priv->rect.width = priv->max_width; ++ priv->rect.height = priv->max_height; ++ ++ ret = v4l2_async_register_subdev(&priv->sd); ++ if (ret) ++ goto cleanup; ++ ++ if (device_create_file(&client->dev, &dev_attr_otp_id_ov490) != 0) { ++ dev_err(&client->dev, "sysfs otp_id entry creation failed\n"); ++ goto cleanup; ++ } ++ ++ priv->init_complete = 1; ++ ++ return 0; ++ ++cleanup: ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++#ifdef CONFIG_SOC_CAMERA_OV490_OV10640 ++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", ++ client->addr, client->adapter->name); ++#endif ++ return ret; ++} ++ ++static int ov490_remove(struct i2c_client *client) ++{ ++ struct ov490_priv *priv = i2c_get_clientdata(client); ++ ++ device_remove_file(&client->dev, &dev_attr_otp_id_ov490); ++ v4l2_async_unregister_subdev(&priv->sd); ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_SOC_CAMERA_OV490_OV10640 ++static const struct i2c_device_id ov490_id[] = { ++ { "ov490-ov10640", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, ov490_id); ++ ++static const struct of_device_id ov490_of_ids[] = { ++ { .compatible = "ovti,ov490-ov10640", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ov490_of_ids); ++ ++static struct i2c_driver ov490_i2c_driver = { ++ .driver = { ++ .name = "ov490-ov10640", ++ .of_match_table = ov490_of_ids, ++ }, ++ .probe = ov490_probe, ++ .remove = ov490_remove, ++ .id_table = ov490_id, ++}; ++ ++module_i2c_driver(ov490_i2c_driver); ++ ++MODULE_DESCRIPTION("SoC Camera driver for OV490-OV10640"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); ++#endif +diff --git a/drivers/media/i2c/soc_camera/ov490_ov10640.h b/drivers/media/i2c/soc_camera/ov490_ov10640.h +new file mode 100644 +index 0000000..86e6524 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov490_ov10640.h +@@ -0,0 +1,33 @@ ++/* ++ * OmniVision ov490-ov10640 sensor camera wizard 1280x1080@30/UYVY/BT601/8bit ++ * ++ * Copyright (C) 2016-2017 Cogent Embedded, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ */ ++ ++struct ov490_reg { ++ u16 reg; ++ u8 val; ++}; ++ ++static const struct ov490_reg ov490_regs_wizard[] = { ++/* The following registers should match firmware */ ++{0xfffd, 0x80}, ++{0xfffe, 0x82}, ++{0x0071, 0x11}, ++{0x0075, 0x11}, ++{0xfffe, 0x29}, ++{0x6010, 0x01}, ++{0x4017, 0x00}, ++{0xfffe, 0x28}, ++{0x6000, 0x04}, ++{0x6004, 0x00}, ++{0x6008, 0x00}, // PCLK polarity - useless due to silicon bug -> use 0x808000bb register ++{0xfffe, 0x80}, ++{0x0091, 0x00}, ++{0x00bb, 0x1d}, // bit[3]=0 - PCLK polarity workaround ++}; +diff --git a/drivers/media/i2c/soc_camera/ov495_ov2775.c b/drivers/media/i2c/soc_camera/ov495_ov2775.c +new file mode 100644 +index 0000000..3f55778 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov495_ov2775.c +@@ -0,0 +1,670 @@ ++/* ++ * OmniVision ov495-ov2775 sensor camera driver ++ * ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ */ ++ ++#include <linux/delay.h> ++#include <linux/init.h> ++#include <linux/i2c.h> ++#include <linux/module.h> ++#include <linux/videodev2.h> ++ ++#include <media/soc_camera.h> ++#include <media/v4l2-common.h> ++#include <media/v4l2-ctrls.h> ++#include <media/v4l2-of.h> ++ ++#include "ov495_ov2775.h" ++ ++#define OV495_I2C_ADDR 0x24 ++ ++#define OV495_PID 0x300a ++#define OV495_VER 0x300b ++#define OV495_VERSION_REG 0x0495 ++#define OV495_VERSION(pid, ver) (((pid) << 8) | ((ver) & 0xff)) ++#define OV495_REV 0x0007 ++ ++#define OV495_ISP_HSIZE_LOW 0x60 ++#define OV495_ISP_HSIZE_HIGH 0x61 ++#define OV495_ISP_VSIZE_LOW 0x62 ++#define OV495_ISP_VSIZE_HIGH 0x63 ++ ++struct ov495_priv { ++ struct v4l2_subdev sd; ++ struct v4l2_ctrl_handler hdl; ++ struct media_pad pad; ++ struct v4l2_rect rect; ++ int max_width; ++ int max_height; ++ int init_complete; ++ u8 id[6]; ++ int exposure; ++ int gain; ++ int autogain; ++ int dvp_order; ++ /* serializers */ ++ int max9286_addr; ++ int max9271_addr; ++ int ti960_addr; ++ int ti954_addr; ++ int ti9x3_addr; ++ int port; ++ int gpio_resetb; ++ int gpio_fsin; ++ ++}; ++ ++static int force_conf_link; ++ ++static __init int ov495_force_conf_link(char *str) ++{ ++ /* force configuration link */ ++ /* used only if robust firmware flashing required (f.e. recovery) */ ++ force_conf_link = 1; ++ return 0; ++} ++early_param("force_conf_link", ov495_force_conf_link); ++ ++static inline struct ov495_priv *to_ov495(const struct i2c_client *client) ++{ ++ return container_of(i2c_get_clientdata(client), struct ov495_priv, sd); ++} ++ ++static int ov495_set_regs(struct i2c_client *client, ++ const struct ov495_reg *regs, int nr_regs) ++{ ++ int i; ++ ++ for (i = 0; i < nr_regs; i++) { ++ if (reg16_write(client, regs[i].reg, regs[i].val)) { ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, regs[i].reg, regs[i].val); ++ } ++ } ++ ++ return 0; ++} ++ ++static int ov495_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ return 0; ++} ++ ++static int ov495_get_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov495_priv *priv = to_ov495(client); ++ ++ if (format->pad) ++ return -EINVAL; ++ ++ mf->width = priv->rect.width; ++ mf->height = priv->rect.height; ++ mf->code = MEDIA_BUS_FMT_YUYV8_2X8; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static int ov495_set_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ ++ mf->code = MEDIA_BUS_FMT_YUYV8_2X8; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ if (format->which == V4L2_SUBDEV_FORMAT_TRY) ++ cfg->try_fmt = *mf; ++ ++ return 0; ++} ++ ++static int ov495_enum_mbus_code(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ if (code->pad || code->index > 0) ++ return -EINVAL; ++ ++ code->code = MEDIA_BUS_FMT_YUYV8_2X8; ++ ++ return 0; ++} ++ ++static int ov495_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov495_priv *priv = to_ov495(client); ++ ++ memcpy(edid->edid, priv->id, 6); ++ ++ edid->edid[6] = 0xff; ++ edid->edid[7] = client->addr; ++ edid->edid[8] = OV495_VERSION_REG >> 8; ++ edid->edid[9] = OV495_VERSION_REG & 0xff; ++ ++ return 0; ++} ++ ++static int ov495_set_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct v4l2_rect *rect = &sel->r; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov495_priv *priv = to_ov495(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || ++ sel->target != V4L2_SEL_TGT_CROP) ++ return -EINVAL; ++ ++ rect->left = ALIGN(rect->left, 2); ++ rect->top = ALIGN(rect->top, 2); ++ rect->width = ALIGN(rect->width, 2); ++ rect->height = ALIGN(rect->height, 2); ++ ++ if ((rect->left + rect->width > priv->max_width) || ++ (rect->top + rect->height > priv->max_height)) ++ *rect = priv->rect; ++ ++ priv->rect.left = rect->left; ++ priv->rect.top = rect->top; ++ priv->rect.width = rect->width; ++ priv->rect.height = rect->height; ++ ++ return 0; ++} ++ ++static int ov495_get_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov495_priv *priv = to_ov495(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) ++ return -EINVAL; ++ ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = priv->max_width; ++ sel->r.height = priv->max_height; ++ return 0; ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = priv->max_width; ++ sel->r.height = priv->max_height; ++ return 0; ++ case V4L2_SEL_TGT_CROP: ++ sel->r = priv->rect; ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int ov495_g_mbus_config(struct v4l2_subdev *sd, ++ struct v4l2_mbus_config *cfg) ++{ ++ cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | ++ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; ++ cfg->type = V4L2_MBUS_CSI2; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int ov495_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ int ret; ++ u8 val = 0; ++ ++ ret = reg16_read(client, (u16)reg->reg, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u16); ++ ++ return 0; ++} ++ ++static int ov495_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ int ret; ++ ++ ret = reg16_write(client, (u16)reg->reg, (u8)reg->val); ++ if ((u8)reg->reg == 0xFFFD) ++ usleep_range(100, 150); /* wait 100 us */ ++ if ((u8)reg->reg == 0xFFFE) ++ usleep_range(100, 150); /* wait 100 us */ ++ return ret; ++} ++#endif ++ ++static struct v4l2_subdev_core_ops ov495_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = ov495_g_register, ++ .s_register = ov495_s_register, ++#endif ++}; ++ ++static int ov495_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct v4l2_subdev *sd = to_sd(ctrl); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov495_priv *priv = to_ov495(client); ++ int ret = -EINVAL; ++ ++ if (!priv->init_complete) ++ return 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_BRIGHTNESS: ++ break; ++ case V4L2_CID_CONTRAST: ++ break; ++ case V4L2_CID_SATURATION: ++ break; ++ case V4L2_CID_HUE: ++ break; ++ case V4L2_CID_GAMMA: ++ break; ++ case V4L2_CID_SHARPNESS: ++ break; ++ case V4L2_CID_AUTOGAIN: ++ case V4L2_CID_GAIN: ++ case V4L2_CID_EXPOSURE: ++ break; ++ case V4L2_CID_HFLIP: ++ ret = reg16_write(client, 0x3516, 0x00); ++ ret |= reg16_write(client, 0x0ffc, 0x00); ++ ret |= reg16_write(client, 0x0500, ctrl->val); ++ ret |= reg16_write(client, 0x0501, 0x00); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x30C0, 0xdc); ++ ret |= reg16_write(client, 0x3516, 0x01); ++ break; ++ case V4L2_CID_VFLIP: ++ ret = reg16_write(client, 0x3516, 0x00); ++ ret |= reg16_write(client, 0x0ffc, 0x00); ++ ret |= reg16_write(client, 0x0500, ctrl->val); ++ ret |= reg16_write(client, 0x0501, 0x01); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x30C0, 0xdc); ++ ret |= reg16_write(client, 0x3516, 0x01); ++ break; ++ } ++ ++ return ret; ++} ++ ++static const struct v4l2_ctrl_ops ov495_ctrl_ops = { ++ .s_ctrl = ov495_s_ctrl, ++}; ++ ++static struct v4l2_subdev_video_ops ov495_video_ops = { ++ .s_stream = ov495_s_stream, ++ .g_mbus_config = ov495_g_mbus_config, ++}; ++ ++static const struct v4l2_subdev_pad_ops ov495_subdev_pad_ops = { ++ .get_edid = ov495_get_edid, ++ .enum_mbus_code = ov495_enum_mbus_code, ++ .get_selection = ov495_get_selection, ++ .set_selection = ov495_set_selection, ++ .get_fmt = ov495_get_fmt, ++ .set_fmt = ov495_set_fmt, ++}; ++ ++static struct v4l2_subdev_ops ov495_subdev_ops = { ++ .core = &ov495_core_ops, ++ .video = &ov495_video_ops, ++ .pad = &ov495_subdev_pad_ops, ++}; ++ ++static void ov495_otp_id_read(struct i2c_client *client) ++{ ++#if 0 ++ struct ov495_priv *priv = to_ov495(client); ++ int i; ++ ++ /* read camera id from ov495 OTP memory */ ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x28); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0xE084, 0x40); /* manual mode, bank#0 */ ++ reg16_write(client, 0xE081, 1); /* start OTP read */ ++ ++ usleep_range(25000, 26000); /* wait 25 ms */ ++ ++ for (i = 0; i < 6; i++) ++ reg16_read(client, 0xe000 + i + 4, &priv->id[i]); ++#else ++#if 0 ++ /* read camera id from ov2775 OTP memory */ ++ reg16_write(client, 0xFFFD, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x5000, 0x00); /* write 0x349C -> 1 */ ++ reg16_write(client, 0x5001, 0x34); ++ reg16_write(client, 0x5002, 0x9C); ++ reg16_write(client, 0x5003, 1); ++ reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x00C0, 0xc1); ++ ++ usleep_range(25000, 25500); /* wait 25 ms */ ++ ++ for (i = 0; i < 6; i++) { ++ reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x5000, 0x01); /* read (0x349E + i) */ ++ reg16_write(client, 0x5001, 0x34); ++ reg16_write(client, 0x5002, 0x9e + i + 6); /* first 6 bytes are equal on all ov2775 */ ++ reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x00C0, 0xc1); ++ reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(1000, 1500); /* wait 1 ms */ ++ reg16_read(client, 0x5000, &priv->id[i]); ++ } ++#endif ++#endif ++} ++ ++static ssize_t ov495_otp_id_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(to_i2c_client(dev)); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov495_priv *priv = to_ov495(client); ++ ++ return snprintf(buf, 32, "%02x:%02x:%02x:%02x:%02x:%02x\n", ++ priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++} ++ ++static DEVICE_ATTR(otp_id_ov495, S_IRUGO, ov495_otp_id_show, NULL); ++ ++static int ov495_initialize(struct i2c_client *client) ++{ ++ struct ov495_priv *priv = to_ov495(client); ++ u8 pid = 0, ver = 0, rev = 0; ++ int ret = 0; ++ ++ /* check and show product ID and manufacturer ID */ ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_read(client, OV495_PID, &pid); ++ reg16_read(client, OV495_VER, &ver); ++ reg16_read(client, OV495_REV, &rev); ++ ++ if (OV495_VERSION(pid, ver) != OV495_VERSION_REG) { ++ dev_err(&client->dev, "Product ID error %x:%x\n", pid, ver); ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ if (unlikely(force_conf_link)) ++ goto out; ++ ++#if 0 ++ /* read resolution used by current firmware */ ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x82); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_read(client, OV495_ISP_HSIZE_HIGH, &val); ++ priv->max_width = val; ++ reg16_read(client, OV495_ISP_HSIZE_LOW, &val); ++ priv->max_width = (priv->max_width << 8) | val; ++ reg16_read(client, OV495_ISP_VSIZE_HIGH, &val); ++ priv->max_height = val; ++ reg16_read(client, OV495_ISP_VSIZE_LOW, &val); ++ priv->max_height = (priv->max_height << 8) | val; ++#else ++ priv->max_width = 1920; ++ priv->max_height = 1080; ++#endif ++ ++ /* set virtual channel */ ++ reg16_write(client, 0x3516, 0x0); /* unlock write */ ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x20); ++ reg16_write(client, 0x8017, 0x1e | (priv->port << 6)); ++ reg16_write(client, 0x3516, 0x1); /* lock write */ ++ ++ /* Program wizard registers */ ++ ov495_set_regs(client, ov495_regs_wizard, ARRAY_SIZE(ov495_regs_wizard)); ++ /* Read OTP IDs */ ++ ov495_otp_id_read(client); ++ ++out: ++ dev_info(&client->dev, "ov495/ov2775 Product ID %x Manufacturer ID %x, rev 1%x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, ver, 0xa + rev, priv->max_width, priv->max_height, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++err: ++ return ret; ++} ++ ++static int ov495_parse_dt(struct device_node *np, struct ov495_priv *priv) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); ++ int i; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ int tmp_addr = 0; ++ ++ for (i = 0; ; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; ++ ++ of_node_put(endpoint); ++ ++ of_property_read_u32(endpoint, "dvp-order", &priv->dvp_order); ++ ++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); ++ if (!rendpoint) ++ continue; ++ ++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti964-ti9x3") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti960_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ ++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti954-ti9x3") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti954_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ } ++ ++ if (!priv->ti960_addr && !priv->ti954_addr) { ++ dev_err(&client->dev, "deserializer does not present\n"); ++ return -EINVAL; ++ } ++ ++ /* setup I2C translator address */ ++ tmp_addr = client->addr; ++ if (priv->ti960_addr) { ++ client->addr = priv->ti960_addr; /* Deserializer I2C address */ ++ ++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x5d, OV495_I2C_ADDR << 1); /* Sensor native I2C address */ ++ ++ reg8_write(client, 0x6e, 0x9a); /* GPIO0 - fsin, GPIO1 - resetb */ ++ /* TODO: why too long? move logic to workqueue? */ ++ mdelay(350); /* time needed to boot all sensor IPs */ ++ } ++ if (priv->ti954_addr) { ++ client->addr = priv->ti954_addr; /* Deserializer I2C address */ ++ ++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x5d, OV495_I2C_ADDR << 1); /* Sensor native I2C address */ ++ ++ reg8_write(client, 0x6e, 0x9a); /* GPIO0 - fsin, GPIO1 - resetb */ ++ /* TODO: why too long? move logic to workqueue? */ ++ mdelay(350); /* time needed to boot all sensor IPs */ ++ } ++ client->addr = tmp_addr; ++ ++ return 0; ++} ++ ++static int ov495_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct ov495_priv *priv; ++ int ret; ++ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ v4l2_i2c_subdev_init(&priv->sd, client, &ov495_subdev_ops); ++ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; ++ ++ priv->exposure = 0x100; ++ priv->gain = 0x100; ++ priv->autogain = 1; ++ v4l2_ctrl_handler_init(&priv->hdl, 4); ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ V4L2_CID_BRIGHTNESS, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ V4L2_CID_CONTRAST, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ V4L2_CID_SATURATION, 0, 7, 1, 2); ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ V4L2_CID_HUE, 0, 23, 1, 12); ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ V4L2_CID_GAMMA, -128, 128, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ V4L2_CID_SHARPNESS, 0, 10, 1, 3); ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ V4L2_CID_AUTOGAIN, 0, 1, 1, priv->autogain); ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ V4L2_CID_GAIN, 0, 0xffff, 1, priv->gain); ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ V4L2_CID_EXPOSURE, 0, 0xffff, 1, priv->exposure); ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ priv->sd.ctrl_handler = &priv->hdl; ++ ++ ret = priv->hdl.error; ++ if (ret) ++ goto cleanup; ++ ++ v4l2_ctrl_handler_setup(&priv->hdl); ++ ++ priv->pad.flags = MEDIA_PAD_FL_SOURCE; ++ priv->sd.entity.flags |= MEDIA_ENT_F_CAM_SENSOR; ++ ret = media_entity_pads_init(&priv->sd.entity, 1, &priv->pad); ++ if (ret < 0) ++ goto cleanup; ++ ++ ret = ov495_parse_dt(client->dev.of_node, priv); ++ if (ret) ++ goto cleanup; ++ ++ ret = ov495_initialize(client); ++ if (ret < 0) ++ goto cleanup; ++ ++ priv->rect.left = 0; ++ priv->rect.top = 0; ++ priv->rect.width = priv->max_width; ++ priv->rect.height = priv->max_height; ++ ++ ret = v4l2_async_register_subdev(&priv->sd); ++ if (ret) ++ goto cleanup; ++ ++ if (device_create_file(&client->dev, &dev_attr_otp_id_ov495) != 0) { ++ dev_err(&client->dev, "sysfs otp_id entry creation failed\n"); ++ goto cleanup; ++ } ++ ++ priv->init_complete = 1; ++ ++ return 0; ++ ++cleanup: ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++#ifdef CONFIG_SOC_CAMERA_OV495_OV2775 ++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", ++ client->addr, client->adapter->name); ++#endif ++ return ret; ++} ++ ++static int ov495_remove(struct i2c_client *client) ++{ ++ struct ov495_priv *priv = i2c_get_clientdata(client); ++ ++ device_remove_file(&client->dev, &dev_attr_otp_id_ov495); ++ v4l2_async_unregister_subdev(&priv->sd); ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_SOC_CAMERA_OV495_OV2775 ++static const struct i2c_device_id ov495_id[] = { ++ { "ov495-ov2775", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, ov495_id); ++ ++static const struct of_device_id ov495_of_ids[] = { ++ { .compatible = "ovti,ov495-ov2775", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ov495_of_ids); ++ ++static struct i2c_driver ov495_i2c_driver = { ++ .driver = { ++ .name = "ov495-ov2775", ++ .of_match_table = ov495_of_ids, ++ }, ++ .probe = ov495_probe, ++ .remove = ov495_remove, ++ .id_table = ov495_id, ++}; ++ ++module_i2c_driver(ov495_i2c_driver); ++ ++MODULE_DESCRIPTION("SoC Camera driver for OV495-OV2775"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); ++#endif +diff --git a/drivers/media/i2c/soc_camera/ov495_ov2775.h b/drivers/media/i2c/soc_camera/ov495_ov2775.h +new file mode 100644 +index 0000000..dc6ad86 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov495_ov2775.h +@@ -0,0 +1,18 @@ ++/* ++ * OmniVision ov495-ov2775 sensor camera wizard 1280x1080@30/UYVY/BT601/8bit ++ * ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ */ ++ ++struct ov495_reg { ++ u16 reg; ++ u8 val; ++}; ++ ++static const struct ov495_reg ov495_regs_wizard[] = { ++}; +diff --git a/drivers/media/i2c/soc_camera/ti954_ti9x3.c b/drivers/media/i2c/soc_camera/ti954_ti9x3.c +new file mode 100644 +index 0000000..81babce +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ti954_ti9x3.c +@@ -0,0 +1,414 @@ ++/* ++ * TI ti954-(ti913/ti953) FPDLinkIII driver ++ * ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ */ ++ ++#include <linux/delay.h> ++#include <linux/i2c.h> ++#include <linux/module.h> ++#include <linux/of_gpio.h> ++#include <linux/videodev2.h> ++#include <linux/notifier.h> ++ ++#include <media/v4l2-common.h> ++#include <media/v4l2-device.h> ++#include <media/v4l2-of.h> ++#include <media/v4l2-subdev.h> ++ ++#include "ti9x4_ti9x3.h" ++ ++struct ti954_ti9x3_priv { ++ struct v4l2_subdev sd[4]; ++ struct device_node *sd_of_node[4]; ++ int des_addr; ++ int links; ++ int lanes; ++ int csi_rate; ++ const char *forwarding_mode; ++ const char *cable_mode; ++ atomic_t use_count; ++ struct i2c_client *client; ++ int ti9x3_addr_map[4]; ++ char chip_id[6]; ++ int xtal_gpio; ++}; ++ ++static int indirect_write(struct i2c_client *client, unsigned int page, u8 reg, u8 val) ++{ ++ if (page > 7) ++ return -EINVAL; ++ ++ reg8_write(client, 0xb0, page << 2); ++ reg8_write(client, 0xb1, reg); ++ reg8_write(client, 0xb2, val); ++ ++ return 0; ++} ++ ++#if 0 ++static int indirect_read(struct i2c_client *client, unsigned int page, u8 reg, u8 *val) ++{ ++ if (page > 7) ++ return -EINVAL; ++ ++ reg8_write(client, 0xb0, page << 2); ++ reg8_write(client, 0xb1, reg); ++ reg8_read(client, 0xb2, val); ++ ++ return 0; ++} ++#endif ++ ++static void ti954_ti9x3_read_chipid(struct i2c_client *client) ++{ ++ struct ti954_ti9x3_priv *priv = i2c_get_clientdata(client); ++ ++ /* Chip ID */ ++ reg8_read(client, 0xf1, &priv->chip_id[0]); ++ reg8_read(client, 0xf2, &priv->chip_id[1]); ++ reg8_read(client, 0xf3, &priv->chip_id[2]); ++ reg8_read(client, 0xf4, &priv->chip_id[3]); ++ reg8_read(client, 0xf5, &priv->chip_id[4]); ++ priv->chip_id[5] = '\0'; ++} ++ ++static void ti954_ti9x3_initial_setup(struct i2c_client *client) ++{ ++ struct ti954_ti9x3_priv *priv = i2c_get_clientdata(client); ++ ++ /* Initial setup */ ++ client->addr = priv->des_addr; /* TI954 I2C */ ++ reg8_write(client, 0x08, 0x1c); /* I2C glitch filter depth */ ++ reg8_write(client, 0x0a, 0x79); /* I2C high pulse width */ ++ reg8_write(client, 0x0b, 0x79); /* I2C low pulse width */ ++ reg8_write(client, 0x0d, 0xb9); /* VDDIO 3.3V */ ++ switch (priv->csi_rate) { ++ case 1600: /* REFCLK = 25MHZ */ ++ case 1450: /* REFCLK = 22.5MHZ */ ++ reg8_write(client, 0x1f, 0x00); /* CSI rate 1.5/1.6Gbps */ ++ break; ++ case 800: /* REFCLK = 25MHZ */ ++ reg8_write(client, 0x1f, 0x02); /* CSI rate 800Mbps */ ++ break; ++ case 400: /* REFCLK = 25MHZ */ ++ reg8_write(client, 0x1f, 0x03); /* CSI rate 400Mbps */ ++ break; ++ default: ++ dev_err(&client->dev, "unsupported CSI rate %d\n", priv->csi_rate); ++ } ++ ++ if (strcmp(priv->forwarding_mode, "round-robin") == 0) { ++ reg8_write(client, 0x21, 0x01); /* Round Robin forwarding enable */ ++ } else if (strcmp(priv->forwarding_mode, "synchronized") == 0) { ++ reg8_write(client, 0x21, 0x44); /* Basic Syncronized forwarding enable (FrameSync must be enabled!!) */ ++ } ++ ++ reg8_write(client, 0x32, 0x01); /* Select TX (CSI) port 0 */ ++ reg8_write(client, 0x33, ((priv->lanes - 1) ^ 0x3) << 4); /* disable CSI output, set CSI lane count, non-continuous CSI mode */ ++ reg8_write(client, 0x20, 0xf0); /* disable port forwarding */ ++#if 1 ++ /* FrameSync setup for REFCLK=25MHz, FPS=30: period_counts=1/FPS*25MHz =1/30*25Mhz =833333 -> FS_TIME=833333 */ ++ /* FrameSync setup for REFCLK=22.5MHz, FPS=30: period_counts=1/FPS*22.5Mhz=1/30*22.5Mhz=750000 -> FS_TIME=750000 */ ++ #define FS_TIME (priv->csi_rate == 1450 ? 750000 : 833333) ++ reg8_write(client, 0x1a, FS_TIME >> 16); /* FrameSync time 24bit */ ++ reg8_write(client, 0x1b, (FS_TIME >> 8) & 0xff); ++ reg8_write(client, 0x1c, FS_TIME & 0xff); ++ reg8_write(client, 0x18, 0x43); /* Enable FrameSync, 50/50 mode, Frame clock from 25MHz */ ++#else ++ /* FrameSync setup for 30FPS: period_counts=1/FPS/12mks=1/30/12e-6=2777 -> HI=2, LO=2775 FPS=30.008 */ ++ reg8_write(client, 0x19, 2 >> 8); /* FrameSync high time MSB */ ++ reg8_write(client, 0x1a, 2 >> 16); /* FrameSync high time LSB */ ++ reg8_write(client, 0x1b, 2775 & 0xff); /* FrameSync low time MSB */ ++ reg8_write(client, 0x1c, 2775 & 0xff); /* FrameSync low time LSB */ ++ reg8_write(client, 0x18, 0x01); /* Enable FrameSync, HI/LO mode, Frame clock from port0 */ ++#endif ++} ++ ++//#define SENSOR_ID 0x30 // ov10635 ++//#define SENSOR_ID 0x24 // ov490 ++ ++static void ti954_ti9x3_fpdlink3_setup(struct i2c_client *client, int idx) ++{ ++ struct ti954_ti9x3_priv *priv = i2c_get_clientdata(client); ++ ++ /* FPDLinkIII setup */ ++ client->addr = priv->des_addr; /* TI954 I2C */ ++ reg8_write(client, 0x4c, (idx << 4) | (1 << idx)); /* Select RX port number */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x58, 0x58); /* Back channel: pass-through/backchannel/CRC enable, Freq=2.5Mbps */ ++ reg8_write(client, 0x5c, priv->ti9x3_addr_map[idx] << 1); /* TI9X3 I2C addr */ ++// reg8_write(client, 0x5d, SENSOR_ID << 1); /* SENSOR I2C native - must be set by sensor driver */ ++// reg8_write(client, 0x65, (0x60 + idx) << 1); /* SENSOR I2C translated - must be set by sensor driver */ ++ if (strcmp(priv->cable_mode, "coax") == 0) { ++ reg8_write(client, 0x6d, 0x7f); /* Coax, RAW10 */ ++ } else if (strcmp(priv->cable_mode, "stp") == 0) { ++ reg8_write(client, 0x6d, 0x78); /* STP, CSI */ ++ } ++ reg8_write(client, 0x70, (idx << 6) | 0x1e); /* CSI data type: yuv422 8-bit, assign VC */ ++ reg8_write(client, 0x7c, 0x81); /* BIT(7) - magic to Use RAW10 as 8-bit mode */ ++ reg8_write(client, 0x6e, 0x99); /* Backchannel GPIO0/GPIO1 set high */ ++} ++ ++static int ti954_ti9x3_initialize(struct i2c_client *client) ++{ ++ struct ti954_ti9x3_priv *priv = i2c_get_clientdata(client); ++ int idx; ++ ++ dev_info(&client->dev, "LINKs=%d, LANES=%d, FORWARDING=%s, CABLE=%s, ID=%s\n", ++ priv->links, priv->lanes, priv->forwarding_mode, priv->cable_mode, priv->chip_id); ++ ++ ti954_ti9x3_initial_setup(client); ++ ++ for (idx = 0; idx < priv->links; idx++) ++ ti954_ti9x3_fpdlink3_setup(client, idx); ++ ++ client->addr = priv->des_addr; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int ti954_ti9x3_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct ti954_ti9x3_priv *priv = v4l2_get_subdevdata(sd); ++ struct i2c_client *client = priv->client; ++ int ret; ++ u8 val = 0; ++ ++ ret = reg8_read(client, (u8)reg->reg, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u8); ++ ++ return 0; ++} ++ ++static int ti954_ti9x3_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct ti954_ti9x3_priv *priv = v4l2_get_subdevdata(sd); ++ struct i2c_client *client = priv->client; ++ ++ return reg8_write(client, (u8)reg->reg, (u8)reg->val); ++} ++#endif ++ ++static int ti954_ti9x3_s_power(struct v4l2_subdev *sd, int on) ++{ ++ struct ti954_ti9x3_priv *priv = v4l2_get_subdevdata(sd); ++ struct i2c_client *client = priv->client; ++ ++ if (on) { ++ if (atomic_inc_return(&priv->use_count) == 1) ++ reg8_write(client, 0x20, 0x00); /* enable port forwarding to CSI */ ++ } else { ++ if (atomic_dec_return(&priv->use_count) == 0) ++ reg8_write(client, 0x20, 0xf0); /* disable port forwarding to CSI */ ++ } ++ ++ return 0; ++} ++ ++static int ti954_ti9x3_registered_async(struct v4l2_subdev *sd) ++{ ++ struct ti954_ti9x3_priv *priv = v4l2_get_subdevdata(sd); ++ struct i2c_client *client = priv->client; ++ ++ reg8_write(client, 0x33, ((priv->lanes - 1) ^ 0x3) << 4 | 0x1); /* enable CSI output, set CSI lane count, non-continuous CSI mode */ ++ ++ return 0; ++} ++ ++static struct v4l2_subdev_core_ops ti954_ti9x3_subdev_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = ti954_ti9x3_g_register, ++ .s_register = ti954_ti9x3_s_register, ++#endif ++ .s_power = ti954_ti9x3_s_power, ++ .registered_async = ti954_ti9x3_registered_async, ++}; ++ ++static struct v4l2_subdev_ops ti954_ti9x3_subdev_ops = { ++ .core = &ti954_ti9x3_subdev_core_ops, ++}; ++ ++static int ti954_ti9x3_parse_dt(struct i2c_client *client) ++{ ++ struct ti954_ti9x3_priv *priv = i2c_get_clientdata(client); ++ struct device_node *np = client->dev.of_node; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ struct property *prop; ++ int err, i; ++ int sensor_delay; ++ char forwarding_mode_default[20] = "round-robin"; /* round-robin, synchronized */ ++ char cable_mode_default[5] = "coax"; /* coax, stp */ ++ struct property *csi_rate_prop, *dvp_order_prop; ++ u8 val = 0; ++ ++ if (of_property_read_u32(np, "ti,links", &priv->links)) ++ priv->links = 2; ++ ++ if (of_property_read_u32(np, "ti,lanes", &priv->lanes)) ++ priv->lanes = 4; ++ ++ priv->xtal_gpio = of_get_gpio(np, 0); ++ if (priv->xtal_gpio > 0) { ++ err = gpio_request_one(priv->xtal_gpio, GPIOF_OUT_INIT_LOW, dev_name(&client->dev)); ++ if (err) ++ dev_err(&client->dev, "cannot request XTAL gpio %d: %d\n", priv->xtal_gpio, err); ++ else ++ mdelay(250); ++ } ++ ++ reg8_read(client, 0x00, &val); /* read TI954 I2C address */ ++ if (val != (priv->des_addr << 1)) { ++ prop = of_find_property(np, "reg", NULL); ++ if (prop) ++ of_remove_property(np, prop); ++ return -ENODEV; ++ } ++ ++ ti954_ti9x3_read_chipid(client); ++ ++ indirect_write(client, 7, 0x15, 0x30); ++ gpio_set_value(priv->xtal_gpio, 1); ++ usleep_range(5000, 5500); /* wait 5ms */ ++ indirect_write(client, 7, 0x15, 0); ++ ++ if (!of_property_read_u32(np, "ti,sensor_delay", &sensor_delay)) ++ mdelay(sensor_delay); ++ ++ err = of_property_read_string(np, "ti,forwarding-mode", &priv->forwarding_mode); ++ if (err) ++ priv->forwarding_mode = forwarding_mode_default; ++ ++ err = of_property_read_string(np, "ti,cable-mode", &priv->cable_mode); ++ if (err) ++ priv->cable_mode = cable_mode_default; ++ ++ for (i = 0; ; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; ++ ++ of_node_put(endpoint); ++ ++ if (i < priv->links) { ++ if (of_property_read_u32(endpoint, "ti9x3-addr", &priv->ti9x3_addr_map[i])) { ++ dev_err(&client->dev, "ti9x3-addr not set\n"); ++ return -EINVAL; ++ } ++ priv->sd_of_node[i] = endpoint; ++ } ++ ++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); ++ if (!rendpoint) ++ continue; ++ ++ csi_rate_prop = of_find_property(endpoint, "csi-rate", NULL); ++ if (csi_rate_prop) { ++ of_property_read_u32(endpoint, "csi-rate", &priv->csi_rate); ++ of_update_property(rendpoint, csi_rate_prop); ++ } ++ ++ dvp_order_prop = of_find_property(endpoint, "dvp-order", NULL); ++ if (dvp_order_prop) ++ of_update_property(rendpoint, dvp_order_prop); ++ } ++ ++ return 0; ++} ++ ++static int ti954_ti9x3_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct ti954_ti9x3_priv *priv; ++ int err, i; ++ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ i2c_set_clientdata(client, priv); ++ priv->des_addr = client->addr; ++ priv->client = client; ++ atomic_set(&priv->use_count, 0); ++ ++ err = ti954_ti9x3_parse_dt(client); ++ if (err) ++ goto out; ++ ++ err = ti954_ti9x3_initialize(client); ++ if (err < 0) ++ goto out; ++ ++ for (i = 0; i < priv->links; i++) { ++ v4l2_subdev_init(&priv->sd[i], &ti954_ti9x3_subdev_ops); ++ priv->sd[i].owner = client->dev.driver->owner; ++ priv->sd[i].dev = &client->dev; ++ priv->sd[i].grp_id = i; ++ v4l2_set_subdevdata(&priv->sd[i], priv); ++ priv->sd[i].of_node = priv->sd_of_node[i]; ++ ++ snprintf(priv->sd[i].name, V4L2_SUBDEV_NAME_SIZE, "%s %d-%04x", ++ client->dev.driver->name, i2c_adapter_id(client->adapter), ++ client->addr); ++ ++ err = v4l2_async_register_subdev(&priv->sd[i]); ++ if (err < 0) ++ goto out; ++ } ++ ++out: ++ return err; ++} ++ ++static int ti954_ti9x3_remove(struct i2c_client *client) ++{ ++ struct ti954_ti9x3_priv *priv = i2c_get_clientdata(client); ++ int i; ++ ++ for (i = 0; i < priv->links; i++) { ++ v4l2_async_unregister_subdev(&priv->sd[i]); ++ v4l2_device_unregister_subdev(&priv->sd[i]); ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id ti954_ti9x3_dt_ids[] = { ++ { .compatible = "ti,ti954-ti9x3" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, ti954_ti9x3_dt_ids); ++ ++static const struct i2c_device_id ti954_ti9x3_id[] = { ++ { "ti954_ti9x3", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, ti954_ti9x3_id); ++ ++static struct i2c_driver ti954_ti9x3_i2c_driver = { ++ .driver = { ++ .name = "ti954_ti9x3", ++ .of_match_table = of_match_ptr(ti954_ti9x3_dt_ids), ++ }, ++ .probe = ti954_ti9x3_probe, ++ .remove = ti954_ti9x3_remove, ++ .id_table = ti954_ti9x3_id, ++}; ++ ++module_i2c_driver(ti954_ti9x3_i2c_driver); ++ ++MODULE_DESCRIPTION("FPDLinkIII driver for TI954-TI9X3"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/i2c/soc_camera/ti964_ti9x3.c b/drivers/media/i2c/soc_camera/ti964_ti9x3.c +new file mode 100644 +index 0000000..e66e639 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ti964_ti9x3.c +@@ -0,0 +1,382 @@ ++/* ++ * TI (ti964/ti960)-(ti913/ti953) FPDLinkIII driver ++ * ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ */ ++ ++#include <linux/delay.h> ++#include <linux/i2c.h> ++#include <linux/module.h> ++#include <linux/of_gpio.h> ++#include <linux/videodev2.h> ++#include <linux/notifier.h> ++ ++#include <media/v4l2-common.h> ++#include <media/v4l2-device.h> ++#include <media/v4l2-of.h> ++#include <media/v4l2-subdev.h> ++ ++#include "ti9x4_ti9x3.h" ++ ++struct ti964_ti9x3_priv { ++ struct v4l2_subdev sd[4]; ++ struct device_node *sd_of_node[4]; ++ int des_addr; ++ int links; ++ int lanes; ++ int csi_rate; ++ const char *forwarding_mode; ++ const char *cable_mode; ++ atomic_t use_count; ++ struct i2c_client *client; ++ int ti9x3_addr_map[4]; ++ char chip_id[6]; ++}; ++ ++static void ti964_ti9x3_read_chipid(struct i2c_client *client) ++{ ++ struct ti964_ti9x3_priv *priv = i2c_get_clientdata(client); ++ ++ /* Chip ID */ ++ reg8_read(client, 0xf1, &priv->chip_id[0]); ++ reg8_read(client, 0xf2, &priv->chip_id[1]); ++ reg8_read(client, 0xf3, &priv->chip_id[2]); ++ reg8_read(client, 0xf4, &priv->chip_id[3]); ++ reg8_read(client, 0xf5, &priv->chip_id[4]); ++ priv->chip_id[5] = '\0'; ++} ++ ++static void ti964_ti9x3_initial_setup(struct i2c_client *client) ++{ ++ struct ti964_ti9x3_priv *priv = i2c_get_clientdata(client); ++ ++ /* Initial setup */ ++ client->addr = priv->des_addr; /* TI964 I2C */ ++ reg8_write(client, 0x08, 0x1c); /* I2C glitch filter depth */ ++ reg8_write(client, 0x0a, 0x79); /* I2C high pulse width */ ++ reg8_write(client, 0x0b, 0x79); /* I2C low pulse width */ ++ reg8_write(client, 0x0d, 0xb9); /* VDDIO 3.3V */ ++ switch (priv->csi_rate) { ++ case 1600: /* REFCLK = 25MHZ */ ++ case 1450: /* REFCLK = 22.5MHZ */ ++ reg8_write(client, 0x1f, 0x00); /* CSI rate 1.5/1.6Gbps */ ++ break; ++ case 800: /* REFCLK = 25MHZ */ ++ reg8_write(client, 0x1f, 0x02); /* CSI rate 800Mbps */ ++ break; ++ case 400: /* REFCLK = 25MHZ */ ++ reg8_write(client, 0x1f, 0x03); /* CSI rate 400Mbps */ ++ break; ++ default: ++ dev_err(&client->dev, "unsupported CSI rate %d\n", priv->csi_rate); ++ } ++ ++ if (strcmp(priv->forwarding_mode, "round-robin") == 0) { ++ reg8_write(client, 0x21, 0x01); /* Round Robin forwarding enable */ ++ } else if (strcmp(priv->forwarding_mode, "synchronized") == 0) { ++ reg8_write(client, 0x21, 0x44); /* Basic Syncronized forwarding enable (FrameSync must be enabled!!) */ ++ } ++ ++ reg8_write(client, 0x32, 0x01); /* Select TX (CSI) port 0 */ ++ reg8_write(client, 0x33, ((priv->lanes - 1) ^ 0x3) << 4); /* disable CSI output, set CSI lane count, non-continuous CSI mode */ ++ reg8_write(client, 0x20, 0xf0); /* disable port forwarding */ ++#if 1 ++ /* FrameSync setup for REFCLK=25MHz, FPS=30: period_counts=1/FPS*25MHz =1/30*25Mhz =833333 -> FS_TIME=833333 */ ++ /* FrameSync setup for REFCLK=22.5MHz, FPS=30: period_counts=1/FPS*22.5Mhz=1/30*22.5Mhz=750000 -> FS_TIME=750000 */ ++ #define FS_TIME (priv->csi_rate == 1450 ? 750000 : 833333) ++ reg8_write(client, 0x1a, FS_TIME >> 16); /* FrameSync time 24bit */ ++ reg8_write(client, 0x1b, (FS_TIME >> 8) & 0xff); ++ reg8_write(client, 0x1c, FS_TIME & 0xff); ++ reg8_write(client, 0x18, 0x43); /* Enable FrameSync, 50/50 mode, Frame clock from 25MHz */ ++#else ++ /* FrameSync setup for 30FPS: period_counts=1/FPS/12mks=1/30/12e-6=2777 -> HI=2, LO=2775 FPS=30.008 */ ++ reg8_write(client, 0x19, 2 >> 8); /* FrameSync high time MSB */ ++ reg8_write(client, 0x1a, 2 >> 16); /* FrameSync high time LSB */ ++ reg8_write(client, 0x1b, 2775 & 0xff); /* FrameSync low time MSB */ ++ reg8_write(client, 0x1c, 2775 & 0xff); /* FrameSync low time LSB */ ++ reg8_write(client, 0x18, 0x01); /* Enable FrameSync, HI/LO mode, Frame clock from port0 */ ++#endif ++} ++ ++//#define SENSOR_ID 0x30 // ov10635 ++//#define SENSOR_ID 0x24 // ov490 ++ ++static void ti964_ti9x3_fpdlink3_setup(struct i2c_client *client, int idx) ++{ ++ struct ti964_ti9x3_priv *priv = i2c_get_clientdata(client); ++ ++ /* FPDLinkIII setup */ ++ client->addr = priv->des_addr; /* TI964 I2C */ ++ reg8_write(client, 0x4c, (idx << 4) | (1 << idx)); /* Select RX port number */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x58, 0x58); /* Back channel: pass-through/backchannel/CRC enable, Freq=2.5Mbps */ ++ reg8_write(client, 0x5c, priv->ti9x3_addr_map[idx] << 1); /* TI9X3 I2C addr */ ++// reg8_write(client, 0x5d, SENSOR_ID << 1); /* SENSOR I2C native - must be set by sensor driver */ ++// reg8_write(client, 0x65, (0x60 + idx) << 1); /* SENSOR I2C translated - must be set by sensor driver */ ++ if (strcmp(priv->cable_mode, "coax") == 0) { ++ reg8_write(client, 0x6d, 0x7f); /* Coax, RAW10 */ ++ } else if (strcmp(priv->cable_mode, "stp") == 0) { ++ reg8_write(client, 0x6d, 0x78); /* STP, CSI */ ++ } ++ reg8_write(client, 0x70, (idx << 6) | 0x1e); /* CSI data type: yuv422 8-bit, assign VC */ ++ reg8_write(client, 0x7c, 0x81); /* BIT(7) - magic to Use RAW10 as 8-bit mode */ ++ reg8_write(client, 0x6e, 0x99); /* Backchannel GPIO0/GPIO1 set high */ ++} ++ ++static int ti964_ti9x3_initialize(struct i2c_client *client) ++{ ++ struct ti964_ti9x3_priv *priv = i2c_get_clientdata(client); ++ int idx; ++ ++ dev_info(&client->dev, "LINKs=%d, LANES=%d, FORWARDING=%s, CABLE=%s, ID=%s\n", ++ priv->links, priv->lanes, priv->forwarding_mode, priv->cable_mode, priv->chip_id); ++ ++ ti964_ti9x3_initial_setup(client); ++ ++ for (idx = 0; idx < priv->links; idx++) ++ ti964_ti9x3_fpdlink3_setup(client, idx); ++ ++ client->addr = priv->des_addr; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int ti964_ti9x3_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct ti964_ti9x3_priv *priv = v4l2_get_subdevdata(sd); ++ struct i2c_client *client = priv->client; ++ int ret; ++ u8 val = 0; ++ ++ ret = reg8_read(client, (u8)reg->reg, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u8); ++ ++ return 0; ++} ++ ++static int ti964_ti9x3_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct ti964_ti9x3_priv *priv = v4l2_get_subdevdata(sd); ++ struct i2c_client *client = priv->client; ++ ++ return reg8_write(client, (u8)reg->reg, (u8)reg->val); ++} ++#endif ++ ++static int ti964_ti9x3_s_power(struct v4l2_subdev *sd, int on) ++{ ++ struct ti964_ti9x3_priv *priv = v4l2_get_subdevdata(sd); ++ struct i2c_client *client = priv->client; ++ ++ if (on) { ++ if (atomic_inc_return(&priv->use_count) == 1) ++ reg8_write(client, 0x20, 0x00); /* enable port forwarding to CSI */ ++ } else { ++ if (atomic_dec_return(&priv->use_count) == 0) ++ reg8_write(client, 0x20, 0xf0); /* disable port forwarding to CSI */ ++ } ++ ++ return 0; ++} ++ ++static int ti964_ti9x3_registered_async(struct v4l2_subdev *sd) ++{ ++ struct ti964_ti9x3_priv *priv = v4l2_get_subdevdata(sd); ++ struct i2c_client *client = priv->client; ++ ++ reg8_write(client, 0x33, ((priv->lanes - 1) ^ 0x3) << 4 | 0x1); /* enable CSI output, set CSI lane count, non-continuous CSI mode */ ++ ++ return 0; ++} ++ ++static struct v4l2_subdev_core_ops ti964_ti9x3_subdev_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = ti964_ti9x3_g_register, ++ .s_register = ti964_ti9x3_s_register, ++#endif ++ .s_power = ti964_ti9x3_s_power, ++ .registered_async = ti964_ti9x3_registered_async, ++}; ++ ++static struct v4l2_subdev_ops ti964_ti9x3_subdev_ops = { ++ .core = &ti964_ti9x3_subdev_core_ops, ++}; ++ ++static int ti964_ti9x3_parse_dt(struct i2c_client *client) ++{ ++ struct ti964_ti9x3_priv *priv = i2c_get_clientdata(client); ++ struct device_node *np = client->dev.of_node; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ struct property *prop; ++ int err, pwen, i; ++ int sensor_delay; ++ char forwarding_mode_default[20] = "round-robin"; /* round-robin, synchronized */ ++ char cable_mode_default[5] = "coax"; /* coax, stp */ ++ struct property *csi_rate_prop, *dvp_order_prop; ++ u8 val = 0; ++ ++ if (of_property_read_u32(np, "ti,links", &priv->links)) ++ priv->links = 4; ++ ++ if (of_property_read_u32(np, "ti,lanes", &priv->lanes)) ++ priv->lanes = 4; ++ ++ pwen = of_get_gpio(np, 0); ++ if (pwen > 0) { ++ err = gpio_request_one(pwen, GPIOF_OUT_INIT_HIGH, dev_name(&client->dev)); ++ if (err) ++ dev_err(&client->dev, "cannot request PWEN gpio %d: %d\n", pwen, err); ++ else ++ mdelay(250); ++ } ++ ++ reg8_read(client, 0x00, &val); /* read TI964 I2C address */ ++ if (val != (priv->des_addr << 1)) { ++ prop = of_find_property(np, "reg", NULL); ++ if (prop) ++ of_remove_property(np, prop); ++ return -ENODEV; ++ } ++ ++ ti964_ti9x3_read_chipid(client); ++ ++ if (!of_property_read_u32(np, "ti,sensor_delay", &sensor_delay)) ++ mdelay(sensor_delay); ++ ++ err = of_property_read_string(np, "ti,forwarding-mode", &priv->forwarding_mode); ++ if (err) ++ priv->forwarding_mode = forwarding_mode_default; ++ ++ err = of_property_read_string(np, "ti,cable-mode", &priv->cable_mode); ++ if (err) ++ priv->cable_mode = cable_mode_default; ++ ++ for (i = 0; ; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; ++ ++ of_node_put(endpoint); ++ ++ if (i < priv->links) { ++ if (of_property_read_u32(endpoint, "ti9x3-addr", &priv->ti9x3_addr_map[i])) { ++ dev_err(&client->dev, "ti9x3-addr not set\n"); ++ return -EINVAL; ++ } ++ priv->sd_of_node[i] = endpoint; ++ } ++ ++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); ++ if (!rendpoint) ++ continue; ++ ++ csi_rate_prop = of_find_property(endpoint, "csi-rate", NULL); ++ if (csi_rate_prop) { ++ of_property_read_u32(endpoint, "csi-rate", &priv->csi_rate); ++ of_update_property(rendpoint, csi_rate_prop); ++ } ++ ++ dvp_order_prop = of_find_property(endpoint, "dvp-order", NULL); ++ if (dvp_order_prop) ++ of_update_property(rendpoint, dvp_order_prop); ++ } ++ ++ return 0; ++} ++ ++static int ti964_ti9x3_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct ti964_ti9x3_priv *priv; ++ int err, i; ++ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ i2c_set_clientdata(client, priv); ++ priv->des_addr = client->addr; ++ priv->client = client; ++ atomic_set(&priv->use_count, 0); ++ ++ err = ti964_ti9x3_parse_dt(client); ++ if (err) ++ goto out; ++ ++ err = ti964_ti9x3_initialize(client); ++ if (err < 0) ++ goto out; ++ ++ for (i = 0; i < priv->links; i++) { ++ v4l2_subdev_init(&priv->sd[i], &ti964_ti9x3_subdev_ops); ++ priv->sd[i].owner = client->dev.driver->owner; ++ priv->sd[i].dev = &client->dev; ++ priv->sd[i].grp_id = i; ++ v4l2_set_subdevdata(&priv->sd[i], priv); ++ priv->sd[i].of_node = priv->sd_of_node[i]; ++ ++ snprintf(priv->sd[i].name, V4L2_SUBDEV_NAME_SIZE, "%s %d-%04x", ++ client->dev.driver->name, i2c_adapter_id(client->adapter), ++ client->addr); ++ ++ err = v4l2_async_register_subdev(&priv->sd[i]); ++ if (err < 0) ++ goto out; ++ } ++ ++out: ++ return err; ++} ++ ++static int ti964_ti9x3_remove(struct i2c_client *client) ++{ ++ struct ti964_ti9x3_priv *priv = i2c_get_clientdata(client); ++ int i; ++ ++ for (i = 0; i < priv->links; i++) { ++ v4l2_async_unregister_subdev(&priv->sd[i]); ++ v4l2_device_unregister_subdev(&priv->sd[i]); ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id ti964_ti9x3_dt_ids[] = { ++ { .compatible = "ti,ti964-ti9x3" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, ti964_ti9x3_dt_ids); ++ ++static const struct i2c_device_id ti964_ti9x3_id[] = { ++ { "ti964_ti9x3", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, ti964_ti9x3_id); ++ ++static struct i2c_driver ti964_ti9x3_i2c_driver = { ++ .driver = { ++ .name = "ti964_ti9x3", ++ .of_match_table = of_match_ptr(ti964_ti9x3_dt_ids), ++ }, ++ .probe = ti964_ti9x3_probe, ++ .remove = ti964_ti9x3_remove, ++ .id_table = ti964_ti9x3_id, ++}; ++ ++module_i2c_driver(ti964_ti9x3_i2c_driver); ++ ++MODULE_DESCRIPTION("FPDLinkIII driver for TI964-TI9X3"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/i2c/soc_camera/ti9x4_ti9x3.h b/drivers/media/i2c/soc_camera/ti9x4_ti9x3.h +new file mode 100644 +index 0000000..0cee5f1 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ti9x4_ti9x3.h +@@ -0,0 +1,108 @@ ++/* ++ * TI FPDLinkIII driver include file ++ * ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ */ ++ ++#ifndef _TI9X4_H ++#define _TI9X4_H ++ ++//#define DEBUG ++#ifdef DEBUG ++#undef dev_dbg ++#define dev_dbg dev_info ++#endif ++ ++#define MAXIM_NUM_RETRIES 1 /* number of read/write retries */ ++#define BROADCAST 0x6f ++ ++static inline int reg8_read(struct i2c_client *client, u8 reg, u8 *val) ++{ ++ int ret, retries; ++ ++ for (retries = MAXIM_NUM_RETRIES; retries; retries--) { ++ ret = i2c_smbus_read_byte_data(client, reg); ++ if (!(ret < 0)) ++ break; ++ } ++ ++ if (ret < 0) { ++ dev_dbg(&client->dev, ++ "read fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } else { ++ *val = ret; ++ } ++ ++ return ret < 0 ? ret : 0; ++} ++ ++static inline int reg8_write(struct i2c_client *client, u8 reg, u8 val) ++{ ++ int ret, retries; ++ ++ for (retries = MAXIM_NUM_RETRIES; retries; retries--) { ++ ret = i2c_smbus_write_byte_data(client, reg, val); ++ if (!(ret < 0)) ++ break; ++ } ++ ++ if (ret < 0) { ++ dev_dbg(&client->dev, ++ "write fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } ++ ++ return ret < 0 ? ret : 0; ++} ++ ++static inline int reg16_read(struct i2c_client *client, u16 reg, u8 *val) ++{ ++ int ret, retries; ++ u8 buf[2] = {reg >> 8, reg & 0xff}; ++ ++ for (retries = MAXIM_NUM_RETRIES; retries; retries--) { ++ ret = i2c_master_send(client, buf, 2); ++ if (ret == 2) { ++ ret = i2c_master_recv(client, buf, 1); ++ if (ret == 1) ++ break; ++ } ++ } ++ ++ if (ret < 0) { ++ dev_dbg(&client->dev, ++ "read fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } else { ++ *val = buf[0]; ++ } ++ ++ return ret < 0 ? ret : 0; ++} ++ ++static inline int reg16_write(struct i2c_client *client, u16 reg, u8 val) ++{ ++ int ret, retries; ++ u8 buf[3] = {reg >> 8, reg & 0xff, val}; ++ ++ for (retries = MAXIM_NUM_RETRIES; retries; retries--) { ++ ret = i2c_master_send(client, buf, 3); ++ if (ret == 3) ++ break; ++ } ++ ++ if (ret < 0) { ++ dev_dbg(&client->dev, ++ "write fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } ++ ++ return ret < 0 ? ret : 0; ++} ++#endif /* _TI9X4_H */ +diff --git a/drivers/media/platform/soc_camera/rcar_csi2.c b/drivers/media/platform/soc_camera/rcar_csi2.c +index 7373ac3..b3bc810 100644 +--- a/drivers/media/platform/soc_camera/rcar_csi2.c ++++ b/drivers/media/platform/soc_camera/rcar_csi2.c +@@ -37,8 +37,9 @@ + + #include <media/v4l2-of.h> + ++//#define RCAR_CSI2_DUMP ++ + #define DRV_NAME "rcar_csi2" +-#define CONNECT_SLAVE_NAME "adv7482" + #define VC_MAX_CHANNEL 4 + + #define RCAR_CSI2_TREF 0x00 +@@ -63,6 +64,7 @@ + + #define RCAR_CSI2_LINKCNT 0x48 + #define RCAR_CSI2_LSWAP 0x4C ++#define RCAR_CSI2_PHTW 0x50 + #define RCAR_CSI2_PHTC 0x58 + #define RCAR_CSI2_PHYPLL 0x68 + +@@ -106,6 +108,9 @@ + #define RCAR_CSI2_LSWAP_L0SEL_PLANE2 (2 << 0) + #define RCAR_CSI2_LSWAP_L0SEL_PLANE3 (3 << 0) + ++#define RCAR_CSI2_PHTW_DWEN (1 << 24) ++#define RCAR_CSI2_PHTW_CWEN (1 << 8) ++ + #define RCAR_CSI2_PHTC_TESTCLR (1 << 0) + + /* interrupt status registers */ +@@ -179,6 +184,7 @@ struct rcar_csi2_link_config { + unsigned char lanes; + unsigned long vcdt; + unsigned long vcdt2; ++ unsigned int csi_rate; + }; + + #define INIT_RCAR_CSI2_LINK_CONFIG(m) \ +@@ -192,8 +198,7 @@ struct rcar_csi_irq_counter_log { + }; + + struct rcar_csi2 { +- struct v4l2_subdev subdev; +- struct v4l2_mbus_framefmt *mf; ++ struct v4l2_subdev subdev[4]; + unsigned int irq; + unsigned long mipi_flags; + void __iomem *base; +@@ -205,7 +210,9 @@ struct rcar_csi2 { + unsigned int field; + unsigned int code; + unsigned int lanes; ++ unsigned int csi_rate; + spinlock_t lock; ++ atomic_t use_count; + }; + + #define RCAR_CSI_80MBPS 0 +@@ -251,6 +258,89 @@ struct rcar_csi2 { + #define RCAR_CSI_1400MBPS 40 + #define RCAR_CSI_1450MBPS 41 + #define RCAR_CSI_1500MBPS 42 ++#define RCAR_CSI_NUMRATES 43 ++ ++#define RCAR_CSI2_PHxM0(i) (0xf0 + i * 0x08) ++#define RCAR_CSI2_PHxM1(i) (0xf4 + i * 0x08) ++#define RCAR_CSI2_PHRM(i) (0x110 + i * 0x04) ++#define RCAR_CSI2_PHCM(i) (0x120 + i * 0x04) ++#define RCAR_CSI2_SERCCNT 0x140 ++#define RCAR_CSI2_SSERCCNT 0x144 ++#define RCAR_CSI2_ECCCM 0x148 ++#define RCAR_CSI2_ECECM 0x14c ++#define RCAR_CSI2_CRCECM 0x150 ++#define RCAR_CSI2_LCNT(i) (0x160 + i * 0x04) ++#define RCAR_CSI2_LCNTM(i) (0x168 + i * 0x04) ++#define RCAR_CSI2_FCNTM 0x170 ++#define RCAR_CSI2_FCNTM2 0x174 ++#define RCAR_CSI2_VINSM(i) (0x190 + i * 0x04) ++#define RCAR_CSI2_PHM(i) (0x1C0 + i * 0x04) ++ ++#define RCAR_CSI2_INTSTATE_ALL 0x3FFFFCDD ++ ++#ifdef RCAR_CSI2_DUMP ++static void rcar_sci2_debug_show(struct rcar_csi2 *priv) ++{ ++ int i; ++ u32 reg0, reg1; ++ ++ printk("Debug registers:\n"); ++ printk("FCNTM : 0x%08x\n", ioread32(priv->base + RCAR_CSI2_FCNTM)); ++ printk("FCNTM2: 0x%08x\n", ioread32(priv->base + RCAR_CSI2_FCNTM2)); ++ ++ for (i = 0; i < 4; i++) { ++ reg0 = ioread32(priv->base + RCAR_CSI2_PHxM0(i)); ++ reg1 = ioread32(priv->base + RCAR_CSI2_PHxM1(i)); ++ ++ printk("Packet header %d: dt: 0x%02x, vc: %d, wc: %d, cnt: %d\n", ++ i, ++ reg0 & 0x3F, (reg0 >> 6) & 0x03, (reg0 >> 8) & 0xffff, ++ reg1 & 0xffff); ++ } ++ for (i = 0; i < 3; i++) { ++ reg0 = ioread32(priv->base + RCAR_CSI2_PHRM(i)); ++ ++ printk("Packet header R %d dt: 0x%02x, vc: %d, wc: %d, ecc: 0x%02x\n", ++ i, ++ reg0 & 0x3F, (reg0 >> 6) & 0x03, (reg0 >> 8) & 0xffff, ++ (reg0 >> 24) & 0xff); ++ } ++ for (i = 0; i < 2; i++) { ++ reg0 = ioread32(priv->base + RCAR_CSI2_PHCM(i)); ++ ++ printk("Packet header C %d: dt: 0x%02x, vc: %d, wc: %d, cal_parity: 0x%02x\n", ++ i, ++ reg0 & 0x3F, (reg0 >> 6) & 0x03, (reg0 >> 8) & 0xffff, ++ (reg0 >> 24) & 0xff); ++ } ++ for (i = 0; i < 8; i++) { ++ reg0 = ioread32(priv->base + RCAR_CSI2_PHM(i)); ++ ++ printk("Packet header Monitor %d: dt: 0x%02x, vc: %d, wc: %d, ecc: 0x%02x\n", ++ i + 1, ++ reg0 & 0x3F, (reg0 >> 6) & 0x03, (reg0 >> 8) & 0xffff, ++ (reg0 >> 24) & 0xff); ++ } ++ for (i = 0; i < 3; i++) ++ printk("VINSM%d: 0x%08x\n", i, ioread32(priv->base + RCAR_CSI2_VINSM(i))); ++ printk("SERCCNT: %d\n", ++ ioread32(priv->base + RCAR_CSI2_SERCCNT)); ++ printk("SSERCCNT: %d\n", ++ ioread32(priv->base + RCAR_CSI2_SSERCCNT)); ++ printk("ECCCM: %d\n", ++ ioread32(priv->base + RCAR_CSI2_ECCCM)); ++ printk("ECECM: %d\n", ++ ioread32(priv->base + RCAR_CSI2_ECECM)); ++ printk("CRCECM: %d\n", ++ ioread32(priv->base + RCAR_CSI2_CRCECM)); ++ for (i = 0; i < 2; i++) ++ printk("LCNT%d: 0x%08x\n", i, ioread32(priv->base + RCAR_CSI2_LCNT(i))); ++ for (i = 0; i < 2; i++) ++ printk("LCNTM%d: 0x%08x\n", i, ioread32(priv->base + RCAR_CSI2_LCNTM(i))); ++} ++#else ++#define rcar_sci2_debug_show(args) ++#endif /* RCAR_CSI2_DUMP */ + + static int rcar_csi2_set_phy_freq(struct rcar_csi2 *priv) + { +@@ -276,47 +366,22 @@ static int rcar_csi2_set_phy_freq(struct rcar_csi2 *priv) + 0x0B, 0x1B, 0x2B, 0x3B, 0x0C, /* 35-39 */ + 0x1C, 0x2C, 0x3C /* 40-42 */ + }; ++ const uint32_t const csi2_rate_range[43] = { ++ 80, 90, 100, 110, 120, /* 0-4 */ ++ 130, 140, 150, 160, 170, /* 5-9 */ ++ 180, 190, 205, 220, 235, /* 10-14 */ ++ 250, 275, 300, 325, 350, /* 15-19 */ ++ 400, 450, 500, 550, 600, /* 20-24 */ ++ 650, 700, 750, 800, 850, /* 25-29 */ ++ 900, 950, 1000, 1050, 1100, /* 30-34 */ ++ 1150, 1200, 1250, 1300, 1350, /* 35-39 */ ++ 1400, 1450, 1500 /* 40-42 */ ++ }; + uint32_t bps_per_lane = RCAR_CSI_190MBPS; + +- dev_dbg(&priv->pdev->dev, "Input size (%dx%d%c)\n", +- priv->mf->width, priv->mf->height, +- (priv->mf->field == V4L2_FIELD_NONE) ? 'p' : 'i'); +- +- switch (priv->lanes) { +- case 1: +- bps_per_lane = RCAR_CSI_400MBPS; +- break; +- case 4: +- if (priv->mf->field == V4L2_FIELD_NONE) { +- if ((priv->mf->width == 1920) && +- (priv->mf->height == 1080)) +- bps_per_lane = RCAR_CSI_900MBPS; +- else if ((priv->mf->width == 1280) && +- (priv->mf->height == 720)) +- bps_per_lane = RCAR_CSI_450MBPS; +- else if ((priv->mf->width == 720) && +- (priv->mf->height == 480)) +- bps_per_lane = RCAR_CSI_190MBPS; +- else if ((priv->mf->width == 720) && +- (priv->mf->height == 576)) +- bps_per_lane = RCAR_CSI_190MBPS; +- else if ((priv->mf->width == 640) && +- (priv->mf->height == 480)) +- bps_per_lane = RCAR_CSI_100MBPS; +- else +- goto error; +- } else { +- if ((priv->mf->width == 1920) && +- (priv->mf->height == 1080)) +- bps_per_lane = RCAR_CSI_450MBPS; +- else +- goto error; +- } +- break; +- default: +- dev_err(&priv->pdev->dev, "ERROR: lanes is invalid (%d)\n", +- priv->lanes); +- return -EINVAL; ++ for (bps_per_lane = 0; bps_per_lane < RCAR_CSI_NUMRATES; bps_per_lane++) { ++ if (priv->csi_rate <= csi2_rate_range[bps_per_lane]) ++ break; + } + + dev_dbg(&priv->pdev->dev, "bps_per_lane (%d)\n", bps_per_lane); +@@ -329,12 +394,6 @@ static int rcar_csi2_set_phy_freq(struct rcar_csi2 *priv) + iowrite32(hs_freq_range[bps_per_lane] << 16, + priv->base + RCAR_CSI2_PHYPLL); + return 0; +- +-error: +- dev_err(&priv->pdev->dev, "Not support resolution (%dx%d%c)\n", +- priv->mf->width, priv->mf->height, +- (priv->mf->field == V4L2_FIELD_NONE) ? 'p' : 'i'); +- return -EINVAL; + } + + static irqreturn_t rcar_csi2_irq(int irq, void *data) +@@ -392,6 +451,16 @@ static int rcar_csi2_hwinit(struct rcar_csi2 *priv) + iowrite32(0x0001000f, priv->base + RCAR_CSI2_FLD); + tmp |= 0x1; + break; ++ case 2: ++ /* First field number setting */ ++ iowrite32(0x0001000f, priv->base + RCAR_CSI2_FLD); ++ tmp |= 0x3; ++ break; ++ case 3: ++ /* First field number setting */ ++ iowrite32(0x0001000f, priv->base + RCAR_CSI2_FLD); ++ tmp |= 0x7; ++ break; + case 4: + /* First field number setting */ + iowrite32(0x0002000f, priv->base + RCAR_CSI2_FLD); +@@ -469,32 +538,22 @@ static int rcar_csi2_hwinit(struct rcar_csi2 *priv) + + static int rcar_csi2_s_power(struct v4l2_subdev *sd, int on) + { +- struct rcar_csi2 *priv = container_of(sd, struct rcar_csi2, subdev); +- struct v4l2_subdev *tmp_sd; +- struct v4l2_subdev_format fmt = { +- .which = V4L2_SUBDEV_FORMAT_ACTIVE, +- }; +- struct v4l2_mbus_framefmt *mf = &fmt.format; ++ struct rcar_csi2 *priv = v4l2_get_subdevdata(sd); + int ret = 0; + + if (on) { +- v4l2_device_for_each_subdev(tmp_sd, sd->v4l2_dev) { +- if (strncmp(tmp_sd->name, CONNECT_SLAVE_NAME, +- sizeof(CONNECT_SLAVE_NAME) - 1) == 0) { +- v4l2_subdev_call(tmp_sd, pad, get_fmt, +- NULL, &fmt); +- if (ret < 0) +- return ret; +- } ++ if (atomic_inc_return(&priv->use_count) == 1) { ++ pm_runtime_get_sync(&priv->pdev->dev); ++ ret = rcar_csi2_hwinit(priv); ++ if (ret < 0) ++ return ret; + } +- priv->mf = mf; +- pm_runtime_get_sync(&priv->pdev->dev); +- ret = rcar_csi2_hwinit(priv); +- if (ret < 0) +- return ret; + } else { +- rcar_csi2_hwdeinit(priv); +- pm_runtime_put_sync(&priv->pdev->dev); ++ if (atomic_dec_return(&priv->use_count) == 0) { ++ rcar_sci2_debug_show(priv); ++ rcar_csi2_hwdeinit(priv); ++ pm_runtime_put_sync(&priv->pdev->dev); ++ } + } + + return ret; +@@ -543,18 +602,19 @@ static int rcar_csi2_parse_dt(struct device_node *np, + return -EINVAL; + + v4l2_of_parse_endpoint(endpoint, &bus_cfg); ++ ret = of_property_read_u32(endpoint, "csi-rate", &config->csi_rate); ++ if (ret < 0) { ++ printk(KERN_ERR "csi-rate not set\n"); ++ return ret; ++ } + of_node_put(endpoint); + + config->lanes = bus_cfg.bus.mipi_csi2.num_data_lanes; + +- ret = of_property_read_string(np, "adi,input-interface", &str); +- if (ret < 0) +- return ret; +- + vc_np = of_get_child_by_name(np, "virtual,channel"); + +- config->vcdt = 0; +- config->vcdt2 = 0; ++ config->vcdt = 0x81008000; ++ config->vcdt2 = 0x83008200; + for (i = 0; i < VC_MAX_CHANNEL; i++) { + sprintf(csi_name, "csi2_vc%d", i); + +@@ -573,6 +633,8 @@ static int rcar_csi2_parse_dt(struct device_node *np, + config->vcdt |= (0x24 << (i * 16)); + else if (!strcmp(str, "ycbcr422")) + config->vcdt |= (0x1e << (i * 16)); ++ else if (!strcmp(str, "raw8")) ++ config->vcdt |= (0x2a << (i * 16)); + else + config->vcdt |= 0; + +@@ -587,6 +649,8 @@ static int rcar_csi2_parse_dt(struct device_node *np, + config->vcdt2 |= (0x24 << (j * 16)); + else if (!strcmp(str, "ycbcr422")) + config->vcdt2 |= (0x1e << (j * 16)); ++ else if (!strcmp(str, "raw8")) ++ config->vcdt2 |= (0x2a << (j * 16)); + else + config->vcdt2 |= 0; + +@@ -608,6 +672,7 @@ static int rcar_csi2_probe(struct platform_device *pdev) + /* Platform data specify the PHY, lanes, ECC, CRC */ + struct rcar_csi2_pdata *pdata; + struct rcar_csi2_link_config link_config; ++ int i; + + dev_dbg(&pdev->dev, "CSI2 probed.\n"); + +@@ -618,12 +683,7 @@ static int rcar_csi2_probe(struct platform_device *pdev) + if (ret) + return ret; + +- if (link_config.lanes == 4) +- dev_info(&pdev->dev, +- "Detected rgb888 in rcar_csi2_parse_dt\n"); +- else +- dev_info(&pdev->dev, +- "Detected YCbCr422 in rcar_csi2_parse_dt\n"); ++ dev_info(&pdev->dev, "Data lanes %d, link freq %d\n", link_config.lanes, link_config.csi_rate); + } else { + pdata = pdev->dev.platform_data; + if (!pdata) +@@ -655,23 +715,27 @@ static int rcar_csi2_probe(struct platform_device *pdev) + return ret; + + priv->pdev = pdev; +- priv->subdev.owner = THIS_MODULE; +- priv->subdev.dev = &pdev->dev; + priv->lanes = link_config.lanes; + priv->vcdt = link_config.vcdt; + priv->vcdt2 = link_config.vcdt2; ++ priv->csi_rate = link_config.csi_rate; ++ atomic_set(&priv->use_count, 0); + +- platform_set_drvdata(pdev, &priv->subdev); ++ platform_set_drvdata(pdev, priv); + +- v4l2_subdev_init(&priv->subdev, &rcar_csi2_subdev_ops); +- v4l2_set_subdevdata(&priv->subdev, &pdev->dev); ++ for (i= 0; i < 4; i++) { ++ priv->subdev[i].owner = THIS_MODULE; ++ priv->subdev[i].dev = &pdev->dev; ++ v4l2_subdev_init(&priv->subdev[i], &rcar_csi2_subdev_ops); ++ v4l2_set_subdevdata(&priv->subdev[i], priv); + +- snprintf(priv->subdev.name, V4L2_SUBDEV_NAME_SIZE, "rcar_csi2.%s", +- dev_name(&pdev->dev)); ++ snprintf(priv->subdev[i].name, V4L2_SUBDEV_NAME_SIZE, "rcar_csi2.%s", ++ dev_name(&pdev->dev)); + +- ret = v4l2_async_register_subdev(&priv->subdev); +- if (ret < 0) +- return ret; ++ ret = v4l2_async_register_subdev(&priv->subdev[i]); ++ if (ret < 0) ++ return ret; ++ } + + spin_lock_init(&priv->lock); + +@@ -684,10 +748,11 @@ static int rcar_csi2_probe(struct platform_device *pdev) + + static int rcar_csi2_remove(struct platform_device *pdev) + { +- struct v4l2_subdev *subdev = platform_get_drvdata(pdev); +- struct rcar_csi2 *priv = container_of(subdev, struct rcar_csi2, subdev); ++ struct rcar_csi2 *priv = platform_get_drvdata(pdev); ++ int i; + +- v4l2_async_unregister_subdev(&priv->subdev); ++ for (i= 0; i < 4; i++) ++ v4l2_async_unregister_subdev(&priv->subdev[i]); + pm_runtime_disable(&pdev->dev); + + return 0; +diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c +index 74fb005..f5c2528 100644 +--- a/drivers/media/platform/soc_camera/rcar_vin.c ++++ b/drivers/media/platform/soc_camera/rcar_vin.c +@@ -106,6 +106,7 @@ + #define VNMC_INF_YUV8_BT601 (1 << 16) + #define VNMC_INF_YUV10_BT656 (2 << 16) + #define VNMC_INF_YUV10_BT601 (3 << 16) ++#define VNMC_INF_RAW8 (4 << 16) + #define VNMC_INF_YUV16 (5 << 16) + #define VNMC_INF_RGB888 (6 << 16) + #define VNMC_INF_MASK (7 << 16) +@@ -138,6 +139,7 @@ + #define VNINTS_FOS (1 << 0) + + /* Video n Data Mode Register bits */ ++#define VNDMR_YMODE_Y8 (1 << 12) + #define VNDMR_EXRGB (1 << 8) + #define VNDMR_BPSM (1 << 4) + #define VNDMR_DTMD_YCSEP (1 << 1) +@@ -408,6 +410,7 @@ enum csi2_fmt { + RCAR_CSI_FMT_NONE = -1, + RCAR_CSI_RGB888, + RCAR_CSI_YCBCR422, ++ RCAR_CSI_RAW8, + }; + + struct vin_coeff { +@@ -773,10 +776,13 @@ struct rcar_vin_priv { + enum csi2_fmt csi_fmt; + enum virtual_ch vc; + bool csi_sync; ++ bool deser_sync; + + struct rcar_vin_async_client *async_client; + /* Asynchronous CSI2 linking */ + struct v4l2_subdev *csi2_sd; ++ /* Asynchronous Deserializer linking */ ++ struct v4l2_subdev *deser_sd; + /* Synchronous probing compatibility */ + struct platform_device *csi2_pdev; + +@@ -989,6 +995,9 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) + VNMC_INF_YUV10_BT656 : VNMC_INF_YUV10_BT601; + input_is_yuv = true; + break; ++ case MEDIA_BUS_FMT_SBGGR8_1X8: ++ vnmc |= VNMC_INF_RAW8 | VNMC_BPS; ++ break; + default: + break; + } +@@ -1021,6 +1030,10 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) + dmr = 0; + output_is_yuv = true; + break; ++ case V4L2_PIX_FMT_GREY: ++ dmr = VNDMR_DTMD_YCSEP | VNDMR_YMODE_Y8; ++ output_is_yuv = true; ++ break; + case V4L2_PIX_FMT_ARGB555: + dmr = VNDMR_DTMD_ARGB; + break; +@@ -1043,6 +1056,9 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) + + dmr = VNDMR_EXRGB | VNDMR_DTMD_ARGB; + break; ++ case V4L2_PIX_FMT_SBGGR8: ++ dmr = 0; ++ break; + default: + goto e_format; + } +@@ -1061,7 +1077,8 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) + else + vnmc |= VNMC_DPINE; + +- if ((icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_NV12) ++ if ((icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_NV12) && ++ (icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_SBGGR8) + && is_scaling(cam)) + vnmc |= VNMC_SCLE; + } +@@ -1211,6 +1228,10 @@ static void rcar_vin_videobuf_queue(struct vb2_buffer *vb) + */ + static void rcar_vin_wait_stop_streaming(struct rcar_vin_priv *priv) + { ++ /* update the status if hardware is not stopped */ ++ if (ioread32(priv->base + VNMS_REG) & VNMS_CA) ++ priv->state = RUNNING; ++ + while (priv->state != STOPPED) { + /* issue stop if running */ + if (priv->state == RUNNING) +@@ -1361,6 +1382,31 @@ static struct v4l2_subdev *find_csi2(struct rcar_vin_priv *pcdev) + return NULL; + } + ++static struct v4l2_subdev *find_deser(struct rcar_vin_priv *pcdev) ++{ ++ struct v4l2_subdev *sd; ++ char name[] = "max9286_max9271"; ++ char name2[] = "ti964_ti9x3"; ++ char name3[] = "ti954_ti9x3"; ++ ++ v4l2_device_for_each_subdev(sd, &pcdev->ici.v4l2_dev) { ++ if (!strncmp(name, sd->name, sizeof(name) - 1)) { ++ pcdev->deser_sd = sd; ++ return sd; ++ } ++ if (!strncmp(name2, sd->name, sizeof(name2) - 1)) { ++ pcdev->deser_sd = sd; ++ return sd; ++ } ++ if (!strncmp(name3, sd->name, sizeof(name3) - 1)) { ++ pcdev->deser_sd = sd; ++ return sd; ++ } ++ } ++ ++ return NULL; ++} ++ + static int rcar_vin_add_device(struct soc_camera_device *icd) + { + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); +@@ -1375,7 +1421,8 @@ static int rcar_vin_add_device(struct soc_camera_device *icd) + if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || + priv->chip == RCAR_V3M) { + struct v4l2_subdev *csi2_sd = find_csi2(priv); +- int ret; ++ struct v4l2_subdev *deser_sd = find_deser(priv); ++ int ret = 0; + + if (csi2_sd) { + csi2_sd->grp_id = soc_camera_grp_id(icd); +@@ -1390,6 +1437,18 @@ static int rcar_vin_add_device(struct soc_camera_device *icd) + if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) + return ret; + } ++ if (deser_sd) { ++ v4l2_set_subdev_hostdata(deser_sd, icd); ++ ++ ret = v4l2_subdev_call(deser_sd, core, s_power, 1); ++ priv->deser_sync = true; ++ ++ if (ret < 0 && ret != -EINVAL) ++ priv->deser_sync = false; ++ ++ if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) ++ return ret; ++ } + /* + * -ENODEV is special: + * either csi2_sd == NULL or the CSI-2 driver +@@ -1417,6 +1476,7 @@ static void rcar_vin_remove_device(struct soc_camera_device *icd) + struct rcar_vin_priv *priv = ici->priv; + struct vb2_v4l2_buffer *vbuf; + struct v4l2_subdev *csi2_sd = find_csi2(priv); ++ struct v4l2_subdev *deser_sd = find_deser(priv); + int i; + + /* disable capture, disable interrupts */ +@@ -1443,6 +1503,8 @@ static void rcar_vin_remove_device(struct soc_camera_device *icd) + + if ((csi2_sd) && (priv->csi_sync)) + v4l2_subdev_call(csi2_sd, core, s_power, 0); ++ if ((deser_sd) && (priv->deser_sync)) ++ v4l2_subdev_call(deser_sd, core, s_power, 0); + + dev_dbg(icd->parent, "R-Car VIN driver detached from camera %d\n", + icd->devnum); +@@ -1621,13 +1683,17 @@ static int rcar_vin_set_rect(struct soc_camera_device *icd) + + if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || + priv->chip == RCAR_V3M) { +- if ((icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_NV12) ++ if ((icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_NV12) && ++ (icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_SBGGR8) + && is_scaling(cam)) { + ret = rcar_vin_uds_set(priv, cam); + if (ret < 0) + return ret; + } +- if (is_scaling(cam) || ++ if (icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_SBGGR8) ++ iowrite32(ALIGN(cam->out_width / 2, 0x10), ++ priv->base + VNIS_REG); ++ else if (is_scaling(cam) || + (icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_NV16) || + (icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_NV12)) + iowrite32(ALIGN(cam->out_width, 0x20), +@@ -1868,6 +1934,14 @@ static bool rcar_vin_packing_supported(const struct soc_mbus_pixelfmt *fmt) + .layout = SOC_MBUS_LAYOUT_PACKED, + }, + { ++ .fourcc = V4L2_PIX_FMT_GREY, ++ .name = "GREY8", ++ .bits_per_sample = 8, ++ .packing = SOC_MBUS_PACKING_NONE, ++ .order = SOC_MBUS_ORDER_LE, ++ .layout = SOC_MBUS_LAYOUT_PACKED, ++ }, ++ { + .fourcc = V4L2_PIX_FMT_RGB565, + .name = "RGB565", + .bits_per_sample = 16, +@@ -1899,6 +1973,14 @@ static bool rcar_vin_packing_supported(const struct soc_mbus_pixelfmt *fmt) + .order = SOC_MBUS_ORDER_LE, + .layout = SOC_MBUS_LAYOUT_PACKED, + }, ++ { ++ .fourcc = V4L2_PIX_FMT_SBGGR8, ++ .name = "Bayer 8 BGGR", ++ .bits_per_sample = 8, ++ .packing = SOC_MBUS_PACKING_NONE, ++ .order = SOC_MBUS_ORDER_LE, ++ .layout = SOC_MBUS_LAYOUT_PACKED, ++ }, + }; + + static int rcar_vin_get_formats(struct soc_camera_device *icd, unsigned int idx, +@@ -2012,6 +2094,7 @@ static int rcar_vin_get_formats(struct soc_camera_device *icd, unsigned int idx, + case MEDIA_BUS_FMT_YUYV8_2X8: + case MEDIA_BUS_FMT_YUYV10_2X10: + case MEDIA_BUS_FMT_RGB888_1X24: ++ case MEDIA_BUS_FMT_SBGGR8_1X8: + if (cam->extra_fmt) + break; + +@@ -2218,12 +2301,14 @@ static int rcar_vin_set_fmt(struct soc_camera_device *icd, + case V4L2_PIX_FMT_ABGR32: + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_YUYV: ++ case V4L2_PIX_FMT_GREY: + case V4L2_PIX_FMT_RGB565: + case V4L2_PIX_FMT_ARGB555: + case V4L2_PIX_FMT_NV16: + can_scale = true; + break; + case V4L2_PIX_FMT_NV12: ++ case V4L2_PIX_FMT_SBGGR8: + default: + can_scale = false; + break; +@@ -2316,7 +2401,8 @@ static int rcar_vin_try_fmt(struct soc_camera_device *icd, + /* odd number clipping by pixel post clip processing, */ + /* it is outputted to a memory per even pixels. */ + if ((pixfmt == V4L2_PIX_FMT_NV16) || (pixfmt == V4L2_PIX_FMT_NV12) || +- (pixfmt == V4L2_PIX_FMT_YUYV) || (pixfmt == V4L2_PIX_FMT_UYVY)) ++ (pixfmt == V4L2_PIX_FMT_YUYV) || (pixfmt == V4L2_PIX_FMT_UYVY) || ++ (pixfmt == V4L2_PIX_FMT_GREY)) + v4l_bound_align_image(&pix->width, 5, priv->max_width, 1, + &pix->height, 2, priv->max_height, 0, 0); + else +@@ -2486,6 +2572,19 @@ static int rcar_vin_cropcap(struct soc_camera_device *icd, + } + #endif + ++static int rcar_vin_get_edid(struct soc_camera_device *icd, ++ struct v4l2_edid *edid) ++{ ++ struct v4l2_subdev *sd = soc_camera_to_subdev(icd); ++ int ret; ++ ++ ret = v4l2_subdev_call(sd, pad, get_edid, edid); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ + static struct soc_camera_host_ops rcar_vin_host_ops = { + .owner = THIS_MODULE, + .add = rcar_vin_add_device, +@@ -2504,6 +2603,7 @@ static int rcar_vin_cropcap(struct soc_camera_device *icd, + .get_selection = rcar_vin_get_selection, + .cropcap = rcar_vin_cropcap, + #endif ++ .get_edid = rcar_vin_get_edid, + }; + + #ifdef CONFIG_OF +@@ -2524,7 +2624,7 @@ static int rcar_vin_cropcap(struct soc_camera_device *icd, + MODULE_DEVICE_TABLE(of, rcar_vin_of_table); + #endif + +-#define MAP_MAX_NUM 32 ++#define MAP_MAX_NUM 128 + static DECLARE_BITMAP(device_map, MAP_MAX_NUM); + static DEFINE_MUTEX(list_lock); + +@@ -2714,7 +2814,11 @@ static int rcar_vin_probe(struct platform_device *pdev) + const char *str; + unsigned int i; + struct device_node *epn = NULL, *ren = NULL; ++ struct device_node *csi2_ren = NULL, *max9286_ren = NULL, *ti964_ren = NULL, *ti954_ren = NULL; + bool csi_use = false; ++ bool max9286_use = false; ++ bool ti964_use = false; ++ bool ti954_use = false; + + match = of_match_device(of_match_ptr(rcar_vin_of_table), &pdev->dev); + +@@ -2741,13 +2845,27 @@ static int rcar_vin_probe(struct platform_device *pdev) + dev_dbg(&pdev->dev, "node name:%s\n", + of_node_full_name(ren->parent)); + +- if (strcmp(ren->parent->name, "csi2") == 0) ++ if (strcmp(ren->parent->name, "csi2") == 0) { ++ csi2_ren = ren; + csi_use = true; ++ } + +- of_node_put(ren); ++ if (strcmp(ren->parent->name, "max9286-max9271") == 0) { ++ max9286_ren = of_parse_phandle(epn, "remote-endpoint", 0); ++ max9286_use = true; ++ } + +- if (i) +- break; ++ if (strcmp(ren->parent->name, "ti964-ti9x3") == 0) { ++ ti964_ren = of_parse_phandle(epn, "remote-endpoint", 0); ++ ti964_use = true; ++ } ++ ++ if (strcmp(ren->parent->name, "ti954-ti9x3") == 0) { ++ ti954_ren = of_parse_phandle(epn, "remote-endpoint", 0); ++ ti954_use = true; ++ } ++ ++ of_node_put(ren); + } + + ret = v4l2_of_parse_endpoint(np, &ep); +@@ -2799,6 +2917,7 @@ static int rcar_vin_probe(struct platform_device *pdev) + priv->ici.drv_name = dev_name(&pdev->dev); + priv->ici.ops = &rcar_vin_host_ops; + priv->csi_sync = false; ++ priv->deser_sync = false; + + priv->pdata_flags = pdata_flags; + if (!match) { +@@ -2983,7 +3102,25 @@ static int rcar_vin_probe(struct platform_device *pdev) + goto cleanup; + + if (csi_use) { +- ret = rcar_vin_soc_of_bind(priv, &priv->ici, epn, ren->parent); ++ ret = rcar_vin_soc_of_bind(priv, &priv->ici, epn, csi2_ren->parent); ++ if (ret) ++ goto cleanup; ++ } ++ ++ if (max9286_use) { ++ ret = rcar_vin_soc_of_bind(priv, &priv->ici, epn, max9286_ren); ++ if (ret) ++ goto cleanup; ++ } ++ ++ if (ti964_use) { ++ ret = rcar_vin_soc_of_bind(priv, &priv->ici, epn, ti964_ren); ++ if (ret) ++ goto cleanup; ++ } ++ ++ if (ti954_use) { ++ ret = rcar_vin_soc_of_bind(priv, &priv->ici, epn, ti954_ren); + if (ret) + goto cleanup; + } +diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c +index edd1c1d..54f4c9d 100644 +--- a/drivers/media/platform/soc_camera/soc_camera.c ++++ b/drivers/media/platform/soc_camera/soc_camera.c +@@ -49,7 +49,7 @@ + (icd)->vb_vidq.streaming : \ + vb2_is_streaming(&(icd)->vb2_vidq)) + +-#define MAP_MAX_NUM 32 ++#define MAP_MAX_NUM 128 + static DECLARE_BITMAP(device_map, MAP_MAX_NUM); + static LIST_HEAD(hosts); + static LIST_HEAD(devices); +@@ -1106,6 +1106,18 @@ static int soc_camera_s_parm(struct file *file, void *fh, + return -ENOIOCTLCMD; + } + ++static int soc_camera_g_edid(struct file *file, void *fh, ++ struct v4l2_edid *edid) ++{ ++ struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ ++ if (ici->ops->get_edid) ++ return ici->ops->get_edid(icd, edid); ++ ++ return -ENOIOCTLCMD; ++} ++ + static int soc_camera_probe(struct soc_camera_host *ici, + struct soc_camera_device *icd); + +@@ -1664,7 +1676,7 @@ static void scan_of_host(struct soc_camera_host *ici) + of_node_put(ren); + + if (i) { +- dev_err(dev, "multiple subdevices aren't supported yet!\n"); ++ dev_dbg(dev, "multiple subdevices aren't supported yet!\n"); + break; + } + } +@@ -2077,6 +2089,7 @@ static int soc_camera_device_register(struct soc_camera_device *icd) + .vidioc_s_selection = soc_camera_s_selection, + .vidioc_g_parm = soc_camera_g_parm, + .vidioc_s_parm = soc_camera_s_parm, ++ .vidioc_g_edid = soc_camera_g_edid, + }; + + static int video_dev_create(struct soc_camera_device *icd) +diff --git a/drivers/media/platform/soc_camera/soc_mediabus.c b/drivers/media/platform/soc_camera/soc_mediabus.c +index e3e665e..84754a4 100644 +--- a/drivers/media/platform/soc_camera/soc_mediabus.c ++++ b/drivers/media/platform/soc_camera/soc_mediabus.c +@@ -57,6 +57,16 @@ + .layout = SOC_MBUS_LAYOUT_PACKED, + }, + }, { ++ .code = MEDIA_BUS_FMT_YUYV10_2X10, ++ .fmt = { ++ .fourcc = V4L2_PIX_FMT_YUYV, ++ .name = "YUYV", ++ .bits_per_sample = 10, ++ .packing = SOC_MBUS_PACKING_2X10_PADHI, ++ .order = SOC_MBUS_ORDER_LE, ++ .layout = SOC_MBUS_LAYOUT_PACKED, ++ }, ++}, { + .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE, + .fmt = { + .fourcc = V4L2_PIX_FMT_RGB555, +@@ -403,6 +413,10 @@ int soc_mbus_samples_per_pixel(const struct soc_mbus_pixelfmt *mf, + *numerator = 2; + *denominator = 1; + return 0; ++ case SOC_MBUS_PACKING_2X10_PADHI: ++ *numerator = 3; ++ *denominator = 1; ++ return 0; + case SOC_MBUS_PACKING_1_5X8: + *numerator = 3; + *denominator = 2; +@@ -428,6 +442,8 @@ s32 soc_mbus_bytes_per_line(u32 width, const struct soc_mbus_pixelfmt *mf) + case SOC_MBUS_PACKING_2X8_PADLO: + case SOC_MBUS_PACKING_EXTEND16: + return width * 2; ++ case SOC_MBUS_PACKING_2X10_PADHI: ++ return width * 3; + case SOC_MBUS_PACKING_1_5X8: + return width * 3 / 2; + case SOC_MBUS_PACKING_VARIABLE: +diff --git a/include/media/drv-intf/soc_mediabus.h b/include/media/drv-intf/soc_mediabus.h +index 2ff7737..e5f3f53 100644 +--- a/include/media/drv-intf/soc_mediabus.h ++++ b/include/media/drv-intf/soc_mediabus.h +@@ -21,6 +21,8 @@ + * @SOC_MBUS_PACKING_2X8_PADHI: 16 bits transferred in 2 8-bit samples, in the + * possibly incomplete byte high bits are padding + * @SOC_MBUS_PACKING_2X8_PADLO: as above, but low bits are padding ++ * @SOC_MBUS_PACKING_2X10_PADHI:20 bits transferred in 2 10-bit samples. The ++ * high bits are padding + * @SOC_MBUS_PACKING_EXTEND16: sample width (e.g., 10 bits) has to be extended + * to 16 bits + * @SOC_MBUS_PACKING_VARIABLE: compressed formats with variable packing +@@ -33,6 +35,7 @@ enum soc_mbus_packing { + SOC_MBUS_PACKING_NONE, + SOC_MBUS_PACKING_2X8_PADHI, + SOC_MBUS_PACKING_2X8_PADLO, ++ SOC_MBUS_PACKING_2X10_PADHI, + SOC_MBUS_PACKING_EXTEND16, + SOC_MBUS_PACKING_VARIABLE, + SOC_MBUS_PACKING_1_5X8, +diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h +index 1a15c3e..dad1ed8 100644 +--- a/include/media/soc_camera.h ++++ b/include/media/soc_camera.h +@@ -125,6 +125,7 @@ struct soc_camera_host_ops { + int (*set_parm)(struct soc_camera_device *, struct v4l2_streamparm *); + int (*enum_framesizes)(struct soc_camera_device *, struct v4l2_frmsizeenum *); + unsigned int (*poll)(struct file *, poll_table *); ++ int (*get_edid)(struct soc_camera_device *, struct v4l2_edid *); + }; + + #define SOCAM_SENSOR_INVERT_PCLK (1 << 0) +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0031-arm64-dts-r8a7795-es1-salvator-x-view-add-ADAS-board.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0031-arm64-dts-r8a7795-es1-salvator-x-view-add-ADAS-board.patch new file mode 100644 index 0000000..ddcff1d --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0031-arm64-dts-r8a7795-es1-salvator-x-view-add-ADAS-board.patch @@ -0,0 +1,588 @@ +From c4d2ada2089db7db1a059af37f371f6e2df213f4 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Wed, 4 Jan 2017 10:37:23 +0300 +Subject: [PATCH] arm64: dts: r8a7795-es1-salvator-x-view: add ADAS board + +Salvator-X.View board on R8A7795 ES1.x SoC + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + arch/arm64/boot/dts/renesas/Makefile | 3 + + .../dts/renesas/r8a7795-es1-salvator-x-view.dts | 552 +++++++++++++++++++++ + 2 files changed, 555 insertions(+) + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts + +diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile +index 32fb4d9..2a00759 100644 +--- a/arch/arm64/boot/dts/renesas/Makefile ++++ b/arch/arm64/boot/dts/renesas/Makefile +@@ -4,5 +4,8 @@ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-salvator-x.dtb r8a7795-es1-h3ulcb.dtb + dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-x.dtb r8a7796-m3ulcb.dtb + dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-xs.dtb + ++# ADAS boards ++dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-salvator-x-view.dtb ++ + always := $(dtb-y) + clean-files := *.dtb +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts +new file mode 100644 +index 0000000..3f3d66a +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts +@@ -0,0 +1,552 @@ ++/* ++ * Device Tree Source for the Salvator-X.View board on r8a7795 ES1.x ++ * ++ * Copyright (C) 2016-2017 Renesas Electronics Corp. ++ * Copyright (C) 2015-2017 Cogent Embedded, Inc ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7795-es1-salvator-x.dts" ++ ++/ { ++ model = "Renesas Salvator-X.View board based on r8a7795"; ++}; ++ ++&pfc { ++ can0_pins: can0 { ++ groups = "can0_data_a"; ++ function = "can0"; ++ }; ++ ++ can1_pins: can1 { ++ groups = "can1_data"; ++ function = "can1"; ++ }; ++}; ++ ++&i2c4 { ++ /delete-node/hdmi-in@34; ++ /delete-node/composite-in@70; ++ ++ ov106xx@0 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x60>; ++ ++ port@0 { ++ ov106xx_in0: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin0ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@1 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x61>; ++ ++ port@0 { ++ ov106xx_in1: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin1ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@2 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x62>; ++ ++ port@0 { ++ ov106xx_in2: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin2ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@3 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x63>; ++ ++ port@0 { ++ ov106xx_in3: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin3ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_des0ep3: endpoint { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ }; ++ }; ++ ++ ov106xx@4 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x64>; ++ ++ port@0 { ++ ov106xx_in4: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin4ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@5 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x65>; ++ ++ port@0 { ++ ov106xx_in5: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin5ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@6 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x66>; ++ ++ port@0 { ++ ov106xx_in6: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin6ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@7 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x67>; ++ ++ port@0 { ++ ov106xx_in7: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin7ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_des1ep3: endpoint { ++ remote-endpoint = <&max9286_des1ep3>; ++ }; ++ }; ++ }; ++ ++ max9286-max9271@0 { ++ compatible = "maxim,max9286-max9271"; ++ reg = <0x4c>; ++ gpios = <&gpio6 30 GPIO_ACTIVE_LOW>; ++ maxim,sensor_delay = <0>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ maxim,i2c-quirk = <0x6c>; ++ ++ port@0 { ++ max9286_des0ep0: endpoint@0 { ++ max9271-addr = <0x50>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ max9286_des0ep1: endpoint@1 { ++ max9271-addr = <0x51>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ max9286_des0ep2: endpoint@2 { ++ max9271-addr = <0x52>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ max9286_des0ep3: endpoint@3 { ++ max9271-addr = <0x53>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ max9286_csi0ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ }; ++ ++ max9286-max9271@1 { ++ compatible = "maxim,max9286-max9271"; ++ reg = <0x6c>; ++ maxim,sensor_delay = <0>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ ++ port@0 { ++ max9286_des1ep0: endpoint@0 { ++ max9271-addr = <0x54>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in4>; ++ }; ++ max9286_des1ep1: endpoint@1 { ++ max9271-addr = <0x55>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in5>; ++ }; ++ max9286_des1ep2: endpoint@2 { ++ max9271-addr = <0x56>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in6>; ++ }; ++ max9286_des1ep3: endpoint@3 { ++ max9271-addr = <0x57>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in7>; ++ }; ++ }; ++ port@1 { ++ max9286_csi2ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ }; ++}; ++ ++&vin0 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin0ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ }; ++ port@1 { ++ csi0ep0: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin0_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin1 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin1ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <1>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ }; ++ port@1 { ++ csi0ep1: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin1_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin2 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin2ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <2>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ }; ++ port@1 { ++ csi0ep2: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin2_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin3 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin3ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <3>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ csi0ep3: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin3_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ }; ++ }; ++}; ++ ++&vin4 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin4ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <0>; ++ remote-endpoint = <&ov106xx_in4>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep0: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ vin4_max9286_des1ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin5 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin5ep0: endpoint@0 { ++ csi,select = "csi41"; ++ virtual,channel = <1>; ++ remote-endpoint = <&ov106xx_in5>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep1: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ vin5_max9286_des1ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin6 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin6ep0: endpoint@0 { ++ csi,select = "csi41"; ++ virtual,channel = <2>; ++ remote-endpoint = <&ov106xx_in6>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep2: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ vin6_max9286_des1ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin7 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin7ep0: endpoint@0 { ++ csi,select = "csi41"; ++ virtual,channel = <3>; ++ remote-endpoint = <&ov106xx_in7>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep3: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ vin7_max9286_des1ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep3>; ++ }; ++ }; ++ }; ++}; ++ ++&csi2_20 { ++ status = "disabled"; ++ /delete-node/ports; ++}; ++ ++&csi2_40 { ++ /delete-node/ports; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi2_40_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; ++ ++&csi2_41 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi2_41_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; ++ ++&can0 { ++ pinctrl-0 = <&can0_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++}; ++ ++&can1 { ++ pinctrl-0 = <&can1_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++}; +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0032-arm64-dts-r8a7795-es1-h3ulcb-view-add-ADAS-board.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0032-arm64-dts-r8a7795-es1-h3ulcb-view-add-ADAS-board.patch new file mode 100644 index 0000000..24af837 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0032-arm64-dts-r8a7795-es1-h3ulcb-view-add-ADAS-board.patch @@ -0,0 +1,581 @@ +From 14d2ada2089db7db1a059af37f371f6e2df213f4 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Wed, 4 Jan 2017 10:37:23 +0300 +Subject: [PATCH] arm64: dts: r8a7795-es1-h3ulcb-view: add ADAS board + +H3ULCB.View board on R8A7795 ES1.x SoC + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + arch/arm64/boot/dts/renesas/Makefile | 1 + + .../boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts | 546 +++++++++++++++++++++ + 2 files changed, 547 insertions(+) + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts + +diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile +index 2a00759..43aa35d 100644 +--- a/arch/arm64/boot/dts/renesas/Makefile ++++ b/arch/arm64/boot/dts/renesas/Makefile +@@ -6,6 +6,7 @@ dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-xs.dtb + + # ADAS boards + dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-salvator-x-view.dtb ++dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-h3ulcb-view.dtb + + always := $(dtb-y) + clean-files := *.dtb +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts +new file mode 100644 +index 0000000..de56fa4 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts +@@ -0,0 +1,546 @@ ++/* ++ * Device Tree Source for the H3ULCB.View board on r8a7795 ES1.x ++ * ++ * Copyright (C) 2016-2017 Renesas Electronics Corp. ++ * Copyright (C) 2016-2017 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7795-es1-h3ulcb.dts" ++ ++/ { ++ model = "Renesas H3ULCB.View board based on r8a7795"; ++}; ++ ++&i2c4 { ++ ov106xx@0 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x60>; ++ ++ port@0 { ++ ov106xx_in0: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin0ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@1 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x61>; ++ ++ port@0 { ++ ov106xx_in1: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin1ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@2 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x62>; ++ ++ port@0 { ++ ov106xx_in2: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin2ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@3 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x63>; ++ ++ port@0 { ++ ov106xx_in3: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin3ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_des0ep3: endpoint { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ }; ++ }; ++ ++ ov106xx@4 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x64>; ++ ++ port@0 { ++ ov106xx_in4: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin4ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@5 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x65>; ++ ++ port@0 { ++ ov106xx_in5: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin5ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@6 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x66>; ++ ++ port@0 { ++ ov106xx_in6: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin6ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@7 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x67>; ++ ++ port@0 { ++ ov106xx_in7: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin7ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_des1ep3: endpoint { ++ remote-endpoint = <&max9286_des1ep3>; ++ }; ++ }; ++ }; ++ ++ max9286-max9271@0 { ++ compatible = "maxim,max9286-max9271"; ++ reg = <0x4c>; ++ gpios = <&gpio2 6 GPIO_ACTIVE_HIGH>; ++ maxim,sensor_delay = <0>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ maxim,i2c-quirk = <0x6c>; ++ ++ port@0 { ++ max9286_des0ep0: endpoint@0 { ++ max9271-addr = <0x50>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ max9286_des0ep1: endpoint@1 { ++ max9271-addr = <0x51>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ max9286_des0ep2: endpoint@2 { ++ max9271-addr = <0x52>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ max9286_des0ep3: endpoint@3 { ++ max9271-addr = <0x53>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ max9286_csi0ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ }; ++ ++ max9286-max9271@1 { ++ compatible = "maxim,max9286-max9271"; ++ reg = <0x6c>; ++ gpios = <&gpio5 25 GPIO_ACTIVE_HIGH>; ++ maxim,sensor_delay = <0>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ ++ port@0 { ++ max9286_des1ep0: endpoint@0 { ++ max9271-addr = <0x54>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in4>; ++ }; ++ max9286_des1ep1: endpoint@1 { ++ max9271-addr = <0x55>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in5>; ++ }; ++ max9286_des1ep2: endpoint@2 { ++ max9271-addr = <0x56>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in6>; ++ }; ++ max9286_des1ep3: endpoint@3 { ++ max9271-addr = <0x57>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in7>; ++ }; ++ }; ++ port@1 { ++ max9286_csi2ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ }; ++}; ++ ++&pcie_bus_clk { ++ clock-frequency = <100000000>; ++ status = "okay"; ++}; ++ ++&pciec1 { ++ status = "okay"; ++}; ++ ++&vin0 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin0ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ }; ++ port@1 { ++ csi0ep0: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin0_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin1 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin1ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <1>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ }; ++ port@1 { ++ csi0ep1: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin1_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin2 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin2ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <2>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ }; ++ port@1 { ++ csi0ep2: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin2_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin3 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin3ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <3>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ csi0ep3: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin3_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ }; ++ }; ++}; ++ ++&vin4 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin4ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <0>; ++ remote-endpoint = <&ov106xx_in4>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep0: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ vin4_max9286_des1ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin5 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin5ep0: endpoint@0 { ++ csi,select = "csi41"; ++ virtual,channel = <1>; ++ remote-endpoint = <&ov106xx_in5>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep1: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ vin5_max9286_des1ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin6 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin6ep0: endpoint@0 { ++ csi,select = "csi41"; ++ virtual,channel = <2>; ++ remote-endpoint = <&ov106xx_in6>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep2: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ vin6_max9286_des1ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin7 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin7ep0: endpoint@0 { ++ csi,select = "csi41"; ++ virtual,channel = <3>; ++ remote-endpoint = <&ov106xx_in7>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep3: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ vin7_max9286_des1ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep3>; ++ }; ++ }; ++ }; ++}; ++ ++&csi2_40 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi2_40_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; ++ ++&csi2_41 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi2_41_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0033-arm64-dts-r8a7795-es1-h3ulcb-had-add-ADAS-board.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0033-arm64-dts-r8a7795-es1-h3ulcb-had-add-ADAS-board.patch new file mode 100644 index 0000000..f8fb983 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0033-arm64-dts-r8a7795-es1-h3ulcb-had-add-ADAS-board.patch @@ -0,0 +1,320 @@ +From 40240b74fe0b5c851127996328504e86a9fc4407 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Wed, 4 Jan 2017 10:41:48 +0300 +Subject: [PATCH] arm64: dts: r8a7795-es1-h3ulcb-had: add ADAS board + +H3ULCB.HAD board on R8A7795 ES1.x SoC + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + arch/arm64/boot/dts/renesas/Makefile | 1 + + .../dts/renesas/r8a7795-es1-h3ulcb-had-alfa.dts | 22 ++ + .../dts/renesas/r8a7795-es1-h3ulcb-had-beta.dts | 23 +++ + .../boot/dts/renesas/r8a7795-es1-h3ulcb-had.dtsi | 224 +++++++++++++++++++++ + 4 files changed, 270 insertions(+) + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-had-alfa.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-had-beta.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-had.dtsi + +diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile +index 43aa35d..51a4ac9 100644 +--- a/arch/arm64/boot/dts/renesas/Makefile ++++ b/arch/arm64/boot/dts/renesas/Makefile +@@ -7,6 +7,7 @@ dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-xs.dtb + # ADAS boards + dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-salvator-x-view.dtb + dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-h3ulcb-view.dtb ++dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-h3ulcb-had-alfa.dtb r8a7795-es1-h3ulcb-had-beta.dtb + + always := $(dtb-y) + clean-files := *.dtb +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-had-alfa.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-had-alfa.dts +new file mode 100644 +index 0000000..6b13f07 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-had-alfa.dts +@@ -0,0 +1,22 @@ ++/* ++ * Device Tree Source for the H3ULCB.HAD board Alfa side on r8a7795 ES1.x ++ * ++ * Copyright (C) 2017 Renesas Electronics Corp. ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7795-es1-h3ulcb-had.dtsi" ++ ++/ { ++ model = "Renesas H3ULCB.HAD board Alfa side based on r8a7795"; ++}; ++ ++&pciec0 { ++ status = "okay"; ++ ++ /* Root complex */ ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-had-beta.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-had-beta.dts +new file mode 100644 +index 0000000..2f8b274 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-had-beta.dts +@@ -0,0 +1,23 @@ ++/* ++ * Device Tree Source for the H3ULCB.HAD board Beta side on r8a7795 ES1.x ++ * ++ * Copyright (C) 2017 Renesas Electronics Corp. ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7795-es1-h3ulcb-had.dtsi" ++ ++/ { ++ model = "Renesas H3ULCB.HAD board Beta side based on r8a7795"; ++}; ++ ++&pciec0 { ++ status = "okay"; ++ ++ /* Endpoint */ ++ endpoint; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-had.dtsi b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-had.dtsi +new file mode 100644 +index 0000000..d18ff37 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-had.dtsi +@@ -0,0 +1,224 @@ ++/* ++ * Device Tree Source for the H3ULCB.HAD board on r8a7795 ES1.x ++ * ++ * Copyright (C) 2016-2017 Renesas Electronics Corp. ++ * Copyright (C) 2016-2017 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++/* ++ * MSIOF0 - /dev/spidev1.0 connected to FPGA ethernet switch (both sides) ++ * MSIOF1 - /dev/spidev2.0 connected to RH850 (sideA to CSIH1, sideB to CSIH0) ++ */ ++ ++#include "r8a7795-es1-h3ulcb-view.dts" ++ ++/ { ++ model = "Renesas H3ULCB.HAD board based on r8a7795"; ++ ++ aliases { ++ spi1 = &spi0_gpio; ++ spi2 = &spi1_gpio; ++ }; ++ ++ chosen { ++ stdout-path = "serial1:115200n8"; ++ }; ++ ++ spi0_gpio: spi_gpio@0 { ++ compatible = "spi-gpio"; ++ num-chipselects = <1>; ++ gpio-sck = <&gpio5 17 0>; ++ gpio-mosi = <&gpio5 20 0>; ++ gpio-miso = <&gpio5 22 0>; ++ cs-gpios = <&gpio5 19 0>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ spidev@0 { ++ compatible = "spi-gpio"; ++ reg = <0>; ++ spi-max-frequency = <2000000>; ++ spi-cpha; ++ spi-cpol; ++ }; ++ }; ++ ++ spi1_gpio: spi_gpio@1 { ++ compatible = "spi-gpio"; ++ num-chipselects = <1>; ++ gpio-sck = <&gpio6 8 0>; ++ gpio-mosi = <&gpio6 7 0>; ++ gpio-miso = <&gpio6 10 0>; ++ cs-gpios = <&gpio6 5 0>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ spidev@0 { ++ compatible = "spi-gpio"; ++ reg = <0>; ++ spi-max-frequency = <2000000>; ++ spi-cpha; ++ spi-cpol; ++ }; ++ }; ++ ++ hdmi1-out { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi1_con: endpoint { ++ remote-endpoint = <&rcar_dw_hdmi1_out>; ++ }; ++ }; ++ }; ++}; ++ ++&du { ++ ports { ++ port@1 { ++ endpoint { ++ remote-endpoint = <&rcar_dw_hdmi0_in>; ++ }; ++ }; ++ port@2 { ++ endpoint { ++ remote-endpoint = <&rcar_dw_hdmi1_in>; ++ }; ++ }; ++ }; ++}; ++ ++&hdmi1 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ port@0 { ++ reg = <0>; ++ rcar_dw_hdmi1_in: endpoint { ++ remote-endpoint = <&du_out_hdmi1>; ++ }; ++ }; ++ port@1 { ++ reg = <1>; ++ rcar_dw_hdmi1_out: endpoint { ++ remote-endpoint = <&hdmi1_con>; ++ }; ++ }; ++ }; ++}; ++ ++&pfc { ++ scif1_pins: scif1 { ++ groups = "scif1_data_a"; ++ function = "scif1"; ++ }; ++ ++ msiof0_pins: spi1 { ++ groups = "msiof0_clk", "msiof0_rxd", "msiof0_txd", ++ "msiof0_ss1"; ++ function = "msiof0"; ++ }; ++ ++ msiof1_pins: spi2 { ++ groups = "msiof1_clk_a", "msiof1_rxd_a", "msiof1_txd_a", ++ "msiof1_ss1_a"; ++ function = "msiof1"; ++ }; ++ ++ sound_clk_pins: sound-clk { ++ groups = "audio_clk_a_a", "audio_clk_b_a", "audio_clk_c_a", ++ "audio_clkout_a" /*, "audio_clkout3_a"*/; ++ function = "audio_clk"; ++ }; ++ ++ usb31_pins: usb31 { ++ groups = "usb31"; ++ function = "usb31"; ++ }; ++ ++ can0_pins: can0 { ++ groups = "can0_data_a"; ++ function = "can0"; ++ }; ++ ++ canfd0_pins: canfd0 { ++ groups = "canfd0_data_a"; ++ function = "canfd0"; ++ }; ++}; ++ ++&scif1 { ++ pinctrl-0 = <&scif1_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++}; ++ ++&avb { ++ /delete-property/phy-handle; ++ /delete-property/phy-gpios; ++ /delete-node/ethernet-phy@0; ++ ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ }; ++}; ++ ++&msiof0 { ++ pinctrl-0 = <&msiof0_pins>; ++ pinctrl-names = "default"; ++ status = "disabled"; ++ cs-gpios = <&gpio5 19 0>; ++ ++ spidev@0 { ++ compatible = "renesas,sh-msiof"; ++ reg = <0>; ++ spi-max-frequency = <66666666>; ++ spi-cpha; ++ spi-cpol; ++ }; ++}; ++ ++&msiof1 { ++ status = "disabled"; ++ cs-gpios = <&gpio6 5 0>; ++}; ++ ++&can0 { ++ pinctrl-0 = <&can0_pins>; ++ pinctrl-names = "default"; ++ status = "disabled"; ++ ++ renesas,can-clock-select = <0x0>; ++ gpios = <&gpio2 6 GPIO_ACTIVE_HIGH /* enable - shared with camera board */ ++ &gpio2 7 GPIO_ACTIVE_LOW /* standby */ ++ >; ++}; ++ ++&canfd { ++ pinctrl-0 = <&canfd0_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ renesas,can-clock-select = <0x0>; ++ gpios = <&gpio2 6 GPIO_ACTIVE_HIGH /* enable - shared with camera board */ ++ &gpio2 7 GPIO_ACTIVE_LOW /* standby */ ++ >; ++ ++ channel0 { ++ status = "okay"; ++ }; ++}; ++ ++&xhci1 { ++ status = "okay"; ++ pinctrl-0 = <&usb31_pins>; ++ pinctrl-names = "default"; ++}; +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0034-arm64-dts-r8a7795-es1-h3ulcb-kf-add-ADAS-board.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0034-arm64-dts-r8a7795-es1-h3ulcb-kf-add-ADAS-board.patch new file mode 100644 index 0000000..985863a --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0034-arm64-dts-r8a7795-es1-h3ulcb-kf-add-ADAS-board.patch @@ -0,0 +1,1718 @@ +From f0f043eab3dd06552b3600af1caf50e535f766f1 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Wed, 4 Jan 2017 10:37:23 +0300 +Subject: [PATCH] arm64: dts: r8a7795-es1-h3ulcb-kf: add ADAS board + +H3ULCB.View board on R8A7795 ES1.x SoC + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + arch/arm64/boot/dts/renesas/Makefile | 1 + + .../boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts | 1683 ++++++++++++++++++++ + 2 files changed, 1684 insertions(+) + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts + +diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile +index 06207e3..a5dd1d3 100644 +--- a/arch/arm64/boot/dts/renesas/Makefile ++++ b/arch/arm64/boot/dts/renesas/Makefile +@@ -10,6 +10,7 @@ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-h3ulcb-view.dtb + dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-salvator-x-view.dtb + dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-h3ulcb-view.dtb + dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-h3ulcb-had-alfa.dtb r8a7795-es1-h3ulcb-had-beta.dtb ++dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-h3ulcb-kf.dtb + + always := $(dtb-y) + clean-files := *.dtb +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts +new file mode 100644 +index 0000000..50a37e0 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts +@@ -0,0 +1,1683 @@ ++/* ++ * Device Tree Source for the H3ULCB Kingfisher board on r8a7795 ES1.x ++ * ++ * Copyright (C) 2017 Renesas Electronics Corp. ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7795-es1-h3ulcb.dts" ++ ++/ { ++ model = "Renesas H3ULCB Kingfisher board based on r8a7795"; ++ ++ aliases { ++ serial1 = &hscif4; ++ }; ++ ++ snd_clk: snd_clk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <24576000>; ++ clock-output-names = "scki"; ++ }; ++ ++ wlan_en: regulator@4 { ++ compatible = "regulator-fixed"; ++ regulator-name = "wlan-en-regulator"; ++ ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ gpio = <&gpio_ext_20 4 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ vccq_sdhi3: regulator@5 { ++ compatible = "regulator-fixed"; ++ ++ regulator-name = "SDHI3 VccQ"; ++ /* external voltage translator to 1.8V */ ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ }; ++ ++ codec_en_reg: regulator@6 { ++ compatible = "regulator-fixed"; ++ regulator-name = "codec-en-regulator"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ gpio = <&gpio_ext_20 15 0>; ++ ++ /* delay - CHECK */ ++ startup-delay-us = <70000>; ++ enable-active-high; ++ }; ++ ++ amp_en_reg: regulator@7 { ++ compatible = "regulator-fixed"; ++ regulator-name = "amp-en-regulator"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ gpio = <&gpio_ext_20 0 0>; ++ ++ startup-delay-us = <0>; ++ enable-active-high; ++ }; ++ ++ lvds_switch: regulator@8 { ++ compatible = "regulator-fixed"; ++ regulator-name = "lvds_on"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&gpio1 24 0>; ++ enable-active-high; ++ regulator-always-on; ++ }; ++ ++ sdio_switch: regulator@9 { ++ compatible = "regulator-fixed"; ++ regulator-name = "wifi_on"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&gpio_ext_20 5 0>; ++ enable-active-low; ++ regulator-always-on; ++ }; ++ ++ sound_switch: regulator@10 { ++ compatible = "regulator-fixed"; ++ regulator-name = "pcm3168a_on"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&gpio_ext_21 5 0>; ++ enable-active-low; ++ regulator-always-on; ++ }; ++ ++ radio_switch: regulator@11 { ++ compatible = "regulator-fixed"; ++ regulator-name = "radio_on"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&gpio_ext_20 13 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ regulator-always-on; ++ }; ++ ++ kim { ++ compatible = "kim"; ++ nshutdown_gpio = <343>; /* pca9535@i2c2.0x20 pin 3 */ ++ /* serial1 */ ++ dev_name = "/dev/ttySC1"; ++ flow_cntrl = <1>; ++ /* int div 8 hscif@26.6666656MHz */ ++ baud_rate = <3333332>; ++ }; ++ ++ btwilink { ++ compatible = "btwilink"; ++ }; ++ ++ sound_ext: sound@0 { ++ pinctrl-0 = <&sound_0_pins>; ++ pinctrl-names = "default"; ++ compatible = "simple-audio-card"; ++ ++ simple-audio-card,format = "left_j"; ++ simple-audio-card,name = "pcm3168a"; ++ ++ simple-audio-card,bitclock-master = <&sound_ext_master>; ++ simple-audio-card,frame-master = <&sound_ext_master>; ++ sound_ext_master: simple-audio-card,cpu@0 { ++ sound-dai = <&rcar_sound 0>; ++ dai-tdm-slot-num = <8>; ++ dai-tdm-slot-width = <32>; ++ }; ++ ++ simple-audio-card,codec@0 { ++ sound-dai = <&pcm3168a>; ++ dai-tdm-slot-num = <8>; ++ dai-tdm-slot-width = <32>; ++ system-clock-frequency = <24576000>; ++ }; ++ }; ++ ++ /delete-node/sound; ++ ++ rsnd_ak4613: sound@1 { ++ pinctrl-0 = <&sound_1_pins>; ++ pinctrl-names = "default"; ++ compatible = "simple-audio-card"; ++ ++ simple-audio-card,format = "left_j"; ++ simple-audio-card,name = "ak4613"; ++ ++ simple-audio-card,bitclock-master = <&sndcpu>; ++ simple-audio-card,frame-master = <&sndcpu>; ++ ++ sndcpu: simple-audio-card,cpu@1 { ++ sound-dai = <&rcar_sound 1>; ++ }; ++ ++ sndcodec: simple-audio-card,codec@1 { ++ sound-dai = <&ak4613>; ++ }; ++ }; ++ ++ sound_radio: sound@2 { ++ pinctrl-0 = <&sound_2_pins>; ++ pinctrl-names = "default"; ++ compatible = "simple-audio-card"; ++ ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,name = "radio"; ++ ++ simple-audio-card,bitclock-master = <&sound_radio_master>; ++ simple-audio-card,frame-master = <&sound_radio_master>; ++ simple-audio-card,cpu@2 { ++ sound-dai = <&rcar_sound 2>; ++ }; ++ ++ sound_radio_master: simple-audio-card,codec@2 { ++ sound-dai = <&radio>; ++ system-clock-frequency = <12288000>; ++ }; ++ }; ++ ++ sound_amp: sound@3 { ++ pinctrl-0 = <&sound_9_pins>; ++ pinctrl-names = "default"; ++ compatible = "simple-audio-card"; ++ ++ simple-audio-card,name = "power_amp"; ++ ++ simple-audio-card,dai-link@0 { ++ format = "i2s"; ++ cpu { ++ sound-dai = <&rcar_sound 3>; ++ }; ++ codec { ++ sound-dai = <&max98371_L>; ++ }; ++ }; ++ simple-audio-card,dai-link@1 { ++ format = "i2s"; ++ cpu { ++ sound-dai = <&rcar_sound 3>; ++ }; ++ codec { ++ sound-dai = <&max98371_R>; ++ }; ++ }; ++ simple-audio-card,dai-link@2 { ++ format = "i2s"; ++ cpu { ++ sound-dai = <&rcar_sound 3>; ++ }; ++ codec { ++ sound-dai = <&max98371_RL>; ++ }; ++ }; ++ simple-audio-card,dai-link@3 { ++ format = "i2s"; ++ cpu { ++ sound-dai = <&rcar_sound 3>; ++ }; ++ codec { ++ sound-dai = <&max98371_RR>; ++ }; ++ }; ++ simple-audio-card,dai-link@4 { ++ format = "i2s"; ++ cpu { ++ sound-dai = <&rcar_sound 3>; ++ }; ++ codec { ++ sound-dai = <&max98371_C>; ++ }; ++ }; ++ simple-audio-card,dai-link@5 { ++ format = "i2s"; ++ cpu { ++ sound-dai = <&rcar_sound 3>; ++ }; ++ codec { ++ sound-dai = <&max98371_S>; ++ }; ++ }; ++ }; ++ ++ lvds-encoder { ++ compatible = "thine,thc63lvdm83d"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ port@0 { ++ reg = <0>; ++ lvds_enc_in: endpoint { ++ remote-endpoint = <&du_out_lvds0>; ++ }; ++ }; ++ port@1 { ++ reg = <1>; ++ lvds_enc_out: endpoint { ++ remote-endpoint = <&lvds_in>; ++ }; ++ }; ++ }; ++ }; ++ ++ lvds { ++ compatible = "lvds-connector"; ++ ++ width-mm = <210>; ++ height-mm = <158>; ++ ++ panel-timing { ++ /* 1280x800 @60Hz */ ++ clock-frequency = <65000000>; ++ hactive = <1280>; ++ vactive = <800>; ++ hsync-len = <40>; ++ hfront-porch = <80>; ++ hback-porch = <40>; ++ vfront-porch = <14>; ++ vback-porch = <14>; ++ vsync-len = <4>; ++ }; ++ ++ port { ++ lvds_in: endpoint { ++ remote-endpoint = <&lvds_enc_out>; ++ }; ++ }; ++ }; ++ ++ radio: si468x@0 { ++ compatible = "si,si468x-pcm"; ++ status = "okay"; ++ ++ #sound-dai-cells = <0>; ++ }; ++}; ++ ++&pfc { ++ hscif4_pins: hscif4 { ++ groups = "hscif4_data_a", "hscif4_ctrl"; ++ function = "hscif4"; ++ }; ++ ++ sdhi3_pins_3v3: sd3_3v3 { ++ groups = "sdhi3_data4", "sdhi3_ctrl"; ++ function = "sdhi3"; ++ power-source = <3300>; ++ }; ++ ++ sound_0_pins: sound0 { ++ groups = "ssi78_ctrl", "ssi7_data", "ssi8_data"; ++ function = "ssi"; ++ }; ++ ++ sound_1_pins: sound1 { ++ groups = "ssi01239_ctrl", "ssi0_data", "ssi1_data_a"; ++ function = "ssi"; ++ }; ++ ++ sound_2_pins: sound2 { ++ groups = "ssi6_ctrl", "ssi6_data"; ++ function = "ssi"; ++ }; ++ ++ sound_9_pins: sound2 { ++ groups = "ssi9_ctrl_b", "ssi9_data_b"; ++ function = "ssi"; ++ }; ++ ++ usb0_pins: usb0 { ++ groups = "usb0"; ++ function = "usb0"; ++ }; ++}; ++ ++&gpio0 { ++ video_a_irq { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-A irq"; ++ }; ++ ++ video_b_irq { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-B irq"; ++ }; ++ ++ gpioext_2_20_irq { ++ gpio-hog; ++ gpios = <15 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "0x20@i2c2 irq"; ++ }; ++}; ++ ++&gpio1 { ++ gpioext_2_21_irq { ++ gpio-hog; ++ gpios = <15 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "0x21@i2c2 irq"; ++ }; ++ ++ wifi_irq { ++ gpio-hog; ++ gpios = <25 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "wifi irq"; ++ }; ++}; ++ ++&gpio5 { ++ touch_irq { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "touch irq"; ++ }; ++ ++ /* From TI forum */ ++ /* BT_AUD_OUT should be pulled low when WL_EN is activated. */ ++ /* in case it isn't, wilink8 ends up in one of the test modes that introduces various issues */ ++ bt_strap { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "BT strap pin"; ++ }; ++}; ++ ++&gpio7 { ++ gpioext_2_21_irq { ++ gpio-hog; ++ gpios = <3 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "0x21@i2c4 irq"; ++ }; ++}; ++ ++&hscif4 { ++ pinctrl-0 = <&hscif4_pins>; ++ pinctrl-names = "default"; ++ ctsrts; ++ ++ status = "okay"; ++}; ++ ++&i2c2 { ++ clock-frequency = <400000>; ++ ++ gpio_ext_20: pca9535@20 { ++ compatible = "nxp,pca9535"; ++ reg = <0x20>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ interrupt-parent = <&gpio0>; ++ interrupts = <15 IRQ_TYPE_EDGE_FALLING>; ++ }; ++ ++ gpio_ext_21: pca9535@21 { ++ compatible = "nxp,pca9535"; ++ reg = <0x21>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ interrupt-parent = <&gpio1>; ++ interrupts = <15 IRQ_TYPE_EDGE_FALLING>; ++ }; ++ ++ i2cswitch2@74 { ++ compatible = "nxp,pca9548"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x74>; ++ reset-gpios = <&gpio6 5 GPIO_ACTIVE_LOW>; ++ ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ /* BCM node(s) */ ++ }; ++ ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ /* USB3.0 HUB node(s) */ ++ }; ++ ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ /* Power amp node(s) */ ++ ++ max98371_L: max98371@0x31 { ++ compatible = "maxim,max98371"; ++ reg = <0x31>; ++ #sound-dai-cells = <0>; ++ }; ++ max98371_R: max98371@0x32 { ++ compatible = "maxim,max98371"; ++ reg = <0x32>; ++ #sound-dai-cells = <0>; ++ }; ++ max98371_RL: max98371@0x33 { ++ compatible = "maxim,max98371"; ++ reg = <0x33>; ++ #sound-dai-cells = <0>; ++ }; ++ max98371_RR: max98371@0x34 { ++ compatible = "maxim,max98371"; ++ reg = <0x34>; ++ #sound-dai-cells = <0>; ++ }; ++ max98371_C: max98371@0x35 { ++ compatible = "maxim,max98371"; ++ reg = <0x35>; ++ #sound-dai-cells = <0>; ++ }; ++ max98371_S: max98371@0x36 { ++ compatible = "maxim,max98371"; ++ reg = <0x36>; ++ #sound-dai-cells = <0>; ++ }; ++ }; ++ ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ /* Radio node(s) */ ++ }; ++ ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ /* A2B node(s) */ ++ }; ++ ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ /* PCIe node(s) */ ++ }; ++ ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ /* LVDS display node(s) */ ++ ++ polytouch: edt-ft5x06@38 { ++ compatible = "edt,edt-ft5x06"; ++ reg = <0x38>; ++ interrupt-parent = <&gpio5>; ++ interrupts = <6 IRQ_TYPE_EDGE_FALLING>; ++ }; ++ }; ++ ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ /* Audio, GPS and Gyro node(s) */ ++ ++ pcm3168a: audio-codec@44 { ++ #sound-dai-cells = <0>; ++ compatible = "ti,pcm3168a"; ++ reg = <0x44>; ++ clocks = <&snd_clk>; ++ clock-names = "scki"; ++ tdm; ++ VDD1-supply = <&codec_en_reg>; ++ VDD2-supply = <&codec_en_reg>; ++ VCCAD1-supply = <&codec_en_reg>; ++ VCCAD2-supply = <&codec_en_reg>; ++ VCCDA1-supply = <&_en_reg>; ++ VCCDA2-supply = <&_en_reg>; ++ }; ++ ++ lsm9ds0_acc_mag@1d { ++ compatible = "st,lsm9ds0_acc_mag"; ++ reg = <0x1d>; ++ }; ++ ++ lsm9ds0_gyr@6b { ++ compatible = "st,lsm9ds0-gyro"; ++ reg = <0x6b>; ++ }; ++ ++ /* GPS@ 0x42 */ ++ }; ++ }; ++}; ++ ++&i2c4 { ++ gpio_ext_22: pca9535@21 { ++ compatible = "nxp,pca9535"; ++ reg = <0x22>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ interrupt-parent = <&gpio7>; ++ interrupts = <3 IRQ_TYPE_EDGE_FALLING>; ++ }; ++ ++ i2cswitch4@74 { ++ compatible = "nxp,pca9548"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x74>; ++ reset-gpios= <&gpio6 21 GPIO_ACTIVE_LOW>; ++ ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ /* SAM node(s) */ ++ }; ++ ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ /* Video input "A" acc node(s) */ ++ ++ ov106xx@0 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x60>; ++ ++ port@0 { ++ ov106xx_in0: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin0ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ ov106xx_ti964_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti964_des0ep0>; ++ }; ++ ov106xx_ti954_des0ep0: endpoint@2 { ++ remote-endpoint = <&ti954_des0ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@1 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x61>; ++ ++ port@0 { ++ ov106xx_in1: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin1ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ ov106xx_ti964_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti964_des0ep1>; ++ }; ++ ov106xx_ti954_des0ep1: endpoint@2 { ++ remote-endpoint = <&ti954_des0ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@2 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x62>; ++ ++ port@0 { ++ ov106xx_in2: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin2ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ ov106xx_ti964_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti964_des0ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@3 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x63>; ++ ++ port@0 { ++ ov106xx_in3: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin3ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ ov106xx_ti964_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti964_des0ep3>; ++ }; ++ }; ++ }; ++ ++ /* DS90UB964 @ 0x3a */ ++ ti964-ti9x3@0 { ++ compatible = "ti,ti964-ti9x3"; ++ reg = <0x3a>; ++ ti,sensor_delay = <350>; ++ ti,links = <4>; ++ ti,lanes = <4>; ++ ti,forwarding-mode = "round-robin"; ++ ti,cable-mode = "coax"; ++ ++ port@0 { ++ ti964_des0ep0: endpoint@0 { ++ ti9x3-addr = <0x0c>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ ti964_des0ep1: endpoint@1 { ++ ti9x3-addr = <0x0d>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ ti964_des0ep2: endpoint@2 { ++ ti9x3-addr = <0x0e>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ ti964_des0ep3: endpoint@3 { ++ ti9x3-addr = <0x0f>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ ti964_csi0ep0: endpoint { ++ csi-rate = <1450>; ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ }; ++ ++ /* DS90UB954 @ 0x38 */ ++ ti954-ti9x3@0 { ++ compatible = "ti,ti954-ti9x3"; ++ reg = <0x38>; ++ gpios = <&video_a_ext1 10 GPIO_ACTIVE_HIGH>; ++ ti,sensor_delay = <350>; ++ ti,links = <2>; ++ ti,lanes = <4>; ++ ti,forwarding-mode = "round-robin"; ++ ti,cable-mode = "coax"; ++ ++ port@0 { ++ ti954_des0ep0: endpoint@0 { ++ ti9x3-addr = <0x0c>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ ti954_des0ep1: endpoint@1 { ++ ti9x3-addr = <0x0d>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ }; ++ port@1 { ++ ti954_csi0ep0: endpoint { ++ csi-rate = <1450>; ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ }; ++ ++ /* MAX9286 @ 0x2a */ ++ max9286-max9271@0 { ++ compatible = "maxim,max9286-max9271"; ++ reg = <0x2a>; ++ maxim,sensor_delay = <350>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ ++ port@0 { ++ max9286_des0ep0: endpoint@0 { ++ max9271-addr = <0x50>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ max9286_des0ep1: endpoint@1 { ++ max9271-addr = <0x51>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ max9286_des0ep2: endpoint@2 { ++ max9271-addr = <0x52>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ max9286_des0ep3: endpoint@3 { ++ max9271-addr = <0x53>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ max9286_csi0ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ }; ++ }; ++ ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ /* Video input "B" acc node(s) */ ++ ++ ov106xx@4 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x64>; ++ ++ port@0 { ++ ov106xx_in4: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin4ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep0>; ++ }; ++ ov106xx_ti964_des1ep0: endpoint@1 { ++ remote-endpoint = <&ti964_des1ep0>; ++ }; ++ ov106xx_ti954_des1ep0: endpoint@2 { ++ remote-endpoint = <&ti954_des1ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@5 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x65>; ++ ++ port@0 { ++ ov106xx_in5: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin5ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep1>; ++ }; ++ ov106xx_ti964_des1ep1: endpoint@1 { ++ remote-endpoint = <&ti964_des1ep1>; ++ }; ++ ov106xx_ti954_des1ep1: endpoint@2 { ++ remote-endpoint = <&ti954_des1ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@6 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x66>; ++ ++ port@0 { ++ ov106xx_in6: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin6ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep2>; ++ }; ++ ov106xx_ti964_des1ep2: endpoint@1 { ++ remote-endpoint = <&ti964_des1ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@7 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x67>; ++ ++ port@0 { ++ ov106xx_in7: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin7ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep3>; ++ }; ++ ov106xx_ti964_des1ep3: endpoint@1 { ++ remote-endpoint = <&ti964_des1ep3>; ++ }; ++ }; ++ }; ++ ++ /* DS90UB964 @ 0x3a */ ++ ti964-ti9x3@1 { ++ compatible = "ti,ti964-ti9x3"; ++ reg = <0x3a>; ++ ti,sensor_delay = <350>; ++ ti,links = <4>; ++ ti,lanes = <4>; ++ ti,forwarding-mode = "round-robin"; ++ ti,cable-mode = "coax"; ++ ++ port@0 { ++ ti964_des1ep0: endpoint@0 { ++ ti9x3-addr = <0x0c>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in4>; ++ }; ++ ti964_des1ep1: endpoint@1 { ++ ti9x3-addr = <0x0d>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in5>; ++ }; ++ ti964_des1ep2: endpoint@2 { ++ ti9x3-addr = <0x0e>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in6>; ++ }; ++ ti964_des1ep3: endpoint@3 { ++ ti9x3-addr = <0x0f>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in7>; ++ }; ++ }; ++ port@1 { ++ ti964_csi2ep0: endpoint { ++ csi-rate = <1450>; ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ }; ++ ++ /* DS90UB954 @ 0x38 */ ++ ti954-ti9x3@1 { ++ compatible = "ti,ti954-ti9x3"; ++ reg = <0x38>; ++ gpios = <&video_b_ext1 10 GPIO_ACTIVE_HIGH>; ++ ti,sensor_delay = <350>; ++ ti,links = <2>; ++ ti,lanes = <4>; ++ ti,forwarding-mode = "round-robin"; ++ ti,cable-mode = "coax"; ++ ++ port@0 { ++ ti954_des1ep0: endpoint@0 { ++ ti9x3-addr = <0x0c>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in4>; ++ }; ++ ti954_des1ep1: endpoint@1 { ++ ti9x3-addr = <0x0d>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in5>; ++ }; ++ }; ++ port@1 { ++ ti954_csi2ep0: endpoint { ++ csi-rate = <1450>; ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ }; ++ ++ /* MAX9286 @ 0x2a */ ++ max9286-max9271@1 { ++ compatible = "maxim,max9286-max9271"; ++ reg = <0x2a>; ++ maxim,sensor_delay = <350>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ ++ port@0 { ++ max9286_des1ep0: endpoint@0 { ++ max9271-addr = <0x50>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in4>; ++ }; ++ max9286_des1ep1: endpoint@1 { ++ max9271-addr = <0x51>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in5>; ++ }; ++ max9286_des1ep2: endpoint@2 { ++ max9271-addr = <0x52>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in6>; ++ }; ++ max9286_des1ep3: endpoint@3 { ++ max9271-addr = <0x53>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in7>; ++ }; ++ }; ++ port@1 { ++ max9286_csi2ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ }; ++ }; ++ ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ /* MOST node(s) */ ++ }; ++ ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ /* CSI camera node(s) */ ++ }; ++ ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ /* CMOS camera node(s) */ ++ }; ++ ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ /* Video input "B" main node(s) */ ++ ++ video_b_ext0: pca9535@27 { ++ compatible = "nxp,pca9535"; ++ reg = <0x27>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ video_b_des_cfg1 { ++ gpio-hog; ++ gpios = <5 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B cfg1"; ++ }; ++ video_b_des_cfg0 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B cfg0"; ++ }; ++ video_b_pwr_shdn { ++ gpio-hog; ++ gpios = <3 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR_SHDN"; ++ }; ++ video_b_cam_pwr0 { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR0"; ++ }; ++ video_b_cam_pwr1 { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR1"; ++ }; ++ video_b_cam_pwr2 { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR2"; ++ }; ++ video_b_cam_pwr3 { ++ gpio-hog; ++ gpios = <15 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR3"; ++ }; ++ video_b_des_shdn { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B DES_SHDN"; ++ }; ++ video_b_des_led { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-B led"; ++ }; ++ }; ++ ++ video_b_ext1: max7325@5c { ++ compatible = "maxim,max7325"; ++ reg = <0x5c>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ video_b_des_cfg2 { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-B cfg2"; ++ }; ++ video_b_des_cfg1 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-B cfg1"; ++ }; ++ video_b_des_cfg0 { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-B cfg0"; ++ }; ++ video_b_pwr_shdn { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR_SHDN"; ++ }; ++ video_b_cam_pwr0 { ++ gpio-hog; ++ gpios = <8 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR0"; ++ }; ++ video_b_cam_pwr1 { ++ gpio-hog; ++ gpios = <9 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR1"; ++ }; ++ }; ++ }; ++ ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ /* Video input "A" main node(s) */ ++ ++ video_a_ext0: pca9535@26 { ++ compatible = "nxp,pca9535"; ++ reg = <0x26>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ video_a_des_cfg1 { ++ gpio-hog; ++ gpios = <5 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A cfg1"; ++ }; ++ video_a_des_cfg0 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A cfg0"; ++ }; ++ video_a_pwr_shdn { ++ gpio-hog; ++ gpios = <3 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR_SHDN"; ++ }; ++ video_a_cam_pwr0 { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR0"; ++ }; ++ video_a_cam_pwr1 { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR1"; ++ }; ++ video_a_cam_pwr2 { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR2"; ++ }; ++ video_a_cam_pwr3 { ++ gpio-hog; ++ gpios = <15 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR3"; ++ }; ++ video_a_des_shdn { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A DES_SHDN"; ++ }; ++ video_a_des_led { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-A led"; ++ }; ++ }; ++ ++ video_a_ext1: max7325@5c { ++ compatible = "maxim,max7325"; ++ reg = <0x5c>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ video_a_des_cfg2 { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-A cfg2"; ++ }; ++ video_a_des_cfg1 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-A cfg1"; ++ }; ++ video_a_des_cfg0 { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-A cfg0"; ++ }; ++ video_a_pwr_shdn { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR_SHDN"; ++ }; ++ video_a_cam_pwr0 { ++ gpio-hog; ++ gpios = <8 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR0"; ++ }; ++ video_a_cam_pwr1 { ++ gpio-hog; ++ gpios = <9 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR1"; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&pcie_bus_clk { ++ clock-frequency = <100000000>; ++ status = "okay"; ++}; ++ ++&pciec0 { ++ status = "okay"; ++}; ++ ++&pciec1 { ++ status = "okay"; ++}; ++ ++&vin0 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin0ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ }; ++ port@1 { ++ csi0ep0: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin0_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ vin0_ti964_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti964_des0ep0>; ++ }; ++ vin0_ti954_des0ep0: endpoint@2 { ++ remote-endpoint = <&ti954_des0ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin1 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin1ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <1>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ }; ++ port@1 { ++ csi0ep1: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin1_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ vin1_ti964_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti964_des0ep1>; ++ }; ++ vin1_ti954_des0ep1: endpoint@2 { ++ remote-endpoint = <&ti954_des0ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin2 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin2ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <2>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ }; ++ port@1 { ++ csi0ep2: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin2_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ vin2_ti964_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti964_des0ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin3 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin3ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <3>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ csi0ep3: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin3_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ vin3_ti964_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti964_des0ep3>; ++ }; ++ }; ++ }; ++}; ++ ++&vin4 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin4ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <0>; ++ remote-endpoint = <&ov106xx_in4>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep0: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ vin4_max9286_des1ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep0>; ++ }; ++ vin4_ti964_des1ep0: endpoint@1 { ++ remote-endpoint = <&ti964_des1ep0>; ++ }; ++ vin4_ti954_des1ep0: endpoint@2 { ++ remote-endpoint = <&ti954_des1ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin5 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin5ep0: endpoint@0 { ++ csi,select = "csi41"; ++ virtual,channel = <1>; ++ remote-endpoint = <&ov106xx_in5>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep1: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ vin5_max9286_des1ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep1>; ++ }; ++ vin5_ti964_des1ep1: endpoint@1 { ++ remote-endpoint = <&ti964_des1ep1>; ++ }; ++ vin5_ti954_des1ep1: endpoint@2 { ++ remote-endpoint = <&ti954_des1ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin6 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin6ep0: endpoint@0 { ++ csi,select = "csi41"; ++ virtual,channel = <2>; ++ remote-endpoint = <&ov106xx_in6>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep2: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ vin6_max9286_des1ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep2>; ++ }; ++ vin6_ti964_des1ep2: endpoint@1 { ++ remote-endpoint = <&ti964_des1ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin7 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin7ep0: endpoint@0 { ++ csi,select = "csi41"; ++ virtual,channel = <3>; ++ remote-endpoint = <&ov106xx_in7>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep3: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ vin7_max9286_des1ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep3>; ++ }; ++ vin7_ti964_des1ep3: endpoint@1 { ++ remote-endpoint = <&ti964_des1ep3>; ++ }; ++ }; ++ }; ++}; ++ ++&csi2_40 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi2_40_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; ++ ++&csi2_41 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi2_41_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; ++ ++&rcar_sound { ++ pinctrl-0 = <&sound_clk_pins>; ++ ++ /* Multi DAI */ ++ #sound-dai-cells = <1>; ++ ++ rcar_sound,dai { ++ dai0 { ++ playback = <&ssi7>; ++ capture = <&ssi8>; ++ }; ++ ++ dai1 { ++ playback = <&ssi0 &src0 &dvc0>; ++ capture = <&ssi1 &src1 &dvc1>; ++ }; ++ ++ dai2 { ++ capture = <&ssi6>; ++ }; ++ ++ dai3 { ++ playback = <&ssi9>; ++ }; ++ }; ++}; ++ ++&sdhi3 { ++ pinctrl-0 = <&sdhi3_pins_3v3>; ++ pinctrl-names = "default"; ++ ++ vmmc-supply = <&wlan_en>; ++ vqmmc-supply = <&vccq_sdhi3>; ++ keep-power-in-suspend; ++ enable-sdio-wakeup; ++ bus-width = <4>; ++ no-1-8-v; ++ non-removable; ++ cap-power-off-card; ++ max-frequency = <26000000>; ++ status = "okay"; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ wlcore: wlcore@2 { ++ compatible = "ti,wl1837"; ++ reg = <2>; ++ interrupt-parent = <&gpio1>; ++ interrupts = <25 IRQ_TYPE_EDGE_RISING>; ++ }; ++}; ++ ++&xhci0 { ++ status = "okay"; ++}; ++ ++&usb2_phy0 { ++ pinctrl-0 = <&usb0_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&hsusb { ++ status = "okay"; ++}; ++ ++&ehci0 { ++ status = "okay"; ++}; ++ ++&ohci0 { ++ status = "okay"; ++}; +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0035-arm64-dts-r8a7796-salvator-x-view-add-ADAS-board.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0035-arm64-dts-r8a7796-salvator-x-view-add-ADAS-board.patch new file mode 100644 index 0000000..9ca64c6 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0035-arm64-dts-r8a7796-salvator-x-view-add-ADAS-board.patch @@ -0,0 +1,353 @@ +From 782e569e0b0e252b03fdaecae2e6f7c3267a4bcd Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Mon, 17 Apr 2017 19:12:29 +0300 +Subject: [PATCH] arm64: dts: r8a7796-salvator-x-view: add ADAS board + +Salvator-X.View board on R8A7796 SoC + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + arch/arm64/boot/dts/renesas/Makefile | 1 + + .../boot/dts/renesas/r8a7796-salvator-x-view.dts | 318 +++++++++++++++++++++ + 2 files changed, 319 insertions(+) + create mode 100644 arch/arm64/boot/dts/renesas/r8a7796-salvator-x-view.dts + +diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile +index 49ddbd1..52bbef2 100644 +--- a/arch/arm64/boot/dts/renesas/Makefile ++++ b/arch/arm64/boot/dts/renesas/Makefile +@@ -8,6 +8,7 @@ dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-xs.dtb + dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-h3ulcb-view.dtb + dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-h3ulcb-had-alfa.dtb r8a7795-es1-h3ulcb-had-beta.dtb + dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-h3ulcb-kf.dtb ++dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-x-view.dtb + + always := $(dtb-y) + clean-files := *.dtb +diff --git a/arch/arm64/boot/dts/renesas/r8a7796-salvator-x-view.dts b/arch/arm64/boot/dts/renesas/r8a7796-salvator-x-view.dts +new file mode 100644 +index 0000000..cc6866c +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7796-salvator-x-view.dts +@@ -0,0 +1,318 @@ ++/* ++ * Device Tree Source for the Salvator-X.View board ++ * ++ * Copyright (C) 2016-2017 Renesas Electronics Corp. ++ * Copyright (C) 2016-2017 Cogent Embedded, Inc ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7796-salvator-x.dts" ++ ++/ { ++ model = "Renesas Salvator-X.View board based on r8a7796"; ++}; ++ ++&pfc { ++ can0_pins: can0 { ++ groups = "can0_data_a"; ++ function = "can0"; ++ }; ++ ++ can1_pins: can1 { ++ groups = "can1_data"; ++ function = "can1"; ++ }; ++}; ++ ++&i2c4 { ++ /delete-node/hdmi-in@34; ++ /delete-node/composite-in@70; ++ ++ ov106xx@0 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x60>; ++ ++ port@0 { ++ ov106xx_in0: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin0ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@1 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x61>; ++ ++ port@0 { ++ ov106xx_in1: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin1ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@2 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x62>; ++ ++ port@0 { ++ ov106xx_in2: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin2ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@3 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x63>; ++ ++ port@0 { ++ ov106xx_in3: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin3ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_des0ep3: endpoint { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ }; ++ }; ++ ++ max9286-max9271@0 { ++ compatible = "maxim,max9286-max9271"; ++ reg = <0x4c>; ++ gpios = <&gpio6 30 GPIO_ACTIVE_LOW>; ++ maxim,sensor_delay = <0>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ maxim,i2c-quirk = <0x6c>; ++ ++ port@0 { ++ max9286_des0ep0: endpoint@0 { ++ max9271-addr = <0x50>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ max9286_des0ep1: endpoint@1 { ++ max9271-addr = <0x51>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ max9286_des0ep2: endpoint@2 { ++ max9271-addr = <0x52>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ max9286_des0ep3: endpoint@3 { ++ max9271-addr = <0x53>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ max9286_csi0ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ }; ++}; ++ ++&vin0 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin0ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ }; ++ port@1 { ++ csi0ep0: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin0_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin1 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin1ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <1>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ }; ++ port@1 { ++ csi0ep1: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin1_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin2 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin2ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <2>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ }; ++ port@1 { ++ csi0ep2: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin2_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin3 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin3ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <3>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ csi0ep3: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin3_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ }; ++ }; ++}; ++ ++&vin4 { ++ status = "disabled"; ++}; ++ ++&vin5 { ++ status = "disabled"; ++}; ++ ++&vin6 { ++ status = "disabled"; ++}; ++ ++&vin7 { ++ status = "disabled"; ++}; ++ ++&csi2_20 { ++ status = "disabled"; ++ /delete-node/ports; ++}; ++ ++&csi2_40 { ++ /delete-node/ports; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi2_40_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; ++ ++&can0 { ++ pinctrl-0 = <&can0_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++}; ++ ++&can1 { ++ pinctrl-0 = <&can1_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++}; +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0036-arm64-dts-r8a7796-m3ulcb-view-add-ADAS-board.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0036-arm64-dts-r8a7796-m3ulcb-view-add-ADAS-board.patch new file mode 100644 index 0000000..9fb6a37 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0036-arm64-dts-r8a7796-m3ulcb-view-add-ADAS-board.patch @@ -0,0 +1,322 @@ +From 51c5d0d6f36c1d049afc542130ac8186c12e3a46 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Wed, 4 Jan 2017 10:37:23 +0300 +Subject: [PATCH] arm64: dts: r8a7796-m3ulcb-view: add ADAS board + +M3ULCB.View board on R8A7796 SoC + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + arch/arm64/boot/dts/renesas/Makefile | 1 + + .../arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts | 287 +++++++++++++++++++++ + 2 files changed, 288 insertions(+) + create mode 100644 arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts + +diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile +index 52bbef2..06207e3 100644 +--- a/arch/arm64/boot/dts/renesas/Makefile ++++ b/arch/arm64/boot/dts/renesas/Makefile +@@ -9,6 +9,7 @@ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-salvator-x-view.dtb + dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-h3ulcb-had-alfa.dtb r8a7795-es1-h3ulcb-had-beta.dtb + dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-h3ulcb-kf.dtb + dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-x-view.dtb ++dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-m3ulcb-view.dtb + + always := $(dtb-y) + clean-files := *.dtb +diff --git a/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts +new file mode 100644 +index 0000000..1ac0041 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts +@@ -0,0 +1,287 @@ ++/* ++ * Device Tree Source for the M3ULCB.View board on r8a7796 ++ * ++ * Copyright (C) 2016-2017 Renesas Electronics Corp. ++ * Copyright (C) 2016-2017 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7796-m3ulcb.dts" ++ ++/ { ++ model = "Renesas M3ULCB.View board based on r8a7796"; ++}; ++ ++&i2c4 { ++ ov106xx@0 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x60>; ++ ++ port@0 { ++ ov106xx_in0: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin0ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@1 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x61>; ++ ++ port@0 { ++ ov106xx_in1: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin1ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@2 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x62>; ++ ++ port@0 { ++ ov106xx_in2: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin2ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@3 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x63>; ++ ++ port@0 { ++ ov106xx_in3: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin3ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_des0ep3: endpoint { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ }; ++ }; ++ ++ max9286-max9271@0 { ++ compatible = "maxim,max9286-max9271"; ++ reg = <0x4c>; ++ gpios = <&gpio2 6 GPIO_ACTIVE_HIGH>; ++ maxim,sensor_delay = <0>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ maxim,i2c-quirk = <0x6c>; ++ ++ port@0 { ++ max9286_des0ep0: endpoint@0 { ++ max9271-addr = <0x50>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ max9286_des0ep1: endpoint@1 { ++ max9271-addr = <0x51>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ max9286_des0ep2: endpoint@2 { ++ max9271-addr = <0x52>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ max9286_des0ep3: endpoint@3 { ++ max9271-addr = <0x53>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ max9286_csi0ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ }; ++}; ++ ++&pcie_bus_clk { ++ clock-frequency = <100000000>; ++ status = "okay"; ++}; ++ ++&pciec1 { ++ status = "okay"; ++}; ++ ++&vin0 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin0ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ }; ++ port@1 { ++ csi0ep0: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin0_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin1 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin1ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <1>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ }; ++ port@1 { ++ csi0ep1: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin1_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin2 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin2ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <2>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ }; ++ port@1 { ++ csi0ep2: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin2_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin3 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin3ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <3>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ csi0ep3: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin3_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ }; ++ }; ++}; ++ ++&csi2_40 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi2_40_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0037-arm64-dts-r8a7796-m3ulcb-kf-add-ADAS-board.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0037-arm64-dts-r8a7796-m3ulcb-kf-add-ADAS-board.patch new file mode 100644 index 0000000..92d3bf5 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0037-arm64-dts-r8a7796-m3ulcb-kf-add-ADAS-board.patch @@ -0,0 +1,1232 @@ +From dffbc2287b4fd0c54b49fd4bb41d7f06c23e20b6 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Wed, 4 Jan 2017 10:37:23 +0300 +Subject: [PATCH] arm64: dts: r8a7796-m3ulcb-kf: add ADAS board + +M3ULCB.View board on R8A7796 + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + arch/arm64/boot/dts/renesas/Makefile | 1 + + arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts | 1197 +++++++++++++++++++++ + 2 files changed, 1198 insertions(+) + create mode 100644 arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts + +diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile +index a5dd1d3..5cb7eb1 100644 +--- a/arch/arm64/boot/dts/renesas/Makefile ++++ b/arch/arm64/boot/dts/renesas/Makefile +@@ -11,6 +11,7 @@ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-h3ulcb-had.dtb + dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-h3ulcb-kf.dtb + dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-x-view.dtb + dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-m3ulcb-view.dtb ++dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-m3ulcb-kf.dtb + + always := $(dtb-y) + clean-files := *.dtb +diff --git a/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts +new file mode 100644 +index 0000000..ffaef74 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts +@@ -0,0 +1,1197 @@ ++/* ++ * Device Tree Source for the M3ULCB Kingfisher board on r8a7796 ++ * ++ * Copyright (C) 2017 Renesas Electronics Corp. ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7796-m3ulcb.dts" ++ ++/ { ++ model = "Renesas M3ULCB Kingfisher board based on r8a7796"; ++ ++ aliases { ++ serial1 = &hscif4; ++ }; ++ ++ snd_clk: snd_clk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <24576000>; ++ clock-output-names = "scki"; ++ }; ++ ++ wlan_en: regulator@4 { ++ compatible = "regulator-fixed"; ++ regulator-name = "wlan-en-regulator"; ++ ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ gpio = <&gpio_ext_20 4 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ vccq_sdhi3: regulator@5 { ++ compatible = "regulator-fixed"; ++ ++ regulator-name = "SDHI3 VccQ"; ++ /* external voltage translator to 1.8V */ ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ }; ++ ++ codec_en_reg: regulator@6 { ++ compatible = "regulator-fixed"; ++ regulator-name = "codec-en-regulator"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ gpio = <&gpio_ext_20 15 0>; ++ ++ /* delay - CHECK */ ++ startup-delay-us = <70000>; ++ enable-active-high; ++ }; ++ ++ amp_en_reg: regulator@7 { ++ compatible = "regulator-fixed"; ++ regulator-name = "amp-en-regulator"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ gpio = <&gpio_ext_20 0 0>; ++ ++ startup-delay-us = <0>; ++ enable-active-high; ++ }; ++ ++ lvds_switch: regulator@8 { ++ compatible = "regulator-fixed"; ++ regulator-name = "lvds_on"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&gpio1 24 0>; ++ enable-active-high; ++ regulator-always-on; ++ }; ++ ++ sdio_switch: regulator@9 { ++ compatible = "regulator-fixed"; ++ regulator-name = "wifi_on"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&gpio_ext_20 5 0>; ++ enable-active-low; ++ regulator-always-on; ++ }; ++ ++ sound_switch: regulator@10 { ++ compatible = "regulator-fixed"; ++ regulator-name = "pcm3168a_on"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&gpio_ext_21 5 0>; ++ enable-active-low; ++ regulator-always-on; ++ }; ++ ++ radio_switch: regulator@11 { ++ compatible = "regulator-fixed"; ++ regulator-name = "radio_on"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&gpio_ext_20 13 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ regulator-always-on; ++ }; ++ ++ kim { ++ compatible = "kim"; ++ nshutdown_gpio = <343>; /* pca9535@i2c2.0x20 pin 3 */ ++ /* serial1 */ ++ dev_name = "/dev/ttySC1"; ++ flow_cntrl = <1>; ++ /* int div 8 hscif@26.6666656MHz */ ++ baud_rate = <3333332>; ++ }; ++ ++ btwilink { ++ compatible = "btwilink"; ++ }; ++ ++ sound_ext: sound@0 { ++ pinctrl-0 = <&sound_0_pins>; ++ pinctrl-names = "default"; ++ compatible = "simple-audio-card"; ++ ++ simple-audio-card,format = "left_j"; ++ simple-audio-card,name = "pcm3168a"; ++ ++ simple-audio-card,bitclock-master = <&sound_ext_master>; ++ simple-audio-card,frame-master = <&sound_ext_master>; ++ sound_ext_master: simple-audio-card,cpu@0 { ++ sound-dai = <&rcar_sound 0>; ++ dai-tdm-slot-num = <8>; ++ dai-tdm-slot-width = <32>; ++ }; ++ ++ simple-audio-card,codec@0 { ++ sound-dai = <&pcm3168a>; ++ dai-tdm-slot-num = <8>; ++ dai-tdm-slot-width = <32>; ++ system-clock-frequency = <24576000>; ++ }; ++ }; ++ ++ /delete-node/sound; ++ ++ rsnd_ak4613: sound@1 { ++ pinctrl-0 = <&sound_1_pins>; ++ pinctrl-names = "default"; ++ compatible = "simple-audio-card"; ++ ++ simple-audio-card,format = "left_j"; ++ simple-audio-card,name = "ak4613"; ++ ++ simple-audio-card,bitclock-master = <&sndcpu>; ++ simple-audio-card,frame-master = <&sndcpu>; ++ ++ sndcpu: simple-audio-card,cpu@1 { ++ sound-dai = <&rcar_sound 1>; ++ }; ++ ++ sndcodec: simple-audio-card,codec@1 { ++ sound-dai = <&ak4613>; ++ }; ++ }; ++ ++ sound_radio: sound@2 { ++ pinctrl-0 = <&sound_2_pins>; ++ pinctrl-names = "default"; ++ compatible = "simple-audio-card"; ++ ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,name = "radio"; ++ ++ simple-audio-card,bitclock-master = <&sound_radio_master>; ++ simple-audio-card,frame-master = <&sound_radio_master>; ++ simple-audio-card,cpu@2 { ++ sound-dai = <&rcar_sound 2>; ++ }; ++ ++ sound_radio_master: simple-audio-card,codec@2 { ++ sound-dai = <&radio>; ++ system-clock-frequency = <12288000>; ++ }; ++ }; ++ ++ sound_amp: sound@3 { ++ pinctrl-0 = <&sound_9_pins>; ++ pinctrl-names = "default"; ++ compatible = "simple-audio-card"; ++ ++ simple-audio-card,name = "power_amp"; ++ ++ simple-audio-card,dai-link@0 { ++ format = "i2s"; ++ cpu { ++ sound-dai = <&rcar_sound 3>; ++ }; ++ codec { ++ sound-dai = <&max98371_L>; ++ }; ++ }; ++ simple-audio-card,dai-link@1 { ++ format = "i2s"; ++ cpu { ++ sound-dai = <&rcar_sound 3>; ++ }; ++ codec { ++ sound-dai = <&max98371_R>; ++ }; ++ }; ++ simple-audio-card,dai-link@2 { ++ format = "i2s"; ++ cpu { ++ sound-dai = <&rcar_sound 3>; ++ }; ++ codec { ++ sound-dai = <&max98371_RL>; ++ }; ++ }; ++ simple-audio-card,dai-link@3 { ++ format = "i2s"; ++ cpu { ++ sound-dai = <&rcar_sound 3>; ++ }; ++ codec { ++ sound-dai = <&max98371_RR>; ++ }; ++ }; ++ simple-audio-card,dai-link@4 { ++ format = "i2s"; ++ cpu { ++ sound-dai = <&rcar_sound 3>; ++ }; ++ codec { ++ sound-dai = <&max98371_C>; ++ }; ++ }; ++ simple-audio-card,dai-link@5 { ++ format = "i2s"; ++ cpu { ++ sound-dai = <&rcar_sound 3>; ++ }; ++ codec { ++ sound-dai = <&max98371_S>; ++ }; ++ }; ++ }; ++ ++ lvds-encoder { ++ compatible = "thine,thc63lvdm83d"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ port@0 { ++ reg = <0>; ++ lvds_enc_in: endpoint { ++ remote-endpoint = <&du_out_lvds0>; ++ }; ++ }; ++ port@1 { ++ reg = <1>; ++ lvds_enc_out: endpoint { ++ remote-endpoint = <&lvds_in>; ++ }; ++ }; ++ }; ++ }; ++ ++ lvds { ++ compatible = "lvds-connector"; ++ ++ width-mm = <210>; ++ height-mm = <158>; ++ ++ panel-timing { ++ /* 1280x800 @60Hz */ ++ clock-frequency = <65000000>; ++ hactive = <1280>; ++ vactive = <800>; ++ hsync-len = <40>; ++ hfront-porch = <80>; ++ hback-porch = <40>; ++ vfront-porch = <14>; ++ vback-porch = <14>; ++ vsync-len = <4>; ++ }; ++ ++ port { ++ lvds_in: endpoint { ++ remote-endpoint = <&lvds_enc_out>; ++ }; ++ }; ++ }; ++ ++ radio: si468x@0 { ++ compatible = "si,si468x-pcm"; ++ status = "okay"; ++ ++ #sound-dai-cells = <0>; ++ }; ++}; ++ ++&pfc { ++ hscif4_pins: hscif4 { ++ groups = "hscif4_data_a", "hscif4_ctrl"; ++ function = "hscif4"; ++ }; ++ ++ sdhi3_pins_3v3: sd3_3v3 { ++ groups = "sdhi3_data4", "sdhi3_ctrl"; ++ function = "sdhi3"; ++ power-source = <3300>; ++ }; ++ ++ sound_0_pins: sound0 { ++ groups = "ssi78_ctrl", "ssi7_data", "ssi8_data"; ++ function = "ssi"; ++ }; ++ ++ sound_1_pins: sound1 { ++ groups = "ssi01239_ctrl", "ssi0_data", "ssi1_data_a"; ++ function = "ssi"; ++ }; ++ ++ sound_2_pins: sound2 { ++ groups = "ssi6_ctrl", "ssi6_data"; ++ function = "ssi"; ++ }; ++ ++ sound_9_pins: sound2 { ++ groups = "ssi9_ctrl_b", "ssi9_data_b"; ++ function = "ssi"; ++ }; ++ ++ usb0_pins: usb0 { ++ groups = "usb0"; ++ function = "usb0"; ++ }; ++}; ++ ++&gpio0 { ++ video_a_irq { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-A irq"; ++ }; ++ ++ video_b_irq { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-B irq"; ++ }; ++ ++ gpioext_2_20_irq { ++ gpio-hog; ++ gpios = <15 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "0x20@i2c2 irq"; ++ }; ++}; ++ ++&gpio1 { ++ gpioext_2_21_irq { ++ gpio-hog; ++ gpios = <15 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "0x21@i2c2 irq"; ++ }; ++ ++ wifi_irq { ++ gpio-hog; ++ gpios = <25 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "wifi irq"; ++ }; ++}; ++ ++&gpio5 { ++ touch_irq { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "touch irq"; ++ }; ++ ++ /* From TI forum */ ++ /* BT_AUD_OUT should be pulled low when WL_EN is activated. */ ++ /* in case it isn't, wilink8 ends up in one of the test modes that introduces various issues */ ++ bt_strap { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "BT strap pin"; ++ }; ++}; ++ ++&gpio7 { ++ gpioext_2_21_irq { ++ gpio-hog; ++ gpios = <3 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "0x21@i2c4 irq"; ++ }; ++}; ++ ++&hscif4 { ++ pinctrl-0 = <&hscif4_pins>; ++ pinctrl-names = "default"; ++ ctsrts; ++ ++ status = "okay"; ++}; ++ ++&i2c2 { ++ clock-frequency = <400000>; ++ ++ gpio_ext_20: pca9535@20 { ++ compatible = "nxp,pca9535"; ++ reg = <0x20>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ interrupt-parent = <&gpio0>; ++ interrupts = <15 IRQ_TYPE_EDGE_FALLING>; ++ }; ++ ++ gpio_ext_21: pca9535@21 { ++ compatible = "nxp,pca9535"; ++ reg = <0x21>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ interrupt-parent = <&gpio1>; ++ interrupts = <15 IRQ_TYPE_EDGE_FALLING>; ++ }; ++ ++ i2cswitch2@74 { ++ compatible = "nxp,pca9548"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x74>; ++ reset-gpios = <&gpio6 5 GPIO_ACTIVE_LOW>; ++ ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ /* BCM node(s) */ ++ }; ++ ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ /* USB3.0 HUB node(s) */ ++ }; ++ ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ /* Power amp node(s) */ ++ ++ max98371_L: max98371@0x31 { ++ compatible = "maxim,max98371"; ++ reg = <0x31>; ++ #sound-dai-cells = <0>; ++ }; ++ max98371_R: max98371@0x32 { ++ compatible = "maxim,max98371"; ++ reg = <0x32>; ++ #sound-dai-cells = <0>; ++ }; ++ max98371_RL: max98371@0x33 { ++ compatible = "maxim,max98371"; ++ reg = <0x33>; ++ #sound-dai-cells = <0>; ++ }; ++ max98371_RR: max98371@0x34 { ++ compatible = "maxim,max98371"; ++ reg = <0x34>; ++ #sound-dai-cells = <0>; ++ }; ++ max98371_C: max98371@0x35 { ++ compatible = "maxim,max98371"; ++ reg = <0x35>; ++ #sound-dai-cells = <0>; ++ }; ++ max98371_S: max98371@0x36 { ++ compatible = "maxim,max98371"; ++ reg = <0x36>; ++ #sound-dai-cells = <0>; ++ }; ++ }; ++ ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ /* Radio node(s) */ ++ }; ++ ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ /* A2B node(s) */ ++ }; ++ ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ /* PCIe node(s) */ ++ }; ++ ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ /* LVDS display node(s) */ ++ ++ polytouch: edt-ft5x06@38 { ++ compatible = "edt,edt-ft5x06"; ++ reg = <0x38>; ++ interrupt-parent = <&gpio5>; ++ interrupts = <6 IRQ_TYPE_EDGE_FALLING>; ++ }; ++ }; ++ ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ /* Audio, GPS and Gyro node(s) */ ++ ++ pcm3168a: audio-codec@44 { ++ #sound-dai-cells = <0>; ++ compatible = "ti,pcm3168a"; ++ reg = <0x44>; ++ clocks = <&snd_clk>; ++ clock-names = "scki"; ++ tdm; ++ VDD1-supply = <&codec_en_reg>; ++ VDD2-supply = <&codec_en_reg>; ++ VCCAD1-supply = <&codec_en_reg>; ++ VCCAD2-supply = <&codec_en_reg>; ++ VCCDA1-supply = <&_en_reg>; ++ VCCDA2-supply = <&_en_reg>; ++ }; ++ ++ lsm9ds0_acc_mag@1d { ++ compatible = "st,lsm9ds0_acc_mag"; ++ reg = <0x1d>; ++ }; ++ ++ lsm9ds0_gyr@6b { ++ compatible = "st,lsm9ds0-gyro"; ++ reg = <0x6b>; ++ }; ++ ++ /* GPS@ 0x42 */ ++ }; ++ }; ++}; ++ ++&i2c4 { ++ gpio_ext_22: pca9535@21 { ++ compatible = "nxp,pca9535"; ++ reg = <0x22>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ interrupt-parent = <&gpio7>; ++ interrupts = <3 IRQ_TYPE_EDGE_FALLING>; ++ }; ++ ++ i2cswitch4@74 { ++ compatible = "nxp,pca9548"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x74>; ++ reset-gpios= <&gpio6 21 GPIO_ACTIVE_LOW>; ++ ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ /* SAM node(s) */ ++ }; ++ ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ /* Video input "A" acc node(s) */ ++ ++ ov106xx@0 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x60>; ++ ++ port@0 { ++ ov106xx_in0: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin0ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ ov106xx_ti964_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti964_des0ep0>; ++ }; ++ ov106xx_ti954_des0ep0: endpoint@2 { ++ remote-endpoint = <&ti954_des0ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@1 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x61>; ++ ++ port@0 { ++ ov106xx_in1: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin1ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ ov106xx_ti964_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti964_des0ep1>; ++ }; ++ ov106xx_ti954_des0ep1: endpoint@2 { ++ remote-endpoint = <&ti954_des0ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@2 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x62>; ++ ++ port@0 { ++ ov106xx_in2: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin2ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ ov106xx_ti964_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti964_des0ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@3 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x63>; ++ ++ port@0 { ++ ov106xx_in3: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin3ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ ov106xx_ti964_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti964_des0ep3>; ++ }; ++ }; ++ }; ++ ++ /* DS90UB964 @ 0x3a */ ++ ti964-ti9x3@0 { ++ compatible = "ti,ti964-ti9x3"; ++ reg = <0x3a>; ++ ti,sensor_delay = <350>; ++ ti,links = <4>; ++ ti,lanes = <4>; ++ ti,forwarding-mode = "round-robin"; ++ ti,cable-mode = "coax"; ++ ++ port@0 { ++ ti964_des0ep0: endpoint@0 { ++ ti9x3-addr = <0x0c>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ ti964_des0ep1: endpoint@1 { ++ ti9x3-addr = <0x0d>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ ti964_des0ep2: endpoint@2 { ++ ti9x3-addr = <0x0e>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ ti964_des0ep3: endpoint@3 { ++ ti9x3-addr = <0x0f>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ ti964_csi0ep0: endpoint { ++ csi-rate = <1450>; ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ }; ++ ++ /* DS90UB954 @ 0x38 */ ++ ti954-ti9x3@0 { ++ compatible = "ti,ti954-ti9x3"; ++ reg = <0x38>; ++ gpios = <&video_a_ext1 10 GPIO_ACTIVE_HIGH>; ++ ti,sensor_delay = <350>; ++ ti,links = <2>; ++ ti,lanes = <4>; ++ ti,forwarding-mode = "round-robin"; ++ ti,cable-mode = "coax"; ++ ++ port@0 { ++ ti954_des0ep0: endpoint@0 { ++ ti9x3-addr = <0x0c>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ ti954_des0ep1: endpoint@1 { ++ ti9x3-addr = <0x0d>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ }; ++ port@1 { ++ ti954_csi0ep0: endpoint { ++ csi-rate = <1450>; ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ }; ++ ++ /* MAX9286 @ 0x2a */ ++ max9286-max9271@0 { ++ compatible = "maxim,max9286-max9271"; ++ reg = <0x2a>; ++ maxim,sensor_delay = <350>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ ++ port@0 { ++ max9286_des0ep0: endpoint@0 { ++ max9271-addr = <0x50>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ max9286_des0ep1: endpoint@1 { ++ max9271-addr = <0x51>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ max9286_des0ep2: endpoint@2 { ++ max9271-addr = <0x52>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ max9286_des0ep3: endpoint@3 { ++ max9271-addr = <0x53>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ max9286_csi0ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ }; ++ }; ++ ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ /* MOST node(s) */ ++ }; ++ ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ /* CSI camera node(s) */ ++ }; ++ ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ /* CMOS camera node(s) */ ++ }; ++ ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ /* Video input "A" main node(s) */ ++ ++ video_a_ext0: pca9535@26 { ++ compatible = "nxp,pca9535"; ++ reg = <0x26>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ video_a_des_cfg1 { ++ gpio-hog; ++ gpios = <5 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A cfg1"; ++ }; ++ video_a_des_cfg0 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A cfg0"; ++ }; ++ video_a_pwr_shdn { ++ gpio-hog; ++ gpios = <3 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR_SHDN"; ++ }; ++ video_a_cam_pwr0 { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR0"; ++ }; ++ video_a_cam_pwr1 { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR1"; ++ }; ++ video_a_cam_pwr2 { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR2"; ++ }; ++ video_a_cam_pwr3 { ++ gpio-hog; ++ gpios = <15 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR3"; ++ }; ++ video_a_des_shdn { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A DES_SHDN"; ++ }; ++ video_a_des_led { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-A led"; ++ }; ++ }; ++ ++ video_a_ext1: max7325@5c { ++ compatible = "maxim,max7325"; ++ reg = <0x5c>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ video_a_des_cfg2 { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-A cfg2"; ++ }; ++ video_a_des_cfg1 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-A cfg1"; ++ }; ++ video_a_des_cfg0 { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-A cfg0"; ++ }; ++ video_a_pwr_shdn { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR_SHDN"; ++ }; ++ video_a_cam_pwr0 { ++ gpio-hog; ++ gpios = <8 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR0"; ++ }; ++ video_a_cam_pwr1 { ++ gpio-hog; ++ gpios = <9 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR1"; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&pcie_bus_clk { ++ clock-frequency = <100000000>; ++ status = "okay"; ++}; ++ ++&pciec0 { ++ status = "okay"; ++}; ++ ++&pciec1 { ++ status = "okay"; ++}; ++ ++&vin0 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin0ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ }; ++ port@1 { ++ csi0ep0: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin0_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ vin0_ti964_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti964_des0ep0>; ++ }; ++ vin0_ti954_des0ep0: endpoint@2 { ++ remote-endpoint = <&ti954_des0ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin1 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin1ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <1>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ }; ++ port@1 { ++ csi0ep1: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin1_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ vin1_ti964_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti964_des0ep1>; ++ }; ++ vin1_ti954_des0ep1: endpoint@2 { ++ remote-endpoint = <&ti954_des0ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin2 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin2ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <2>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ }; ++ port@1 { ++ csi0ep2: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin2_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ vin2_ti964_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti964_des0ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin3 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin3ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <3>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ csi0ep3: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin3_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ vin3_ti964_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti964_des0ep3>; ++ }; ++ }; ++ }; ++}; ++ ++&csi2_40 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi2_40_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; ++ ++&rcar_sound { ++ pinctrl-0 = <&sound_clk_pins>; ++ ++ /* Multi DAI */ ++ #sound-dai-cells = <1>; ++ ++ rcar_sound,dai { ++ dai0 { ++ playback = <&ssi7>; ++ capture = <&ssi8>; ++ }; ++ ++ dai1 { ++ playback = <&ssi0 &src0 &dvc0>; ++ capture = <&ssi1 &src1 &dvc1>; ++ }; ++ ++ dai2 { ++ capture = <&ssi6>; ++ }; ++ ++ dai3 { ++ playback = <&ssi9>; ++ }; ++ }; ++}; ++ ++&sdhi3 { ++ pinctrl-0 = <&sdhi3_pins_3v3>; ++ pinctrl-names = "default"; ++ ++ vmmc-supply = <&wlan_en>; ++ vqmmc-supply = <&vccq_sdhi3>; ++ keep-power-in-suspend; ++ enable-sdio-wakeup; ++ bus-width = <4>; ++ no-1-8-v; ++ non-removable; ++ cap-power-off-card; ++ max-frequency = <26000000>; ++ status = "okay"; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ wlcore: wlcore@2 { ++ compatible = "ti,wl1837"; ++ reg = <2>; ++ interrupt-parent = <&gpio1>; ++ interrupts = <25 IRQ_TYPE_EDGE_RISING>; ++ }; ++}; ++ ++&xhci0 { ++ status = "okay"; ++}; ++ ++&usb2_phy0 { ++ pinctrl-0 = <&usb0_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&hsusb { ++ status = "okay"; ++}; ++ ++&ehci0 { ++ status = "okay"; ++}; ++ ++&ohci0 { ++ status = "okay"; ++}; +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0038-arm64-dts-r8a7795-salvator-x-view-add-ADAS-board.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0038-arm64-dts-r8a7795-salvator-x-view-add-ADAS-board.patch new file mode 100644 index 0000000..3609bb1 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0038-arm64-dts-r8a7795-salvator-x-view-add-ADAS-board.patch @@ -0,0 +1,587 @@ +From c5d2ada2089db7db1a059af37f371f6e2df213f4 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Wed, 4 Jan 2017 10:37:23 +0300 +Subject: [PATCH] arm64: dts: r8a7795-salvator-x-view: add ADAS board + +Salvator-X.View board on R8A7795 SoC + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + arch/arm64/boot/dts/renesas/Makefile | 3 + + .../dts/renesas/r8a7795-salvator-x-view.dts | 552 +++++++++++++++++++++ + 2 files changed, 555 insertions(+) + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts + +diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile +index 32fb4d9..2a00759 100644 +--- a/arch/arm64/boot/dts/renesas/Makefile ++++ b/arch/arm64/boot/dts/renesas/Makefile +@@ -4,6 +4,7 @@ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-salvator-x.dtb r8a7795-es1-h3ulcb.dtb + dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-x-view.dtb + dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-m3ulcb-view.dtb + dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-m3ulcb-kf.dtb ++dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-salvator-x-view.dtb + + always := $(dtb-y) + clean-files := *.dtb +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts +new file mode 100644 +index 0000000..3f3d66a +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts +@@ -0,0 +1,552 @@ ++/* ++ * Device Tree Source for the Salvator-X.View board ++ * ++ * Copyright (C) 2016-2017 Renesas Electronics Corp. ++ * Copyright (C) 2015-2017 Cogent Embedded, Inc ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7795-salvator-x.dts" ++ ++/ { ++ model = "Renesas Salvator-X.View board based on r8a7795"; ++}; ++ ++&pfc { ++ can0_pins: can0 { ++ groups = "can0_data_a"; ++ function = "can0"; ++ }; ++ ++ can1_pins: can1 { ++ groups = "can1_data"; ++ function = "can1"; ++ }; ++}; ++ ++&i2c4 { ++ /delete-node/hdmi-in@34; ++ /delete-node/composite-in@70; ++ ++ ov106xx@0 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x60>; ++ ++ port@0 { ++ ov106xx_in0: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin0ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@1 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x61>; ++ ++ port@0 { ++ ov106xx_in1: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin1ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@2 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x62>; ++ ++ port@0 { ++ ov106xx_in2: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin2ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@3 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x63>; ++ ++ port@0 { ++ ov106xx_in3: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin3ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_des0ep3: endpoint { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ }; ++ }; ++ ++ ov106xx@4 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x64>; ++ ++ port@0 { ++ ov106xx_in4: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin4ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@5 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x65>; ++ ++ port@0 { ++ ov106xx_in5: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin5ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@6 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x66>; ++ ++ port@0 { ++ ov106xx_in6: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin6ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@7 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x67>; ++ ++ port@0 { ++ ov106xx_in7: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin7ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_des1ep3: endpoint { ++ remote-endpoint = <&max9286_des1ep3>; ++ }; ++ }; ++ }; ++ ++ max9286-max9271@0 { ++ compatible = "maxim,max9286-max9271"; ++ reg = <0x4c>; ++ gpios = <&gpio6 30 GPIO_ACTIVE_LOW>; ++ maxim,sensor_delay = <0>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ maxim,i2c-quirk = <0x6c>; ++ ++ port@0 { ++ max9286_des0ep0: endpoint@0 { ++ max9271-addr = <0x50>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ max9286_des0ep1: endpoint@1 { ++ max9271-addr = <0x51>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ max9286_des0ep2: endpoint@2 { ++ max9271-addr = <0x52>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ max9286_des0ep3: endpoint@3 { ++ max9271-addr = <0x53>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ max9286_csi0ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ }; ++ ++ max9286-max9271@1 { ++ compatible = "maxim,max9286-max9271"; ++ reg = <0x6c>; ++ maxim,sensor_delay = <0>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ ++ port@0 { ++ max9286_des1ep0: endpoint@0 { ++ max9271-addr = <0x54>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in4>; ++ }; ++ max9286_des1ep1: endpoint@1 { ++ max9271-addr = <0x55>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in5>; ++ }; ++ max9286_des1ep2: endpoint@2 { ++ max9271-addr = <0x56>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in6>; ++ }; ++ max9286_des1ep3: endpoint@3 { ++ max9271-addr = <0x57>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in7>; ++ }; ++ }; ++ port@1 { ++ max9286_csi2ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ }; ++}; ++ ++&vin0 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin0ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ }; ++ port@1 { ++ csi0ep0: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin0_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin1 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin1ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <1>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ }; ++ port@1 { ++ csi0ep1: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin1_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin2 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin2ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <2>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ }; ++ port@1 { ++ csi0ep2: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin2_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin3 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin3ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <3>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ csi0ep3: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin3_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ }; ++ }; ++}; ++ ++&vin4 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin4ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <0>; ++ remote-endpoint = <&ov106xx_in4>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep0: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ vin4_max9286_des1ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin5 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin5ep0: endpoint@0 { ++ csi,select = "csi41"; ++ virtual,channel = <1>; ++ remote-endpoint = <&ov106xx_in5>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep1: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ vin5_max9286_des1ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin6 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin6ep0: endpoint@0 { ++ csi,select = "csi41"; ++ virtual,channel = <2>; ++ remote-endpoint = <&ov106xx_in6>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep2: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ vin6_max9286_des1ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin7 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin7ep0: endpoint@0 { ++ csi,select = "csi41"; ++ virtual,channel = <3>; ++ remote-endpoint = <&ov106xx_in7>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep3: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ vin7_max9286_des1ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep3>; ++ }; ++ }; ++ }; ++}; ++ ++&csi2_20 { ++ status = "disabled"; ++ /delete-node/ports; ++}; ++ ++&csi2_40 { ++ /delete-node/ports; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi2_40_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; ++ ++&csi2_41 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi2_41_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; ++ ++&can0 { ++ pinctrl-0 = <&can0_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++}; ++ ++&can1 { ++ pinctrl-0 = <&can1_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++}; +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0039-arm64-dts-r8a7795-h3ulcb-view-add-ADAS-board.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0039-arm64-dts-r8a7795-h3ulcb-view-add-ADAS-board.patch new file mode 100644 index 0000000..f8304df --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0039-arm64-dts-r8a7795-h3ulcb-view-add-ADAS-board.patch @@ -0,0 +1,581 @@ +From 24d2ada2089db7db1a059af37f371f6e2df213f4 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Wed, 4 Jan 2017 10:37:23 +0300 +Subject: [PATCH] arm64: dts: r8a7795-h3ulcb-view: add ADAS board + +H3ULCB.View board on R8A7795 SoC + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + arch/arm64/boot/dts/renesas/Makefile | 1 + + .../boot/dts/renesas/r8a7795-h3ulcb-view.dts | 546 +++++++++++++++++++++ + 2 files changed, 547 insertions(+) + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts + +diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile +index 2a00759..43aa35d 100644 +--- a/arch/arm64/boot/dts/renesas/Makefile ++++ b/arch/arm64/boot/dts/renesas/Makefile +@@ -6,6 +6,7 @@ dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-xs.dtb + dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-m3ulcb-view.dtb + dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-m3ulcb-kf.dtb + dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-salvator-x-view.dtb ++dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-view.dtb + + always := $(dtb-y) + clean-files := *.dtb +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts +new file mode 100644 +index 0000000..de56fa4 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts +@@ -0,0 +1,546 @@ ++/* ++ * Device Tree Source for the H3ULCB.View board ++ * ++ * Copyright (C) 2016-2017 Renesas Electronics Corp. ++ * Copyright (C) 2016-2017 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7795-h3ulcb.dts" ++ ++/ { ++ model = "Renesas H3ULCB.View board based on r8a7795"; ++}; ++ ++&i2c4 { ++ ov106xx@0 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x60>; ++ ++ port@0 { ++ ov106xx_in0: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin0ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@1 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x61>; ++ ++ port@0 { ++ ov106xx_in1: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin1ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@2 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x62>; ++ ++ port@0 { ++ ov106xx_in2: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin2ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@3 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x63>; ++ ++ port@0 { ++ ov106xx_in3: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin3ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_des0ep3: endpoint { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ }; ++ }; ++ ++ ov106xx@4 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x64>; ++ ++ port@0 { ++ ov106xx_in4: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin4ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@5 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x65>; ++ ++ port@0 { ++ ov106xx_in5: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin5ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@6 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x66>; ++ ++ port@0 { ++ ov106xx_in6: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin6ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@7 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x67>; ++ ++ port@0 { ++ ov106xx_in7: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin7ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_des1ep3: endpoint { ++ remote-endpoint = <&max9286_des1ep3>; ++ }; ++ }; ++ }; ++ ++ max9286-max9271@0 { ++ compatible = "maxim,max9286-max9271"; ++ reg = <0x4c>; ++ gpios = <&gpio2 6 GPIO_ACTIVE_HIGH>; ++ maxim,sensor_delay = <0>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ maxim,i2c-quirk = <0x6c>; ++ ++ port@0 { ++ max9286_des0ep0: endpoint@0 { ++ max9271-addr = <0x50>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ max9286_des0ep1: endpoint@1 { ++ max9271-addr = <0x51>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ max9286_des0ep2: endpoint@2 { ++ max9271-addr = <0x52>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ max9286_des0ep3: endpoint@3 { ++ max9271-addr = <0x53>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ max9286_csi0ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ }; ++ ++ max9286-max9271@1 { ++ compatible = "maxim,max9286-max9271"; ++ reg = <0x6c>; ++ gpios = <&gpio5 25 GPIO_ACTIVE_HIGH>; ++ maxim,sensor_delay = <0>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ ++ port@0 { ++ max9286_des1ep0: endpoint@0 { ++ max9271-addr = <0x54>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in4>; ++ }; ++ max9286_des1ep1: endpoint@1 { ++ max9271-addr = <0x55>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in5>; ++ }; ++ max9286_des1ep2: endpoint@2 { ++ max9271-addr = <0x56>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in6>; ++ }; ++ max9286_des1ep3: endpoint@3 { ++ max9271-addr = <0x57>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in7>; ++ }; ++ }; ++ port@1 { ++ max9286_csi2ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ }; ++}; ++ ++&pcie_bus_clk { ++ clock-frequency = <100000000>; ++ status = "okay"; ++}; ++ ++&pciec1 { ++ status = "okay"; ++}; ++ ++&vin0 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin0ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ }; ++ port@1 { ++ csi0ep0: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin0_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin1 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin1ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <1>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ }; ++ port@1 { ++ csi0ep1: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin1_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin2 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin2ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <2>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ }; ++ port@1 { ++ csi0ep2: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin2_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin3 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin3ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <3>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ csi0ep3: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin3_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ }; ++ }; ++}; ++ ++&vin4 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin4ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <0>; ++ remote-endpoint = <&ov106xx_in4>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep0: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ vin4_max9286_des1ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin5 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin5ep0: endpoint@0 { ++ csi,select = "csi41"; ++ virtual,channel = <1>; ++ remote-endpoint = <&ov106xx_in5>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep1: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ vin5_max9286_des1ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin6 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin6ep0: endpoint@0 { ++ csi,select = "csi41"; ++ virtual,channel = <2>; ++ remote-endpoint = <&ov106xx_in6>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep2: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ vin6_max9286_des1ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin7 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin7ep0: endpoint@0 { ++ csi,select = "csi41"; ++ virtual,channel = <3>; ++ remote-endpoint = <&ov106xx_in7>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep3: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ vin7_max9286_des1ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep3>; ++ }; ++ }; ++ }; ++}; ++ ++&csi2_40 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi2_40_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; ++ ++&csi2_41 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi2_41_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-r8a7795-h3ulcb-had-add-ADAS-board.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-r8a7795-h3ulcb-had-add-ADAS-board.patch new file mode 100644 index 0000000..b669d26 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-r8a7795-h3ulcb-had-add-ADAS-board.patch @@ -0,0 +1,314 @@ +From 30240b74fe0b5c851127996328504e86a9fc4407 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Wed, 4 Jan 2017 10:41:48 +0300 +Subject: [PATCH] arm64: dts: r8a7795-h3ulcb-had: add ADAS board + +H3ULCB.HAD board on R8A7795 SoC + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + arch/arm64/boot/dts/renesas/Makefile | 1 + + .../boot/dts/renesas/r8a7795-h3ulcb-had-alfa.dts | 22 +++ + .../boot/dts/renesas/r8a7795-h3ulcb-had-beta.dts | 23 +++ + .../arm64/boot/dts/renesas/r8a7795-h3ulcb-had.dtsi | 218 +++++++++++++++++++++ + 4 files changed, 264 insertions(+) + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-had-alfa.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-had-beta.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-had.dtsi + +diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile +index 387652e..9dad6dc 100644 +--- a/arch/arm64/boot/dts/renesas/Makefile ++++ b/arch/arm64/boot/dts/renesas/Makefile +@@ -14,6 +14,7 @@ dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-m3ulcb-view.dtb + dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-m3ulcb-kf.dtb + dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-salvator-x-view.dtb + dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-view.dtb ++dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-had-alfa.dtb r8a7795-h3ulcb-had-beta.dtb + + always := $(dtb-y) + clean-files := *.dtb +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-had-alfa.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-had-alfa.dts +new file mode 100644 +index 0000000..ae115bd +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-had-alfa.dts +@@ -0,0 +1,22 @@ ++/* ++ * Device Tree Source for the H3ULCB.HAD board Alfa side ++ * ++ * Copyright (C) 2017 Renesas Electronics Corp. ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7795-h3ulcb-had.dtsi" ++ ++/ { ++ model = "Renesas H3ULCB.HAD board Alfa side based on r8a7795"; ++}; ++ ++&pciec0 { ++ status = "okay"; ++ ++ /* Root complex */ ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-had-beta.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-had-beta.dts +new file mode 100644 +index 0000000..805067e +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-had-beta.dts +@@ -0,0 +1,23 @@ ++/* ++ * Device Tree Source for the H3ULCB.HAD board Beta side ++ * ++ * Copyright (C) 2017 Renesas Electronics Corp. ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7795-h3ulcb-had.dtsi" ++ ++/ { ++ model = "Renesas H3ULCB.HAD board Beta side based on r8a7795"; ++}; ++ ++&pciec0 { ++ status = "okay"; ++ ++ /* Endpoint */ ++ endpoint; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-had.dtsi b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-had.dtsi +new file mode 100644 +index 0000000..d146938 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-had.dtsi +@@ -0,0 +1,218 @@ ++/* ++ * Device Tree Source for the H3ULCB.HAD board on r8a7795 ++ * ++ * Copyright (C) 2016-2017 Renesas Electronics Corp. ++ * Copyright (C) 2016-2017 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++/* ++ * MSIOF0 - /dev/spidev1.0 connected to FPGA ethernet switch (both sides) ++ * MSIOF1 - /dev/spidev2.0 connected to RH850 (sideA to CSIH1, sideB to CSIH0) ++ */ ++ ++#include "r8a7795-h3ulcb-view.dts" ++ ++/ { ++ model = "Renesas H3ULCB.HAD board based on r8a7795"; ++ ++ aliases { ++ spi1 = &spi0_gpio; ++ spi2 = &spi1_gpio; ++ }; ++ ++ chosen { ++ stdout-path = "serial1:115200n8"; ++ }; ++ ++ spi0_gpio: spi_gpio@0 { ++ compatible = "spi-gpio"; ++ num-chipselects = <1>; ++ gpio-sck = <&gpio5 17 0>; ++ gpio-mosi = <&gpio5 20 0>; ++ gpio-miso = <&gpio5 22 0>; ++ cs-gpios = <&gpio5 19 0>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ spidev@0 { ++ compatible = "spi-gpio"; ++ reg = <0>; ++ spi-max-frequency = <2000000>; ++ spi-cpha; ++ spi-cpol; ++ }; ++ }; ++ ++ spi1_gpio: spi_gpio@1 { ++ compatible = "spi-gpio"; ++ num-chipselects = <1>; ++ gpio-sck = <&gpio6 8 0>; ++ gpio-mosi = <&gpio6 7 0>; ++ gpio-miso = <&gpio6 10 0>; ++ cs-gpios = <&gpio6 5 0>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ spidev@0 { ++ compatible = "spi-gpio"; ++ reg = <0>; ++ spi-max-frequency = <2000000>; ++ spi-cpha; ++ spi-cpol; ++ }; ++ }; ++ ++ hdmi1-out { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi1_con: endpoint { ++ remote-endpoint = <&rcar_dw_hdmi1_out>; ++ }; ++ }; ++ }; ++}; ++ ++&du { ++ ports { ++ port@1 { ++ endpoint { ++ remote-endpoint = <&rcar_dw_hdmi0_in>; ++ }; ++ }; ++ port@2 { ++ endpoint { ++ remote-endpoint = <&rcar_dw_hdmi1_in>; ++ }; ++ }; ++ }; ++}; ++ ++&hdmi1 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ port@0 { ++ reg = <0>; ++ rcar_dw_hdmi1_in: endpoint { ++ remote-endpoint = <&du_out_hdmi1>; ++ }; ++ }; ++ port@1 { ++ reg = <1>; ++ rcar_dw_hdmi1_out: endpoint { ++ remote-endpoint = <&hdmi1_con>; ++ }; ++ }; ++ }; ++}; ++ ++&pfc { ++ scif1_pins: scif1 { ++ groups = "scif1_data_a"; ++ function = "scif1"; ++ }; ++ ++ msiof0_pins: spi1 { ++ groups = "msiof0_clk", "msiof0_rxd", "msiof0_txd", ++ "msiof0_ss1"; ++ function = "msiof0"; ++ }; ++ ++ msiof1_pins: spi2 { ++ groups = "msiof1_clk_a", "msiof1_rxd_a", "msiof1_txd_a", ++ "msiof1_ss1_a"; ++ function = "msiof1"; ++ }; ++ ++ sound_clk_pins: sound-clk { ++ groups = "audio_clk_a_a", "audio_clk_b_a", "audio_clk_c_a", ++ "audio_clkout_a" /*, "audio_clkout3_a"*/; ++ function = "audio_clk"; ++ }; ++ ++ usb31_pins: usb31 { ++ groups = "usb31"; ++ function = "usb31"; ++ }; ++ ++ can0_pins: can0 { ++ groups = "can0_data_a"; ++ function = "can0"; ++ }; ++ ++ canfd0_pins: canfd0 { ++ groups = "canfd0_data_a"; ++ function = "canfd0"; ++ }; ++}; ++ ++&scif1 { ++ pinctrl-0 = <&scif1_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++}; ++ ++&avb { ++ /delete-property/phy-handle; ++ /delete-property/phy-gpios; ++ /delete-node/ethernet-phy@0; ++ ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ }; ++}; ++ ++&msiof0 { ++ pinctrl-0 = <&msiof0_pins>; ++ pinctrl-names = "default"; ++ status = "disabled"; ++ cs-gpios = <&gpio5 19 0>; ++ ++ spidev@0 { ++ compatible = "renesas,sh-msiof"; ++ reg = <0>; ++ spi-max-frequency = <66666666>; ++ spi-cpha; ++ spi-cpol; ++ }; ++}; ++ ++&msiof1 { ++ status = "disabled"; ++ cs-gpios = <&gpio6 5 0>; ++}; ++ ++&can0 { ++ pinctrl-0 = <&can0_pins>; ++ pinctrl-names = "default"; ++ status = "disabled"; ++ ++ renesas,can-clock-select = <0x0>; ++ gpios = <&gpio2 6 GPIO_ACTIVE_HIGH /* enable - shared with camera board */ ++ &gpio2 7 GPIO_ACTIVE_LOW /* standby */ ++ >; ++}; ++ ++&canfd { ++ pinctrl-0 = <&canfd0_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ renesas,can-clock-select = <0x0>; ++ gpios = <&gpio2 6 GPIO_ACTIVE_HIGH /* enable - shared with camera board */ ++ &gpio2 7 GPIO_ACTIVE_LOW /* standby */ ++ >; ++ ++ channel0 { ++ status = "okay"; ++ }; ++}; +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0041-arm64-dts-r8a7795-h3ulcb-kf-add-ADAS-board.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0041-arm64-dts-r8a7795-h3ulcb-kf-add-ADAS-board.patch new file mode 100644 index 0000000..6898c49 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0041-arm64-dts-r8a7795-h3ulcb-kf-add-ADAS-board.patch @@ -0,0 +1,1714 @@ +From f1f043eab3dd06552b3600af1caf50e535f766f1 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Wed, 4 Jan 2017 10:37:23 +0300 +Subject: [PATCH] arm64: dts: r8a7795-h3ulcb-kf: add ADAS board + +H3ULCB.View board on R8A7795 SoC + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + arch/arm64/boot/dts/renesas/Makefile | 1 + + .../boot/dts/renesas/r8a7795-h3ulcb-kf.dts | 1683 ++++++++++++++++++++ + 2 files changed, 1684 insertions(+) + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts + +diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile +index 06207e3..a5dd1d3 100644 +--- a/arch/arm64/boot/dts/renesas/Makefile ++++ b/arch/arm64/boot/dts/renesas/Makefile +@@ -10,6 +10,7 @@ dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-h3ulcb-view.dtb + dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-salvator-x-view.dtb + dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-view.dtb + dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-had-alfa.dtb r8a7795-h3ulcb-had-beta.dtb ++dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-kf.dtb + + always := $(dtb-y) + clean-files := *.dtb +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts +new file mode 100644 +index 0000000..50a37e0 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts +@@ -0,0 +1,1679 @@ ++/* ++ * Device Tree Source for the H3ULCB Kingfisher board on r8a7795 ++ * ++ * Copyright (C) 2017 Renesas Electronics Corp. ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7795-h3ulcb.dts" ++ ++/ { ++ model = "Renesas H3ULCB Kingfisher board based on r8a7795"; ++ ++ aliases { ++ serial1 = &hscif4; ++ }; ++ ++ snd_clk: snd_clk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <24576000>; ++ clock-output-names = "scki"; ++ }; ++ ++ wlan_en: regulator@4 { ++ compatible = "regulator-fixed"; ++ regulator-name = "wlan-en-regulator"; ++ ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ gpio = <&gpio_ext_20 4 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ vccq_sdhi3: regulator@5 { ++ compatible = "regulator-fixed"; ++ ++ regulator-name = "SDHI3 VccQ"; ++ /* external voltage translator to 1.8V */ ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ }; ++ ++ codec_en_reg: regulator@6 { ++ compatible = "regulator-fixed"; ++ regulator-name = "codec-en-regulator"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ gpio = <&gpio_ext_20 15 0>; ++ ++ /* delay - CHECK */ ++ startup-delay-us = <70000>; ++ enable-active-high; ++ }; ++ ++ amp_en_reg: regulator@7 { ++ compatible = "regulator-fixed"; ++ regulator-name = "amp-en-regulator"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ gpio = <&gpio_ext_20 0 0>; ++ ++ startup-delay-us = <0>; ++ enable-active-high; ++ }; ++ ++ lvds_switch: regulator@8 { ++ compatible = "regulator-fixed"; ++ regulator-name = "lvds_on"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&gpio1 24 0>; ++ enable-active-high; ++ regulator-always-on; ++ }; ++ ++ sdio_switch: regulator@9 { ++ compatible = "regulator-fixed"; ++ regulator-name = "wifi_on"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&gpio_ext_20 5 0>; ++ enable-active-low; ++ regulator-always-on; ++ }; ++ ++ sound_switch: regulator@10 { ++ compatible = "regulator-fixed"; ++ regulator-name = "pcm3168a_on"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&gpio_ext_21 5 0>; ++ enable-active-low; ++ regulator-always-on; ++ }; ++ ++ radio_switch: regulator@11 { ++ compatible = "regulator-fixed"; ++ regulator-name = "radio_on"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&gpio_ext_20 13 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ regulator-always-on; ++ }; ++ ++ kim { ++ compatible = "kim"; ++ nshutdown_gpio = <343>; /* pca9535@i2c2.0x20 pin 3 */ ++ /* serial1 */ ++ dev_name = "/dev/ttySC1"; ++ flow_cntrl = <1>; ++ /* int div 8 hscif@26.6666656MHz */ ++ baud_rate = <3333332>; ++ }; ++ ++ btwilink { ++ compatible = "btwilink"; ++ }; ++ ++ sound_ext: sound@0 { ++ pinctrl-0 = <&sound_0_pins>; ++ pinctrl-names = "default"; ++ compatible = "simple-audio-card"; ++ ++ simple-audio-card,format = "left_j"; ++ simple-audio-card,name = "pcm3168a"; ++ ++ simple-audio-card,bitclock-master = <&sound_ext_master>; ++ simple-audio-card,frame-master = <&sound_ext_master>; ++ sound_ext_master: simple-audio-card,cpu@0 { ++ sound-dai = <&rcar_sound 0>; ++ dai-tdm-slot-num = <8>; ++ dai-tdm-slot-width = <32>; ++ }; ++ ++ simple-audio-card,codec@0 { ++ sound-dai = <&pcm3168a>; ++ dai-tdm-slot-num = <8>; ++ dai-tdm-slot-width = <32>; ++ system-clock-frequency = <24576000>; ++ }; ++ }; ++ ++ /delete-node/sound; ++ ++ rsnd_ak4613: sound@1 { ++ pinctrl-0 = <&sound_1_pins>; ++ pinctrl-names = "default"; ++ compatible = "simple-audio-card"; ++ ++ simple-audio-card,format = "left_j"; ++ simple-audio-card,name = "ak4613"; ++ ++ simple-audio-card,bitclock-master = <&sndcpu>; ++ simple-audio-card,frame-master = <&sndcpu>; ++ ++ sndcpu: simple-audio-card,cpu@1 { ++ sound-dai = <&rcar_sound 1>; ++ }; ++ ++ sndcodec: simple-audio-card,codec@1 { ++ sound-dai = <&ak4613>; ++ }; ++ }; ++ ++ sound_radio: sound@2 { ++ pinctrl-0 = <&sound_2_pins>; ++ pinctrl-names = "default"; ++ compatible = "simple-audio-card"; ++ ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,name = "radio"; ++ ++ simple-audio-card,bitclock-master = <&sound_radio_master>; ++ simple-audio-card,frame-master = <&sound_radio_master>; ++ simple-audio-card,cpu@2 { ++ sound-dai = <&rcar_sound 2>; ++ }; ++ ++ sound_radio_master: simple-audio-card,codec@2 { ++ sound-dai = <&radio>; ++ system-clock-frequency = <12288000>; ++ }; ++ }; ++ ++ sound_amp: sound@3 { ++ pinctrl-0 = <&sound_9_pins>; ++ pinctrl-names = "default"; ++ compatible = "simple-audio-card"; ++ ++ simple-audio-card,name = "power_amp"; ++ ++ simple-audio-card,dai-link@0 { ++ format = "i2s"; ++ cpu { ++ sound-dai = <&rcar_sound 3>; ++ }; ++ codec { ++ sound-dai = <&max98371_L>; ++ }; ++ }; ++ simple-audio-card,dai-link@1 { ++ format = "i2s"; ++ cpu { ++ sound-dai = <&rcar_sound 3>; ++ }; ++ codec { ++ sound-dai = <&max98371_R>; ++ }; ++ }; ++ simple-audio-card,dai-link@2 { ++ format = "i2s"; ++ cpu { ++ sound-dai = <&rcar_sound 3>; ++ }; ++ codec { ++ sound-dai = <&max98371_RL>; ++ }; ++ }; ++ simple-audio-card,dai-link@3 { ++ format = "i2s"; ++ cpu { ++ sound-dai = <&rcar_sound 3>; ++ }; ++ codec { ++ sound-dai = <&max98371_RR>; ++ }; ++ }; ++ simple-audio-card,dai-link@4 { ++ format = "i2s"; ++ cpu { ++ sound-dai = <&rcar_sound 3>; ++ }; ++ codec { ++ sound-dai = <&max98371_C>; ++ }; ++ }; ++ simple-audio-card,dai-link@5 { ++ format = "i2s"; ++ cpu { ++ sound-dai = <&rcar_sound 3>; ++ }; ++ codec { ++ sound-dai = <&max98371_S>; ++ }; ++ }; ++ }; ++ ++ lvds-encoder { ++ compatible = "thine,thc63lvdm83d"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ port@0 { ++ reg = <0>; ++ lvds_enc_in: endpoint { ++ remote-endpoint = <&du_out_lvds0>; ++ }; ++ }; ++ port@1 { ++ reg = <1>; ++ lvds_enc_out: endpoint { ++ remote-endpoint = <&lvds_in>; ++ }; ++ }; ++ }; ++ }; ++ ++ lvds { ++ compatible = "lvds-connector"; ++ ++ width-mm = <210>; ++ height-mm = <158>; ++ ++ panel-timing { ++ /* 1280x800 @60Hz */ ++ clock-frequency = <65000000>; ++ hactive = <1280>; ++ vactive = <800>; ++ hsync-len = <40>; ++ hfront-porch = <80>; ++ hback-porch = <40>; ++ vfront-porch = <14>; ++ vback-porch = <14>; ++ vsync-len = <4>; ++ }; ++ ++ port { ++ lvds_in: endpoint { ++ remote-endpoint = <&lvds_enc_out>; ++ }; ++ }; ++ }; ++ ++ radio: si468x@0 { ++ compatible = "si,si468x-pcm"; ++ status = "okay"; ++ ++ #sound-dai-cells = <0>; ++ }; ++}; ++ ++&pfc { ++ hscif4_pins: hscif4 { ++ groups = "hscif4_data_a", "hscif4_ctrl"; ++ function = "hscif4"; ++ }; ++ ++ sdhi3_pins_3v3: sd3_3v3 { ++ groups = "sdhi3_data4", "sdhi3_ctrl"; ++ function = "sdhi3"; ++ power-source = <3300>; ++ }; ++ ++ sound_0_pins: sound0 { ++ groups = "ssi78_ctrl", "ssi7_data", "ssi8_data"; ++ function = "ssi"; ++ }; ++ ++ sound_1_pins: sound1 { ++ groups = "ssi01239_ctrl", "ssi0_data", "ssi1_data_a"; ++ function = "ssi"; ++ }; ++ ++ sound_2_pins: sound2 { ++ groups = "ssi6_ctrl", "ssi6_data"; ++ function = "ssi"; ++ }; ++ ++ sound_9_pins: sound2 { ++ groups = "ssi9_ctrl_b", "ssi9_data_b"; ++ function = "ssi"; ++ }; ++ ++ usb0_pins: usb0 { ++ groups = "usb0"; ++ function = "usb0"; ++ }; ++}; ++ ++&gpio0 { ++ video_a_irq { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-A irq"; ++ }; ++ ++ video_b_irq { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "Video-B irq"; ++ }; ++ ++ gpioext_2_20_irq { ++ gpio-hog; ++ gpios = <15 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "0x20@i2c2 irq"; ++ }; ++}; ++ ++&gpio1 { ++ gpioext_2_21_irq { ++ gpio-hog; ++ gpios = <15 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "0x21@i2c2 irq"; ++ }; ++ ++ wifi_irq { ++ gpio-hog; ++ gpios = <25 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "wifi irq"; ++ }; ++}; ++ ++&gpio5 { ++ touch_irq { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "touch irq"; ++ }; ++ ++ /* From TI forum */ ++ /* BT_AUD_OUT should be pulled low when WL_EN is activated. */ ++ /* in case it isn't, wilink8 ends up in one of the test modes that introduces various issues */ ++ bt_strap { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "BT strap pin"; ++ }; ++}; ++ ++&gpio7 { ++ gpioext_2_21_irq { ++ gpio-hog; ++ gpios = <3 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "0x21@i2c4 irq"; ++ }; ++}; ++ ++&hscif4 { ++ pinctrl-0 = <&hscif4_pins>; ++ pinctrl-names = "default"; ++ ctsrts; ++ ++ status = "okay"; ++}; ++ ++&i2c2 { ++ clock-frequency = <400000>; ++ ++ gpio_ext_20: pca9535@20 { ++ compatible = "nxp,pca9535"; ++ reg = <0x20>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ interrupt-parent = <&gpio0>; ++ interrupts = <15 IRQ_TYPE_EDGE_FALLING>; ++ }; ++ ++ gpio_ext_21: pca9535@21 { ++ compatible = "nxp,pca9535"; ++ reg = <0x21>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ interrupt-parent = <&gpio1>; ++ interrupts = <15 IRQ_TYPE_EDGE_FALLING>; ++ }; ++ ++ i2cswitch2@74 { ++ compatible = "nxp,pca9548"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x74>; ++ reset-gpios = <&gpio6 5 GPIO_ACTIVE_LOW>; ++ ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ /* BCM node(s) */ ++ }; ++ ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ /* USB3.0 HUB node(s) */ ++ }; ++ ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ /* Power amp node(s) */ ++ ++ max98371_L: max98371@0x31 { ++ compatible = "maxim,max98371"; ++ reg = <0x31>; ++ #sound-dai-cells = <0>; ++ }; ++ max98371_R: max98371@0x32 { ++ compatible = "maxim,max98371"; ++ reg = <0x32>; ++ #sound-dai-cells = <0>; ++ }; ++ max98371_RL: max98371@0x33 { ++ compatible = "maxim,max98371"; ++ reg = <0x33>; ++ #sound-dai-cells = <0>; ++ }; ++ max98371_RR: max98371@0x34 { ++ compatible = "maxim,max98371"; ++ reg = <0x34>; ++ #sound-dai-cells = <0>; ++ }; ++ max98371_C: max98371@0x35 { ++ compatible = "maxim,max98371"; ++ reg = <0x35>; ++ #sound-dai-cells = <0>; ++ }; ++ max98371_S: max98371@0x36 { ++ compatible = "maxim,max98371"; ++ reg = <0x36>; ++ #sound-dai-cells = <0>; ++ }; ++ }; ++ ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ /* Radio node(s) */ ++ }; ++ ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ /* A2B node(s) */ ++ }; ++ ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ /* PCIe node(s) */ ++ }; ++ ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ /* LVDS display node(s) */ ++ ++ polytouch: edt-ft5x06@38 { ++ compatible = "edt,edt-ft5x06"; ++ reg = <0x38>; ++ interrupt-parent = <&gpio5>; ++ interrupts = <6 IRQ_TYPE_EDGE_FALLING>; ++ }; ++ }; ++ ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ /* Audio, GPS and Gyro node(s) */ ++ ++ pcm3168a: audio-codec@44 { ++ #sound-dai-cells = <0>; ++ compatible = "ti,pcm3168a"; ++ reg = <0x44>; ++ clocks = <&snd_clk>; ++ clock-names = "scki"; ++ tdm; ++ VDD1-supply = <&codec_en_reg>; ++ VDD2-supply = <&codec_en_reg>; ++ VCCAD1-supply = <&codec_en_reg>; ++ VCCAD2-supply = <&codec_en_reg>; ++ VCCDA1-supply = <&_en_reg>; ++ VCCDA2-supply = <&_en_reg>; ++ }; ++ ++ lsm9ds0_acc_mag@1d { ++ compatible = "st,lsm9ds0_acc_mag"; ++ reg = <0x1d>; ++ }; ++ ++ lsm9ds0_gyr@6b { ++ compatible = "st,lsm9ds0-gyro"; ++ reg = <0x6b>; ++ }; ++ ++ /* GPS@ 0x42 */ ++ }; ++ }; ++}; ++ ++&i2c4 { ++ gpio_ext_22: pca9535@21 { ++ compatible = "nxp,pca9535"; ++ reg = <0x22>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ interrupt-parent = <&gpio7>; ++ interrupts = <3 IRQ_TYPE_EDGE_FALLING>; ++ }; ++ ++ i2cswitch4@74 { ++ compatible = "nxp,pca9548"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x74>; ++ reset-gpios= <&gpio6 21 GPIO_ACTIVE_LOW>; ++ ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ /* SAM node(s) */ ++ }; ++ ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ /* Video input "A" acc node(s) */ ++ ++ ov106xx@0 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x60>; ++ ++ port@0 { ++ ov106xx_in0: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin0ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ ov106xx_ti964_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti964_des0ep0>; ++ }; ++ ov106xx_ti954_des0ep0: endpoint@2 { ++ remote-endpoint = <&ti954_des0ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@1 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x61>; ++ ++ port@0 { ++ ov106xx_in1: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin1ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ ov106xx_ti964_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti964_des0ep1>; ++ }; ++ ov106xx_ti954_des0ep1: endpoint@2 { ++ remote-endpoint = <&ti954_des0ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@2 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x62>; ++ ++ port@0 { ++ ov106xx_in2: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin2ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ ov106xx_ti964_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti964_des0ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@3 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x63>; ++ ++ port@0 { ++ ov106xx_in3: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin3ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ ov106xx_ti964_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti964_des0ep3>; ++ }; ++ }; ++ }; ++ ++ /* DS90UB964 @ 0x3a */ ++ ti964-ti9x3@0 { ++ compatible = "ti,ti964-ti9x3"; ++ reg = <0x3a>; ++ ti,sensor_delay = <350>; ++ ti,links = <4>; ++ ti,lanes = <4>; ++ ti,forwarding-mode = "round-robin"; ++ ti,cable-mode = "coax"; ++ ++ port@0 { ++ ti964_des0ep0: endpoint@0 { ++ ti9x3-addr = <0x0c>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ ti964_des0ep1: endpoint@1 { ++ ti9x3-addr = <0x0d>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ ti964_des0ep2: endpoint@2 { ++ ti9x3-addr = <0x0e>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ ti964_des0ep3: endpoint@3 { ++ ti9x3-addr = <0x0f>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ ti964_csi0ep0: endpoint { ++ csi-rate = <1450>; ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ }; ++ ++ /* DS90UB954 @ 0x38 */ ++ ti954-ti9x3@0 { ++ compatible = "ti,ti954-ti9x3"; ++ reg = <0x38>; ++ gpios = <&video_a_ext1 10 GPIO_ACTIVE_HIGH>; ++ ti,sensor_delay = <350>; ++ ti,links = <2>; ++ ti,lanes = <4>; ++ ti,forwarding-mode = "round-robin"; ++ ti,cable-mode = "coax"; ++ ++ port@0 { ++ ti954_des0ep0: endpoint@0 { ++ ti9x3-addr = <0x0c>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ ti954_des0ep1: endpoint@1 { ++ ti9x3-addr = <0x0d>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ }; ++ port@1 { ++ ti954_csi0ep0: endpoint { ++ csi-rate = <1450>; ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ }; ++ ++ /* MAX9286 @ 0x2a */ ++ max9286-max9271@0 { ++ compatible = "maxim,max9286-max9271"; ++ reg = <0x2a>; ++ maxim,sensor_delay = <350>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ ++ port@0 { ++ max9286_des0ep0: endpoint@0 { ++ max9271-addr = <0x50>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ max9286_des0ep1: endpoint@1 { ++ max9271-addr = <0x51>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ max9286_des0ep2: endpoint@2 { ++ max9271-addr = <0x52>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ max9286_des0ep3: endpoint@3 { ++ max9271-addr = <0x53>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ max9286_csi0ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ }; ++ }; ++ ++ i2c@2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <2>; ++ /* Video input "B" acc node(s) */ ++ ++ ov106xx@4 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x64>; ++ ++ port@0 { ++ ov106xx_in4: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin4ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep0>; ++ }; ++ ov106xx_ti964_des1ep0: endpoint@1 { ++ remote-endpoint = <&ti964_des1ep0>; ++ }; ++ ov106xx_ti954_des1ep0: endpoint@2 { ++ remote-endpoint = <&ti954_des1ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@5 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x65>; ++ ++ port@0 { ++ ov106xx_in5: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin5ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep1>; ++ }; ++ ov106xx_ti964_des1ep1: endpoint@1 { ++ remote-endpoint = <&ti964_des1ep1>; ++ }; ++ ov106xx_ti954_des1ep1: endpoint@2 { ++ remote-endpoint = <&ti954_des1ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@6 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x66>; ++ ++ port@0 { ++ ov106xx_in6: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin6ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep2>; ++ }; ++ ov106xx_ti964_des1ep2: endpoint@1 { ++ remote-endpoint = <&ti964_des1ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@7 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x67>; ++ ++ port@0 { ++ ov106xx_in7: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin7ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep3>; ++ }; ++ ov106xx_ti964_des1ep3: endpoint@1 { ++ remote-endpoint = <&ti964_des1ep3>; ++ }; ++ }; ++ }; ++ ++ /* DS90UB964 @ 0x3a */ ++ ti964-ti9x3@1 { ++ compatible = "ti,ti964-ti9x3"; ++ reg = <0x3a>; ++ ti,sensor_delay = <350>; ++ ti,links = <4>; ++ ti,lanes = <4>; ++ ti,forwarding-mode = "round-robin"; ++ ti,cable-mode = "coax"; ++ ++ port@0 { ++ ti964_des1ep0: endpoint@0 { ++ ti9x3-addr = <0x0c>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in4>; ++ }; ++ ti964_des1ep1: endpoint@1 { ++ ti9x3-addr = <0x0d>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in5>; ++ }; ++ ti964_des1ep2: endpoint@2 { ++ ti9x3-addr = <0x0e>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in6>; ++ }; ++ ti964_des1ep3: endpoint@3 { ++ ti9x3-addr = <0x0f>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in7>; ++ }; ++ }; ++ port@1 { ++ ti964_csi2ep0: endpoint { ++ csi-rate = <1450>; ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ }; ++ ++ /* DS90UB954 @ 0x38 */ ++ ti954-ti9x3@1 { ++ compatible = "ti,ti954-ti9x3"; ++ reg = <0x38>; ++ gpios = <&video_b_ext1 10 GPIO_ACTIVE_HIGH>; ++ ti,sensor_delay = <350>; ++ ti,links = <2>; ++ ti,lanes = <4>; ++ ti,forwarding-mode = "round-robin"; ++ ti,cable-mode = "coax"; ++ ++ port@0 { ++ ti954_des1ep0: endpoint@0 { ++ ti9x3-addr = <0x0c>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in4>; ++ }; ++ ti954_des1ep1: endpoint@1 { ++ ti9x3-addr = <0x0d>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in5>; ++ }; ++ }; ++ port@1 { ++ ti954_csi2ep0: endpoint { ++ csi-rate = <1450>; ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ }; ++ ++ /* MAX9286 @ 0x2a */ ++ max9286-max9271@1 { ++ compatible = "maxim,max9286-max9271"; ++ reg = <0x2a>; ++ maxim,sensor_delay = <350>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ ++ port@0 { ++ max9286_des1ep0: endpoint@0 { ++ max9271-addr = <0x50>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in4>; ++ }; ++ max9286_des1ep1: endpoint@1 { ++ max9271-addr = <0x51>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in5>; ++ }; ++ max9286_des1ep2: endpoint@2 { ++ max9271-addr = <0x52>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in6>; ++ }; ++ max9286_des1ep3: endpoint@3 { ++ max9271-addr = <0x53>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in7>; ++ }; ++ }; ++ port@1 { ++ max9286_csi2ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ }; ++ }; ++ ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ /* MOST node(s) */ ++ }; ++ ++ i2c@4 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <4>; ++ /* CSI camera node(s) */ ++ }; ++ ++ i2c@5 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <5>; ++ /* CMOS camera node(s) */ ++ }; ++ ++ i2c@6 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <6>; ++ /* Video input "B" main node(s) */ ++ ++ video_b_ext0: pca9535@27 { ++ compatible = "nxp,pca9535"; ++ reg = <0x27>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ video_b_des_cfg1 { ++ gpio-hog; ++ gpios = <5 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B cfg1"; ++ }; ++ video_b_des_cfg0 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B cfg0"; ++ }; ++ video_b_pwr_shdn { ++ gpio-hog; ++ gpios = <3 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR_SHDN"; ++ }; ++ video_b_cam_pwr0 { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR0"; ++ }; ++ video_b_cam_pwr1 { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR1"; ++ }; ++ video_b_cam_pwr2 { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR2"; ++ }; ++ video_b_cam_pwr3 { ++ gpio-hog; ++ gpios = <15 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR3"; ++ }; ++ video_b_des_shdn { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B DES_SHDN"; ++ }; ++ video_b_des_led { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-B led"; ++ }; ++ }; ++ ++ video_b_ext1: max7325@5c { ++ compatible = "maxim,max7325"; ++ reg = <0x5c>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ video_b_des_cfg2 { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-B cfg2"; ++ }; ++ video_b_des_cfg1 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-B cfg1"; ++ }; ++ video_b_des_cfg0 { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-B cfg0"; ++ }; ++ video_b_pwr_shdn { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR_SHDN"; ++ }; ++ video_b_cam_pwr0 { ++ gpio-hog; ++ gpios = <8 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR0"; ++ }; ++ video_b_cam_pwr1 { ++ gpio-hog; ++ gpios = <9 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-B PWR1"; ++ }; ++ }; ++ }; ++ ++ i2c@7 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <7>; ++ /* Video input "A" main node(s) */ ++ ++ video_a_ext0: pca9535@26 { ++ compatible = "nxp,pca9535"; ++ reg = <0x26>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ video_a_des_cfg1 { ++ gpio-hog; ++ gpios = <5 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A cfg1"; ++ }; ++ video_a_des_cfg0 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A cfg0"; ++ }; ++ video_a_pwr_shdn { ++ gpio-hog; ++ gpios = <3 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR_SHDN"; ++ }; ++ video_a_cam_pwr0 { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR0"; ++ }; ++ video_a_cam_pwr1 { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR1"; ++ }; ++ video_a_cam_pwr2 { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR2"; ++ }; ++ video_a_cam_pwr3 { ++ gpio-hog; ++ gpios = <15 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR3"; ++ }; ++ video_a_des_shdn { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A DES_SHDN"; ++ }; ++ video_a_des_led { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-A led"; ++ }; ++ }; ++ ++ video_a_ext1: max7325@5c { ++ compatible = "maxim,max7325"; ++ reg = <0x5c>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ video_a_des_cfg2 { ++ gpio-hog; ++ gpios = <4 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-A cfg2"; ++ }; ++ video_a_des_cfg1 { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-A cfg1"; ++ }; ++ video_a_des_cfg0 { ++ gpio-hog; ++ gpios = <7 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "Video-A cfg0"; ++ }; ++ video_a_pwr_shdn { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR_SHDN"; ++ }; ++ video_a_cam_pwr0 { ++ gpio-hog; ++ gpios = <8 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR0"; ++ }; ++ video_a_cam_pwr1 { ++ gpio-hog; ++ gpios = <9 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Video-A PWR1"; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&pcie_bus_clk { ++ clock-frequency = <100000000>; ++ status = "okay"; ++}; ++ ++&pciec0 { ++ status = "okay"; ++}; ++ ++&pciec1 { ++ status = "okay"; ++}; ++ ++&vin0 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin0ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ }; ++ port@1 { ++ csi0ep0: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin0_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ vin0_ti964_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti964_des0ep0>; ++ }; ++ vin0_ti954_des0ep0: endpoint@2 { ++ remote-endpoint = <&ti954_des0ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin1 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin1ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <1>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ }; ++ port@1 { ++ csi0ep1: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin1_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ vin1_ti964_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti964_des0ep1>; ++ }; ++ vin1_ti954_des0ep1: endpoint@2 { ++ remote-endpoint = <&ti954_des0ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin2 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin2ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <2>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ }; ++ port@1 { ++ csi0ep2: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin2_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ vin2_ti964_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti964_des0ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin3 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin3ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <3>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ csi0ep3: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin3_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ vin3_ti964_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti964_des0ep3>; ++ }; ++ }; ++ }; ++}; ++ ++&vin4 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin4ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <0>; ++ remote-endpoint = <&ov106xx_in4>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep0: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ vin4_max9286_des1ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep0>; ++ }; ++ vin4_ti964_des1ep0: endpoint@1 { ++ remote-endpoint = <&ti964_des1ep0>; ++ }; ++ vin4_ti954_des1ep0: endpoint@2 { ++ remote-endpoint = <&ti954_des1ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin5 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin5ep0: endpoint@0 { ++ csi,select = "csi41"; ++ virtual,channel = <1>; ++ remote-endpoint = <&ov106xx_in5>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep1: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ vin5_max9286_des1ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep1>; ++ }; ++ vin5_ti964_des1ep1: endpoint@1 { ++ remote-endpoint = <&ti964_des1ep1>; ++ }; ++ vin5_ti954_des1ep1: endpoint@2 { ++ remote-endpoint = <&ti954_des1ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin6 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin6ep0: endpoint@0 { ++ csi,select = "csi41"; ++ virtual,channel = <2>; ++ remote-endpoint = <&ov106xx_in6>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep2: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ vin6_max9286_des1ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep2>; ++ }; ++ vin6_ti964_des1ep2: endpoint@1 { ++ remote-endpoint = <&ti964_des1ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin7 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin7ep0: endpoint@0 { ++ csi,select = "csi41"; ++ virtual,channel = <3>; ++ remote-endpoint = <&ov106xx_in7>; ++ data-lanes = <1 2 3 4>; ++ }; ++ }; ++ port@1 { ++ csi2ep3: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ vin7_max9286_des1ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep3>; ++ }; ++ vin7_ti964_des1ep3: endpoint@1 { ++ remote-endpoint = <&ti964_des1ep3>; ++ }; ++ }; ++ }; ++}; ++ ++&csi2_40 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi2_40_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; ++ ++&csi2_41 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi2_41_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; ++ ++&rcar_sound { ++ pinctrl-0 = <&sound_clk_pins>; ++ ++ /* Multi DAI */ ++ #sound-dai-cells = <1>; ++ ++ rcar_sound,dai { ++ dai0 { ++ playback = <&ssi7>; ++ capture = <&ssi8>; ++ }; ++ ++ dai1 { ++ playback = <&ssi0 &src0 &dvc0>; ++ capture = <&ssi1 &src1 &dvc1>; ++ }; ++ ++ dai2 { ++ capture = <&ssi6>; ++ }; ++ ++ dai3 { ++ playback = <&ssi9>; ++ }; ++ }; ++}; ++ ++&sdhi3 { ++ pinctrl-0 = <&sdhi3_pins_3v3>; ++ pinctrl-names = "default"; ++ ++ vmmc-supply = <&wlan_en>; ++ vqmmc-supply = <&vccq_sdhi3>; ++ keep-power-in-suspend; ++ enable-sdio-wakeup; ++ bus-width = <4>; ++ no-1-8-v; ++ non-removable; ++ cap-power-off-card; ++ max-frequency = <26000000>; ++ status = "okay"; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ wlcore: wlcore@2 { ++ compatible = "ti,wl1837"; ++ reg = <2>; ++ interrupt-parent = <&gpio1>; ++ interrupts = <25 IRQ_TYPE_EDGE_RISING>; ++ }; ++}; ++ ++&xhci0 { ++ status = "okay"; ++}; ++ ++&usb2_phy0 { ++ pinctrl-0 = <&usb0_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&ehci0 { ++ status = "okay"; ++}; ++ ++&ohci0 { ++ status = "okay"; ++}; +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0044-arm64-renesas-TTA-R-Drive-board-support.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0044-arm64-renesas-TTA-R-Drive-board-support.patch new file mode 100644 index 0000000..6d669c2 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0044-arm64-renesas-TTA-R-Drive-board-support.patch @@ -0,0 +1,1314 @@ +From 408420d2ceedc1b8c92dd132fd2617bc001120b8 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Thu, 16 Feb 2017 05:42:47 +0300 +Subject: [PATCH] arm64: renesas: TTA-R-Drive board support + +Add support for TTA-R-Drive board + +Signed-off-by: Stefan Hepp <stefan.hepp@tttech-automotive.com> +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + arch/arm64/boot/dts/renesas/Makefile | 3 +- + .../boot/dts/renesas/r8a7795-ttardrive-alfa.dts | 225 +++++ + .../boot/dts/renesas/r8a7795-ttardrive-beta.dts | 129 +++ + arch/arm64/boot/dts/renesas/r8a7795-ttardrive.dtsi | 909 +++++++++++++++++++++ + 4 files changed, 1265 insertions(+), 1 deletion(-) + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-ttardrive-alfa.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-ttardrive-beta.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7795-ttardrive.dtsi + +diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile +index e42396e..fc4438b 100644 +--- a/arch/arm64/boot/dts/renesas/Makefile ++++ b/arch/arm64/boot/dts/renesas/Makefile +@@ -1,7 +1,8 @@ + dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-salvator-x.dtb r8a7795-h3ulcb.dtb \ + r8a7795-salvator-x-view.dtb r8a7795-h3ulcb-had.dtb \ + r8a7795-h3ulcb-view.dtb \ +- r8a7795-h3ulcb-kf.dtb ++ r8a7795-h3ulcb-kf.dtb \ ++ r8a7795-ttardrive-alfa.dtb r8a7795-ttardrive-beta.dtb + dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-es1-salvator-x.dtb + dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-x.dtb r8a7796-m3ulcb.dtb \ + r8a7796-salvator-x-view.dtb r8a7796-m3ulcb-view.dtb \ +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-ttardrive-alfa.dts b/arch/arm64/boot/dts/renesas/r8a7795-ttardrive-alfa.dts +new file mode 100644 +index 0000000..2a1ae85 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-ttardrive-alfa.dts +@@ -0,0 +1,224 @@ ++/* ++ * Base Device Tree Source for the TTA-R-Drive board Alfa CPU ++ * ++ * Copyright (C) 2016 TTTech Automotive GmbH ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++/dts-v1/; ++#include "r8a7795-ttardrive.dtsi" ++#include <dt-bindings/gpio/gpio.h> ++#include <dt-bindings/input/input.h> ++ ++/ { ++ model = "TTTech TTA-R-Drive board Alfa CPU based on r8a7795"; ++ ++ aliases { ++ /* Using GPIO SPI instead of MSIOF; remove to use HW MSIOF */ ++ /* On Alfa: ++ * MSIOF0 is interconnect master ++ * MSIOF1_C is Switch 1 master ++ * MSIOF2_B is FPDLink master ++ * MSIOF2_D is RH850 slave (not used) ++ * MSIOF3_A is Switch 2 master ++ */ ++ spi1 = &spi0_gpio; ++ spi2 = &spi1_gpio; ++ spi3 = &spi2_gpio; ++ spi4 = &spi3_gpio; ++ }; ++ ++ /* Software SPI driver */ ++ spi0_gpio: spi_gpio@0 { ++ compatible = "spi-gpio"; ++ num-chipselects = <1>; ++ gpio-sck = <&gpio5 17 0>; ++ gpio-mosi = <&gpio5 20 0>; ++ gpio-miso = <&gpio5 22 0>; ++ cs-gpios = <&gpio5 18 0>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ spidev@0 { ++ compatible = "spi-gpio"; ++ reg = <0>; ++ spi-max-frequency = <2000000>; ++ spi-cpha; ++ spi-cpol; ++ }; ++ }; ++ ++ spi1_gpio: spi_gpio@1 { ++ compatible = "spi-gpio"; ++ num-chipselects = <1>; ++ gpio-sck = <&gpio6 17 0>; ++ gpio-mosi = <&gpio6 20 0>; ++ gpio-miso = <&gpio6 19 0>; ++ cs-gpios = <&gpio6 18 0>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ spidev@0 { ++ compatible = "spi-gpio"; ++ reg = <0>; ++ spi-max-frequency = <2000000>; ++ spi-cpha; ++ spi-cpol; ++ }; ++ }; ++ ++ spi2_gpio: spi_gpio@2 { ++ compatible = "spi-gpio"; ++ num-chipselects = <1>; ++ gpio-sck = <&gpio0 4 0>; ++ gpio-mosi = <&gpio0 7 0>; ++ gpio-miso = <&gpio0 6 0>; ++ cs-gpios = <&gpio0 5 0>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ spidev@0 { ++ compatible = "spi-gpio"; ++ reg = <0>; ++ spi-max-frequency = <2000000>; ++ spi-cpha; ++ spi-cpol; ++ }; ++ }; ++ ++ spi3_gpio: spi_gpio@3 { ++ compatible = "spi-gpio"; ++ num-chipselects = <1>; ++ gpio-sck = <&gpio0 0 0>; ++ gpio-mosi = <&gpio0 3 0>; ++ gpio-miso = <&gpio0 2 0>; ++ cs-gpios = <&gpio0 1 0>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ spidev@0 { ++ compatible = "spi-gpio"; ++ reg = <0>; ++ spi-max-frequency = <2000000>; ++ spi-cpha; ++ spi-cpol; ++ }; ++ }; ++ ++}; ++ ++&pcie_bus_clk { ++ clock-frequency = <100000000>; ++}; ++ ++&pfc { ++ msiof0_pins: spi1 { ++ groups = "msiof0_clk", "msiof0_sync", ++ "msiof0_rxd", "msiof0_txd"; ++ function = "msiof0"; ++ }; ++ ++ msiof1_pins: spi2 { ++ groups = "msiof1_clk_c", "msiof1_sync_c", ++ "msiof1_rxd_c", "msiof1_txd_c"; ++ function = "msiof1"; ++ }; ++ ++ msiof2_pins: spi3 { ++ groups = "msiof2_clk_b", "msiof2_sync_b", ++ "msiof2_rxd_b", "msiof2_txd_b"; ++ function = "msiof2"; ++ }; ++ ++ msiof3_pins: spi4 { ++ groups = "msiof3_clk_a", "msiof3_sync_a", ++ "msiof3_rxd_a", "msiof3_txd_a"; ++ function = "msiof3"; ++ }; ++}; ++ ++&msiof0 { ++ pinctrl-0 = <&msiof0_pins>; ++ pinctrl-names = "default"; ++ status = "disabled"; ++ cs-gpios = <&gpio5 18 0>; ++ ++ spidev@0 { ++ compatible = "renesas,sh-msiof"; ++ reg = <0>; ++ spi-max-frequency = <66666666>; ++ spi-cpha; ++ spi-cpol; ++ }; ++}; ++ ++&msiof1 { ++ pinctrl-0 = <&msiof1_pins>; ++ pinctrl-names = "default"; ++ status = "disabled"; ++ cs-gpios = <&gpio6 18 0>; ++ ++ spidev@0 { ++ compatible = "renesas,sh-msiof"; ++ reg = <0>; ++ spi-max-frequency = <33333333>; ++ spi-cpha; ++ spi-cpol; ++ }; ++}; ++ ++&msiof2 { ++ pinctrl-0 = <&msiof2_pins>; ++ pinctrl-names = "default"; ++ status = "disabled"; ++ cs-gpios = <&gpio0 5 0>; ++ ++ spidev@0 { ++ compatible = "renesas,sh-msiof"; ++ reg = <0>; ++ spi-max-frequency = <66666666>; ++ spi-cpha; ++ spi-cpol; ++ }; ++}; ++ ++&msiof3 { ++ pinctrl-0 = <&msiof3_pins>; ++ pinctrl-names = "default"; ++ status = "disabled"; ++ cs-gpios = <&gpio0 1 0>; ++ ++ spidev@0 { ++ compatible = "renesas,sh-msiof"; ++ reg = <0>; ++ spi-max-frequency = <66666666>; ++ spi-cpha; ++ spi-cpol; ++ }; ++}; ++ ++ ++&i2c4 { ++ status = "okay"; ++ clock-frequency = <100000>; ++ ++ /* TODO support for 5P49V5901B device, is it compatible?? ++ clk_5p49v5901b: programmable_clk@6a { ++ compatible = "idt,5p49v5923a"; ++ reg = <0x6a>; ++ ++ programable_clk0: 5p49v5901b_clk1@6a { ++ #clock-cells = <0>; ++ clocks = <&dclkin_p0>; ++ }; ++ ++ programable_clk1: 5p49v5901b_clk2@6a { ++ #clock-cells = <0>; ++ clocks = <&dclkin_p3>; ++ }; ++ }; ++ */ ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-ttardrive-beta.dts b/arch/arm64/boot/dts/renesas/r8a7795-ttardrive-beta.dts +new file mode 100644 +index 0000000..234bb68 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-ttardrive-beta.dts +@@ -0,0 +1,128 @@ ++/* ++ * Base Device Tree Source for the TTA-R-Drive board Beta CPU ++ * ++ * Copyright (C) 2016 TTTech Automotive GmbH ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++/dts-v1/; ++#include "r8a7795-ttardrive.dtsi" ++#include <dt-bindings/gpio/gpio.h> ++#include <dt-bindings/input/input.h> ++ ++/ { ++ model = "TTTech TTA-R-Drive board Beta CPU based on r8a7795"; ++ ++ aliases { ++ /* Using GPIO SPI instead of MSIOF; remove to use HW MSIOF */ ++ /* On Beta: ++ * MSIOF0 is interconnect slave (not used) ++ * MSIOF1_C is RH850 slave (not used) ++ * MSIOF3_B is FPDLink master ++ */ ++ spi4 = &spi3_gpio; ++ }; ++ ++ /* Software SPI driver */ ++ spi3_gpio: spi_gpio@3 { ++ compatible = "spi-gpio"; ++ num-chipselects = <1>; ++ gpio-sck = <&gpio1 2 0>; ++ gpio-mosi = <&gpio1 1 0>; ++ gpio-miso = <&gpio1 3 0>; ++ cs-gpios = <&gpio1 0 0>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ spidev@0 { ++ compatible = "spi-gpio"; ++ reg = <0>; ++ spi-max-frequency = <2000000>; ++ spi-cpha; ++ spi-cpol; ++ }; ++ }; ++ ++}; ++ ++&pcie_bus_clk { ++ clock-frequency = <100000000>; ++}; ++ ++&pfc { ++ msiof3_pins: spi4 { ++ groups = "msiof3_clk_b", "msiof3_sync_b", ++ "msiof3_rxd_b", "msiof3_txd_b"; ++ function = "msiof3"; ++ }; ++ ++ can0_pins: can0 { ++ groups = "can0_data_b"; ++ function = "can0"; ++ }; ++ ++ can1_pins: can1 { ++ groups = "can1_data"; ++ function = "can1"; ++ }; ++ ++ canfd0_pins: canfd0 { ++ groups = "canfd0_data_b"; ++ function = "canfd0"; ++ }; ++ ++ canfd1_pins: canfd1 { ++ groups = "canfd1_data"; ++ function = "canfd1"; ++ }; ++}; ++ ++&msiof3 { ++ pinctrl-0 = <&msiof3_pins>; ++ pinctrl-names = "default"; ++ status = "disabled"; ++ cs-gpios = <&gpio1 0 0>; ++ ++ spidev@0 { ++ compatible = "renesas,sh-msiof"; ++ reg = <0>; ++ spi-max-frequency = <66666666>; ++ spi-cpha; ++ spi-cpol; ++ }; ++}; ++ ++&can0 { ++ pinctrl-0 = <&can0_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ renesas,can-clock-select = <0x0>; ++}; ++ ++&can1 { ++ pinctrl-0 = <&can1_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ renesas,can-clock-select = <0x0>; ++}; ++ ++ ++&canfd { ++ pinctrl-0 = <&canfd0_pins &canfd1_pins>; ++ pinctrl-names = "default"; ++ status = "disabled"; ++ ++ renesas,can-clock-select = <0x0>; ++ ++ channel0 { ++ status = "okay"; ++ }; ++ channel1 { ++ status = "okay"; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-ttardrive.dtsi b/arch/arm64/boot/dts/renesas/r8a7795-ttardrive.dtsi +new file mode 100644 +index 0000000..e74a2c1 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7795-ttardrive.dtsi +@@ -0,0 +1,908 @@ ++/* ++ * Base Device Tree Source for the TTA-R-Drive board ++ * ++ * Copyright (C) 2016 Renesas Electronics Corp. ++ * Copyright (C) 2016 Cogent Embedded, Inc. ++ * Copyright (C) 2016 TTTech Automotive GmbH ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7795.dtsi" ++#include <dt-bindings/gpio/gpio.h> ++#include <dt-bindings/input/input.h> ++ ++/ { ++ compatible = "tttech,ttardrive", "renesas,r8a7795"; ++ ++ aliases { ++ serial0 = &scif2; ++ serial1 = &scif1; ++ serial2 = &scif0; ++ serial3 = &hscif0; ++ ethernet0 = &avb; ++ }; ++ ++ chosen { ++ bootargs = "ignore_loglevel rw root=/dev/nfs ip=dhcp"; ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ memory@48000000 { ++ device_type = "memory"; ++ /* first 128MB is reserved for secure area. */ ++ reg = <0x0 0x48000000 0x0 0x78000000>; ++ }; ++ ++ memory@500000000 { ++ device_type = "memory"; ++ reg = <0x5 0x00000000 0x0 0x80000000>; ++ }; ++ ++ memory@600000000 { ++ device_type = "memory"; ++ reg = <0x6 0x00000000 0x0 0x80000000>; ++ }; ++ ++ memory@700000000 { ++ device_type = "memory"; ++ reg = <0x7 0x00000000 0x0 0x80000000>; ++ }; ++ ++ reserved-memory { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ /* device specific region for Lossy Decompression */ ++ lossy_decompress: linux,lossy_decompress { ++ no-map; ++ reg = <0x00000000 0x54000000 0x0 0x03000000>; ++ }; ++ ++ /* For Audio DSP */ ++ adsp_reserved: linux,adsp { ++ compatible = "shared-dma-pool"; ++ reusable; ++ reg = <0x00000000 0x57000000 0x0 0x01000000>; ++ }; ++ ++ /* global autoconfigured region for contiguous allocations */ ++ linux,cma { ++ compatible = "shared-dma-pool"; ++ reusable; ++ reg = <0x00000000 0x58000000 0x0 0x18000000>; ++ linux,cma-default; ++ }; ++ ++ /* device specific region for contiguous allocations */ ++ linux,multimedia { ++ compatible = "shared-dma-pool"; ++ reusable; ++ reg = <0x00000000 0x70000000 0x0 0x10000000>; ++ }; ++ }; ++ ++ mmngr { ++ compatible = "renesas,mmngr"; ++ memory-region = <&lossy_decompress>; ++ }; ++ ++ mmngrbuf { ++ compatible = "renesas,mmngrbuf"; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ pwr { ++ gpios = <&gpio6 4 GPIO_ACTIVE_HIGH>; ++ default-state = "on"; ++ }; ++ load { ++ gpios = <&gpio6 5 GPIO_ACTIVE_HIGH>; ++ default-state = "off"; ++ linux,default-trigger = "heartbeat"; ++ }; ++ ++ /* Workaround to avoid clearing the USB clock enable during boot. ++ * Should be moved to the clock driver */ ++ clken { ++ gpios = <&gpio6 7 GPIO_ACTIVE_LOW>; ++ default-state = "keep"; ++ }; ++ }; ++ ++ fixedregulator3v3: regulator@0 { ++ compatible = "regulator-fixed"; ++ regulator-name = "fixed-3.3V"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ fixedregulator1v8: regulator@1 { ++ compatible = "regulator-fixed"; ++ regulator-name = "fixed-1.8V"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ vspm_if { ++ compatible = "renesas,vspm_if"; ++ }; ++ ++ hdmi0-encoder { ++ compatible = "rockchip,rcar-dw-hdmi"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ port@0 { ++ reg = <0>; ++ rcar_dw_hdmi0_in: endpoint { ++ remote-endpoint = <&du_out_hdmi0>; ++ }; ++ }; ++ port@1 { ++ reg = <1>; ++ rcar_dw_hdmi0_out: endpoint { ++ remote-endpoint = <&hdmi0_con>; ++ }; ++ }; ++ }; ++ }; ++ ++ hdmi0-out { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi0_con: endpoint { ++ remote-endpoint = <&rcar_dw_hdmi0_out>; ++ }; ++ }; ++ }; ++ ++ hdmi1-encoder { ++ compatible = "rockchip,rcar-dw-hdmi"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ port@0 { ++ reg = <0>; ++ rcar_dw_hdmi1_in: endpoint { ++ remote-endpoint = <&du_out_hdmi1>; ++ }; ++ }; ++ port@1 { ++ reg = <1>; ++ rcar_dw_hdmi1_out: endpoint { ++ remote-endpoint = <&hdmi1_con>; ++ }; ++ }; ++ }; ++ }; ++ ++ hdmi1-out { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi1_con: endpoint { ++ remote-endpoint = <&rcar_dw_hdmi1_out>; ++ }; ++ }; ++ }; ++ ++ /* TODO check clcoks */ ++ programable_clk0: 5p49v5923a_clk0 { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <148500000>; ++ }; ++ ++ x21_clk: 5p49v5923a_clk2 { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <33000000>; ++ }; ++ ++ x22_clk: 5p49v5923a_clk3 { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <33000000>; ++ }; ++ ++ programable_clk1: 5p49v5923a_clk1 { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <108000000>; ++ }; ++ ++ /* Module clock for all MSIOFs baud rate generators, provided by CPG */ ++ msiof_ref_clk: msiof-ref-clock { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <66666666>; ++ }; ++}; ++ ++&du { ++ status = "okay"; ++ ++ ports { ++ port@1 { ++ endpoint { ++ remote-endpoint = <&rcar_dw_hdmi0_in>; ++ }; ++ }; ++ port@2 { ++ endpoint { ++ remote-endpoint = <&rcar_dw_hdmi1_in>; ++ }; ++ }; ++ }; ++}; ++ ++&extal_clk { ++ clock-frequency = <20000000>; ++}; ++ ++&extalr_clk { ++ clock-frequency = <32768>; ++}; ++ ++&pfc { ++ pwm1_pins: pwm1 { ++ groups = "pwm1_b"; ++ function = "pwm1"; ++ }; ++ ++ pwm2_pins: pwm2 { ++ groups = "pwm2_b"; ++ function = "pwm2"; ++ }; ++ ++ scif0_pins: scif0 { ++ groups = "scif0_data"; ++ function = "scif0"; ++ }; ++ scif1_pins: scif1 { ++ groups = "scif1_data_a"; ++ function = "scif1"; ++ }; ++ scif2_pins: scif2 { ++ groups = "scif2_data_a"; ++ function = "scif2"; ++ }; ++ ++ hscif0_pins: hscif0 { ++ groups = "hscif0_data"; ++ function = "hscif0"; ++ }; ++ ++ i2c1_pins: i2c1 { ++ groups = "i2c1_b"; ++ function = "i2c1"; ++ }; ++ ++ avb_pins: avb { ++ groups = "avb_mdc"; ++ function = "avb"; ++ }; ++ ++ mmc1_pins_3v3: mmc1_3v3 { ++ groups = "sdhi3_data8", "sdhi3_ctrl"; ++ function = "sdhi3"; ++ power-source = <3300>; ++ }; ++ ++ usb2_pins: usb2 { ++ groups = "usb2"; ++ function = "usb2"; ++ }; ++}; ++ ++/* PWMs */ ++&pwm1 { ++ pinctrl-0 = <&pwm1_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++}; ++ ++&pwm2 { ++ pinctrl-0 = <&pwm2_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++}; ++ ++/* UARTs */ ++ ++&scif0 { ++ pinctrl-0 = <&scif0_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&scif1 { ++ pinctrl-0 = <&scif1_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&scif2 { ++ pinctrl-0 = <&scif2_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&hscif0 { ++ pinctrl-0 = <&hscif0_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++/* eMMC */ ++&mmc1 { ++ pinctrl-0 = <&mmc1_pins_3v3>; ++ pinctrl-1 = <&mmc1_pins_3v3>; ++ pinctrl-names = "default", "state_uhs"; ++ ++ /delete-property/mmc-hs200-1_8v; ++ ++ vmmc-supply = <&fixedregulator3v3>; ++ vqmmc-supply = <&fixedregulator3v3>; ++ bus-width = <8>; ++ status = "okay"; ++}; ++ ++/* I2C busses */ ++&i2c0 { ++ status = "okay"; ++ clock-frequency = <400000>; ++ ++ ov106xx@0 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x60>; ++ ++ port@0 { ++ ov106xx_in0: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin0ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@1 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x61>; ++ ++ port@0 { ++ ov106xx_in1: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin1ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@2 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x62>; ++ ++ port@0 { ++ ov106xx_in2: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin2ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@3 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x63>; ++ ++ port@0 { ++ ov106xx_in3: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin3ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_des0ep3: endpoint { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ }; ++ }; ++ ++ max9286-max9271@0 { ++ compatible = "maxim,max9286-max9271"; ++ reg = <0x48>; ++ gpios = <&gpio3 7 GPIO_ACTIVE_HIGH>; ++ maxim,sensor_delay = <0>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ ++ port@0 { ++ max9286_des0ep0: endpoint@0 { ++ max9271-addr = <0x50>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ max9286_des0ep1: endpoint@1 { ++ max9271-addr = <0x51>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ max9286_des0ep2: endpoint@2 { ++ max9271-addr = <0x52>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ max9286_des0ep3: endpoint@3 { ++ max9271-addr = <0x53>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ max9286_csi0ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ }; ++}; ++ ++&i2c1 { ++ pinctrl-0 = <&i2c1_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++ clock-frequency = <100000>; ++ ++ /* TODO FPDLink support */ ++}; ++ ++&i2c3 { ++ status = "okay"; ++ clock-frequency = <400000>; ++ ++ ov106xx@4 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x64>; ++ ++ port@0 { ++ ov106xx_in4: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ remote-endpoint = <&vin4ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@5 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x65>; ++ ++ port@0 { ++ ov106xx_in5: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ remote-endpoint = <&vin5ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des1ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep1>; ++ }; ++ }; ++ }; ++ ++ max9286-max9271@1 { ++ compatible = "maxim,max9286-max9271"; ++ reg = <0x48>; ++ gpios = <&gpio4 4 GPIO_ACTIVE_HIGH>; ++ maxim,sensor_delay = <0>; ++ maxim,links = <2>; ++ maxim,lanes = <2>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ ++ port@0 { ++ max9286_des1ep0: endpoint@0 { ++ max9271-addr = <0x54>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in4>; ++ }; ++ max9286_des1ep1: endpoint@1 { ++ max9271-addr = <0x55>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in5>; ++ }; ++ }; ++ port@1 { ++ max9286_csi2ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi2_20_ep>; ++ }; ++ }; ++ }; ++}; ++ ++&i2c5 { ++ status = "okay"; ++ clock-frequency = <100000>; ++ ++ /* TODO support for 5P49V5901B device, is it compatible?? ++ clk_5p49v5923a: programmable_clk@6a { ++ compatible = "idt,5p49v5923a"; ++ reg = <0x6a>; ++ ++ programable_clk0: 5p49v5923a_clk1@6a { ++ #clock-cells = <0>; ++ clocks = <&dclkin_p0>; ++ }; ++ ++ programable_clk1: 5p49v5923a_clk2@6a { ++ #clock-cells = <0>; ++ clocks = <&dclkin_p3>; ++ }; ++ }; ++ */ ++}; ++ ++&i2c_dvfs { ++ status = "okay"; ++ ++ vdd_dvfs: regulator@30 { ++ compatible = "rohm,bd9571mwv"; ++ reg = <0x30>; ++ ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <1030000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++}; ++ ++/* Ethernet */ ++&avb { ++ pinctrl-0 = <&avb_pins>; ++ pinctrl-names = "default"; ++ renesas,no-ether-link; ++ status = "okay"; ++ ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ reg = <0>; ++ }; ++}; ++ ++/* USB */ ++&usb2_phy2 { ++ pinctrl-0 = <&usb2_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&ehci2 { ++ status = "okay"; ++}; ++ ++&ohci2 { ++ status = "okay"; ++}; ++ ++/* PCIe and SATA */ ++&pcie_bus_clk { ++ clock-frequency = <100000000>; ++ status = "okay"; ++}; ++ ++&pciec0 { ++ status = "disabled"; ++}; ++ ++&pciec1 { ++ status = "disabled"; ++}; ++ ++&sata { ++ status = "okay"; ++}; ++ ++/* Watchdog timer */ ++&wdt0 { ++ status = "okay"; ++}; ++ ++ ++/* Video Codec interfaces. */ ++&vin0 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin0ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ }; ++ port@1 { ++ csi0ep0: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin0_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin1 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin1ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <1>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ }; ++ port@1 { ++ csi0ep1: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin1_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin2 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin2ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <2>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ }; ++ port@1 { ++ csi0ep2: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin2_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin3 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin3ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <3>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ csi0ep3: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin3_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ }; ++ }; ++}; ++ ++&vin4 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin4ep0: endpoint { ++ csi,select = "csi20"; ++ virtual,channel = <0>; ++ remote-endpoint = <&ov106xx_in4>; ++ data-lanes = <1 2>; ++ }; ++ }; ++ port@1 { ++ csi1ep0: endpoint { ++ remote-endpoint = <&csi2_20_ep>; ++ }; ++ }; ++ port@2 { ++ vin4_max9286_des1ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin5 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin5ep0: endpoint@0 { ++ csi,select = "csi20"; ++ virtual,channel = <1>; ++ remote-endpoint = <&ov106xx_in5>; ++ data-lanes = <1 2>; ++ }; ++ }; ++ port@1 { ++ csi1ep1: endpoint { ++ remote-endpoint = <&csi2_20_ep>; ++ }; ++ }; ++ port@2 { ++ vin5_max9286_des1ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&csi2_40 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi2_40_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <700>; ++ }; ++ }; ++}; ++ ++&csi2_20 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi2_20_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ csi-rate = <350>; ++ }; ++ }; ++}; ++ ++&vspbc { ++ status = "okay"; ++}; ++ ++&vspbd { ++ status = "okay"; ++}; ++ ++&vspi0 { ++ status = "okay"; ++}; ++ ++&vspi1 { ++ status = "okay"; ++}; ++ ++&vspi2 { ++ status = "okay"; ++}; +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0050-arm64-dts-Gen3-view-boards-TYPE1-first-4-cameras.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0050-arm64-dts-Gen3-view-boards-TYPE1-first-4-cameras.patch new file mode 100644 index 0000000..d368b6a --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0050-arm64-dts-Gen3-view-boards-TYPE1-first-4-cameras.patch @@ -0,0 +1,302 @@ +From 67d29f4fe320f555366ea45f5439ac52641472ec Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Mon, 15 May 2017 19:16:23 +0300 +Subject: [PATCH] arm64: dts: Gen3 view boards: TYPE1 first 4 cameras + +This set 4 cameras to TYPE1 in DT + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts | 8 ++++---- + arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts | 8 ++++---- + arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts | 8 ++++---- + arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts | 8 ++++---- + arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts | 8 ++++---- + arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts | 8 ++++---- + arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts | 8 ++++---- + arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts | 8 ++++---- + arch/arm64/boot/dts/renesas/r8a7796-salvator-x-view.dts | 8 ++++---- + 9 files changed, 36 insertions(+), 36 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts +index 50a37e0..8da87dd 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts +@@ -780,22 +780,22 @@ + port@0 { + max9286_des0ep0: endpoint@0 { + max9271-addr = <0x50>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in0>; + }; + max9286_des0ep1: endpoint@1 { + max9271-addr = <0x51>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in1>; + }; + max9286_des0ep2: endpoint@2 { + max9271-addr = <0x52>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in2>; + }; + max9286_des0ep3: endpoint@3 { + max9271-addr = <0x53>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in3>; + }; + }; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts +index de56fa4..b36b9d8 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts +@@ -175,22 +175,22 @@ + port@0 { + max9286_des0ep0: endpoint@0 { + max9271-addr = <0x50>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in0>; + }; + max9286_des0ep1: endpoint@1 { + max9271-addr = <0x51>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in1>; + }; + max9286_des0ep2: endpoint@2 { + max9271-addr = <0x52>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in2>; + }; + max9286_des0ep3: endpoint@3 { + max9271-addr = <0x53>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in3>; + }; + }; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts +index 3f3d66a..c063899 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts +@@ -190,22 +190,22 @@ + port@0 { + max9286_des0ep0: endpoint@0 { + max9271-addr = <0x50>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in0>; + }; + max9286_des0ep1: endpoint@1 { + max9271-addr = <0x51>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in1>; + }; + max9286_des0ep2: endpoint@2 { + max9271-addr = <0x52>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in2>; + }; + max9286_des0ep3: endpoint@3 { + max9271-addr = <0x53>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in3>; + }; + }; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts +index 94c86f6..b26d8e2 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts +@@ -780,22 +780,22 @@ + port@0 { + max9286_des0ep0: endpoint@0 { + max9271-addr = <0x50>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in0>; + }; + max9286_des0ep1: endpoint@1 { + max9271-addr = <0x51>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in1>; + }; + max9286_des0ep2: endpoint@2 { + max9271-addr = <0x52>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in2>; + }; + max9286_des0ep3: endpoint@3 { + max9271-addr = <0x53>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in3>; + }; + }; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts +index 2c24b85..a8b9eea 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts +@@ -175,22 +175,22 @@ + port@0 { + max9286_des0ep0: endpoint@0 { + max9271-addr = <0x50>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in0>; + }; + max9286_des0ep1: endpoint@1 { + max9271-addr = <0x51>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in1>; + }; + max9286_des0ep2: endpoint@2 { + max9271-addr = <0x52>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in2>; + }; + max9286_des0ep3: endpoint@3 { + max9271-addr = <0x53>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in3>; + }; + }; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts +index fb12a39f3..eb09ef0 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts +@@ -190,22 +190,22 @@ + port@0 { + max9286_des0ep0: endpoint@0 { + max9271-addr = <0x50>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in0>; + }; + max9286_des0ep1: endpoint@1 { + max9271-addr = <0x51>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in1>; + }; + max9286_des0ep2: endpoint@2 { + max9271-addr = <0x52>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in2>; + }; + max9286_des0ep3: endpoint@3 { + max9271-addr = <0x53>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in3>; + }; + }; +diff --git a/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts +index ffaef74..83c6355 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts +@@ -780,22 +780,22 @@ + port@0 { + max9286_des0ep0: endpoint@0 { + max9271-addr = <0x50>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in0>; + }; + max9286_des0ep1: endpoint@1 { + max9271-addr = <0x51>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in1>; + }; + max9286_des0ep2: endpoint@2 { + max9271-addr = <0x52>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in2>; + }; + max9286_des0ep3: endpoint@3 { + max9271-addr = <0x53>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in3>; + }; + }; +diff --git a/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts +index 1ac0041..096fb5f 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts +@@ -103,22 +103,22 @@ + port@0 { + max9286_des0ep0: endpoint@0 { + max9271-addr = <0x50>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in0>; + }; + max9286_des0ep1: endpoint@1 { + max9271-addr = <0x51>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in1>; + }; + max9286_des0ep2: endpoint@2 { + max9271-addr = <0x52>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in2>; + }; + max9286_des0ep3: endpoint@3 { + max9271-addr = <0x53>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in3>; + }; + }; +diff --git a/arch/arm64/boot/dts/renesas/r8a7796-salvator-x-view.dts b/arch/arm64/boot/dts/renesas/r8a7796-salvator-x-view.dts +index cc6866c..7a592d1 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7796-salvator-x-view.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7796-salvator-x-view.dts +@@ -118,22 +118,22 @@ + port@0 { + max9286_des0ep0: endpoint@0 { + max9271-addr = <0x50>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in0>; + }; + max9286_des0ep1: endpoint@1 { + max9271-addr = <0x51>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in1>; + }; + max9286_des0ep2: endpoint@2 { + max9271-addr = <0x52>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in2>; + }; + max9286_des0ep3: endpoint@3 { + max9271-addr = <0x53>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in3>; + }; + }; +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-dts-Gen3-view-boards-TYPE1-second-4-cameras.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-dts-Gen3-view-boards-TYPE1-second-4-cameras.patch new file mode 100644 index 0000000..a09c485 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-dts-Gen3-view-boards-TYPE1-second-4-cameras.patch @@ -0,0 +1,206 @@ +From d9ec2149ffc47fd2ea4ab5e9a503a3be7c6f09f5 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Mon, 15 May 2017 19:18:06 +0300 +Subject: [PATCH] arm64: dts: Gen3 view boards: TYPE1 second 4 cameras + +This set 4 cameras to TYPE1 in DT + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts | 8 ++++---- + arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts | 8 ++++---- + arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts | 8 ++++---- + arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts | 8 ++++---- + arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts | 8 ++++---- + arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts | 8 ++++---- + 6 files changed, 24 insertions(+), 24 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts +index 8da87dd..d2e6f66 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts +@@ -989,22 +989,22 @@ + port@0 { + max9286_des1ep0: endpoint@0 { + max9271-addr = <0x50>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in4>; + }; + max9286_des1ep1: endpoint@1 { + max9271-addr = <0x51>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in5>; + }; + max9286_des1ep2: endpoint@2 { + max9271-addr = <0x52>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in6>; + }; + max9286_des1ep3: endpoint@3 { + max9271-addr = <0x53>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in7>; + }; + }; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts +index b36b9d8..e3a9414 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts +@@ -216,22 +216,22 @@ + port@0 { + max9286_des1ep0: endpoint@0 { + max9271-addr = <0x54>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in4>; + }; + max9286_des1ep1: endpoint@1 { + max9271-addr = <0x55>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in5>; + }; + max9286_des1ep2: endpoint@2 { + max9271-addr = <0x56>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in6>; + }; + max9286_des1ep3: endpoint@3 { + max9271-addr = <0x57>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in7>; + }; + }; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts +index c063899..2785fd7 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts +@@ -230,22 +230,22 @@ + port@0 { + max9286_des1ep0: endpoint@0 { + max9271-addr = <0x54>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in4>; + }; + max9286_des1ep1: endpoint@1 { + max9271-addr = <0x55>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in5>; + }; + max9286_des1ep2: endpoint@2 { + max9271-addr = <0x56>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in6>; + }; + max9286_des1ep3: endpoint@3 { + max9271-addr = <0x57>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in7>; + }; + }; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts +index b26d8e2..b8f8819 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts +@@ -989,22 +989,22 @@ + port@0 { + max9286_des1ep0: endpoint@0 { + max9271-addr = <0x50>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in4>; + }; + max9286_des1ep1: endpoint@1 { + max9271-addr = <0x51>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in5>; + }; + max9286_des1ep2: endpoint@2 { + max9271-addr = <0x52>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in6>; + }; + max9286_des1ep3: endpoint@3 { + max9271-addr = <0x53>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in7>; + }; + }; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts +index a8b9eea..86ed4a8 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts +@@ -216,22 +216,22 @@ + port@0 { + max9286_des1ep0: endpoint@0 { + max9271-addr = <0x54>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in4>; + }; + max9286_des1ep1: endpoint@1 { + max9271-addr = <0x55>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in5>; + }; + max9286_des1ep2: endpoint@2 { + max9271-addr = <0x56>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in6>; + }; + max9286_des1ep3: endpoint@3 { + max9271-addr = <0x57>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in7>; + }; + }; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts +index eb09ef0..37eabc0 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts +@@ -230,22 +230,22 @@ + port@0 { + max9286_des1ep0: endpoint@0 { + max9271-addr = <0x54>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in4>; + }; + max9286_des1ep1: endpoint@1 { + max9271-addr = <0x55>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in5>; + }; + max9286_des1ep2: endpoint@2 { + max9271-addr = <0x56>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in6>; + }; + max9286_des1ep3: endpoint@3 { + max9271-addr = <0x57>; +- dvp-order = <1>; ++ dvp-order = <2>; + remote-endpoint = <&ov106xx_in7>; + }; + }; +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0052-arm64-dts-Gen3-view-boards-TYPE2-first-4-cameras.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0052-arm64-dts-Gen3-view-boards-TYPE2-first-4-cameras.patch new file mode 100644 index 0000000..2c4d9f3 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0052-arm64-dts-Gen3-view-boards-TYPE2-first-4-cameras.patch @@ -0,0 +1,527 @@ +From fa7c75c71d40c8ce44b0fbaea79031daaede2ba7 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +Date: Mon, 15 May 2017 19:24:29 +0300 +Subject: [PATCH] arm64: dts: Gen3 view boards: TYPE2 first 4 cameras + +This set 4 cameras to TYPE2 in DT + +Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com> +--- + arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts | 17 +++++++++++++++-- + arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts | 17 +++++++++++++++-- + .../boot/dts/renesas/r8a7795-es1-salvator-x-view.dts | 17 +++++++++++++++-- + arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts | 17 +++++++++++++++-- + arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts | 17 +++++++++++++++-- + arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts | 17 +++++++++++++++-- + arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts | 17 +++++++++++++++-- + arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts | 17 +++++++++++++++-- + arch/arm64/boot/dts/renesas/r8a7796-salvator-x-view.dts | 17 +++++++++++++++-- + 9 files changed, 135 insertions(+), 18 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts +index 50a37e0..8808e80 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts +@@ -609,6 +609,9 @@ + compatible = "ovti,ov106xx"; + reg = <0x60>; + ++ maxim,fixed-sensor = "ov490"; ++ maxim,width = <1280>; ++ maxim,height = <966>; + port@0 { + ov106xx_in0: endpoint { + clock-lanes = <0>; +@@ -633,6 +636,9 @@ + compatible = "ovti,ov106xx"; + reg = <0x61>; + ++ maxim,fixed-sensor = "ov490"; ++ maxim,width = <1280>; ++ maxim,height = <966>; + port@0 { + ov106xx_in1: endpoint { + clock-lanes = <0>; +@@ -657,6 +663,9 @@ + compatible = "ovti,ov106xx"; + reg = <0x62>; + ++ maxim,fixed-sensor = "ov490"; ++ maxim,width = <1280>; ++ maxim,height = <966>; + port@0 { + ov106xx_in2: endpoint { + clock-lanes = <0>; +@@ -678,6 +687,9 @@ + compatible = "ovti,ov106xx"; + reg = <0x63>; + ++ maxim,fixed-sensor = "ov490"; ++ maxim,width = <1280>; ++ maxim,height = <966>; + port@0 { + ov106xx_in3: endpoint { + clock-lanes = <0>; +@@ -773,8 +785,9 @@ + maxim,sensor_delay = <350>; + maxim,links = <4>; + maxim,lanes = <4>; +- maxim,resetb-gpio = <1>; +- maxim,fsync-mode = "automatic"; ++ maxim,resetb-gpio = <4>; ++ maxim,resetb-active-high; ++ maxim,fsync-mode = "manual"; + maxim,timeout = <100>; + + port@0 { +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts +index de56fa4..007aa7a 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts +@@ -20,6 +20,9 @@ + compatible = "ovti,ov106xx"; + reg = <0x60>; + ++ maxim,fixed-sensor = "ov490"; ++ maxim,width = <1280>; ++ maxim,height = <966>; + port@0 { + ov106xx_in0: endpoint { + clock-lanes = <0>; +@@ -38,6 +41,9 @@ + compatible = "ovti,ov106xx"; + reg = <0x61>; + ++ maxim,fixed-sensor = "ov490"; ++ maxim,width = <1280>; ++ maxim,height = <966>; + port@0 { + ov106xx_in1: endpoint { + clock-lanes = <0>; +@@ -56,6 +62,9 @@ + compatible = "ovti,ov106xx"; + reg = <0x62>; + ++ maxim,fixed-sensor = "ov490"; ++ maxim,width = <1280>; ++ maxim,height = <966>; + port@0 { + ov106xx_in2: endpoint { + clock-lanes = <0>; +@@ -74,6 +83,9 @@ + compatible = "ovti,ov106xx"; + reg = <0x63>; + ++ maxim,fixed-sensor = "ov490"; ++ maxim,width = <1280>; ++ maxim,height = <966>; + port@0 { + ov106xx_in3: endpoint { + clock-lanes = <0>; +@@ -167,8 +179,9 @@ + maxim,sensor_delay = <0>; + maxim,links = <4>; + maxim,lanes = <4>; +- maxim,resetb-gpio = <1>; +- maxim,fsync-mode = "automatic"; ++ maxim,resetb-gpio = <4>; ++ maxim,resetb-active-high; ++ maxim,fsync-mode = "manual"; + maxim,timeout = <100>; + maxim,i2c-quirk = <0x6c>; + +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts +index 3f3d66a..4b3513a 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts +@@ -35,6 +35,9 @@ + compatible = "ovti,ov106xx"; + reg = <0x60>; + ++ maxim,fixed-sensor = "ov490"; ++ maxim,width = <1280>; ++ maxim,height = <966>; + port@0 { + ov106xx_in0: endpoint { + clock-lanes = <0>; +@@ -53,6 +56,9 @@ + compatible = "ovti,ov106xx"; + reg = <0x61>; + ++ maxim,fixed-sensor = "ov490"; ++ maxim,width = <1280>; ++ maxim,height = <966>; + port@0 { + ov106xx_in1: endpoint { + clock-lanes = <0>; +@@ -71,6 +77,9 @@ + compatible = "ovti,ov106xx"; + reg = <0x62>; + ++ maxim,fixed-sensor = "ov490"; ++ maxim,width = <1280>; ++ maxim,height = <966>; + port@0 { + ov106xx_in2: endpoint { + clock-lanes = <0>; +@@ -89,6 +98,9 @@ + compatible = "ovti,ov106xx"; + reg = <0x63>; + ++ maxim,fixed-sensor = "ov490"; ++ maxim,width = <1280>; ++ maxim,height = <966>; + port@0 { + ov106xx_in3: endpoint { + clock-lanes = <0>; +@@ -182,8 +194,9 @@ + maxim,sensor_delay = <0>; + maxim,links = <4>; + maxim,lanes = <4>; +- maxim,resetb-gpio = <1>; +- maxim,fsync-mode = "automatic"; ++ maxim,resetb-gpio = <4>; ++ maxim,resetb-active-high; ++ maxim,fsync-mode = "manual"; + maxim,timeout = <100>; + maxim,i2c-quirk = <0x6c>; + +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts +index 94c86f6..e650c5b 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts +@@ -609,6 +609,9 @@ + compatible = "ovti,ov106xx"; + reg = <0x60>; + ++ maxim,fixed-sensor = "ov490"; ++ maxim,width = <1280>; ++ maxim,height = <966>; + port@0 { + ov106xx_in0: endpoint { + clock-lanes = <0>; +@@ -633,6 +636,9 @@ + compatible = "ovti,ov106xx"; + reg = <0x61>; + ++ maxim,fixed-sensor = "ov490"; ++ maxim,width = <1280>; ++ maxim,height = <966>; + port@0 { + ov106xx_in1: endpoint { + clock-lanes = <0>; +@@ -657,6 +663,9 @@ + compatible = "ovti,ov106xx"; + reg = <0x62>; + ++ maxim,fixed-sensor = "ov490"; ++ maxim,width = <1280>; ++ maxim,height = <966>; + port@0 { + ov106xx_in2: endpoint { + clock-lanes = <0>; +@@ -678,6 +687,9 @@ + compatible = "ovti,ov106xx"; + reg = <0x63>; + ++ maxim,fixed-sensor = "ov490"; ++ maxim,width = <1280>; ++ maxim,height = <966>; + port@0 { + ov106xx_in3: endpoint { + clock-lanes = <0>; +@@ -773,8 +785,9 @@ + maxim,sensor_delay = <350>; + maxim,links = <4>; + maxim,lanes = <4>; +- maxim,resetb-gpio = <1>; +- maxim,fsync-mode = "automatic"; ++ maxim,resetb-gpio = <4>; ++ maxim,resetb-active-high; ++ maxim,fsync-mode = "manual"; + maxim,timeout = <100>; + + port@0 { +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts +index 2c24b85..ac0723d 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts +@@ -20,6 +20,9 @@ + compatible = "ovti,ov106xx"; + reg = <0x60>; + ++ maxim,fixed-sensor = "ov490"; ++ maxim,width = <1280>; ++ maxim,height = <966>; + port@0 { + ov106xx_in0: endpoint { + clock-lanes = <0>; +@@ -38,6 +41,9 @@ + compatible = "ovti,ov106xx"; + reg = <0x61>; + ++ maxim,fixed-sensor = "ov490"; ++ maxim,width = <1280>; ++ maxim,height = <966>; + port@0 { + ov106xx_in1: endpoint { + clock-lanes = <0>; +@@ -56,6 +62,9 @@ + compatible = "ovti,ov106xx"; + reg = <0x62>; + ++ maxim,fixed-sensor = "ov490"; ++ maxim,width = <1280>; ++ maxim,height = <966>; + port@0 { + ov106xx_in2: endpoint { + clock-lanes = <0>; +@@ -74,6 +83,9 @@ + compatible = "ovti,ov106xx"; + reg = <0x63>; + ++ maxim,fixed-sensor = "ov490"; ++ maxim,width = <1280>; ++ maxim,height = <966>; + port@0 { + ov106xx_in3: endpoint { + clock-lanes = <0>; +@@ -167,8 +179,9 @@ + maxim,sensor_delay = <0>; + maxim,links = <4>; + maxim,lanes = <4>; +- maxim,resetb-gpio = <1>; +- maxim,fsync-mode = "automatic"; ++ maxim,resetb-gpio = <4>; ++ maxim,resetb-active-high; ++ maxim,fsync-mode = "manual"; + maxim,timeout = <100>; + maxim,i2c-quirk = <0x6c>; + +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts +index fb12a39f3..ef0895e 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts +@@ -35,6 +35,9 @@ + compatible = "ovti,ov106xx"; + reg = <0x60>; + ++ maxim,fixed-sensor = "ov490"; ++ maxim,width = <1280>; ++ maxim,height = <966>; + port@0 { + ov106xx_in0: endpoint { + clock-lanes = <0>; +@@ -53,6 +56,9 @@ + compatible = "ovti,ov106xx"; + reg = <0x61>; + ++ maxim,fixed-sensor = "ov490"; ++ maxim,width = <1280>; ++ maxim,height = <966>; + port@0 { + ov106xx_in1: endpoint { + clock-lanes = <0>; +@@ -71,6 +77,9 @@ + compatible = "ovti,ov106xx"; + reg = <0x62>; + ++ maxim,fixed-sensor = "ov490"; ++ maxim,width = <1280>; ++ maxim,height = <966>; + port@0 { + ov106xx_in2: endpoint { + clock-lanes = <0>; +@@ -89,6 +98,9 @@ + compatible = "ovti,ov106xx"; + reg = <0x63>; + ++ maxim,fixed-sensor = "ov490"; ++ maxim,width = <1280>; ++ maxim,height = <966>; + port@0 { + ov106xx_in3: endpoint { + clock-lanes = <0>; +@@ -182,8 +194,9 @@ + maxim,sensor_delay = <0>; + maxim,links = <4>; + maxim,lanes = <4>; +- maxim,resetb-gpio = <1>; +- maxim,fsync-mode = "automatic"; ++ maxim,resetb-gpio = <4>; ++ maxim,resetb-active-high; ++ maxim,fsync-mode = "manual"; + maxim,timeout = <100>; + maxim,i2c-quirk = <0x6c>; + +diff --git a/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts +index ffaef74..5670f3a 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts +@@ -609,6 +609,9 @@ + compatible = "ovti,ov106xx"; + reg = <0x60>; + ++ maxim,fixed-sensor = "ov490"; ++ maxim,width = <1280>; ++ maxim,height = <966>; + port@0 { + ov106xx_in0: endpoint { + clock-lanes = <0>; +@@ -633,6 +636,9 @@ + compatible = "ovti,ov106xx"; + reg = <0x61>; + ++ maxim,fixed-sensor = "ov490"; ++ maxim,width = <1280>; ++ maxim,height = <966>; + port@0 { + ov106xx_in1: endpoint { + clock-lanes = <0>; +@@ -657,6 +663,9 @@ + compatible = "ovti,ov106xx"; + reg = <0x62>; + ++ maxim,fixed-sensor = "ov490"; ++ maxim,width = <1280>; ++ maxim,height = <966>; + port@0 { + ov106xx_in2: endpoint { + clock-lanes = <0>; +@@ -678,6 +687,9 @@ + compatible = "ovti,ov106xx"; + reg = <0x63>; + ++ maxim,fixed-sensor = "ov490"; ++ maxim,width = <1280>; ++ maxim,height = <966>; + port@0 { + ov106xx_in3: endpoint { + clock-lanes = <0>; +@@ -773,8 +785,9 @@ + maxim,sensor_delay = <350>; + maxim,links = <4>; + maxim,lanes = <4>; +- maxim,resetb-gpio = <1>; +- maxim,fsync-mode = "automatic"; ++ maxim,resetb-gpio = <4>; ++ maxim,resetb-active-high; ++ maxim,fsync-mode = "manual"; + maxim,timeout = <100>; + + port@0 { +diff --git a/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts +index 1ac0041..8a67c5f 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts +@@ -20,6 +20,9 @@ + compatible = "ovti,ov106xx"; + reg = <0x60>; + ++ maxim,fixed-sensor = "ov490"; ++ maxim,width = <1280>; ++ maxim,height = <966>; + port@0 { + ov106xx_in0: endpoint { + clock-lanes = <0>; +@@ -38,6 +41,9 @@ + compatible = "ovti,ov106xx"; + reg = <0x61>; + ++ maxim,fixed-sensor = "ov490"; ++ maxim,width = <1280>; ++ maxim,height = <966>; + port@0 { + ov106xx_in1: endpoint { + clock-lanes = <0>; +@@ -56,6 +62,9 @@ + compatible = "ovti,ov106xx"; + reg = <0x62>; + ++ maxim,fixed-sensor = "ov490"; ++ maxim,width = <1280>; ++ maxim,height = <966>; + port@0 { + ov106xx_in2: endpoint { + clock-lanes = <0>; +@@ -74,6 +83,9 @@ + compatible = "ovti,ov106xx"; + reg = <0x63>; + ++ maxim,fixed-sensor = "ov490"; ++ maxim,width = <1280>; ++ maxim,height = <966>; + port@0 { + ov106xx_in3: endpoint { + clock-lanes = <0>; +@@ -95,8 +107,9 @@ + maxim,sensor_delay = <0>; + maxim,links = <4>; + maxim,lanes = <4>; +- maxim,resetb-gpio = <1>; +- maxim,fsync-mode = "automatic"; ++ maxim,resetb-gpio = <4>; ++ maxim,resetb-active-high; ++ maxim,fsync-mode = "manual"; + maxim,timeout = <100>; + maxim,i2c-quirk = <0x6c>; + +diff --git a/arch/arm64/boot/dts/renesas/r8a7796-salvator-x-view.dts b/arch/arm64/boot/dts/renesas/r8a7796-salvator-x-view.dts +index cc6866c..ab6e28a 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7796-salvator-x-view.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7796-salvator-x-view.dts +@@ -35,6 +35,9 @@ + compatible = "ovti,ov106xx"; + reg = <0x60>; + ++ maxim,fixed-sensor = "ov490"; ++ maxim,width = <1280>; ++ maxim,height = <966>; + port@0 { + ov106xx_in0: endpoint { + clock-lanes = <0>; +@@ -53,6 +56,9 @@ + compatible = "ovti,ov106xx"; + reg = <0x61>; + ++ maxim,fixed-sensor = "ov490"; ++ maxim,width = <1280>; ++ maxim,height = <966>; + port@0 { + ov106xx_in1: endpoint { + clock-lanes = <0>; +@@ -71,6 +77,9 @@ + compatible = "ovti,ov106xx"; + reg = <0x62>; + ++ maxim,fixed-sensor = "ov490"; ++ maxim,width = <1280>; ++ maxim,height = <966>; + port@0 { + ov106xx_in2: endpoint { + clock-lanes = <0>; +@@ -89,6 +98,9 @@ + compatible = "ovti,ov106xx"; + reg = <0x63>; + ++ maxim,fixed-sensor = "ov490"; ++ maxim,width = <1280>; ++ maxim,height = <966>; + port@0 { + ov106xx_in3: endpoint { + clock-lanes = <0>; +@@ -110,8 +122,9 @@ + maxim,sensor_delay = <0>; + maxim,links = <4>; + maxim,lanes = <4>; +- maxim,resetb-gpio = <1>; +- maxim,fsync-mode = "automatic"; ++ maxim,resetb-gpio = <4>; ++ maxim,resetb-active-high; ++ maxim,fsync-mode = "manual"; + maxim,timeout = <100>; + maxim,i2c-quirk = <0x6c>; + +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/eagle.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/eagle.cfg new file mode 100644 index 0000000..2b6c4ea --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/eagle.cfg @@ -0,0 +1,26 @@ +CONFIG_ARCH_R8A7797=y +CONFIG_CAN=y +CONFIG_CAN_PEAK_USB=y +CONFIG_CAN_BCM=y +CONFIG_CAN_RAW=y +CONFIG_CAN_DEV=y +CONFIG_CAN_CALC_BITTIMING=y +CONFIG_CAN_RCAR=y +CONFIG_CANFD_RCAR=y +CONFIG_DRM_I2C_ADV7511=y +CONFIG_GPIO_PCA953X=y +CONFIG_GPIO_PCA953X_IRQ=y +CONFIG_VIDEO_ADV_DEBUG=y +CONFIG_VIDEO_RCAR_VIN_LEGACY=y +CONFIG_VIDEO_RCAR_CSI2_LEGACY=y +# CONFIG_VIDEO_RCAR_VIN is not set +# CONFIG_VIDEO_RCAR_CSI2 is not set +CONFIG_SOC_CAMERA=y +CONFIG_SOC_CAMERA_SCALE_CROP=y +CONFIG_SOC_CAMERA_PLATFORM=y +CONFIG_SOC_CAMERA_MAX9286_MAX9271=y +CONFIG_SOC_CAMERA_OV106XX=y +CONFIG_VIDEO_RENESAS_IMR=y +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_PROPERTIES=y +CONFIG_HID_MULTITOUCH=y diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/h3ulcb.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/h3ulcb.cfg new file mode 100644 index 0000000..0e0ade7 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/h3ulcb.cfg @@ -0,0 +1,50 @@ +CONFIG_CAN=y +CONFIG_CAN_PEAK_USB=y +CONFIG_CAN_BCM=y +CONFIG_CAN_RAW=y +CONFIG_CAN_DEV=y +CONFIG_CAN_CALC_BITTIMING=y +CONFIG_CAN_RCAR=y +CONFIG_CANFD_RCAR=y +CONFIG_EXTRA_FIRMWARE="r8a779x_usb3_v2.dlmem" +CONFIG_EXTRA_FIRMWARE_DIR="firmware" +CONFIG_BLK_DEV_NVME=m +CONFIG_SATA_ACARD_AHCI=y +CONFIG_FIXED_PHY=y +CONFIG_SPI_BITBANG=y +CONFIG_SPI_GPIO=y +CONFIG_GPIO_MAX732X=y +CONFIG_GPIO_PCA953X=y +CONFIG_GPIO_PCA953X_IRQ=y +CONFIG_VIDEO_ADV_DEBUG=y +CONFIG_VIDEO_RCAR_VIN_LEGACY=y +CONFIG_VIDEO_RCAR_CSI2_LEGACY=y +# CONFIG_VIDEO_RCAR_VIN is not set +# CONFIG_VIDEO_RCAR_CSI2 is not set +CONFIG_SOC_CAMERA=y +CONFIG_SOC_CAMERA_SCALE_CROP=y +CONFIG_SOC_CAMERA_PLATFORM=y +CONFIG_SOC_CAMERA_MAX9286_MAX9271=y +CONFIG_SOC_CAMERA_TI964_TI9X3=y +CONFIG_SOC_CAMERA_TI954_TI9X3=y +CONFIG_SOC_CAMERA_OV106XX=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_PLATFORM=y +CONFIG_USB_XHCI_RCAR=y +CONFIG_VIDEO_RENESAS_IMR=y +CONFIG_VIRTIO_RCAR_PCIE=y +CONFIG_BT=y +CONFIG_TI_ST=m +CONFIG_BT_WILINK=m +CONFIG_WEXT_CORE=y +CONFIG_WEXT_PROC=y +CONFIG_CFG80211_WEXT=y +CONFIG_MAC80211=y +CONFIG_WLAN=y +CONFIG_WL18XX=m +CONFIG_WLCORE=m +CONFIG_WLCORE_SDIO=m +CONFIG_SND_SOC_SI468X=y +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_PROPERTIES=y +CONFIG_HID_MULTITOUCH=y diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/hyperflash.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/hyperflash.cfg new file mode 100644 index 0000000..df45d5e --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/hyperflash.cfg @@ -0,0 +1,2 @@ +CONFIG_MTD=y +CONFIG_MTD_RPC_HYPERFLASH=y diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/m3ulcb.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/m3ulcb.cfg new file mode 100644 index 0000000..0e0ade7 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/m3ulcb.cfg @@ -0,0 +1,50 @@ +CONFIG_CAN=y +CONFIG_CAN_PEAK_USB=y +CONFIG_CAN_BCM=y +CONFIG_CAN_RAW=y +CONFIG_CAN_DEV=y +CONFIG_CAN_CALC_BITTIMING=y +CONFIG_CAN_RCAR=y +CONFIG_CANFD_RCAR=y +CONFIG_EXTRA_FIRMWARE="r8a779x_usb3_v2.dlmem" +CONFIG_EXTRA_FIRMWARE_DIR="firmware" +CONFIG_BLK_DEV_NVME=m +CONFIG_SATA_ACARD_AHCI=y +CONFIG_FIXED_PHY=y +CONFIG_SPI_BITBANG=y +CONFIG_SPI_GPIO=y +CONFIG_GPIO_MAX732X=y +CONFIG_GPIO_PCA953X=y +CONFIG_GPIO_PCA953X_IRQ=y +CONFIG_VIDEO_ADV_DEBUG=y +CONFIG_VIDEO_RCAR_VIN_LEGACY=y +CONFIG_VIDEO_RCAR_CSI2_LEGACY=y +# CONFIG_VIDEO_RCAR_VIN is not set +# CONFIG_VIDEO_RCAR_CSI2 is not set +CONFIG_SOC_CAMERA=y +CONFIG_SOC_CAMERA_SCALE_CROP=y +CONFIG_SOC_CAMERA_PLATFORM=y +CONFIG_SOC_CAMERA_MAX9286_MAX9271=y +CONFIG_SOC_CAMERA_TI964_TI9X3=y +CONFIG_SOC_CAMERA_TI954_TI9X3=y +CONFIG_SOC_CAMERA_OV106XX=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_PLATFORM=y +CONFIG_USB_XHCI_RCAR=y +CONFIG_VIDEO_RENESAS_IMR=y +CONFIG_VIRTIO_RCAR_PCIE=y +CONFIG_BT=y +CONFIG_TI_ST=m +CONFIG_BT_WILINK=m +CONFIG_WEXT_CORE=y +CONFIG_WEXT_PROC=y +CONFIG_CFG80211_WEXT=y +CONFIG_MAC80211=y +CONFIG_WLAN=y +CONFIG_WL18XX=m +CONFIG_WLCORE=m +CONFIG_WLCORE_SDIO=m +CONFIG_SND_SOC_SI468X=y +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_PROPERTIES=y +CONFIG_HID_MULTITOUCH=y diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/salvator-x.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/salvator-x.cfg new file mode 100644 index 0000000..c5fd6fd --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/salvator-x.cfg @@ -0,0 +1,29 @@ +CONFIG_CAN=y +CONFIG_CAN_PEAK_USB=y +CONFIG_CAN_BCM=y +CONFIG_CAN_RAW=y +CONFIG_CAN_DEV=y +CONFIG_CAN_CALC_BITTIMING=y +CONFIG_CAN_RCAR=y +CONFIG_CANFD_RCAR=y +CONFIG_EXTRA_FIRMWARE="r8a779x_usb3_v2.dlmem" +CONFIG_EXTRA_FIRMWARE_DIR="firmware" +CONFIG_VIDEO_ADV_DEBUG=y +CONFIG_VIDEO_RCAR_VIN_LEGACY=y +CONFIG_VIDEO_RCAR_CSI2_LEGACY=y +# CONFIG_VIDEO_RCAR_VIN is not set +# CONFIG_VIDEO_RCAR_CSI2 is not set +CONFIG_SOC_CAMERA=y +CONFIG_SOC_CAMERA_SCALE_CROP=y +CONFIG_SOC_CAMERA_PLATFORM=y +CONFIG_SOC_CAMERA_MAX9286_MAX9271=y +CONFIG_SOC_CAMERA_OV106XX=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_PLATFORM=y +CONFIG_USB_XHCI_RCAR=y +CONFIG_MMC_SDHI_PRE_REQ=y +CONFIG_MMC_SDHI_SEQ=y +CONFIG_VIDEO_RENESAS_IMR=y +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_PROPERTIES=y +CONFIG_HID_MULTITOUCH=y diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/sdhi_seq.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/sdhi_seq.cfg new file mode 100644 index 0000000..9c43599 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/sdhi_seq.cfg @@ -0,0 +1,2 @@ +CONFIG_MMC_SDHI_PRE_REQ=y +CONFIG_MMC_SDHI_SEQ=y diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas_4.9.bbappend b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas_4.9.bbappend new file mode 100644 index 0000000..bf3c6fc --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas_4.9.bbappend @@ -0,0 +1,75 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" + +SRC_URI_append = " \ + ${@base_conditional("SDHI_SEQ", "1", " file://sdhi_seq.cfg", "", d)} \ + file://0001-spi-sh-msiof-fixes.patch \ + file://0002-spi-spidev-add-spi-gpio-into-spidev.patch \ + file://0003-spi-spi-gpio-fix-CPOL-mode.patch \ + file://0004-xhci-rcar-add-firmware-for-R-Car-H2-M2-USB-3.0-host-.patch \ + file://0005-usb-host-xhci-plat-add-support-for-the-R-Car-H3-xHCI.patch \ + file://0006-spi-spi-gpio-fix-set-CPOL-default-inverted.patch \ + file://0007-mmc-sh_mobile_sdhi-Add-R-CarGen3-SDHI-SEQUENCER-supp.patch \ + file://0008-arm64-do-not-set-dma-masks-that-device-connection-ca.patch \ + file://0009-swiotlb-ensure-that-page-sized-mappings-are-page-ali.patch \ + file://0010-can-rcar_can-add-enable-and-standby-control-pins.patch \ + file://0011-can-rcar_canfd-add-enable-and-standby-control-pins.patch \ + file://0012-mtd-Add-RPC-HyperFlash-driver.patch \ + file://0013-IMR-driver-interim-patch.patch \ + file://0014-lib-swiotlb-reduce-verbosity.patch \ + file://0015-gpio-max732x-fix-gpio-set.patch \ + file://0016-gpio-gpiolib-suppress-gpiod-warning.patch \ + file://0017-media-soc_camera-add-legacy-VIN-CSI2.patch \ + file://0018-arm64-renesas-r8a7797-Add-Renesas-R8A7797-SoC-suppor.patch \ + file://0019-Revert-media-v4l2-async-remove-unneeded-.registered_.patch \ + file://0020-ti-st-add-device-tree-support.patch \ + file://0021-btwilink-add-minimal-device-tree-support.patch \ + file://0022-ASoC-Modify-check-condition-of-multiple-bindings-of-.patch \ + file://0023-ASoC-add-dummy-Si468x-driver.patch \ + file://0030-Gen3-LVDS-cameras.patch \ + file://0031-arm64-dts-r8a7795-es1-salvator-x-view-add-ADAS-board.patch \ + file://0032-arm64-dts-r8a7795-es1-h3ulcb-view-add-ADAS-board.patch \ + file://0033-arm64-dts-r8a7795-es1-h3ulcb-had-add-ADAS-board.patch \ + file://0034-arm64-dts-r8a7795-es1-h3ulcb-kf-add-ADAS-board.patch \ + file://0035-arm64-dts-r8a7796-salvator-x-view-add-ADAS-board.patch \ + file://0036-arm64-dts-r8a7796-m3ulcb-view-add-ADAS-board.patch \ + file://0037-arm64-dts-r8a7796-m3ulcb-kf-add-ADAS-board.patch \ + file://0038-arm64-dts-r8a7795-salvator-x-view-add-ADAS-board.patch \ + file://0039-arm64-dts-r8a7795-h3ulcb-view-add-ADAS-board.patch \ + file://0040-arm64-dts-r8a7795-h3ulcb-had-add-ADAS-board.patch \ + file://0041-arm64-dts-r8a7795-h3ulcb-kf-add-ADAS-board.patch \ + ${@base_conditional("LVDSCAMERA_FIRST4_TYPE1", "1", " file://0050-arm64-dts-Gen3-view-boards-TYPE1-first-4-cameras.patch", "", d)} \ + ${@base_conditional("LVDSCAMERA_SECOND4_TYPE1", "1", " file://0051-arm64-dts-Gen3-view-boards-TYPE1-second-4-cameras.patch", "", d)} \ + ${@base_conditional("LVDSCAMERA_FIRST4_TYPE2", "1", " file://0052-arm64-dts-Gen3-view-boards-TYPE2-first-4-cameras.patch", "", d)} \ +" + +SRC_URI_append_h3ulcb = " file://h3ulcb.cfg" +SRC_URI_append_m3ulcb = " file://m3ulcb.cfg" +SRC_URI_append_salvator-x = " file://salvator-x.cfg" +SRC_URI_append_eagle = " file://eagle.cfg" + +KERNEL_DEVICETREE_append_h3ulcb = " \ + renesas/r8a7795-es1-h3ulcb-view.dtb \ + renesas/r8a7795-es1-h3ulcb-had-alfa.dtb \ + renesas/r8a7795-es1-h3ulcb-had-beta.dtb \ + renesas/r8a7795-es1-h3ulcb-kf.dtb \ + renesas/r8a7795-h3ulcb-view.dtb \ + renesas/r8a7795-h3ulcb-had-alfa.dtb \ + renesas/r8a7795-h3ulcb-had-beta.dtb \ + renesas/r8a7795-h3ulcb-kf.dtb \ +" + +KERNEL_DEVICETREE_append_m3ulcb = " \ + renesas/r8a7796-m3ulcb-view.dtb \ + renesas/r8a7796-m3ulcb-had-alfa.dtb \ + renesas/r8a7796-m3ulcb-had-beta.dtb \ + renesas/r8a7796-m3ulcb-kf.dtb \ +" + +KERNEL_DEVICETREE_append_salvator-x = " \ + renesas/r8a7795-es1-salvator-x-view.dtb \ + renesas/r8a7795-salvator-x-view.dtb \ +" + +KERNEL_DEVICETREE_append_eagle = " \ + renesas/r8a7797-eagle.dtb \ +" |