From fe44bc9356d1a058663367ed9e1416215d3fcd43 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Fri, 19 Jan 2018 21:11:01 +0300 Subject: LVDS cameras: fix MAX96705+AP0101 cameras 1) Fix AP0101+MAX96705 cameras by control FSINC These cameras require GMSL inititialization only with FSYNC disabled 2) add more module options: gpio_resetb and active_low_resetb 3) change automatic buffer fsync_mode_default to static --- .../linux-renesas/0030-Gen3-LVDS-cameras.patch | 50 ++++++++++++++-------- 1 file changed, 33 insertions(+), 17 deletions(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') 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 index 00928d1..9ddbe27 100644 --- 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 @@ -15,7 +15,7 @@ Signed-off-by: Vladimir Barinov drivers/media/i2c/soc_camera/ap0101_ar014x.h | 28 + drivers/media/i2c/soc_camera/ar0132.c | 581 +++++++++++ drivers/media/i2c/soc_camera/ar0132.h | 213 ++++ - drivers/media/i2c/soc_camera/max9286.c | 672 +++++++++++++ + drivers/media/i2c/soc_camera/max9286.c | 688 +++++++++++++ drivers/media/i2c/soc_camera/max9286.h | 244 +++++ drivers/media/i2c/soc_camera/ov10635.c | 758 ++++++++++++++ drivers/media/i2c/soc_camera/ov10635.h | 1139 +++++++++++++++++++++ @@ -34,7 +34,7 @@ Signed-off-by: Vladimir Barinov drivers/media/platform/soc_camera/soc_mediabus.c | 16 + include/media/drv-intf/soc_mediabus.h | 3 + include/media/soc_camera.h | 1 + - 25 files changed, 7755 insertions(+), 109 deletions(-) + 25 files changed, 7771 insertions(+), 109 deletions(-) create mode 100644 drivers/media/i2c/soc_camera/ap0101_ar014x.c create mode 100644 drivers/media/i2c/soc_camera/ap0101_ar014x.h create mode 100644 drivers/media/i2c/soc_camera/ar0132.c @@ -1515,10 +1515,10 @@ index 0000000..bcee0e5 +}; diff --git a/drivers/media/i2c/soc_camera/max9286.c b/drivers/media/i2c/soc_camera/max9286.c new file mode 100644 -index 0000000..20ef2de +index 0000000..8a62b91 --- /dev/null +++ b/drivers/media/i2c/soc_camera/max9286.c -@@ -0,0 +1,672 @@ +@@ -0,0 +1,688 @@ +/* + * MAXIM max9286 GMSL driver + * @@ -1580,6 +1580,8 @@ index 0000000..20ef2de + struct regulator *poc_supply[4]; /* PoC power supply */ +}; + ++static char fsync_mode_default[20] = "manual"; /* manual, automatic, semi-automatic, external */ ++ +static int conf_link; +module_param(conf_link, int, 0644); +MODULE_PARM_DESC(conf_link, " Force configuration link. Used only if robust firmware flashing required (f.e. recovery)"); @@ -1604,6 +1606,14 @@ index 0000000..20ef2de +module_param(vsync, int, 0644); +MODULE_PARM_DESC(vsync, " VSYNC invertion (default: 1 - inverted) */"); + ++static int gpio_resetb; ++module_param(gpio_resetb, int, 0644); ++MODULE_PARM_DESC(gpio_resetb, " Serializer GPIO reset (default: 0 - not used) */"); ++ ++static int active_low_resetb; ++module_param(active_low_resetb, int, 0644); ++MODULE_PARM_DESC(active_low_resetb, " Serializer GPIO reset level (default: 0 - active high) */"); ++ +static char* ser_name(int id) +{ + switch (id) { @@ -1661,6 +1671,16 @@ index 0000000..20ef2de + 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 */ ++ ++ if (strcmp(priv->fsync_mode, "manual") == 0) { ++ 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 */ ++ } +} + +static int max9286_reverse_channel_setup(struct i2c_client *client, int idx) @@ -1771,20 +1791,12 @@ index 0000000..20ef2de + dev_err(&client->dev, "CSI2 lanes number is invalid (%d)\n", priv->lanes); + } + ++ /* Start GMSL initialization with FSYNC disabled. This is required for some odd LVDS cameras */ ++ reg8_write(client, 0x01, 0xc0); /* ECU (aka MCU) based FrameSync using GPI-to-GPO */ + 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); + -+ if (strcmp(priv->fsync_mode, "manual") == 0) { -+ 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, 0x91 | (priv->vsync ? BIT(3) : 0) | (priv->hsync ? BIT(2) : 0)); /* enable HS/VS encoding, use D14/15 for HS/VS, invert HS/VS */ @@ -1975,7 +1987,7 @@ index 0000000..20ef2de + 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)) @@ -2009,9 +2021,9 @@ index 0000000..20ef2de + priv->gpio_resetb = -1; + } else { + if (of_property_read_bool(np, "maxim,resetb-active-high")) -+ priv->active_low_resetb = false; ++ priv->active_low_resetb = 0; + else -+ priv->active_low_resetb = true; ++ priv->active_low_resetb = 1; + } + + if (!of_property_read_u32(np, "maxim,sensor_delay", &sensor_delay)) @@ -2047,6 +2059,10 @@ index 0000000..20ef2de + priv->hsync = hsync; + if (!vsync) + priv->vsync = vsync; ++ if (gpio_resetb) ++ priv->gpio_resetb = gpio_resetb; ++ if (active_low_resetb) ++ priv->active_low_resetb = active_low_resetb; + + for (i = 0; i < priv->links; i++) { + endpoint = of_graph_get_next_endpoint(np, endpoint); -- cgit 1.2.3-korg From 938b82740abe5ab897e7e0c943e5f4edac93732c Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Sat, 20 Jan 2018 01:51:35 +0300 Subject: AP0101-AR014x: add OTP IDs This adds reading fused from AR014x sensors --- .../linux-renesas/0030-Gen3-LVDS-cameras.patch | 53 ++++++++++++++++++++-- 1 file changed, 49 insertions(+), 4 deletions(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') 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 index 9ddbe27..6eb40f3 100644 --- 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 @@ -11,7 +11,7 @@ Signed-off-by: Vladimir Barinov --- drivers/media/i2c/soc_camera/Kconfig | 47 + drivers/media/i2c/soc_camera/Makefile | 7 + - drivers/media/i2c/soc_camera/ap0101_ar014x.c | 536 ++++++++++ + drivers/media/i2c/soc_camera/ap0101_ar014x.c | 581 +++++++++++ drivers/media/i2c/soc_camera/ap0101_ar014x.h | 28 + drivers/media/i2c/soc_camera/ar0132.c | 581 +++++++++++ drivers/media/i2c/soc_camera/ar0132.h | 213 ++++ @@ -34,7 +34,7 @@ Signed-off-by: Vladimir Barinov drivers/media/platform/soc_camera/soc_mediabus.c | 16 + include/media/drv-intf/soc_mediabus.h | 3 + include/media/soc_camera.h | 1 + - 25 files changed, 7771 insertions(+), 109 deletions(-) + 25 files changed, 7816 insertions(+), 109 deletions(-) create mode 100644 drivers/media/i2c/soc_camera/ap0101_ar014x.c create mode 100644 drivers/media/i2c/soc_camera/ap0101_ar014x.h create mode 100644 drivers/media/i2c/soc_camera/ar0132.c @@ -133,10 +133,10 @@ index 6f994f9..e88f6a9 100644 obj-$(CONFIG_SOC_CAMERA_OV6650) += ov6650.o diff --git a/drivers/media/i2c/soc_camera/ap0101_ar014x.c b/drivers/media/i2c/soc_camera/ap0101_ar014x.c new file mode 100644 -index 0000000..4757657 +index 0000000..3ba2a5a --- /dev/null +++ b/drivers/media/i2c/soc_camera/ap0101_ar014x.c -@@ -0,0 +1,536 @@ +@@ -0,0 +1,581 @@ +/* + * ON Semiconductor AP0101-AR014X sensor camera driver + * @@ -222,6 +222,38 @@ index 0000000..4757657 + return 0; +} + ++static u16 ap0101_ar014x_read(struct i2c_client *client, u16 addr) ++{ ++ u16 reg_val = 0; ++ ++ reg16_write16(client, 0x0040, 0x8d00); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write16(client, 0xfc00, addr); ++ reg16_write16(client, 0xfc02, 0x0200); /* 2 bytes */ ++ reg16_write16(client, 0x0040, 0x8d05); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write16(client, 0x0040, 0x8d08); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_read16(client, 0xfc00, ®_val); ++ reg16_write16(client, 0x0040, 0x8d02); ++ ++ return reg_val; ++} ++ ++static void ap0101_ar014x_write(struct i2c_client *client, u16 addr, u16 val) ++{ ++ reg16_write16(client, 0x0040, 0x8d00); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write16(client, 0xfc00, addr); ++ reg16_write16(client, 0xfc02, 0x0200 | (val >> 8)); /* 2 bytes */ ++ reg16_write16(client, 0xfc04, (val & 0xff) << 8); ++ reg16_write16(client, 0x0040, 0x8d06); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write16(client, 0x0040, 0x8d08); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write16(client, 0x0040, 0x8d02); ++} ++ +static int ap0101_s_stream(struct v4l2_subdev *sd, int enable) +{ + return 0; @@ -448,6 +480,19 @@ index 0000000..4757657 + +static void ap0101_otp_id_read(struct i2c_client *client) +{ ++ struct ap0101_priv *priv = to_ap0101(client); ++ int i; ++ ++ /* read camera id from ar014x OTP memory */ ++ ap0101_ar014x_write(client, 0x3054, 0x400); ++ ap0101_ar014x_write(client, 0x304a, 0x110); ++ usleep_range(25000, 25500); /* wait 25 ms */ ++ ++ for (i = 0; i < 6; i += 2) { ++ /* first 4 bytes are equal on all ar014x */ ++ priv->id[i] = ap0101_ar014x_read(client, 0x3800 + i + 4) >> 8; ++ priv->id[i + 1] = ap0101_ar014x_read(client, 0x3800 + i + 4) & 0xff; ++ } +} + +static ssize_t ap0101_otp_id_show(struct device *dev, -- cgit 1.2.3-korg From 49b127aff23ab41e8b1adb0c4ad43871fc754527 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Sat, 20 Jan 2018 01:52:33 +0300 Subject: VideoBox2: I2C, SATA, CAN fixes 1) remove dallas rtc since conflicts address with clk generator on ULCB at 0x68 2) remove sata 3) fix can: add termination resistor and pull-ups --- .../0040-arm64-dts-renesas-add-ADAS-boards.patch | 62 ++++++++-------------- 1 file changed, 21 insertions(+), 41 deletions(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch index 5387ae8..ffaf796 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch @@ -35,7 +35,7 @@ Signed-off-by: Vladimir Barinov .../renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts | 441 +++++ .../dts/renesas/legacy/r8a7795-h3ulcb-kf-v0.dts | 1724 +++++++++++++++++++ .../dts/renesas/legacy/r8a7795-h3ulcb-kf-v1.dts | 465 +++++ - .../dts/renesas/legacy/r8a7796-m3ulcb-kf-v0.dts | 1214 +++++++++++++ + .../dts/renesas/legacy/r8a7796-m3ulcb-kf-v0.dts | 1214 ++++++++++++++ .../dts/renesas/legacy/r8a7796-m3ulcb-kf-v1.dts | 465 +++++ .../dts/renesas/legacy/r8a7797-v3msk-kf-v0.dts | 82 + .../boot/dts/renesas/legacy/ulcb-kf-cmos.dtsi | 75 + @@ -73,9 +73,9 @@ Signed-off-by: Vladimir Barinov arch/arm64/boot/dts/renesas/ulcb-kf.dtsi | 1542 +++++++++++++++++ arch/arm64/boot/dts/renesas/ulcb-vb-cn12.dtsi | 515 ++++++ arch/arm64/boot/dts/renesas/ulcb-vb.dtsi | 1726 +++++++++++++++++++ - arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi | 1792 ++++++++++++++++++++ + arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi | 1772 ++++++++++++++++++++ arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi | 578 +++++++ - 46 files changed, 19179 insertions(+) + 46 files changed, 19159 insertions(+) create mode 100644 arch/arm64/boot/dts/renesas/legacy/Makefile create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts @@ -17201,10 +17201,10 @@ index 0000000..4fcb320 +//#include "ulcb-vb-cn12.dtsi" diff --git a/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi b/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi new file mode 100644 -index 0000000..67b6085 +index 0000000..4b25a2f0 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi -@@ -0,0 +1,1792 @@ +@@ -0,0 +1,1772 @@ +/* + * Device Tree Source for the ULCB Videobox V2 board + * @@ -17502,9 +17502,21 @@ index 0000000..67b6085 + input; + line-name = "Video-C irq"; + }; ++ can2_irq { ++ gpio-hog; ++ gpios = <15 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "CAN2 irq"; ++ }; +}; + +&gpio1 { ++ can3_irq { ++ gpio-hog; ++ gpios = <5 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "CAN3 irq"; ++ }; + gpioext_4_22_irq { + gpio-hog; + gpios = <25 GPIO_ACTIVE_HIGH>; @@ -18083,18 +18095,6 @@ index 0000000..67b6085 + gpio-controller; + #gpio-cells = <2>; + -+ video_a_des_cfg1 { -+ gpio-hog; -+ gpios = <5 GPIO_ACTIVE_HIGH>; -+ input; -+ line-name = "Video-A cfg1"; -+ }; -+ video_a_des_cfg0 { -+ gpio-hog; -+ gpios = <6 GPIO_ACTIVE_HIGH>; -+ input; -+ line-name = "Video-A cfg0"; -+ }; + video_a_pwr_shdn { + gpio-hog; + gpios = <3 GPIO_ACTIVE_HIGH>; @@ -18145,18 +18145,6 @@ index 0000000..67b6085 + gpio-controller; + #gpio-cells = <2>; + -+ video_a_des_cfg2 { -+ gpio-hog; -+ gpios = <4 GPIO_ACTIVE_HIGH>; -+ input; -+ line-name = "Video-A cfg2"; -+ }; -+ video_a_des_cfg1 { -+ gpio-hog; -+ gpios = <6 GPIO_ACTIVE_HIGH>; -+ input; -+ line-name = "Video-A cfg1"; -+ }; + video_a_des_cfg0 { + gpio-hog; + gpios = <7 GPIO_ACTIVE_HIGH>; @@ -18460,7 +18448,7 @@ index 0000000..67b6085 + can0_load { + gpio-hog; + gpios = <0 GPIO_ACTIVE_HIGH>; -+ output-low; ++ output-high; + line-name = "can0_120R_load"; + }; + /* CAN1 */ @@ -18473,7 +18461,7 @@ index 0000000..67b6085 + can1_load { + gpio-hog; + gpios = <1 GPIO_ACTIVE_HIGH>; -+ output-low; ++ output-high; + line-name = "can1_120R_load"; + }; + /* CAN2 */ @@ -18486,7 +18474,7 @@ index 0000000..67b6085 + can2_load { + gpio-hog; + gpios = <2 GPIO_ACTIVE_HIGH>; -+ output-low; ++ output-high; + line-name = "can2_120R_load"; + }; + can2_rst { @@ -18505,7 +18493,7 @@ index 0000000..67b6085 + can3_load { + gpio-hog; + gpios = <3 GPIO_ACTIVE_HIGH>; -+ output-low; ++ output-high; + line-name = "can3_120R_load"; + }; + can3_rst { @@ -18515,10 +18503,6 @@ index 0000000..67b6085 + line-name = "can3_rst"; + }; + }; -+ rtc@68 { -+ compatible = "dallas,ds1338"; -+ reg = <0x68>; -+ }; + }; + + i2c@3 { @@ -18903,10 +18887,6 @@ index 0000000..67b6085 + #sound-dai-cells = <1>; +}; + -+&sata { -+ status = "okay"; -+}; -+ +&ssi1 { + /delete-property/shared-pin; +}; -- cgit 1.2.3-korg From 87c9b2e38b08abd02ed6e6cffeae1f2329709319 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Mon, 22 Jan 2018 18:12:35 +0300 Subject: V3M: enable TMU, CMT timers in kernel, add tmu0 timer 1) enable in kernel TMU,CMT timers via Kconfig 2) add missed timer tmu0 --- ...0018-arm64-renesas-r8a7797-Add-Renesas-R8A7797-SoC-suppor.patch | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') 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 index ffe7684..dc80f98 100644 --- 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 @@ -59,12 +59,14 @@ diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms index ebe0a37..d3b6771 100644 --- a/arch/arm64/Kconfig.platforms +++ b/arch/arm64/Kconfig.platforms -@@ -166,6 +166,12 @@ config ARCH_R8A77965 +@@ -166,6 +166,14 @@ config ARCH_R8A77965 help This enables support for the Renesas R-Car M3N SoC. +config ARCH_R8A7797 + bool "Renesas R-Car V3M SoC Platform" ++ select SYS_SUPPORTS_SH_TMU ++ select SYS_SUPPORTS_SH_CMT + depends on ARCH_RENESAS + help + This enables support for the Renesas R-Car V3M SoC. @@ -1263,7 +1265,7 @@ new file mode 100644 index 0000000..6f481a4 --- /dev/null +++ b/drivers/clk/renesas/r8a7797-cpg-mssr.c -@@ -0,0 +1,231 @@ +@@ -0,0 +1,232 @@ +/* + * r8a7797 Clock Pulse Generator / Module Standby and Software Reset + * @@ -1362,6 +1364,7 @@ index 0000000..6f481a4 + DEF_MOD("tmu3", 122, R8A7797_CLK_S2D2), + DEF_MOD("tmu2", 123, R8A7797_CLK_S2D2), + DEF_MOD("tmu1", 124, R8A7797_CLK_S2D2), ++ DEF_MOD("tmu0", 125, R8A7797_CLK_CP), + 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 */ -- cgit 1.2.3-korg From 9c691a78197540d58df9db7af3cd9e1af3af0a7b Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Mon, 22 Jan 2018 18:14:32 +0300 Subject: Eagle: remove USB_PEAK from kernel config Remove this since Eagle does not have USB --- meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/eagle.cfg | 1 - 1 file changed, 1 deletion(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') 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 index 5b728fd..ce08b0d 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/eagle.cfg +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/eagle.cfg @@ -1,6 +1,5 @@ CONFIG_ARCH_R8A7797=y CONFIG_CAN=y -CONFIG_CAN_PEAK_USB=y CONFIG_CAN_BCM=y CONFIG_CAN_RAW=y CONFIG_CAN_DEV=y -- cgit 1.2.3-korg From 6262288744b7d4a0945e365bef3c01b3440cac01 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Mon, 22 Jan 2018 18:17:51 +0300 Subject: Add V3H support and Condor board 1) add uboot R-Car V3H SoC (r87798) and V3H based Condor board 2) add kernel R-Car V3H SoC (r87798) and V3H based Condor board --- meta-rcar-gen3-adas/conf/layer.conf | 6 + meta-rcar-gen3-adas/conf/machine/condor.conf | 35 + .../conf/machine/include/r8a7798.inc | 3 + .../conf/condor/linaro-gcc/bsp/bblayers.conf | 16 + .../sample/conf/condor/linaro-gcc/bsp/local.conf | 267 + ...m-renesas-Add-Renesas-R8A7798-SoC-support.patch | 3889 ++++++++++++ .../0019-board-renesas-Add-Condor-board.patch | 537 ++ .../recipes-bsp/u-boot/u-boot_2015.04.bbappend | 2 + .../kernel-module-mmngr.bbappend | 1 + .../0040-arm64-dts-renesas-add-ADAS-boards.patch | 958 ++- ...as-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch | 6197 ++++++++++++++++++++ ...0104-media-vsp1-extend-DRM-VSP1-interface.patch | 2 +- .../recipes-kernel/linux/linux-renesas/condor.cfg | 29 + .../linux/linux-renesas_4.9.bbappend | 10 +- 14 files changed, 11944 insertions(+), 8 deletions(-) create mode 100644 meta-rcar-gen3-adas/conf/machine/condor.conf create mode 100644 meta-rcar-gen3-adas/conf/machine/include/r8a7798.inc create mode 100644 meta-rcar-gen3-adas/docs/sample/conf/condor/linaro-gcc/bsp/bblayers.conf create mode 100644 meta-rcar-gen3-adas/docs/sample/conf/condor/linaro-gcc/bsp/local.conf create mode 100644 meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0018-arm-renesas-Add-Renesas-R8A7798-SoC-support.patch create mode 100644 meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0019-board-renesas-Add-Condor-board.patch create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/condor.cfg (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/conf/layer.conf b/meta-rcar-gen3-adas/conf/layer.conf index 30ba1d7..f820387 100644 --- a/meta-rcar-gen3-adas/conf/layer.conf +++ b/meta-rcar-gen3-adas/conf/layer.conf @@ -78,6 +78,12 @@ IMAGE_INSTALL_append_r8a7797 += " \ udev-rules-cvlib \ " +IMAGE_INSTALL_append_r8a7798 += " \ + kernel-module-uio-imp \ + kernel-module-cmemdrv \ + udev-rules-cvlib \ +" + DISTRO_FEATURES_remove="x11" DISTRO_FEATURES_append = " surroundview " DISTRO_FEATURES_append = " opencv-sdk " diff --git a/meta-rcar-gen3-adas/conf/machine/condor.conf b/meta-rcar-gen3-adas/conf/machine/condor.conf new file mode 100644 index 0000000..fc5e167 --- /dev/null +++ b/meta-rcar-gen3-adas/conf/machine/condor.conf @@ -0,0 +1,35 @@ +#@TYPE: Machine +#@NAME: Condor machine +#@DESCRIPTION: Machine configuration for running Condor + +DEFAULTTUNE ?= "cortexa53" +require conf/machine/include/tune-cortexa53.inc +require conf/machine/include/${SOC_FAMILY}.inc + +# 32BIT package install (default is disable) +# This variables can be used only in multilib. +USE_32BIT_PKGS ?= "0" +USE_32BIT_WAYLAND ?= "0" +USE_32BIT_MMP ?= "0" + +MACHINE_FEATURES = "" + +KERNEL_IMAGETYPE = "Image" +IMAGE_FSTYPES = "tar.bz2 ext4 cpio.gz" + +SERIAL_CONSOLE = "115200 ttySC0" + +# Configuration for kernel +PREFERRED_PROVIDER_virtual/kernel = "linux-renesas" +KERNEL_DEVICETREE = "renesas/r8a7798-condor.dtb" + +# u-boot +PREFERRED_VERSION_u-boot = "v2015.04%" +EXTRA_IMAGEDEPENDS += " u-boot" +UBOOT_MACHINE = "r8a7798_condor_defconfig" + +# libdrm +PREFERRED_VERSION_libdrm = "2.4.68" + +# Add variable to Build Configuration in build log +BUILDCFG_VARS_append = " SOC_FAMILY" diff --git a/meta-rcar-gen3-adas/conf/machine/include/r8a7798.inc b/meta-rcar-gen3-adas/conf/machine/include/r8a7798.inc new file mode 100644 index 0000000..e2cc4ac --- /dev/null +++ b/meta-rcar-gen3-adas/conf/machine/include/r8a7798.inc @@ -0,0 +1,3 @@ +SOC_FAMILY =. "rcar-gen3:" +require conf/machine/include/soc-family.inc +LINUXLIBCVERSION = "4.9" diff --git a/meta-rcar-gen3-adas/docs/sample/conf/condor/linaro-gcc/bsp/bblayers.conf b/meta-rcar-gen3-adas/docs/sample/conf/condor/linaro-gcc/bsp/bblayers.conf new file mode 100644 index 0000000..96ff8ad --- /dev/null +++ b/meta-rcar-gen3-adas/docs/sample/conf/condor/linaro-gcc/bsp/bblayers.conf @@ -0,0 +1,16 @@ +# POKY_BBLAYERS_CONF_VERSION is increased each time build/conf/bblayers.conf +# changes incompatibly +POKY_BBLAYERS_CONF_VERSION = "2" + +BBPATH = "${TOPDIR}" +BBFILES ?= "" + +BBLAYERS ?= " \ + ${TOPDIR}/../poky/meta \ + ${TOPDIR}/../poky/meta-poky \ + ${TOPDIR}/../poky/meta-yocto-bsp \ + ${TOPDIR}/../meta-renesas/meta-rcar-gen3 \ + ${TOPDIR}/../meta-linaro/meta-linaro-toolchain \ + ${TOPDIR}/../meta-linaro/meta-optee \ + ${TOPDIR}/../meta-openembedded/meta-oe \ + " diff --git a/meta-rcar-gen3-adas/docs/sample/conf/condor/linaro-gcc/bsp/local.conf b/meta-rcar-gen3-adas/docs/sample/conf/condor/linaro-gcc/bsp/local.conf new file mode 100644 index 0000000..b7c3532 --- /dev/null +++ b/meta-rcar-gen3-adas/docs/sample/conf/condor/linaro-gcc/bsp/local.conf @@ -0,0 +1,267 @@ +# +# This file is your local configuration file and is where all local user settings +# are placed. The comments in this file give some guide to the options a new user +# to the system might want to change but pretty much any configuration option can +# be set in this file. More adventurous users can look at local.conf.extended +# which contains other examples of configuration which can be placed in this file +# but new users likely won't need any of them initially. +# +# Lines starting with the '#' character are commented out and in some cases the +# default values are provided as comments to show people example syntax. Enabling +# the option is a question of removing the # character and making any change to the +# variable as required. + +# +# Machine Selection +# +# You need to select a specific machine to target the build with. There are a selection +# of emulated machines available which can boot and run in the QEMU emulator: +# +#MACHINE ?= "qemuarm" +#MACHINE ?= "qemuarm64" +#MACHINE ?= "qemumips" +#MACHINE ?= "qemumips64" +#MACHINE ?= "qemuppc" +#MACHINE ?= "qemux86" +#MACHINE ?= "qemux86-64" +# +# There are also the following hardware board target machines included for +# demonstration purposes: +# +#MACHINE ?= "beaglebone" +#MACHINE ?= "genericx86" +#MACHINE ?= "genericx86-64" +#MACHINE ?= "mpc8315e-rdb" +#MACHINE ?= "edgerouter" +# +# This sets the default machine to be qemux86 if no other machine is selected: +MACHINE ??= "condor" + +SOC_FAMILY = "r8a7798" + +# +# Where to place downloads +# +# During a first build the system will download many different source code tarballs +# from various upstream projects. This can take a while, particularly if your network +# connection is slow. These are all stored in DL_DIR. When wiping and rebuilding you +# can preserve this directory to speed up this part of subsequent builds. This directory +# is safe to share between multiple builds on the same machine too. +# +# The default is a downloads directory under TOPDIR which is the build directory. +# +#DL_DIR ?= "${TOPDIR}/downloads" + +# +# Where to place shared-state files +# +# BitBake has the capability to accelerate builds based on previously built output. +# This is done using "shared state" files which can be thought of as cache objects +# and this option determines where those files are placed. +# +# You can wipe out TMPDIR leaving this directory intact and the build would regenerate +# from these files if no changes were made to the configuration. If changes were made +# to the configuration, only shared state files where the state was still valid would +# be used (done using checksums). +# +# The default is a sstate-cache directory under TOPDIR. +# +#SSTATE_DIR ?= "${TOPDIR}/sstate-cache" + +# +# Where to place the build output +# +# This option specifies where the bulk of the building work should be done and +# where BitBake should place its temporary files and output. Keep in mind that +# this includes the extraction and compilation of many applications and the toolchain +# which can use Gigabytes of hard disk space. +# +# The default is a tmp directory under TOPDIR. +# +#TMPDIR = "${TOPDIR}/tmp" + +# +# Default policy config +# +# The distribution setting controls which policy settings are used as defaults. +# The default value is fine for general Yocto project use, at least initially. +# Ultimately when creating custom policy, people will likely end up subclassing +# these defaults. +# +DISTRO ?= "poky" +# As an example of a subclass there is a "bleeding" edge policy configuration +# where many versions are set to the absolute latest code from the upstream +# source control systems. This is just mentioned here as an example, its not +# useful to most new users. +# DISTRO ?= "poky-bleeding" + +# +# Package Management configuration +# +# This variable lists which packaging formats to enable. Multiple package backends +# can be enabled at once and the first item listed in the variable will be used +# to generate the root filesystems. +# Options are: +# - 'package_deb' for debian style deb files +# - 'package_ipk' for ipk files are used by opkg (a debian style embedded package manager) +# - 'package_rpm' for rpm style packages +# E.g.: PACKAGE_CLASSES ?= "package_rpm package_deb package_ipk" +# We default to rpm: +PACKAGE_CLASSES ?= "package_ipk" + +# +# SDK target architecture +# +# This variable specifies the architecture to build SDK items for and means +# you can build the SDK packages for architectures other than the machine you are +# running the build on (i.e. building i686 packages on an x86_64 host). +# Supported values are i686 and x86_64 +#SDKMACHINE ?= "i686" + +# +# Extra image configuration defaults +# +# The EXTRA_IMAGE_FEATURES variable allows extra packages to be added to the generated +# images. Some of these options are added to certain image types automatically. The +# variable can contain the following options: +# "dbg-pkgs" - add -dbg packages for all installed packages +# (adds symbol information for debugging/profiling) +# "dev-pkgs" - add -dev packages for all installed packages +# (useful if you want to develop against libs in the image) +# "ptest-pkgs" - add -ptest packages for all ptest-enabled packages +# (useful if you want to run the package test suites) +# "tools-sdk" - add development tools (gcc, make, pkgconfig etc.) +# "tools-debug" - add debugging tools (gdb, strace) +# "eclipse-debug" - add Eclipse remote debugging support +# "tools-profile" - add profiling tools (oprofile, lttng, valgrind) +# "tools-testapps" - add useful testing tools (ts_print, aplay, arecord etc.) +# "debug-tweaks" - make an image suitable for development +# e.g. ssh root access has a blank password +# There are other application targets that can be used here too, see +# meta/classes/image.bbclass and meta/classes/core-image.bbclass for more details. +# We default to enabling the debugging tweaks. +EXTRA_IMAGE_FEATURES ?= "debug-tweaks" + +# +# Additional image features +# +# The following is a list of additional classes to use when building images which +# enable extra features. Some available options which can be included in this variable +# are: +# - 'buildstats' collect build statistics +# - 'image-mklibs' to reduce shared library files size for an image +# - 'image-prelink' in order to prelink the filesystem image +# - 'image-swab' to perform host system intrusion detection +# NOTE: if listing mklibs & prelink both, then make sure mklibs is before prelink +# NOTE: mklibs also needs to be explicitly enabled for a given image, see local.conf.extended +# image-prelink disabled for now due to issues with IFUNC symbol relocation +USER_CLASSES ?= "buildstats image-mklibs" + +# +# Runtime testing of images +# +# The build system can test booting virtual machine images under qemu (an emulator) +# after any root filesystems are created and run tests against those images. To +# enable this uncomment this line. See classes/testimage(-auto).bbclass for +# further details. +#TEST_IMAGE = "1" +# +# Interactive shell configuration +# +# Under certain circumstances the system may need input from you and to do this it +# can launch an interactive shell. It needs to do this since the build is +# multithreaded and needs to be able to handle the case where more than one parallel +# process may require the user's attention. The default is iterate over the available +# terminal types to find one that works. +# +# Examples of the occasions this may happen are when resolving patches which cannot +# be applied, to use the devshell or the kernel menuconfig +# +# Supported values are auto, gnome, xfce, rxvt, screen, konsole (KDE 3.x only), none +# Note: currently, Konsole support only works for KDE 3.x due to the way +# newer Konsole versions behave +#OE_TERMINAL = "auto" +# By default disable interactive patch resolution (tasks will just fail instead): +PATCHRESOLVE = "noop" + +# +# Disk Space Monitoring during the build +# +# Monitor the disk space during the build. If there is less that 1GB of space or less +# than 100K inodes in any key build location (TMPDIR, DL_DIR, SSTATE_DIR), gracefully +# shutdown the build. If there is less that 100MB or 1K inodes, perform a hard abort +# of the build. The reason for this is that running completely out of space can corrupt +# files and damages the build in ways which may not be easily recoverable. +# It's necesary to monitor /tmp, if there is no space left the build will fail +# with very exotic errors. +BB_DISKMON_DIRS = "\ + STOPTASKS,${TMPDIR},1G,100K \ + STOPTASKS,${DL_DIR},1G,100K \ + STOPTASKS,${SSTATE_DIR},1G,100K \ + STOPTASKS,/tmp,100M,100K \ + ABORT,${TMPDIR},100M,1K \ + ABORT,${DL_DIR},100M,1K \ + ABORT,${SSTATE_DIR},100M,1K \ + ABORT,/tmp,10M,1K" + +# +# Shared-state files from other locations +# +# As mentioned above, shared state files are prebuilt cache data objects which can +# used to accelerate build time. This variable can be used to configure the system +# to search other mirror locations for these objects before it builds the data itself. +# +# This can be a filesystem directory, or a remote url such as http or ftp. These +# would contain the sstate-cache results from previous builds (possibly from other +# machines). This variable works like fetcher MIRRORS/PREMIRRORS and points to the +# cache locations to check for the shared objects. +# NOTE: if the mirror uses the same structure as SSTATE_DIR, you need to add PATH +# at the end as shown in the examples below. This will be substituted with the +# correct path within the directory structure. +#SSTATE_MIRRORS ?= "\ +#file://.* http://someserver.tld/share/sstate/PATH;downloadfilename=PATH \n \ +#file://.* file:///some/local/dir/sstate/PATH" + + +# +# Qemu configuration +# +# By default qemu will build with a builtin VNC server where graphical output can be +# seen. The two lines below enable the SDL backend too. By default libsdl-native will +# be built, if you want to use your host's libSDL instead of the minimal libsdl built +# by libsdl-native then uncomment the ASSUME_PROVIDED line below. +PACKAGECONFIG_append_pn-qemu-native = " sdl" +PACKAGECONFIG_append_pn-nativesdk-qemu = " sdl" +#ASSUME_PROVIDED += "libsdl-native" + +# CONF_VERSION is increased each time build/conf/ changes incompatibly and is used to +# track the version of this file when it was generated. This can safely be ignored if +# this doesn't mean anything to you. +CONF_VERSION = "1" + +# Add systemd configuration +DISTRO_FEATURES_append = " systemd" +VIRTUAL-RUNTIME_init_manager = "systemd" + +# Linaro GCC +GCCVERSION = "linaro-5.2" + +# add the static lib to SDK toolchain +SDKIMAGE_FEATURES_append = " staticdev-pkgs" + +# Disable optee in meta-linaro layer +BBMASK = "meta-linaro/meta-optee/recipes-security/optee" + +# Mask graphic Pkgs +BBMASK .= "|gles-user-module|kernel-module-gles|wayland-kms|libgbm" +# Mask MMP recipes +BBMASK .= "|kernel-module-uvcs-drv|omx-user-module" + +# Add for gstreamer plugins ugly +LICENSE_FLAGS_WHITELIST = "commercial" + +# Linux ICCOM driver (RCG3ZLIDL4001ZNO) +# Linux ICCOM library (RCG3ZLILL4001ZNO) +#DISTRO_FEATURES_append = " iccom" + +IMAGE_INSTALL_remove = "optee-linuxdriver optee-linuxdriver-armtz optee-client" diff --git a/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0018-arm-renesas-Add-Renesas-R8A7798-SoC-support.patch b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0018-arm-renesas-Add-Renesas-R8A7798-SoC-support.patch new file mode 100644 index 0000000..f4e3df6 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0018-arm-renesas-Add-Renesas-R8A7798-SoC-support.patch @@ -0,0 +1,3889 @@ +From ff0bbc92aeb87872b0c8e7e05a1604bd8c1c3e98 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Mon, 22 Jan 2018 13:57:14 +0300 +Subject: [PATCH] arm: renesas: Add Renesas R8A7798 SoC support + +This adds Renesas R8A7798 SoC support + +Signed-off-by: Vladimir Barinov +Signed-off-by: Mikhail Ulyanov +--- + arch/arm/cpu/armv8/Kconfig | 3 + + arch/arm/cpu/armv8/rcar_gen3/Makefile | 3 + + arch/arm/cpu/armv8/rcar_gen3/cpu_info-r8a7798.c | 40 + + arch/arm/cpu/armv8/rcar_gen3/cpu_info.c | 8 + + arch/arm/cpu/armv8/rcar_gen3/pfc-r8a7798.c | 3074 ++++++++++++++++++++ + arch/arm/cpu/armv8/rcar_gen3/pfc.c | 2 + + arch/arm/include/asm/arch-rcar_gen3/gpio.h | 4 + + arch/arm/include/asm/arch-rcar_gen3/r8a7798-gpio.h | 522 ++++ + arch/arm/include/asm/arch-rcar_gen3/r8a7798.h | 34 + + arch/arm/include/asm/arch-rcar_gen3/rcar_gen3.h | 2 + + drivers/mtd/spi/sf_probe.c | 2 +- + drivers/net/sh_eth.h | 5 +- + drivers/serial/serial_sh.h | 2 +- + include/configs/rcar-gen3-common.h | 4 + + 14 files changed, 3701 insertions(+), 4 deletions(-) + create mode 100644 arch/arm/cpu/armv8/rcar_gen3/cpu_info-r8a7798.c + create mode 100644 arch/arm/cpu/armv8/rcar_gen3/pfc-r8a7798.c + create mode 100644 arch/arm/include/asm/arch-rcar_gen3/r8a7798-gpio.h + create mode 100644 arch/arm/include/asm/arch-rcar_gen3/r8a7798.h + +diff --git a/arch/arm/cpu/armv8/Kconfig b/arch/arm/cpu/armv8/Kconfig +index 343b121..58a9259 100644 +--- a/arch/arm/cpu/armv8/Kconfig ++++ b/arch/arm/cpu/armv8/Kconfig +@@ -44,6 +44,9 @@ config R8A77965 + config R8A7797 + bool "Renesas SoC R8A7797" + ++config R8A7798 ++ bool "Renesas SoC R8A7798" ++ + endchoice + + config SYS_SOC +diff --git a/arch/arm/cpu/armv8/rcar_gen3/Makefile b/arch/arm/cpu/armv8/rcar_gen3/Makefile +index a7a8f79..a8b7ddf 100644 +--- a/arch/arm/cpu/armv8/rcar_gen3/Makefile ++++ b/arch/arm/cpu/armv8/rcar_gen3/Makefile +@@ -18,3 +18,6 @@ obj-$(CONFIG_R8A7796X) += lowlevel_init.o cpu_info-r8a7796.o \ + obj-$(CONFIG_R8A7797) += lowlevel_init.o cpu_info-r8a7797.o \ + pfc.o pfc-r8a7797.o prr_depend.o \ + board.o ++obj-$(CONFIG_R8A7798) += lowlevel_init.o cpu_info-r8a7798.o \ ++ pfc.o pfc-r8a7798.o prr_depend.o \ ++ board.o +diff --git a/arch/arm/cpu/armv8/rcar_gen3/cpu_info-r8a7798.c b/arch/arm/cpu/armv8/rcar_gen3/cpu_info-r8a7798.c +new file mode 100644 +index 0000000..df94cd6 +--- /dev/null ++++ b/arch/arm/cpu/armv8/rcar_gen3/cpu_info-r8a7798.c +@@ -0,0 +1,40 @@ ++/* ++ * arch/arm/cpu/armv8/rcar_gen3/cpu_info-r8a7798.c ++ * This file defines cpu information funstions. ++ * ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ */ ++#include ++#include ++ ++#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 0046c75..a9366c0 100644 +--- a/arch/arm/cpu/armv8/rcar_gen3/cpu_info.c ++++ b/arch/arm/cpu/armv8/rcar_gen3/cpu_info.c +@@ -89,6 +89,14 @@ int print_cpuinfo(void) + CONFIG_RCAR_TARGET_STRING); + } + break; ++ case 0x56: ++ printf("CPU: Renesas Electronics R8A7798 rev %d.%d\n", ++ rev_integer, rev_fraction); ++ if (strcmp(CONFIG_RCAR_TARGET_STRING, "r8a7798")) { ++ 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-r8a7798.c b/arch/arm/cpu/armv8/rcar_gen3/pfc-r8a7798.c +new file mode 100644 +index 0000000..40444ba +--- /dev/null ++++ b/arch/arm/cpu/armv8/rcar_gen3/pfc-r8a7798.c +@@ -0,0 +1,3074 @@ ++/* ++ * arch/arm/cpu/armv8/rcar_gen3/pfc-r8a7798.c ++ * This file is r8a7798 processor support - PFC hardware block. ++ * ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ */ ++ ++#include ++#include ++#include ++ ++#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_30(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_25(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) ++ ++#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_ALL_PORT(fn, pfx, sfx) \ ++ CPU_32_PORT_22(fn, pfx##_0_, sfx), \ ++ CPU_32_PORT_28(fn, pfx##_1_, sfx), \ ++ CPU_32_PORT_30(fn, pfx##_2_, sfx), \ ++ CPU_32_PORT_17(fn, pfx##_3_, sfx), \ ++ CPU_32_PORT_25(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, ++ GFN_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_FSO_TOE_N, ++ GFN_FSO_CFE_1_N, ++ GFN_FSO_CFE_0_N, ++ GFN_SDA3, ++ GFN_SCL3, ++ GFN_MSIOF0_SS2, ++ GFN_MSIOF0_SS1, ++ GFN_MSIOF0_SYNC, ++ GFN_MSIOF0_SCK, ++ GFN_MSIOF0_TXD, ++ GFN_MSIOF0_RXD, ++ GFN_IRQ5, ++ GFN_IRQ4, ++ 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 */ ++ FN_GETHER_LINK_A, ++ FN_GETHER_PHY_INT_A, ++ FN_GETHER_MAGIC, ++ FN_GETHER_MDC_A, ++ FN_GETHER_MDIO_A, ++ FN_GETHER_TXCREFCLK_MEGA, ++ FN_GETHER_TXCREFCLK, ++ FN_GETHER_TD3, ++ FN_GETHER_TD2, ++ FN_GETHER_TD1, ++ FN_GETHER_TD0, ++ FN_GETHER_TXC, ++ FN_GETHER_TX_CTL, ++ FN_GETHER_RD3, ++ FN_GETHER_RD2, ++ FN_GETHER_RD1, ++ FN_GETHER_RD0, ++ FN_GETHER_RXC, ++ FN_GETHER_RX_CTL, ++ 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_SCK4, ++ FN_GETHER_RMII_CRS_DV, ++ FN_A0, ++ IFN_DU_DR3, ++ FN_RX4, ++ FN_GETHER_RMII_RX_ER, ++ FN_A1, ++ IFN_DU_DR4, ++ FN_TX4, ++ FN_GETHER_RMII_RXD0, ++ FN_A2, ++ IFN_DU_DR5, ++ FN_CTS4_N, ++ FN_GETHER_RMII_RXD1, ++ FN_A3, ++ IFN_DU_DR6, ++ FN_RTS4_N_TANS, ++ FN_GETHER_RMII_TXD_EN, ++ FN_A4, ++ IFN_DU_DR7, ++ FN_GETHER_RMII_TXD0, ++ FN_A5, ++ IFN_DU_DG2, ++ FN_GETHER_RMII_TXD1, ++ FN_A6, ++ IFN_DU_DG3, ++ FN_CPG_CPCKOUT, ++ FN_GETHER_RMII_REFCLK, ++ FN_A7, ++ FN_PWMFSW0, ++ ++ /* IPSR1 */ ++ IFN_DU_DG4, ++ FN_SCL5, ++ FN_A8, ++ IFN_DU_DG5, ++ FN_SDA5, ++ FN_GETHER_MDC_B, ++ FN_A9, ++ IFN_DU_DG6, ++ FN_SCIF_CLK_A, ++ FN_GETHER_MDIO_B, ++ FN_A10, ++ IFN_DU_DG7, ++ FN_HRX0_A, ++ FN_A11, ++ IFN_DU_DB2, ++ FN_HSCK0_A, ++ FN_A12, ++ FN_IRQ1, ++ IFN_DU_DB3, ++ FN_HRTS0_N_A, ++ FN_A13, ++ FN_IRQ2, ++ IFN_DU_DB4, ++ FN_HCTS0_N_A, ++ FN_A14, ++ FN_IRQ3, ++ IFN_DU_DB5, ++ FN_HTX0_A, ++ FN_PWM0_A, ++ FN_A15, ++ ++ /* IPSR2 */ ++ IFN_DU_DB6, ++ FN_MSIOF3_RXD, ++ FN_A16, ++ IFN_DU_DB7, ++ FN_MSIOF3_TXD, ++ FN_A17, ++ IFN_DU_DOTCLKOUT, ++ FN_MSIOF3_SS1, ++ FN_GETHER_LINK_B, ++ FN_A18, ++ IFN_DU_EXHSYNC_DU_HSYNC, ++ FN_MSIOF3_SS2, ++ FN_GETHER_PHY_INT_B, ++ FN_A19, ++ FN_FXR_TXENA_N, ++ IFN_DU_EXVSYNC_DU_VSYNC, ++ FN_MSIOF3_SCK, ++ FN_FXR_TXENB_N, ++ IFN_DU_EXODDF_DU_ODDF_DISP_CDE, ++ FN_MSIOF3_SYNC, ++ 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, ++ IFN_VI0_DATA3, ++ FN_HSCK1, ++ 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, ++ IFN_VI0_DATA9, ++ FN_HCTS2_N, ++ FN_PWM1_A, ++ FN_FSO_CFE_0_N_B, ++ IFN_VI0_DATA10, ++ FN_HRTS2_N, ++ FN_PWM2_A, ++ IFN_VI0_DATA11, ++ FN_HTX2, ++ FN_PWM3_A, ++ IFN_VI0_FIELD, ++ FN_HRX2, ++ FN_PWM4_A, ++ FN_CS1_N, ++ 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, ++ FN_MMC_WP, ++ IFN_VI1_DATA1, ++ FN_MSIOF1_SS2, ++ FN_D4, ++ FN_MMC_CD, ++ IFN_VI1_DATA2, ++ FN_CANFD0_TX_B, ++ FN_D5, ++ FN_MMC_DS, ++ IFN_VI1_DATA3, ++ FN_CANFD0_RX_B, ++ FN_D6, ++ FN_MMC_CMD, ++ ++ /* IPSR6 */ ++ IFN_VI1_DATA4, ++ FN_CANFD_CLK_B, ++ FN_D7, ++ FN_MMC_D0, ++ IFN_VI1_DATA5, ++ FN_D8, ++ FN_MMC_D1, ++ IFN_VI1_DATA6, ++ FN_D9, ++ FN_MMC_D2, ++ IFN_VI1_DATA7, ++ FN_D10, ++ FN_MMC_D3, ++ IFN_VI1_DATA8, ++ FN_D11, ++ FN_MMC_CLK, ++ IFN_VI1_DATA9, ++ FN_TCLK1_A, ++ FN_D12, ++ FN_MMC_D4, ++ IFN_VI1_DATA10, ++ FN_TCLK2_A, ++ FN_D13, ++ FN_MMC_D5, ++ IFN_VI1_DATA11, ++ FN_SCL4, ++ FN_D14, ++ FN_MMC_D6, ++ ++ /* IPSR7 */ ++ IFN_VI1_FIELD, ++ FN_SDA4, ++ FN_D15, ++ FN_MMC_D7, ++ IFN_SCL0, ++ FN_CLKOUT, ++ IFN_SDA0, ++ FN_BS_N, ++ FN_SCK0, ++ FN_HSCK0_B, ++ IFN_SCL1, ++ FN_TPU0TO2, ++ FN_RD_N, ++ FN_CTS0_N, ++ FN_HCTS0_N_B, ++ IFN_SDA1, ++ FN_TPU0TO3, ++ FN_WE0_N, ++ FN_RTS0_N_TANS, ++ FN_HRTS0_N_B, ++ IFN_SCL2, ++ FN_WE1_N, ++ FN_RX0, ++ FN_HRX0_B, ++ IFN_SDA2, ++ FN_EX_WAIT0, ++ FN_TX0, ++ FN_HTX0_B, ++ IFN_AVB0_AVTP_MATCH, ++ FN_TPU0TO0, ++ ++ /* IPSR8 */ ++ IFN_AVB0_AVTP_CAPTURE, ++ FN_TPU0TO1, ++ IFN_CANFD0_TX_A, ++ FN_FXR_TXDA, ++ FN_PWM0_B, ++ FN_DU_DISP, ++ 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, ++ ++ /* IPSR9 */ ++ IFN_IRQ4, ++ FN_VI0_DATA12, ++ IFN_IRQ5, ++ FN_VI0_DATA13, ++ IFN_MSIOF0_RXD, ++ FN_DU_DR0, ++ FN_VI0_DATA14, ++ IFN_MSIOF0_TXD, ++ FN_DU_DR1, ++ FN_VI0_DATA15, ++ IFN_MSIOF0_SCK, ++ FN_DU_DG0, ++ FN_VI0_DATA16, ++ IFN_MSIOF0_SYNC, ++ FN_DU_DG1, ++ FN_VI0_DATA17, ++ IFN_MSIOF0_SS1, ++ FN_DU_DB0, ++ FN_TCLK3, ++ FN_VI0_DATA18, ++ IFN_MSIOF0_SS2, ++ FN_DU_DB1, ++ FN_TCLK4, ++ FN_VI0_DATA19, ++ ++ /* IPSR10 */ ++ IFN_SCL3, ++ FN_VI0_DATA20, ++ IFN_SDA3, ++ FN_VI0_DATA21, ++ IFN_FSO_CFE_0_N, ++ FN_VI0_DATA22, ++ IFN_FSO_CFE_1_N, ++ FN_VI0_DATA23, ++ IFN_FSO_TOE_N, ++ ++ /* MOD_SEL0 */ ++ FN_SEL_CANFD0_0, FN_SEL_CANFD0_1, ++ FN_SEL_GETHER_0, FN_SEL_GETHER_1, ++ FN_SEL_HSCIF0_0, FN_SEL_HSCIF0_1, ++ FN_SEL_PWM0_0, FN_SEL_PWM0_1, ++ FN_SEL_PWM1_0, FN_SEL_PWM1_1, ++ FN_SEL_PWM2_0, FN_SEL_PWM2_1, ++ FN_SEL_PWM3_0, FN_SEL_PWM3_1, ++ FN_SEL_PWM4_0, FN_SEL_PWM4_1, ++ FN_SEL_RSP_0, FN_SEL_RSP_1, ++ FN_SEL_SCIF1_0, FN_SEL_SCIF1_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_GMARK, ++ 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 */ ++ FSO_TOE_N_GMARK, ++ FSO_CFE_1_N_GMARK, ++ FSO_CFE_0_N_GMARK, ++ SDA3_GMARK, ++ SCL3_GMARK, ++ MSIOF0_SS2_GMARK, ++ MSIOF0_SS1_GMARK, ++ MSIOF0_SYNC_GMARK, ++ MSIOF0_SCK_GMARK, ++ MSIOF0_TXD_GMARK, ++ MSIOF0_RXD_GMARK, ++ IRQ5_GMARK, ++ IRQ4_GMARK, ++ 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 */ ++ GETHER_LINK_A_MARK, ++ GETHER_PHY_INT_A_MARK, ++ GETHER_MAGIC_MARK, ++ GETHER_MDC_A_MARK, ++ GETHER_MDIO_A_MARK, ++ GETHER_TXCREFCLK_MEGA_MARK, ++ GETHER_TXCREFCLK_MARK, ++ GETHER_TD3_MARK, ++ GETHER_TD2_MARK, ++ GETHER_TD1_MARK, ++ GETHER_TD0_MARK, ++ GETHER_TXC_MARK, ++ GETHER_TX_CTL_MARK, ++ GETHER_RD3_MARK, ++ GETHER_RD2_MARK, ++ GETHER_RD1_MARK, ++ GETHER_RD0_MARK, ++ GETHER_RXC_MARK, ++ GETHER_RX_CTL_MARK, ++ 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, ++ SCK4_MARK, ++ GETHER_RMII_CRS_DV_MARK, ++ A0_MARK, ++ DU_DR3_IMARK, ++ RX4_MARK, ++ GETHER_RMII_RX_ER_MARK, ++ A1_MARK, ++ DU_DR4_IMARK, ++ TX4_MARK, ++ GETHER_RMII_RXD0_MARK, ++ A2_MARK, ++ DU_DR5_IMARK, ++ CTS4_N_MARK, ++ GETHER_RMII_RXD1_MARK, ++ A3_MARK, ++ DU_DR6_IMARK, ++ RTS4_N_TANS_MARK, ++ GETHER_RMII_TXD_EN_MARK, ++ A4_MARK, ++ DU_DR7_IMARK, ++ GETHER_RMII_TXD0_MARK, ++ A5_MARK, ++ DU_DG2_IMARK, ++ GETHER_RMII_TXD1_MARK, ++ A6_MARK, ++ DU_DG3_IMARK, ++ CPG_CPCKOUT_MARK, ++ GETHER_RMII_REFCLK_MARK, ++ A7_MARK, ++ PWMFSW0_MARK, ++ ++ /* IPSR1 */ ++ DU_DG4_IMARK, ++ SCL5_MARK, ++ A8_MARK, ++ DU_DG5_IMARK, ++ SDA5_MARK, ++ GETHER_MDC_B_MARK, ++ A9_MARK, ++ DU_DG6_IMARK, ++ SCIF_CLK_A_MARK, ++ GETHER_MDIO_B_MARK, ++ A10_MARK, ++ DU_DG7_IMARK, ++ HRX0_A_MARK, ++ A11_MARK, ++ DU_DB2_IMARK, ++ HSCK0_A_MARK, ++ A12_MARK, ++ IRQ1_MARK, ++ DU_DB3_IMARK, ++ HRTS0_N_A_MARK, ++ A13_MARK, ++ IRQ2_MARK, ++ DU_DB4_IMARK, ++ HCTS0_N_A_MARK, ++ A14_MARK, ++ IRQ3_MARK, ++ DU_DB5_IMARK, ++ HTX0_A_MARK, ++ PWM0_A_MARK, ++ A15_MARK, ++ ++ /* IPSR2 */ ++ DU_DB6_IMARK, ++ MSIOF3_RXD_MARK, ++ A16_MARK, ++ DU_DB7_IMARK, ++ MSIOF3_TXD_MARK, ++ A17_MARK, ++ DU_DOTCLKOUT_IMARK, ++ MSIOF3_SS1_MARK, ++ GETHER_LINK_B_MARK, ++ A18_MARK, ++ DU_EXHSYNC_DU_HSYNC_IMARK, ++ MSIOF3_SS2_MARK, ++ GETHER_PHY_INT_B_MARK, ++ A19_MARK, ++ FXR_TXENA_N_MARK, ++ DU_EXVSYNC_DU_VSYNC_IMARK, ++ MSIOF3_SCK_MARK, ++ FXR_TXENB_N_MARK, ++ DU_EXODDF_DU_ODDF_DISP_CDE_IMARK, ++ MSIOF3_SYNC_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, ++ VI0_DATA3_IMARK, ++ HSCK1_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, ++ VI0_DATA9_IMARK, ++ HCTS2_N_MARK, ++ PWM1_A_MARK, ++ FSO_CFE_0_N_B_MARK, ++ VI0_DATA10_IMARK, ++ HRTS2_N_MARK, ++ PWM2_A_MARK, ++ VI0_DATA11_IMARK, ++ HTX2_MARK, ++ PWM3_A_MARK, ++ VI0_FIELD_IMARK, ++ HRX2_MARK, ++ PWM4_A_MARK, ++ CS1_N_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, ++ MMC_WP_MARK, ++ VI1_DATA1_IMARK, ++ MSIOF1_SS2_MARK, ++ D4_MARK, ++ MMC_CD_MARK, ++ VI1_DATA2_IMARK, ++ CANFD0_TX_B_MARK, ++ D5_MARK, ++ MMC_DS_MARK, ++ VI1_DATA3_IMARK, ++ CANFD0_RX_B_MARK, ++ D6_MARK, ++ MMC_CMD_MARK, ++ ++ /* IPSR6 */ ++ VI1_DATA4_IMARK, ++ CANFD_CLK_B_MARK, ++ D7_MARK, ++ MMC_D0_MARK, ++ VI1_DATA5_IMARK, ++ D8_MARK, ++ MMC_D1_MARK, ++ VI1_DATA6_IMARK, ++ D9_MARK, ++ MMC_D2_MARK, ++ VI1_DATA7_IMARK, ++ D10_MARK, ++ MMC_D3_MARK, ++ VI1_DATA8_IMARK, ++ D11_MARK, ++ MMC_CLK_MARK, ++ VI1_DATA9_IMARK, ++ TCLK1_A_MARK, ++ D12_MARK, ++ MMC_D4_MARK, ++ VI1_DATA10_IMARK, ++ TCLK2_A_MARK, ++ D13_MARK, ++ MMC_D5_MARK, ++ VI1_DATA11_IMARK, ++ SCL4_MARK, ++ D14_MARK, ++ MMC_D6_MARK, ++ ++ /* IPSR7 */ ++ VI1_FIELD_IMARK, ++ SDA4_MARK, ++ D15_MARK, ++ MMC_D7_MARK, ++ SCL0_IMARK, ++ CLKOUT_MARK, ++ SDA0_IMARK, ++ BS_N_MARK, ++ SCK0_MARK, ++ HSCK0_B_MARK, ++ SCL1_IMARK, ++ TPU0TO2_MARK, ++ RD_N_MARK, ++ CTS0_N_MARK, ++ HCTS0_N_B_MARK, ++ SDA1_IMARK, ++ TPU0TO3_MARK, ++ WE0_N_MARK, ++ RTS0_N_TANS_MARK, ++ HRTS0_N_B_MARK, ++ SCL2_IMARK, ++ WE1_N_MARK, ++ RX0_MARK, ++ HRX0_B_MARK, ++ SDA2_IMARK, ++ EX_WAIT0_MARK, ++ TX0_MARK, ++ HTX0_B_MARK, ++ AVB0_AVTP_MATCH_IMARK, ++ TPU0TO0_MARK, ++ ++ /* IPSR8 */ ++ AVB0_AVTP_CAPTURE_IMARK, ++ TPU0TO1_MARK, ++ CANFD0_TX_A_IMARK, ++ FXR_TXDA_MARK, ++ PWM0_B_MARK, ++ DU_DISP_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, ++ ++ /* IPSR9 */ ++ IRQ4_IMARK, ++ VI0_DATA12_MARK, ++ IRQ5_IMARK, ++ VI0_DATA13_MARK, ++ MSIOF0_RXD_IMARK, ++ DU_DR0_MARK, ++ VI0_DATA14_MARK, ++ MSIOF0_TXD_IMARK, ++ DU_DR1_MARK, ++ VI0_DATA15_MARK, ++ MSIOF0_SCK_IMARK, ++ DU_DG0_MARK, ++ VI0_DATA16_MARK, ++ MSIOF0_SYNC_IMARK, ++ DU_DG1_MARK, ++ VI0_DATA17_MARK, ++ MSIOF0_SS1_IMARK, ++ DU_DB0_MARK, ++ TCLK3_MARK, ++ VI0_DATA18_MARK, ++ MSIOF0_SS2_IMARK, ++ DU_DB1_MARK, ++ TCLK4_MARK, ++ VI0_DATA19_MARK, ++ ++ /* IPSR10 */ ++ SCL3_IMARK, ++ VI0_DATA20_MARK, ++ SDA3_IMARK, ++ VI0_DATA21_MARK, ++ FSO_CFE_0_N_IMARK, ++ VI0_DATA22_MARK, ++ FSO_CFE_1_N_IMARK, ++ VI0_DATA23_MARK, ++ FSO_TOE_N_IMARK, ++ ++ 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_GMARK, GFN_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(FSO_TOE_N_GMARK, GFN_FSO_TOE_N), ++ PINMUX_DATA(FSO_CFE_1_N_GMARK, GFN_FSO_CFE_1_N), ++ PINMUX_DATA(FSO_CFE_0_N_GMARK, GFN_FSO_CFE_0_N), ++ PINMUX_DATA(SDA3_GMARK, GFN_SDA3), ++ PINMUX_DATA(SCL3_GMARK, GFN_SCL3), ++ PINMUX_DATA(MSIOF0_SS2_GMARK, GFN_MSIOF0_SS2), ++ PINMUX_DATA(MSIOF0_SS1_GMARK, GFN_MSIOF0_SS1), ++ PINMUX_DATA(MSIOF0_SYNC_GMARK, GFN_MSIOF0_SYNC), ++ PINMUX_DATA(MSIOF0_SCK_GMARK, GFN_MSIOF0_SCK), ++ PINMUX_DATA(MSIOF0_TXD_GMARK, GFN_MSIOF0_TXD), ++ PINMUX_DATA(MSIOF0_RXD_GMARK, GFN_MSIOF0_RXD), ++ PINMUX_DATA(IRQ5_GMARK, GFN_IRQ5), ++ PINMUX_DATA(IRQ4_GMARK, GFN_IRQ4), ++ 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(GETHER_LINK_A_MARK, FN_GETHER_LINK_A), ++ PINMUX_DATA(GETHER_PHY_INT_A_MARK, FN_GETHER_PHY_INT_A), ++ PINMUX_DATA(GETHER_MAGIC_MARK, FN_GETHER_MAGIC), ++ PINMUX_DATA(GETHER_MDC_A_MARK, FN_GETHER_MDC_A), ++ PINMUX_DATA(GETHER_MDIO_A_MARK, FN_GETHER_MDIO_A), ++ PINMUX_DATA(GETHER_TXCREFCLK_MEGA_MARK, FN_GETHER_TXCREFCLK_MEGA), ++ PINMUX_DATA(GETHER_TXCREFCLK_MARK, FN_GETHER_TXCREFCLK), ++ PINMUX_DATA(GETHER_TD3_MARK, FN_GETHER_TD3), ++ PINMUX_DATA(GETHER_TD2_MARK, FN_GETHER_TD2), ++ PINMUX_DATA(GETHER_TD1_MARK, FN_GETHER_TD1), ++ PINMUX_DATA(GETHER_TD0_MARK, FN_GETHER_TD0), ++ PINMUX_DATA(GETHER_TXC_MARK, FN_GETHER_TXC), ++ PINMUX_DATA(GETHER_TX_CTL_MARK, FN_GETHER_TX_CTL), ++ PINMUX_DATA(GETHER_RD3_MARK, FN_GETHER_RD3), ++ PINMUX_DATA(GETHER_RD2_MARK, FN_GETHER_RD2), ++ PINMUX_DATA(GETHER_RD1_MARK, FN_GETHER_RD1), ++ PINMUX_DATA(GETHER_RD0_MARK, FN_GETHER_RD0), ++ PINMUX_DATA(GETHER_RXC_MARK, FN_GETHER_RXC), ++ PINMUX_DATA(GETHER_RX_CTL_MARK, FN_GETHER_RX_CTL), ++ 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, SCK4), ++ PINMUX_IPSR_DATA(DU_DR2, GETHER_RMII_CRS_DV), ++ PINMUX_IPSR_DATA(DU_DR2, A0), ++ PINMUX_IPSR_IDATA(DU_DR3), ++ PINMUX_IPSR_DATA(DU_DR3, RX4), ++ PINMUX_IPSR_DATA(DU_DR3, GETHER_RMII_RX_ER), ++ PINMUX_IPSR_DATA(DU_DR3, A1), ++ PINMUX_IPSR_IDATA(DU_DR4), ++ PINMUX_IPSR_DATA(DU_DR4, TX4), ++ PINMUX_IPSR_DATA(DU_DR4, GETHER_RMII_RXD0), ++ PINMUX_IPSR_DATA(DU_DR4, A2), ++ PINMUX_IPSR_IDATA(DU_DR5), ++ PINMUX_IPSR_DATA(DU_DR5, CTS4_N), ++ PINMUX_IPSR_DATA(DU_DR5, GETHER_RMII_RXD1), ++ PINMUX_IPSR_DATA(DU_DR5, A3), ++ PINMUX_IPSR_IDATA(DU_DR6), ++ PINMUX_IPSR_DATA(DU_DR6, RTS4_N_TANS), ++ PINMUX_IPSR_DATA(DU_DR6, GETHER_RMII_TXD_EN), ++ PINMUX_IPSR_DATA(DU_DR6, A4), ++ PINMUX_IPSR_IDATA(DU_DR7), ++ PINMUX_IPSR_DATA(DU_DR7, GETHER_RMII_TXD0), ++ PINMUX_IPSR_DATA(DU_DR7, A5), ++ PINMUX_IPSR_IDATA(DU_DG2), ++ PINMUX_IPSR_DATA(DU_DG2, GETHER_RMII_TXD1), ++ PINMUX_IPSR_DATA(DU_DG2, A6), ++ PINMUX_IPSR_IDATA(DU_DG3), ++ PINMUX_IPSR_DATA(DU_DG3, CPG_CPCKOUT), ++ PINMUX_IPSR_DATA(DU_DG3, GETHER_RMII_REFCLK), ++ PINMUX_IPSR_DATA(DU_DG3, A7), ++ PINMUX_IPSR_DATA(DU_DG3, PWMFSW0), ++ ++ /* IPSR1 */ ++ PINMUX_IPSR_IDATA(DU_DG4), ++ PINMUX_IPSR_DATA(DU_DG4, SCL5), ++ PINMUX_IPSR_DATA(DU_DG4, A8), ++ PINMUX_IPSR_IDATA(DU_DG5), ++ PINMUX_IPSR_DATA(DU_DG5, SDA5), ++ PINMUX_IPSR_DATA(DU_DG5, GETHER_MDC_B), ++ PINMUX_IPSR_DATA(DU_DG5, A9), ++ PINMUX_IPSR_IDATA(DU_DG6), ++ PINMUX_IPSR_DATA(DU_DG6, SCIF_CLK_A), ++ PINMUX_IPSR_DATA(DU_DG6, GETHER_MDIO_B), ++ PINMUX_IPSR_DATA(DU_DG6, A10), ++ PINMUX_IPSR_IDATA(DU_DG7), ++ PINMUX_IPSR_DATA(DU_DG7, HRX0_A), ++ PINMUX_IPSR_DATA(DU_DG7, A11), ++ PINMUX_IPSR_IDATA(DU_DB2), ++ PINMUX_IPSR_DATA(DU_DB2, HSCK0_A), ++ PINMUX_IPSR_DATA(DU_DB2, A12), ++ PINMUX_IPSR_DATA(DU_DB2, IRQ1), ++ PINMUX_IPSR_IDATA(DU_DB3), ++ PINMUX_IPSR_DATA(DU_DB3, HRTS0_N_A), ++ PINMUX_IPSR_DATA(DU_DB3, A13), ++ PINMUX_IPSR_DATA(DU_DB3, IRQ2), ++ PINMUX_IPSR_IDATA(DU_DB4), ++ PINMUX_IPSR_DATA(DU_DB4, HCTS0_N_A), ++ PINMUX_IPSR_DATA(DU_DB4, A14), ++ PINMUX_IPSR_DATA(DU_DB4, IRQ3), ++ PINMUX_IPSR_IDATA(DU_DB5), ++ PINMUX_IPSR_DATA(DU_DB5, HTX0_A), ++ PINMUX_IPSR_DATA(DU_DB5, PWM0_A), ++ PINMUX_IPSR_DATA(DU_DB5, A15), ++ ++ /* IPSR2 */ ++ PINMUX_IPSR_IDATA(DU_DB6), ++ PINMUX_IPSR_DATA(DU_DB6, MSIOF3_RXD), ++ PINMUX_IPSR_DATA(DU_DB6, A16), ++ PINMUX_IPSR_IDATA(DU_DB7), ++ PINMUX_IPSR_DATA(DU_DB7, MSIOF3_TXD), ++ PINMUX_IPSR_DATA(DU_DB7, A17), ++ PINMUX_IPSR_IDATA(DU_DOTCLKOUT), ++ PINMUX_IPSR_DATA(DU_DOTCLKOUT, MSIOF3_SS1), ++ PINMUX_IPSR_DATA(DU_DOTCLKOUT, GETHER_LINK_B), ++ PINMUX_IPSR_DATA(DU_DOTCLKOUT, A18), ++ PINMUX_IPSR_IDATA(DU_EXHSYNC_DU_HSYNC), ++ PINMUX_IPSR_DATA(DU_EXHSYNC_DU_HSYNC, MSIOF3_SS2), ++ PINMUX_IPSR_DATA(DU_EXHSYNC_DU_HSYNC, GETHER_PHY_INT_B), ++ PINMUX_IPSR_DATA(DU_EXHSYNC_DU_HSYNC, A19), ++ PINMUX_IPSR_DATA(DU_EXHSYNC_DU_HSYNC, FXR_TXENA_N), ++ PINMUX_IPSR_IDATA(DU_EXVSYNC_DU_VSYNC), ++ PINMUX_IPSR_DATA(DU_EXVSYNC_DU_VSYNC, MSIOF3_SCK), ++ PINMUX_IPSR_DATA(DU_EXVSYNC_DU_VSYNC, FXR_TXENB_N), ++ PINMUX_IPSR_IDATA(DU_EXODDF_DU_ODDF_DISP_CDE), ++ PINMUX_IPSR_DATA(DU_EXODDF_DU_ODDF_DISP_CDE, MSIOF3_SYNC), ++ 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_DATA1, SCK1), ++ PINMUX_IPSR_DATA(VI0_DATA1, SPEEDIN_A), ++ PINMUX_IPSR_IDATA(VI0_DATA2), ++ PINMUX_IPSR_DATA(VI0_DATA2, AVB0_AVTP_PPS), ++ PINMUX_IPSR_IDATA(VI0_DATA3), ++ PINMUX_IPSR_DATA(VI0_DATA3, HSCK1), ++ 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_IDATA(VI0_DATA9), ++ PINMUX_IPSR_DATA(VI0_DATA9, HCTS2_N), ++ PINMUX_IPSR_DATA(VI0_DATA9, PWM1_A), ++ 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_IDATA(VI0_DATA11), ++ PINMUX_IPSR_DATA(VI0_DATA11, HTX2), ++ PINMUX_IPSR_DATA(VI0_DATA11, PWM3_A), ++ 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), ++ 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_DATA(VI1_DATA0, MMC_WP), ++ PINMUX_IPSR_IDATA(VI1_DATA1), ++ PINMUX_IPSR_DATA(VI1_DATA1, MSIOF1_SS2), ++ PINMUX_IPSR_DATA(VI1_DATA1, D4), ++ PINMUX_IPSR_DATA(VI1_DATA1, MMC_CD), ++ 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_DS), ++ 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_CMD), ++ ++ /* 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_D0), ++ PINMUX_IPSR_IDATA(VI1_DATA5), ++ PINMUX_IPSR_DATA(VI1_DATA5, D8), ++ PINMUX_IPSR_DATA(VI1_DATA5, MMC_D1), ++ PINMUX_IPSR_IDATA(VI1_DATA6), ++ PINMUX_IPSR_DATA(VI1_DATA6, D9), ++ PINMUX_IPSR_DATA(VI1_DATA6, MMC_D2), ++ PINMUX_IPSR_IDATA(VI1_DATA7), ++ PINMUX_IPSR_DATA(VI1_DATA7, D10), ++ PINMUX_IPSR_DATA(VI1_DATA7, MMC_D3), ++ PINMUX_IPSR_IDATA(VI1_DATA8), ++ PINMUX_IPSR_DATA(VI1_DATA8, D11), ++ PINMUX_IPSR_DATA(VI1_DATA8, MMC_CLK), ++ PINMUX_IPSR_IDATA(VI1_DATA9), ++ PINMUX_IPSR_DATA(VI1_DATA9, TCLK1_A), ++ PINMUX_IPSR_DATA(VI1_DATA9, D12), ++ PINMUX_IPSR_DATA(VI1_DATA9, MMC_D4), ++ PINMUX_IPSR_IDATA(VI1_DATA10), ++ PINMUX_IPSR_DATA(VI1_DATA10, TCLK2_A), ++ PINMUX_IPSR_DATA(VI1_DATA10, D13), ++ PINMUX_IPSR_DATA(VI1_DATA10, MMC_D5), ++ PINMUX_IPSR_IDATA(VI1_DATA11), ++ PINMUX_IPSR_DATA(VI1_DATA11, SCL4), ++ PINMUX_IPSR_DATA(VI1_DATA11, D14), ++ PINMUX_IPSR_DATA(VI1_DATA11, MMC_D6), ++ ++ /* IPSR7 */ ++ PINMUX_IPSR_IDATA(VI1_FIELD), ++ PINMUX_IPSR_DATA(VI1_FIELD, SDA4), ++ PINMUX_IPSR_DATA(VI1_FIELD, D15), ++ PINMUX_IPSR_DATA(VI1_FIELD, MMC_D7), ++ PINMUX_IPSR_IDATA(SCL0), ++ PINMUX_IPSR_DATA(SCL0, CLKOUT), ++ PINMUX_IPSR_IDATA(SDA0), ++ PINMUX_IPSR_DATA(SDA0, BS_N), ++ PINMUX_IPSR_DATA(SDA0, SCK0), ++ PINMUX_IPSR_DATA(SDA0, HSCK0_B), ++ PINMUX_IPSR_IDATA(SCL1), ++ PINMUX_IPSR_DATA(SCL1, TPU0TO2), ++ PINMUX_IPSR_DATA(SCL1, RD_N), ++ PINMUX_IPSR_DATA(SCL1, CTS0_N), ++ PINMUX_IPSR_DATA(SCL1, HCTS0_N_B), ++ PINMUX_IPSR_IDATA(SDA1), ++ PINMUX_IPSR_DATA(SDA1, TPU0TO3), ++ PINMUX_IPSR_DATA(SDA1, WE0_N), ++ PINMUX_IPSR_DATA(SDA1, RTS0_N_TANS), ++ PINMUX_IPSR_DATA(SDA1, HRTS0_N_B), ++ PINMUX_IPSR_IDATA(SCL2), ++ PINMUX_IPSR_DATA(SCL2, WE1_N), ++ PINMUX_IPSR_DATA(SCL2, RX0), ++ PINMUX_IPSR_DATA(SCL2, HRX0_B), ++ PINMUX_IPSR_IDATA(SDA2), ++ PINMUX_IPSR_DATA(SDA2, EX_WAIT0), ++ PINMUX_IPSR_DATA(SDA2, TX0), ++ PINMUX_IPSR_DATA(SDA2, HTX0_B), ++ PINMUX_IPSR_IDATA(AVB0_AVTP_MATCH), ++ PINMUX_IPSR_DATA(AVB0_AVTP_MATCH, TPU0TO0), ++ ++ /* IPSR8 */ ++ PINMUX_IPSR_IDATA(AVB0_AVTP_CAPTURE), ++ PINMUX_IPSR_DATA(AVB0_AVTP_CAPTURE, TPU0TO1), ++ 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_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), ++ ++ /* IPSR9 */ ++ PINMUX_IPSR_IDATA(IRQ4), ++ PINMUX_IPSR_DATA(IRQ4, VI0_DATA12), ++ PINMUX_IPSR_IDATA(IRQ5), ++ PINMUX_IPSR_DATA(IRQ5, VI0_DATA13), ++ PINMUX_IPSR_IDATA(MSIOF0_RXD), ++ PINMUX_IPSR_DATA(MSIOF0_RXD, DU_DR0), ++ PINMUX_IPSR_DATA(MSIOF0_RXD, VI0_DATA14), ++ PINMUX_IPSR_IDATA(MSIOF0_TXD), ++ PINMUX_IPSR_DATA(MSIOF0_TXD, DU_DR1), ++ PINMUX_IPSR_DATA(MSIOF0_TXD, VI0_DATA15), ++ PINMUX_IPSR_IDATA(MSIOF0_SCK), ++ PINMUX_IPSR_DATA(MSIOF0_SCK, DU_DG0), ++ PINMUX_IPSR_DATA(MSIOF0_SCK, VI0_DATA16), ++ PINMUX_IPSR_IDATA(MSIOF0_SYNC), ++ PINMUX_IPSR_DATA(MSIOF0_SYNC, DU_DG1), ++ PINMUX_IPSR_DATA(MSIOF0_SYNC, VI0_DATA17), ++ PINMUX_IPSR_IDATA(MSIOF0_SS1), ++ PINMUX_IPSR_DATA(MSIOF0_SS1, DU_DB0), ++ PINMUX_IPSR_DATA(MSIOF0_SS1, TCLK3), ++ PINMUX_IPSR_DATA(MSIOF0_SS1, VI0_DATA18), ++ PINMUX_IPSR_IDATA(MSIOF0_SS2), ++ PINMUX_IPSR_DATA(MSIOF0_SS2, DU_DB1), ++ PINMUX_IPSR_DATA(MSIOF0_SS2, TCLK4), ++ PINMUX_IPSR_DATA(MSIOF0_SS2, VI0_DATA19), ++ ++ /* IPSR10 */ ++ PINMUX_IPSR_IDATA(SCL3), ++ PINMUX_IPSR_DATA(SCL3, VI0_DATA20), ++ PINMUX_IPSR_IDATA(SDA3), ++ PINMUX_IPSR_DATA(SDA3, VI0_DATA21), ++ PINMUX_IPSR_IDATA(FSO_CFE_0_N), ++ PINMUX_IPSR_DATA(FSO_CFE_0_N, VI0_DATA22), ++ PINMUX_IPSR_IDATA(FSO_CFE_1_N), ++ PINMUX_IPSR_DATA(FSO_CFE_1_N, VI0_DATA23), ++ PINMUX_IPSR_IDATA(FSO_TOE_N), ++}; ++ ++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_GFN(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(FSO_TOE_N), ++ GPIO_GFN(FSO_CFE_1_N), ++ GPIO_GFN(FSO_CFE_0_N), ++ GPIO_GFN(SDA3), ++ GPIO_GFN(SCL3), ++ GPIO_GFN(MSIOF0_SS2), ++ GPIO_GFN(MSIOF0_SS1), ++ GPIO_GFN(MSIOF0_SYNC), ++ GPIO_GFN(MSIOF0_SCK), ++ GPIO_GFN(MSIOF0_TXD), ++ GPIO_GFN(MSIOF0_RXD), ++ GPIO_GFN(IRQ5), ++ GPIO_GFN(IRQ4), ++ 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_FN(GETHER_LINK_A), ++ GPIO_FN(GETHER_PHY_INT_A), ++ GPIO_FN(GETHER_MAGIC), ++ GPIO_FN(GETHER_MDC_A), ++ GPIO_FN(GETHER_MDIO_A), ++ GPIO_FN(GETHER_TXCREFCLK_MEGA), ++ GPIO_FN(GETHER_TXCREFCLK), ++ GPIO_FN(GETHER_TD3), ++ GPIO_FN(GETHER_TD2), ++ GPIO_FN(GETHER_TD1), ++ GPIO_FN(GETHER_TD0), ++ GPIO_FN(GETHER_TXC), ++ GPIO_FN(GETHER_TX_CTL), ++ GPIO_FN(GETHER_RD3), ++ GPIO_FN(GETHER_RD2), ++ GPIO_FN(GETHER_RD1), ++ GPIO_FN(GETHER_RD0), ++ GPIO_FN(GETHER_RXC), ++ GPIO_FN(GETHER_RX_CTL), ++ 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(SCK4), ++ GPIO_FN(GETHER_RMII_CRS_DV), ++ GPIO_FN(A0), ++ GPIO_IFN(DU_DR3), ++ GPIO_FN(RX4), ++ GPIO_FN(GETHER_RMII_RX_ER), ++ GPIO_FN(A1), ++ GPIO_IFN(DU_DR4), ++ GPIO_FN(TX4), ++ GPIO_FN(GETHER_RMII_RXD0), ++ GPIO_FN(A2), ++ GPIO_IFN(DU_DR5), ++ GPIO_FN(CTS4_N), ++ GPIO_FN(GETHER_RMII_RXD1), ++ GPIO_FN(A3), ++ GPIO_IFN(DU_DR6), ++ GPIO_FN(RTS4_N_TANS), ++ GPIO_FN(GETHER_RMII_TXD_EN), ++ GPIO_FN(A4), ++ GPIO_IFN(DU_DR7), ++ GPIO_FN(GETHER_RMII_TXD0), ++ GPIO_FN(A5), ++ GPIO_IFN(DU_DG2), ++ GPIO_FN(GETHER_RMII_TXD1), ++ GPIO_FN(A6), ++ GPIO_IFN(DU_DG3), ++ GPIO_FN(CPG_CPCKOUT), ++ GPIO_FN(GETHER_RMII_REFCLK), ++ GPIO_FN(A7), ++ GPIO_FN(PWMFSW0), ++ ++ /* IPSR1 */ ++ GPIO_IFN(DU_DG4), ++ GPIO_FN(SCL5), ++ GPIO_FN(A8), ++ GPIO_IFN(DU_DG5), ++ GPIO_FN(SDA5), ++ GPIO_FN(GETHER_MDC_B), ++ GPIO_FN(A9), ++ GPIO_IFN(DU_DG6), ++ GPIO_FN(SCIF_CLK_A), ++ GPIO_FN(GETHER_MDIO_B), ++ GPIO_FN(A10), ++ GPIO_IFN(DU_DG7), ++ GPIO_FN(HRX0_A), ++ GPIO_FN(A11), ++ GPIO_IFN(DU_DB2), ++ GPIO_FN(HSCK0_A), ++ GPIO_FN(A12), ++ GPIO_FN(IRQ1), ++ GPIO_IFN(DU_DB3), ++ GPIO_FN(HRTS0_N_A), ++ GPIO_FN(A13), ++ GPIO_FN(IRQ2), ++ GPIO_IFN(DU_DB4), ++ GPIO_FN(HCTS0_N_A), ++ GPIO_FN(A14), ++ GPIO_FN(IRQ3), ++ GPIO_IFN(DU_DB5), ++ GPIO_FN(HTX0_A), ++ GPIO_FN(PWM0_A), ++ GPIO_FN(A15), ++ ++ /* IPSR2 */ ++ GPIO_IFN(DU_DB6), ++ GPIO_FN(MSIOF3_RXD), ++ GPIO_FN(A16), ++ GPIO_IFN(DU_DB7), ++ GPIO_FN(MSIOF3_TXD), ++ GPIO_FN(A17), ++ GPIO_IFN(DU_DOTCLKOUT), ++ GPIO_FN(MSIOF3_SS1), ++ GPIO_FN(GETHER_LINK_B), ++ GPIO_FN(A18), ++ GPIO_IFN(DU_EXHSYNC_DU_HSYNC), ++ GPIO_FN(MSIOF3_SS2), ++ GPIO_FN(GETHER_PHY_INT_B), ++ GPIO_FN(A19), ++ GPIO_FN(FXR_TXENA_N), ++ GPIO_IFN(DU_EXVSYNC_DU_VSYNC), ++ GPIO_FN(MSIOF3_SCK), ++ GPIO_FN(FXR_TXENB_N), ++ GPIO_IFN(DU_EXODDF_DU_ODDF_DISP_CDE), ++ GPIO_FN(MSIOF3_SYNC), ++ 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_IFN(VI0_DATA3), ++ GPIO_FN(HSCK1), ++ 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_IFN(VI0_DATA9), ++ GPIO_FN(HCTS2_N), ++ GPIO_FN(PWM1_A), ++ GPIO_FN(FSO_CFE_0_N_B), ++ GPIO_IFN(VI0_DATA10), ++ GPIO_FN(HRTS2_N), ++ GPIO_FN(PWM2_A), ++ GPIO_IFN(VI0_DATA11), ++ GPIO_FN(HTX2), ++ GPIO_FN(PWM3_A), ++ GPIO_IFN(VI0_FIELD), ++ GPIO_FN(HRX2), ++ GPIO_FN(PWM4_A), ++ GPIO_FN(CS1_N), ++ 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_FN(MMC_WP), ++ GPIO_IFN(VI1_DATA1), ++ GPIO_FN(MSIOF1_SS2), ++ GPIO_FN(D4), ++ GPIO_FN(MMC_CD), ++ GPIO_IFN(VI1_DATA2), ++ GPIO_FN(CANFD0_TX_B), ++ GPIO_FN(D5), ++ GPIO_FN(MMC_DS), ++ GPIO_IFN(VI1_DATA3), ++ GPIO_FN(CANFD0_RX_B), ++ GPIO_FN(D6), ++ GPIO_FN(MMC_CMD), ++ ++ /* IPSR6 */ ++ GPIO_IFN(VI1_DATA4), ++ GPIO_FN(CANFD_CLK_B), ++ GPIO_FN(D7), ++ GPIO_FN(MMC_D0), ++ GPIO_IFN(VI1_DATA5), ++ GPIO_FN(D8), ++ GPIO_FN(MMC_D1), ++ GPIO_IFN(VI1_DATA6), ++ GPIO_FN(D9), ++ GPIO_FN(MMC_D2), ++ GPIO_IFN(VI1_DATA7), ++ GPIO_FN(D10), ++ GPIO_FN(MMC_D3), ++ GPIO_IFN(VI1_DATA8), ++ GPIO_FN(D11), ++ GPIO_FN(MMC_CLK), ++ GPIO_IFN(VI1_DATA9), ++ GPIO_FN(TCLK1_A), ++ GPIO_FN(D12), ++ GPIO_FN(MMC_D4), ++ GPIO_IFN(VI1_DATA10), ++ GPIO_FN(TCLK2_A), ++ GPIO_FN(D13), ++ GPIO_FN(MMC_D5), ++ GPIO_IFN(VI1_DATA11), ++ GPIO_FN(SCL4), ++ GPIO_FN(D14), ++ GPIO_FN(MMC_D6), ++ ++ /* IPSR7 */ ++ GPIO_IFN(VI1_FIELD), ++ GPIO_FN(SDA4), ++ GPIO_FN(D15), ++ GPIO_FN(MMC_D7), ++ GPIO_IFN(SCL0), ++ GPIO_FN(CLKOUT), ++ GPIO_IFN(SDA0), ++ GPIO_FN(BS_N), ++ GPIO_FN(SCK0), ++ GPIO_FN(HSCK0_B), ++ GPIO_IFN(SCL1), ++ GPIO_FN(TPU0TO2), ++ GPIO_FN(RD_N), ++ GPIO_FN(CTS0_N), ++ GPIO_FN(HCTS0_N_B), ++ GPIO_IFN(SDA1), ++ GPIO_FN(TPU0TO3), ++ GPIO_FN(WE0_N), ++ GPIO_FN(RTS0_N_TANS), ++ GPIO_FN(HRTS0_N_B), ++ GPIO_IFN(SCL2), ++ GPIO_FN(WE1_N), ++ GPIO_FN(RX0), ++ GPIO_FN(HRX0_B), ++ GPIO_IFN(SDA2), ++ GPIO_FN(EX_WAIT0), ++ GPIO_FN(TX0), ++ GPIO_FN(HTX0_B), ++ GPIO_IFN(AVB0_AVTP_MATCH), ++ GPIO_FN(TPU0TO0), ++ ++ /* IPSR8 */ ++ GPIO_IFN(AVB0_AVTP_CAPTURE), ++ GPIO_FN(TPU0TO1), ++ GPIO_IFN(CANFD0_TX_A), ++ GPIO_FN(FXR_TXDA), ++ GPIO_FN(PWM0_B), ++ GPIO_FN(DU_DISP), ++ 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), ++ ++ /* IPSR9 */ ++ GPIO_IFN(IRQ4), ++ GPIO_FN(VI0_DATA12), ++ GPIO_IFN(IRQ5), ++ GPIO_FN(VI0_DATA13), ++ GPIO_IFN(MSIOF0_RXD), ++ GPIO_FN(DU_DR0), ++ GPIO_FN(VI0_DATA14), ++ GPIO_IFN(MSIOF0_TXD), ++ GPIO_FN(DU_DR1), ++ GPIO_FN(VI0_DATA15), ++ GPIO_IFN(MSIOF0_SCK), ++ GPIO_FN(DU_DG0), ++ GPIO_FN(VI0_DATA16), ++ GPIO_IFN(MSIOF0_SYNC), ++ GPIO_FN(DU_DG1), ++ GPIO_FN(VI0_DATA17), ++ GPIO_IFN(MSIOF0_SS1), ++ GPIO_FN(DU_DB0), ++ GPIO_FN(TCLK3), ++ GPIO_FN(VI0_DATA18), ++ GPIO_IFN(MSIOF0_SS2), ++ GPIO_FN(DU_DB1), ++ GPIO_FN(TCLK4), ++ GPIO_FN(VI0_DATA19), ++ ++ /* IPSR10 */ ++ GPIO_IFN(SCL3), ++ GPIO_FN(VI0_DATA20), ++ GPIO_IFN(SDA3), ++ GPIO_FN(VI0_DATA21), ++ GPIO_IFN(FSO_CFE_0_N), ++ GPIO_FN(VI0_DATA22), ++ GPIO_IFN(FSO_CFE_1_N), ++ GPIO_FN(VI0_DATA23), ++ GPIO_IFN(FSO_TOE_N), ++}; ++ ++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, GFN_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, ++ GP_2_29_FN, GFN_FSO_TOE_N, ++ GP_2_28_FN, GFN_FSO_CFE_1_N, ++ GP_2_27_FN, GFN_FSO_CFE_0_N, ++ GP_2_26_FN, GFN_SDA3, ++ GP_2_25_FN, GFN_SCL3, ++ GP_2_24_FN, GFN_MSIOF0_SS2, ++ GP_2_23_FN, GFN_MSIOF0_SS1, ++ GP_2_22_FN, GFN_MSIOF0_SYNC, ++ GP_2_21_FN, GFN_MSIOF0_SCK, ++ GP_2_20_FN, GFN_MSIOF0_TXD, ++ GP_2_19_FN, GFN_MSIOF0_RXD, ++ GP_2_18_FN, GFN_IRQ5, ++ GP_2_17_FN, GFN_IRQ4, ++ 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, ++ GP_4_24_FN, FN_GETHER_LINK_A, ++ GP_4_23_FN, FN_GETHER_PHY_INT_A, ++ GP_4_22_FN, FN_GETHER_MAGIC, ++ GP_4_21_FN, FN_GETHER_MDC_A, ++ GP_4_20_FN, FN_GETHER_MDIO_A, ++ GP_4_19_FN, FN_GETHER_TXCREFCLK_MEGA, ++ GP_4_18_FN, FN_GETHER_TXCREFCLK, ++ GP_4_17_FN, FN_GETHER_TD3, ++ GP_4_16_FN, FN_GETHER_TD2, ++ GP_4_15_FN, FN_GETHER_TD1, ++ GP_4_14_FN, FN_GETHER_TD0, ++ GP_4_13_FN, FN_GETHER_TXC, ++ GP_4_12_FN, FN_GETHER_TX_CTL, ++ GP_4_11_FN, FN_GETHER_RD3, ++ GP_4_10_FN, FN_GETHER_RD2, ++ GP_4_9_FN, FN_GETHER_RD1, ++ GP_4_8_FN, FN_GETHER_RD0, ++ GP_4_7_FN, FN_GETHER_RXC, ++ GP_4_6_FN, FN_GETHER_RX_CTL, ++ 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_CPG_CPCKOUT, FN_GETHER_RMII_REFCLK, FN_A7, ++ FN_PWMFSW0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR0_27_24 [4] */ ++ IFN_DU_DG2, 0, FN_GETHER_RMII_TXD1, FN_A6, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR0_23_20 [4] */ ++ IFN_DU_DR7, 0, FN_GETHER_RMII_TXD0, FN_A5, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR0_19_16 [4] */ ++ IFN_DU_DR6, FN_RTS4_N_TANS, FN_GETHER_RMII_TXD_EN, FN_A4, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR0_15_12 [4] */ ++ IFN_DU_DR5, FN_CTS4_N, FN_GETHER_RMII_RXD1, FN_A3, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR0_11_8 [4] */ ++ IFN_DU_DR4, FN_TX4, FN_GETHER_RMII_RXD0, FN_A2, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR0_7_4 [4] */ ++ IFN_DU_DR3, FN_RX4, FN_GETHER_RMII_RX_ER, FN_A1, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR0_3_0 [4] */ ++ IFN_DU_DR2, FN_SCK4, FN_GETHER_RMII_CRS_DV, 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, FN_HTX0_A, FN_PWM0_A, FN_A15, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR1_27_24 [4] */ ++ IFN_DU_DB4, FN_HCTS0_N_A, 0, FN_A14, ++ FN_IRQ3, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR1_23_20 [4] */ ++ IFN_DU_DB3, FN_HRTS0_N_A, 0, FN_A13, ++ FN_IRQ2, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR1_19_16 [4] */ ++ IFN_DU_DB2, FN_HSCK0_A, 0, FN_A12, ++ FN_IRQ1, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR1_15_12 [4] */ ++ IFN_DU_DG7, FN_HRX0_A, 0, FN_A11, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR1_11_8 [4] */ ++ IFN_DU_DG6, FN_SCIF_CLK_A, FN_GETHER_MDIO_B, FN_A10, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR1_7_4 [4] */ ++ IFN_DU_DG5, FN_SDA5, FN_GETHER_MDC_B, FN_A9, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR1_3_0 [4] */ ++ IFN_DU_DG4, FN_SCL5, 0, FN_A8, ++ 0, 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, 0, ++ 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, 0, ++ FN_FXR_TXENB_N, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR2_15_12 [4] */ ++ IFN_DU_EXHSYNC_DU_HSYNC, FN_MSIOF3_SS2, FN_GETHER_PHY_INT_B, FN_A19, ++ FN_FXR_TXENA_N, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR2_11_8 [4] */ ++ IFN_DU_DOTCLKOUT, FN_MSIOF3_SS1, FN_GETHER_LINK_B, FN_A18, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR2_7_4 [4] */ ++ IFN_DU_DB7, FN_MSIOF3_TXD, 0, FN_A17, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR2_3_0 [4] */ ++ IFN_DU_DB6, FN_MSIOF3_RXD, 0, FN_A16, ++ 0, 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, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR3_23_20 [4] */ ++ IFN_VI0_DATA2, FN_AVB0_AVTP_PPS, 0, 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, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR4_27_24 [4] */ ++ IFN_VI0_DATA11, FN_HTX2, FN_PWM3_A, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR4_23_20 [4] */ ++ IFN_VI0_DATA10, FN_HRTS2_N, FN_PWM2_A, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR4_19_16 [4] */ ++ IFN_VI0_DATA9, FN_HCTS2_N, FN_PWM1_A, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR4_15_12 [4] */ ++ IFN_VI0_DATA8, FN_HSCK2, 0, 0, ++ 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_CMD, 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_DS, 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_CD, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR5_19_16 [4] */ ++ IFN_VI1_DATA0, FN_MSIOF1_SS1, 0, FN_D3, ++ FN_MMC_WP, 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, 0, FN_D14, ++ FN_MMC_D6, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR6_27_24 [4] */ ++ IFN_VI1_DATA10, FN_TCLK2_A, 0, FN_D13, ++ FN_MMC_D5, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR6_23_20 [4] */ ++ IFN_VI1_DATA9, FN_TCLK1_A, 0, FN_D12, ++ FN_MMC_D4, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR6_19_16 [4] */ ++ IFN_VI1_DATA8, 0, 0, FN_D11, ++ FN_MMC_CLK, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR6_15_12 [4] */ ++ IFN_VI1_DATA7, 0, 0, FN_D10, ++ FN_MMC_D3, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR6_11_8 [4] */ ++ IFN_VI1_DATA6, 0, 0, FN_D9, ++ FN_MMC_D2, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR6_7_4 [4] */ ++ IFN_VI1_DATA5, 0, 0, FN_D8, ++ FN_MMC_D1, 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_D0, 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_MATCH, FN_TPU0TO0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR7_27_24 [4] */ ++ IFN_SDA2, 0, 0, FN_EX_WAIT0, ++ FN_TX0, FN_HTX0_B, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR7_23_20 [4] */ ++ IFN_SCL2, 0, 0, FN_WE1_N, ++ FN_RX0, FN_HRX0_B, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR7_19_16 [4] */ ++ IFN_SDA1, 0, FN_TPU0TO3, FN_WE0_N, ++ FN_RTS0_N_TANS, FN_HRTS0_N_B, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR7_15_12 [4] */ ++ IFN_SCL1, 0, FN_TPU0TO2, FN_RD_N, ++ FN_CTS0_N, FN_HCTS0_N_B, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR7_11_8 [4] */ ++ IFN_SDA0, 0, 0, FN_BS_N, ++ FN_SCK0, FN_HSCK0_B, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR7_7_4 [4] */ ++ IFN_SCL0, 0, 0, FN_CLKOUT, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR7_3_0 [4] */ ++ IFN_VI1_FIELD, FN_SDA4, 0, FN_D15, ++ FN_MMC_D7, 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] */ ++ IFN_DIGRF_CLKOUT, FN_DIGRF_CLKEN_OUT, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR8_27_24 [4] */ ++ IFN_DIGRF_CLKIN, FN_DIGRF_CLKEN_IN, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR8_23_20 [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_19_16 [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_15_12 [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_11_8 [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_7_4 [4] */ ++ IFN_CANFD0_TX_A, FN_FXR_TXDA, FN_PWM0_B, FN_DU_DISP, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR8_3_0 [4] */ ++ IFN_AVB0_AVTP_CAPTURE, FN_TPU0TO1, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ } ++ }, ++ { PINMUX_CFG_REG_VAR("IPSR9", 0xE6060224, 32, ++ 4, 4, 4, 4, 4, 4, 4, 4) { ++ /* IPSR9_31_28 [4] */ ++ IFN_MSIOF0_SS2, FN_DU_DB1, FN_TCLK4, FN_VI0_DATA19, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR9_27_24 [4] */ ++ IFN_MSIOF0_SS1, FN_DU_DB0, FN_TCLK3, FN_VI0_DATA18, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR9_23_20 [4] */ ++ IFN_MSIOF0_SYNC, FN_DU_DG1, 0, FN_VI0_DATA17, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR9_19_16 [4] */ ++ IFN_MSIOF0_SCK, FN_DU_DG0, 0, FN_VI0_DATA16, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR9_15_12 [4] */ ++ IFN_MSIOF0_TXD, FN_DU_DR1, 0, FN_VI0_DATA15, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR9_11_8 [4] */ ++ IFN_MSIOF0_RXD, FN_DU_DR0, 0, FN_VI0_DATA14, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR9_7_4 [4] */ ++ IFN_IRQ5, 0, 0, FN_VI0_DATA13, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR9_3_0 [4] */ ++ IFN_IRQ4, 0, 0, FN_VI0_DATA12, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ } ++ }, ++ { PINMUX_CFG_REG_VAR("IPSR10", 0xE6060228, 32, ++ 4, 4, 4, 4, 4, 4, 4, 4) { ++ /* IPSR10_31_28 [4] */ ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR10_27_24 [4] */ ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR10_23_20 [4] */ ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR10_19_16 [4] */ ++ IFN_FSO_TOE_N, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR10_15_12 [4] */ ++ IFN_FSO_CFE_1_N, 0, 0, FN_VI0_DATA23, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR10_11_8 [4] */ ++ IFN_FSO_CFE_0_N, 0, 0, FN_VI0_DATA22, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR10_7_4 [4] */ ++ IFN_SDA3, 0, 0, FN_VI0_DATA21, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ 0, 0, 0, 0, ++ /* IPSR10_3_0 [4] */ ++ IFN_SCL3, 0, 0, FN_VI0_DATA20, ++ 0, 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, ++ /* SEL_CANFD0 [1] */ ++ FN_SEL_CANFD0_0, ++ FN_SEL_CANFD0_1, ++ /* SEL_GETHER [1] */ ++ FN_SEL_GETHER_0, ++ FN_SEL_GETHER_1, ++ /* SEL_HSCIF0 [1] */ ++ FN_SEL_HSCIF0_0, ++ FN_SEL_HSCIF0_1, ++ /* SEL_PWM4 [1] */ ++ FN_SEL_PWM0_0, ++ FN_SEL_PWM0_1, ++ /* SEL_PWM3 [1] */ ++ FN_SEL_PWM1_0, ++ FN_SEL_PWM1_1, ++ /* SEL_PWM2 [1] */ ++ FN_SEL_PWM2_0, ++ FN_SEL_PWM2_1, ++ /* SEL_PWM1 [1] */ ++ FN_SEL_PWM3_0, ++ FN_SEL_PWM3_1, ++ /* SEL_PWM0 [1] */ ++ FN_SEL_PWM4_0, ++ FN_SEL_PWM4_1, ++ 0, 0, ++ /* SEL_RSP [1] */ ++ FN_SEL_RSP_0, ++ FN_SEL_RSP_1, ++ /* SEL_SCIF1 [1] */ ++ FN_SEL_SCIF1_0, ++ FN_SEL_SCIF1_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, ++ GP_2_29_IN, GP_2_29_OUT, ++ GP_2_28_IN, GP_2_28_OUT, ++ GP_2_27_IN, GP_2_27_OUT, ++ GP_2_26_IN, GP_2_26_OUT, ++ GP_2_25_IN, GP_2_25_OUT, ++ GP_2_24_IN, GP_2_24_OUT, ++ GP_2_23_IN, GP_2_23_OUT, ++ GP_2_22_IN, GP_2_22_OUT, ++ GP_2_21_IN, GP_2_21_OUT, ++ GP_2_20_IN, GP_2_20_OUT, ++ GP_2_19_IN, GP_2_19_OUT, ++ GP_2_18_IN, GP_2_18_OUT, ++ GP_2_17_IN, GP_2_17_OUT, ++ 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, ++ GP_4_24_IN, GP_4_24_OUT, ++ GP_4_23_IN, GP_4_23_OUT, ++ GP_4_22_IN, GP_4_22_OUT, ++ GP_4_21_IN, GP_4_21_OUT, ++ GP_4_20_IN, GP_4_20_OUT, ++ GP_4_19_IN, GP_4_19_OUT, ++ GP_4_18_IN, GP_4_18_OUT, ++ GP_4_17_IN, GP_4_17_OUT, ++ GP_4_16_IN, GP_4_16_OUT, ++ GP_4_15_IN, GP_4_15_OUT, ++ GP_4_14_IN, GP_4_14_OUT, ++ GP_4_13_IN, GP_4_13_OUT, ++ GP_4_12_IN, GP_4_12_OUT, ++ GP_4_11_IN, GP_4_11_OUT, ++ GP_4_10_IN, GP_4_10_OUT, ++ GP_4_9_IN, GP_4_9_OUT, ++ GP_4_8_IN, GP_4_8_OUT, ++ GP_4_7_IN, GP_4_7_OUT, ++ GP_4_6_IN, GP_4_6_OUT, ++ 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, GP_2_29_DATA, GP_2_28_DATA, ++ GP_2_27_DATA, GP_2_26_DATA, GP_2_25_DATA, GP_2_24_DATA, ++ GP_2_23_DATA, GP_2_22_DATA, GP_2_21_DATA, GP_2_20_DATA, ++ GP_2_19_DATA, GP_2_18_DATA, GP_2_17_DATA, 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, GP_4_24_DATA, ++ GP_4_23_DATA, GP_4_22_DATA, GP_4_21_DATA, GP_4_20_DATA, ++ GP_4_19_DATA, GP_4_18_DATA, GP_4_17_DATA, GP_4_16_DATA, ++ GP_4_15_DATA, GP_4_14_DATA, GP_4_13_DATA, GP_4_12_DATA, ++ GP_4_11_DATA, GP_4_10_DATA, GP_4_9_DATA, GP_4_8_DATA, ++ GP_4_7_DATA, GP_4_6_DATA, 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 r8a7798_pinmux_info = { ++ .name = "r8a7798_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_IFN_FSO_TOE_N, ++ ++ .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 r8a7798_pinmux_init(void) ++{ ++ register_pinmux(&r8a7798_pinmux_info); ++} +diff --git a/arch/arm/cpu/armv8/rcar_gen3/pfc.c b/arch/arm/cpu/armv8/rcar_gen3/pfc.c +index bd3aa0a..72c5482 100644 +--- a/arch/arm/cpu/armv8/rcar_gen3/pfc.c ++++ b/arch/arm/cpu/armv8/rcar_gen3/pfc.c +@@ -22,5 +22,7 @@ void pinmux_init(void) + r8a7796_pinmux_init(); + #elif defined(CONFIG_R8A7797) + r8a7797_pinmux_init(); ++#elif defined(CONFIG_R8A7798) ++ r8a7798_pinmux_init(); + #endif + } +diff --git a/arch/arm/include/asm/arch-rcar_gen3/gpio.h b/arch/arm/include/asm/arch-rcar_gen3/gpio.h +index fb8b758..cc94b5c 100644 +--- a/arch/arm/include/asm/arch-rcar_gen3/gpio.h ++++ b/arch/arm/include/asm/arch-rcar_gen3/gpio.h +@@ -18,6 +18,8 @@ + #include + #elif defined(CONFIG_R8A7797) + #include ++#elif defined(CONFIG_R8A7798) ++#include + #endif + + #if defined(CONFIG_R8A7795) +@@ -27,6 +29,8 @@ void r8a7795_es_pinmux_init(void); + void r8a7796_pinmux_init(void); + #elif defined(CONFIG_R8A7797) + void r8a7797_pinmux_init(void); ++#elif defined(CONFIG_R8A7798) ++void r8a7798_pinmux_init(void); + #endif + void pinmux_init(void); + +diff --git a/arch/arm/include/asm/arch-rcar_gen3/r8a7798-gpio.h b/arch/arm/include/asm/arch-rcar_gen3/r8a7798-gpio.h +new file mode 100644 +index 0000000..8d2252f +--- /dev/null ++++ b/arch/arm/include/asm/arch-rcar_gen3/r8a7798-gpio.h +@@ -0,0 +1,522 @@ ++/* ++ * arch/arm/include/asm/arch-rcar_gen3/r8a7798-gpio.h ++ * This file defines pin function control of gpio. ++ * ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ */ ++#ifndef __ASM_R8A7798_GPIO_H__ ++#define __ASM_R8A7798_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_2_17, GPIO_GP_2_18, GPIO_GP_2_19, ++ GPIO_GP_2_20, GPIO_GP_2_21, GPIO_GP_2_22, GPIO_GP_2_23, ++ GPIO_GP_2_24, GPIO_GP_2_25, GPIO_GP_2_26, GPIO_GP_2_27, ++ GPIO_GP_2_28, GPIO_GP_2_29, ++ ++ 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_4_6, GPIO_GP_4_7, ++ GPIO_GP_4_8, GPIO_GP_4_9, GPIO_GP_4_10, GPIO_GP_4_11, ++ GPIO_GP_4_12, GPIO_GP_4_13, GPIO_GP_4_14, GPIO_GP_4_15, ++ GPIO_GP_4_16, GPIO_GP_4_17, GPIO_GP_4_18, GPIO_GP_4_19, ++ GPIO_GP_4_20, GPIO_GP_4_21, GPIO_GP_4_22, GPIO_GP_4_23, ++ GPIO_GP_4_24, ++ ++ 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_GFN_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_FSO_TOE_N, ++ GPIO_GFN_FSO_CFE_1_N, ++ GPIO_GFN_FSO_CFE_0_N, ++ GPIO_GFN_SDA3, ++ GPIO_GFN_SCL3, ++ GPIO_GFN_MSIOF0_SS2, ++ GPIO_GFN_MSIOF0_SS1, ++ GPIO_GFN_MSIOF0_SYNC, ++ GPIO_GFN_MSIOF0_SCK, ++ GPIO_GFN_MSIOF0_TXD, ++ GPIO_GFN_MSIOF0_RXD, ++ GPIO_GFN_IRQ5, ++ GPIO_GFN_IRQ4, ++ 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_FN_GETHER_LINK_A, ++ GPIO_FN_GETHER_PHY_INT_A, ++ GPIO_FN_GETHER_MAGIC, ++ GPIO_FN_GETHER_MDC_A, ++ GPIO_FN_GETHER_MDIO_A, ++ GPIO_FN_GETHER_TXCREFCLK_MEGA, ++ GPIO_FN_GETHER_TXCREFCLK, ++ GPIO_FN_GETHER_TD3, ++ GPIO_FN_GETHER_TD2, ++ GPIO_FN_GETHER_TD1, ++ GPIO_FN_GETHER_TD0, ++ GPIO_FN_GETHER_TXC, ++ GPIO_FN_GETHER_TX_CTL, ++ GPIO_FN_GETHER_RD3, ++ GPIO_FN_GETHER_RD2, ++ GPIO_FN_GETHER_RD1, ++ GPIO_FN_GETHER_RD0, ++ GPIO_FN_GETHER_RXC, ++ GPIO_FN_GETHER_RX_CTL, ++ 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_SCK4, ++ GPIO_FN_GETHER_RMII_CRS_DV, ++ GPIO_FN_A0, ++ GPIO_IFN_DU_DR3, ++ GPIO_FN_RX4, ++ GPIO_FN_GETHER_RMII_RX_ER, ++ GPIO_FN_A1, ++ GPIO_IFN_DU_DR4, ++ GPIO_FN_TX4, ++ GPIO_FN_GETHER_RMII_RXD0, ++ GPIO_FN_A2, ++ GPIO_IFN_DU_DR5, ++ GPIO_FN_CTS4_N, ++ GPIO_FN_GETHER_RMII_RXD1, ++ GPIO_FN_A3, ++ GPIO_IFN_DU_DR6, ++ GPIO_FN_RTS4_N_TANS, ++ GPIO_FN_GETHER_RMII_TXD_EN, ++ GPIO_FN_A4, ++ GPIO_IFN_DU_DR7, ++ GPIO_FN_GETHER_RMII_TXD0, ++ GPIO_FN_A5, ++ GPIO_IFN_DU_DG2, ++ GPIO_FN_GETHER_RMII_TXD1, ++ GPIO_FN_A6, ++ GPIO_IFN_DU_DG3, ++ GPIO_FN_CPG_CPCKOUT, ++ GPIO_FN_GETHER_RMII_REFCLK, ++ GPIO_FN_A7, ++ GPIO_FN_PWMFSW0, ++ ++ /* IPSR1 */ ++ GPIO_IFN_DU_DG4, ++ GPIO_FN_SCL5, ++ GPIO_FN_A8, ++ GPIO_IFN_DU_DG5, ++ GPIO_FN_SDA5, ++ GPIO_FN_GETHER_MDC_B, ++ GPIO_FN_A9, ++ GPIO_IFN_DU_DG6, ++ GPIO_FN_SCIF_CLK_A, ++ GPIO_FN_GETHER_MDIO_B, ++ GPIO_FN_A10, ++ GPIO_IFN_DU_DG7, ++ GPIO_FN_HRX0_A, ++ GPIO_FN_A11, ++ GPIO_IFN_DU_DB2, ++ GPIO_FN_HSCK0_A, ++ GPIO_FN_A12, ++ GPIO_FN_IRQ1, ++ GPIO_IFN_DU_DB3, ++ GPIO_FN_HRTS0_N_A, ++ GPIO_FN_A13, ++ GPIO_FN_IRQ2, ++ GPIO_IFN_DU_DB4, ++ GPIO_FN_HCTS0_N_A, ++ GPIO_FN_A14, ++ GPIO_FN_IRQ3, ++ GPIO_IFN_DU_DB5, ++ GPIO_FN_HTX0_A, ++ GPIO_FN_PWM0_A, ++ GPIO_FN_A15, ++ ++ /* IPSR2 */ ++ GPIO_IFN_DU_DB6, ++ GPIO_FN_MSIOF3_RXD, ++ GPIO_FN_A16, ++ GPIO_IFN_DU_DB7, ++ GPIO_FN_MSIOF3_TXD, ++ GPIO_FN_A17, ++ GPIO_IFN_DU_DOTCLKOUT, ++ GPIO_FN_MSIOF3_SS1, ++ GPIO_FN_GETHER_LINK_B, ++ GPIO_FN_A18, ++ GPIO_IFN_DU_EXHSYNC_DU_HSYNC, ++ GPIO_FN_MSIOF3_SS2, ++ GPIO_FN_GETHER_PHY_INT_B, ++ GPIO_FN_A19, ++ GPIO_FN_FXR_TXENA_N, ++ GPIO_IFN_DU_EXVSYNC_DU_VSYNC, ++ GPIO_FN_MSIOF3_SCK, ++ GPIO_FN_FXR_TXENB_N, ++ GPIO_IFN_DU_EXODDF_DU_ODDF_DISP_CDE, ++ GPIO_FN_MSIOF3_SYNC, ++ 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_IFN_VI0_DATA3, ++ GPIO_FN_HSCK1, ++ 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_IFN_VI0_DATA9, ++ GPIO_FN_HCTS2_N, ++ GPIO_FN_PWM1_A, ++ GPIO_FN_FSO_CFE_0_N_B, ++ GPIO_IFN_VI0_DATA10, ++ GPIO_FN_HRTS2_N, ++ GPIO_FN_PWM2_A, ++ GPIO_IFN_VI0_DATA11, ++ GPIO_FN_HTX2, ++ GPIO_FN_PWM3_A, ++ GPIO_IFN_VI0_FIELD, ++ GPIO_FN_HRX2, ++ GPIO_FN_PWM4_A, ++ GPIO_FN_CS1_N, ++ 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_FN_MMC_WP, ++ GPIO_IFN_VI1_DATA1, ++ GPIO_FN_MSIOF1_SS2, ++ GPIO_FN_D4, ++ GPIO_FN_MMC_CD, ++ GPIO_IFN_VI1_DATA2, ++ GPIO_FN_CANFD0_TX_B, ++ GPIO_FN_D5, ++ GPIO_FN_MMC_DS, ++ GPIO_IFN_VI1_DATA3, ++ GPIO_FN_CANFD0_RX_B, ++ GPIO_FN_D6, ++ GPIO_FN_MMC_CMD, ++ ++ /* IPSR6 */ ++ GPIO_IFN_VI1_DATA4, ++ GPIO_FN_CANFD_CLK_B, ++ GPIO_FN_D7, ++ GPIO_FN_MMC_D0, ++ GPIO_IFN_VI1_DATA5, ++ GPIO_FN_D8, ++ GPIO_FN_MMC_D1, ++ GPIO_IFN_VI1_DATA6, ++ GPIO_FN_D9, ++ GPIO_FN_MMC_D2, ++ GPIO_IFN_VI1_DATA7, ++ GPIO_FN_D10, ++ GPIO_FN_MMC_D3, ++ GPIO_IFN_VI1_DATA8, ++ GPIO_FN_D11, ++ GPIO_FN_MMC_CLK, ++ GPIO_IFN_VI1_DATA9, ++ GPIO_FN_TCLK1_A, ++ GPIO_FN_D12, ++ GPIO_FN_MMC_D4, ++ GPIO_IFN_VI1_DATA10, ++ GPIO_FN_TCLK2_A, ++ GPIO_FN_D13, ++ GPIO_FN_MMC_D5, ++ GPIO_IFN_VI1_DATA11, ++ GPIO_FN_SCL4, ++ GPIO_FN_D14, ++ GPIO_FN_MMC_D6, ++ ++ /* IPSR7 */ ++ GPIO_IFN_VI1_FIELD, ++ GPIO_FN_SDA4, ++ GPIO_FN_D15, ++ GPIO_FN_MMC_D7, ++ GPIO_IFN_SCL0, ++ GPIO_FN_CLKOUT, ++ GPIO_IFN_SDA0, ++ GPIO_FN_BS_N, ++ GPIO_FN_SCK0, ++ GPIO_FN_HSCK0_B, ++ GPIO_IFN_SCL1, ++ GPIO_FN_TPU0TO2, ++ GPIO_FN_RD_N, ++ GPIO_FN_CTS0_N, ++ GPIO_FN_HCTS0_N_B, ++ GPIO_IFN_SDA1, ++ GPIO_FN_TPU0TO3, ++ GPIO_FN_WE0_N, ++ GPIO_FN_RTS0_N_TANS, ++ GPIO_FN_HRTS0_N_B, ++ GPIO_IFN_SCL2, ++ GPIO_FN_WE1_N, ++ GPIO_FN_RX0, ++ GPIO_FN_HRX0_B, ++ GPIO_IFN_SDA2, ++ GPIO_FN_EX_WAIT0, ++ GPIO_FN_TX0, ++ GPIO_FN_HTX0_B, ++ GPIO_IFN_AVB0_AVTP_MATCH, ++ GPIO_FN_TPU0TO0, ++ ++ /* IPSR8 */ ++ GPIO_IFN_AVB0_AVTP_CAPTURE, ++ GPIO_FN_TPU0TO1, ++ GPIO_IFN_CANFD0_TX_A, ++ GPIO_FN_FXR_TXDA, ++ GPIO_FN_PWM0_B, ++ GPIO_FN_DU_DISP, ++ 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, ++ ++ /* IPSR9 */ ++ GPIO_IFN_IRQ4, ++ GPIO_FN_VI0_DATA12, ++ GPIO_IFN_IRQ5, ++ GPIO_FN_VI0_DATA13, ++ GPIO_IFN_MSIOF0_RXD, ++ GPIO_FN_DU_DR0, ++ GPIO_FN_VI0_DATA14, ++ GPIO_IFN_MSIOF0_TXD, ++ GPIO_FN_DU_DR1, ++ GPIO_FN_VI0_DATA15, ++ GPIO_IFN_MSIOF0_SCK, ++ GPIO_FN_DU_DG0, ++ GPIO_FN_VI0_DATA16, ++ GPIO_IFN_MSIOF0_SYNC, ++ GPIO_FN_DU_DG1, ++ GPIO_FN_VI0_DATA17, ++ GPIO_IFN_MSIOF0_SS1, ++ GPIO_FN_DU_DB0, ++ GPIO_FN_TCLK3, ++ GPIO_FN_VI0_DATA18, ++ GPIO_IFN_MSIOF0_SS2, ++ GPIO_FN_DU_DB1, ++ GPIO_FN_TCLK4, ++ GPIO_FN_VI0_DATA19, ++ ++ /* IPSR10 */ ++ GPIO_IFN_SCL3, ++ GPIO_FN_VI0_DATA20, ++ GPIO_IFN_SDA3, ++ GPIO_FN_VI0_DATA21, ++ GPIO_IFN_FSO_CFE_0_N, ++ GPIO_FN_VI0_DATA22, ++ GPIO_IFN_FSO_CFE_1_N, ++ GPIO_FN_VI0_DATA23, ++ GPIO_IFN_FSO_TOE_N, ++}; ++ ++#endif /* __ASM_R8A7798_GPIO_H__ */ +diff --git a/arch/arm/include/asm/arch-rcar_gen3/r8a7798.h b/arch/arm/include/asm/arch-rcar_gen3/r8a7798.h +new file mode 100644 +index 0000000..06514f0 +--- /dev/null ++++ b/arch/arm/include/asm/arch-rcar_gen3/r8a7798.h +@@ -0,0 +1,34 @@ ++/* ++ * arch/arm/include/asm/arch-rcar_gen3/r8a7798.h ++ * This file defines registers and value for r8a7798. ++ * ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ */ ++ ++#ifndef __ASM_ARCH_R8A7798_H ++#define __ASM_ARCH_R8A7798_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_R8A7798_H */ +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 c2ba0fb..c3568b0 100644 +--- a/arch/arm/include/asm/arch-rcar_gen3/rcar_gen3.h ++++ b/arch/arm/include/asm/arch-rcar_gen3/rcar_gen3.h +@@ -16,6 +16,8 @@ + #include + #elif defined(CONFIG_R8A7797) + #include ++ #elif defined(CONFIG_R8A7798) ++ #include + #else + #error "SOC Name not defined" + #endif +diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c +index 4b9a61b..95129ce 100644 +--- a/drivers/mtd/spi/sf_probe.c ++++ b/drivers/mtd/spi/sf_probe.c +@@ -383,7 +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 !defined(CONFIG_R8A7797) && !defined(CONFIG_R8A7798) + if (((flash->dual_flash == SF_SINGLE_FLASH) && + (flash->size > SPI_FLASH_16MB_BOUN)) || + ((flash->dual_flash > SF_SINGLE_FLASH) && +diff --git a/drivers/net/sh_eth.h b/drivers/net/sh_eth.h +index 5cb520c..591e75d 100644 +--- a/drivers/net/sh_eth.h ++++ b/drivers/net/sh_eth.h +@@ -226,7 +226,6 @@ static const u16 sh_eth_offset_gigabit[SH_ETH_MAX_REGISTER_OFFSET] = { + [RMII_MII] = 0x0790, + }; + +-#if defined(SH_ETH_TYPE_RZ) + static const u16 sh_eth_offset_rz[SH_ETH_MAX_REGISTER_OFFSET] = { + [EDSR] = 0x0000, + [EDMR] = 0x0400, +@@ -279,7 +278,6 @@ static const u16 sh_eth_offset_rz[SH_ETH_MAX_REGISTER_OFFSET] = { + [MAFCR] = 0x0778, + [RMII_MII] = 0x0790, + }; +-#endif + + static const u16 sh_eth_offset_fast_sh4[SH_ETH_MAX_REGISTER_OFFSET] = { + [ECMR] = 0x0100, +@@ -361,6 +359,9 @@ static const u16 sh_eth_offset_fast_sh4[SH_ETH_MAX_REGISTER_OFFSET] = { + #elif defined(CONFIG_R7S72100) + #define SH_ETH_TYPE_RZ + #define BASE_IO_ADDR 0xE8203000 ++#elif defined(CONFIG_R8A7798) ++#define SH_ETH_TYPE_RZ ++#define BASE_IO_ADDR 0xE7400000 + #endif + + /* +diff --git a/drivers/serial/serial_sh.h b/drivers/serial/serial_sh.h +index 478824e..ded0d3d 100644 +--- a/drivers/serial/serial_sh.h ++++ b/drivers/serial/serial_sh.h +@@ -227,7 +227,7 @@ struct uart_port { + #elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) || \ + defined(CONFIG_R8A7793) || defined(CONFIG_R8A7794) || \ + defined(CONFIG_R8A7795) || defined(CONFIG_R8A7796X) || \ +- defined(CONFIG_R8A7797) ++ defined(CONFIG_R8A7797) || defined(CONFIG_R8A7798) + # 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 39d86dd..8124369 100644 +--- a/include/configs/rcar-gen3-common.h ++++ b/include/configs/rcar-gen3-common.h +@@ -133,6 +133,10 @@ + #else + #define PHYS_SDRAM_1_SIZE ((unsigned long)(0x40000000 - DRAM_RSV_SIZE)) + #endif ++#elif defined(CONFIG_R8A7798) ++#define CONFIG_NR_DRAM_BANKS 1 ++#define PHYS_SDRAM_1 (0x40000000 + DRAM_RSV_SIZE) /* legacy */ ++#define PHYS_SDRAM_1_SIZE ((unsigned long)(0x80000000 - DRAM_RSV_SIZE)) + #define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1 + #define CONFIG_SYS_SDRAM_SIZE PHYS_SDRAM_1_SIZE + #else +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0019-board-renesas-Add-Condor-board.patch b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0019-board-renesas-Add-Condor-board.patch new file mode 100644 index 0000000..68e0ac9 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0019-board-renesas-Add-Condor-board.patch @@ -0,0 +1,537 @@ +From 8dba0b32243d57d48cc8b821b9252b0a7f40e5c4 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Mon, 22 Jan 2018 13:21:35 +0300 +Subject: [PATCH] board: renesas: Add Condor board + +Condor is a board based on R-Car V3H SoC (R8A7798) + +Signed-off-by: Vladimir Barinov +--- + arch/arm/cpu/armv8/Kconfig | 7 ++ + board/renesas/condor/Kconfig | 15 +++ + board/renesas/condor/MAINTAINERS | 6 + + board/renesas/condor/Makefile | 9 ++ + board/renesas/condor/condor.c | 251 +++++++++++++++++++++++++++++++++++++++ + configs/r8a7798_condor_defconfig | 10 ++ + include/configs/r8a7798_condor.h | 159 +++++++++++++++++++++++++ + 7 files changed, 457 insertions(+) + create mode 100644 board/renesas/condor/Kconfig + create mode 100644 board/renesas/condor/MAINTAINERS + create mode 100644 board/renesas/condor/Makefile + create mode 100644 board/renesas/condor/condor.c + create mode 100644 configs/r8a7798_condor_defconfig + create mode 100644 include/configs/r8a7798_condor.h + +diff --git a/arch/arm/cpu/armv8/Kconfig b/arch/arm/cpu/armv8/Kconfig +index 343b121..0edd5db 100644 +--- a/arch/arm/cpu/armv8/Kconfig ++++ b/arch/arm/cpu/armv8/Kconfig +@@ -22,6 +22,9 @@ config TARGET_EAGLE + config TARGET_V3MSK + bool "V3MSK board" + ++config TARGET_CONDOR ++ bool "CONDOR board" ++ + endchoice + + config R8A7796X +@@ -53,5 +59,6 @@ source "board/renesas/salvator-x/Kconfig" + source "board/renesas/ulcb/Kconfig" + source "board/renesas/eagle/Kconfig" + source "board/renesas/v3msk/Kconfig" ++source "board/renesas/condor/Kconfig" + + endif +diff --git a/board/renesas/condor/Kconfig b/board/renesas/condor/Kconfig +new file mode 100644 +index 0000000..21ba79f +--- /dev/null ++++ b/board/renesas/condor/Kconfig +@@ -0,0 +1,15 @@ ++if TARGET_CONDOR ++ ++config SYS_SOC ++ default "rcar_gen3" ++ ++config SYS_BOARD ++ default "condor" ++ ++config SYS_VENDOR ++ default "renesas" ++ ++config SYS_CONFIG_NAME ++ default "r8a7798_condor" if R8A7798 ++ ++endif +diff --git a/board/renesas/condor/MAINTAINERS b/board/renesas/condor/MAINTAINERS +new file mode 100644 +index 0000000..d0442b8 +--- /dev/null ++++ b/board/renesas/condor/MAINTAINERS +@@ -0,0 +1,6 @@ ++CONDOR BOARD ++M: Cogent Embedded, Inc. ++S: Maintained ++F: board/renesas/condor/ ++F: include/configs/r8a7798_condor.h ++F: configs/r8a7798_condor_defconfig +diff --git a/board/renesas/condor/Makefile b/board/renesas/condor/Makefile +new file mode 100644 +index 0000000..4c5d29b +--- /dev/null ++++ b/board/renesas/condor/Makefile +@@ -0,0 +1,10 @@ ++# ++# board/renesas/condor/Makefile ++# ++# Copyright (C) 2018 Renesas Electronics Corp. ++# Copyright (C) 2018 Cogent Embedded, Inc. ++# ++# SPDX-License-Identifier: GPL-2.0+ ++# ++ ++obj-y := condor.o ../rcar-gen3-common/common.o +diff --git a/board/renesas/condor/condor.c b/board/renesas/condor/condor.c +new file mode 100644 +index 0000000..d31e5fd +--- /dev/null ++++ b/board/renesas/condor/condor.c +@@ -0,0 +1,252 @@ ++/* ++ * board/renesas/condor/condor.c ++ * This is Condor board support. ++ * ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++DECLARE_GLOBAL_DATA_PTR; ++ ++#define SCIF0_MSTP207 (1 << 7) ++#define GETHER_MSTP813 (1 << 13) ++#define RAVB_MSTP812 (1 << 12) ++#define RPC_MSTP917 (1 << 17) ++#define SD0_MSTP314 (1 << 14) ++ ++#define SD0CKCR 0xE6150074 ++ ++void s_init(void) ++{ ++ struct rcar_rwdt *rwdt = (struct rcar_rwdt *)RWDT_BASE; ++ struct rcar_swdt *swdt = (struct rcar_swdt *)SWDT_BASE; ++ ++ /* Watchdog init */ ++ writel(0xA5A5A500, &rwdt->rwtcsra); ++ writel(0xA5A5A500, &swdt->swtcsra); ++} ++ ++int board_early_init_f(void) ++{ ++ int freq; ++ ++ rcar_prr_init(); ++ ++ writel(0xa5a5ffff, 0xe6150900); ++ writel(0x5a5a0000, 0xe6150904); ++ mstp_clrbits_le32(MSTPSR1, SMSTPCR1, 0x02000000); ++ /* SCIF0 */ ++ mstp_clrbits_le32(MSTPSR2, SMSTPCR2, SCIF0_MSTP207); ++ /* SDHI0/MMC */ ++ mstp_clrbits_le32(MSTPSR3, SMSTPCR3, SD0_MSTP314); ++ /* Gigabit Ethernet */ ++ mstp_clrbits_le32(MSTPSR8, SMSTPCR8, GETHER_MSTP813); ++ /* RAVB Ethernet */ ++ mstp_clrbits_le32(MSTPSR8, SMSTPCR8, RAVB_MSTP812); ++ /* QSPI/RPC */ ++ mstp_clrbits_le32(MSTPSR9, SMSTPCR9, RPC_MSTP917); ++ ++ freq = rcar_get_sdhi_config_clk(); ++ writel(freq, SD0CKCR); ++ ++ 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 ++ gpio_request(GPIO_GFN_AVB0_AVTP_CAPTURE, NULL); ++ gpio_request(GPIO_GFN_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); ++ gpio_request(GPIO_IFN_AVB0_AVTP_CAPTURE, NULL); ++ gpio_request(GPIO_FN_AVB0_AVTP_PPS, NULL); ++#endif ++#ifdef CONFIG_SH_ETHER ++ gpio_request(GPIO_FN_GETHER_LINK_A, NULL); ++ gpio_request(GPIO_FN_GETHER_PHY_INT_A, NULL); ++ /* GPIO_FN_GETHER_MAGIC: PHY reset gpio */ ++ gpio_request(GPIO_FN_GETHER_MDC_A, NULL); ++ gpio_request(GPIO_FN_GETHER_MDIO_A, NULL); ++ gpio_request(GPIO_FN_GETHER_TXCREFCLK, NULL); ++ gpio_request(GPIO_FN_GETHER_TXCREFCLK_MEGA, NULL); ++ gpio_request(GPIO_FN_GETHER_TD3, NULL); ++ gpio_request(GPIO_FN_GETHER_TD2, NULL); ++ gpio_request(GPIO_FN_GETHER_TD1, NULL); ++ gpio_request(GPIO_FN_GETHER_TD0, NULL); ++ gpio_request(GPIO_FN_GETHER_TXC, NULL); ++ gpio_request(GPIO_FN_GETHER_TX_CTL, NULL); ++ gpio_request(GPIO_FN_GETHER_RD3, NULL); ++ gpio_request(GPIO_FN_GETHER_RD2, NULL); ++ gpio_request(GPIO_FN_GETHER_RD1, NULL); ++ gpio_request(GPIO_FN_GETHER_RD0, NULL); ++ gpio_request(GPIO_FN_GETHER_RXC, NULL); ++ gpio_request(GPIO_FN_GETHER_RX_CTL, NULL); ++#endif ++ /* QSPI/RPC */ ++ 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); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_RAVB ++#define MAHR 0xE68005C0 ++#define MALR 0xE68005C8 ++#endif ++#ifdef CONFIG_SH_ETHER ++#define MAHR 0xE74005C0 ++#define MALR 0xE74005C8 ++#endif ++int board_eth_init(bd_t *bis) ++{ ++ int ret = -ENODEV; ++#ifdef CONFIG_RAVB ++ 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); ++ ++ ret = ravb_initialize(bis); ++#endif ++#ifdef CONFIG_SH_ETHER ++ u32 val; ++ unsigned char enetaddr[6]; ++ ++ ret = sh_eth_initialize(bis); ++ 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); ++#endif ++ return ret; ++} ++ ++/* Condor has KSZ9031RNX */ ++int board_phy_config(struct phy_device *phydev) ++{ ++ return 0; ++} ++ ++int board_mmc_init(bd_t *bis) ++{ ++ int ret = -ENODEV; ++#ifdef CONFIG_SH_SDHI ++ /* SDHI2/eMMC */ ++ gpio_request(GPIO_FN_MMC_D0, NULL); ++ gpio_request(GPIO_FN_MMC_D1, NULL); ++ gpio_request(GPIO_FN_MMC_D2, NULL); ++ gpio_request(GPIO_FN_MMC_D3, NULL); ++ gpio_request(GPIO_FN_MMC_D4, NULL); ++ gpio_request(GPIO_FN_MMC_D5, NULL); ++ gpio_request(GPIO_FN_MMC_D6, NULL); ++ gpio_request(GPIO_FN_MMC_D7, NULL); ++ gpio_request(GPIO_FN_MMC_CLK, NULL); ++ gpio_request(GPIO_FN_MMC_CMD, NULL); ++ gpio_request(GPIO_FN_MMC_CD, NULL); ++ gpio_request(GPIO_FN_MMC_WP, NULL); ++ ++ ret = sh_sdhi_init(CONFIG_SYS_SH_SDHI2_BASE, 0, ++ SH_SDHI_QUIRK_64BIT_BUF); ++#endif ++ return ret; ++} ++ ++int dram_init(void) ++{ ++ gd->ram_size = PHYS_SDRAM_1_SIZE; ++ ++ 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; ++} ++ ++const struct rcar_sysinfo sysinfo = { ++ CONFIG_RCAR_BOARD_STRING ++}; ++ ++void reset_cpu(ulong addr) ++{ ++} ++ ++#if defined(CONFIG_DISPLAY_BOARDINFO) ++int checkboard(void) ++{ ++ printf("Board: %s\n", sysinfo.board_string); ++ return 0; ++} ++#endif +diff --git a/configs/r8a7798_condor_defconfig b/configs/r8a7798_condor_defconfig +new file mode 100644 +index 0000000..1cab2ae +--- /dev/null ++++ b/configs/r8a7798_condor_defconfig +@@ -0,0 +1,10 @@ ++CONFIG_ARM=y ++CONFIG_RCAR_GEN3=y ++CONFIG_DM_SERIAL=y ++CONFIG_TARGET_CONDOR=y ++CONFIG_R8A7798=y ++CONFIG_SPL=y ++CONFIG_SH_SDHI=y ++CONFIG_SPI_FLASH=y ++CONFIG_SPI_FLASH_SPANSION=y ++CONFIG_SPI_FLASH_BAR=y +diff --git a/include/configs/r8a7798_condor.h b/include/configs/r8a7798_condor.h +new file mode 100644 +index 0000000..f0b2e0b +--- /dev/null ++++ b/include/configs/r8a7798_condor.h +@@ -0,0 +1,160 @@ ++/* ++ * include/configs/r8a7798_condor.h ++ * This file is Condor board configuration. ++ * CPU r8a7798. ++ * ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ */ ++ ++#ifndef __CONDOR_H ++#define __CONDOR_H ++ ++#undef DEBUG ++#define CONFIG_RCAR_BOARD_STRING "Condor" ++#define CONFIG_RCAR_TARGET_STRING "r8a7798" ++ ++#include "rcar-gen3-common.h" ++ ++//#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 ++ ++#if 1 ++/* 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 ++#else ++/* SH Ether */ ++#define CONFIG_NET_MULTI ++#define CONFIG_SH_ETHER ++#define CONFIG_SH_ETHER_USE_PORT 0 ++#define CONFIG_SH_ETHER_PHY_ADDR 0x0 ++#define CONFIG_SH_ETHER_PHY_MODE PHY_INTERFACE_MODE_RGMII_ID ++#define CONFIG_SH_ETHER_ALIGNE_SIZE 64 ++#define CONFIG_SH_ETHER_CACHE_WRITEBACK ++#define CONFIG_SH_ETHER_CACHE_INVALIDATE ++#define CONFIG_PHYLIB ++#define CONFIG_PHY_MICREL ++#define CONFIG_BITBANGMII ++#define CONFIG_BITBANGMII_MULTI ++#endif ++ ++/* 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 ++ ++/* SDHI */ ++#define CONFIG_MMC ++#define CONFIG_CMD_MMC ++#define CONFIG_GENERIC_MMC ++#define CONFIG_SH_SDHI_FREQ 200000000 ++#define CONFIG_SH_SDHI_MMC ++ ++/* ENV setting */ ++#define CONFIG_ENV_OVERWRITE ++#define CONFIG_ENV_SECT_SIZE (256 * 1024) ++#define CONFIG_ENV_SIZE (CONFIG_ENV_SECT_SIZE) ++#define CONFIG_ENV_SIZE_REDUND (CONFIG_ENV_SIZE) ++ ++//#define CONFIG_ENV_IS_IN_MMC ++#define CONFIG_ENV_IS_IN_SPI_FLASH ++ ++#if defined(CONFIG_ENV_IS_IN_MMC) ++/* Environment in eMMC, at the end of 2nd "boot sector" */ ++#define CONFIG_ENV_OFFSET (-CONFIG_ENV_SIZE) ++#define CONFIG_SYS_MMC_ENV_DEV 0 ++#define CONFIG_SYS_MMC_ENV_PART 2 ++#elif defined(CONFIG_ENV_IS_IN_SPI_FLASH) ++/* Environment in QSPI */ ++#define CONFIG_ENV_ADDR 0x700000 ++#define CONFIG_ENV_OFFSET (CONFIG_ENV_ADDR) ++#else ++#define CONFIG_ENV_IS_NOWHERE ++#endif ++ ++/* 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 ++ ++#define CONFIG_EXTRA_ENV_SETTINGS \ ++ "fdt_high=0xffffffffffffffff\0" \ ++ "initrd_high=0xffffffffffffffff\0" \ ++ "ethaddr=2E:11:22:33:44:55\0" ++ ++#define CONFIG_BOOTARGS \ ++ "root=/dev/nfs rw ip=dhcp" ++ ++#define CONFIG_BOOTCOMMAND \ ++ "bootp 0x48080000 Image; tftp 0x48000000 r8a7798-condor.dtb; " \ ++ "booti 0x48080000 - 0x48000000" ++ ++#endif /* __CONDOR_H */ +-- +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 index 8171d10..3be0e60 100644 --- 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 @@ -17,6 +17,8 @@ SRC_URI_append = " \ file://0015-board-renesas-Add-V3M-Eagle-board.patch \ file://0016-tools-fix-build-fail.patch \ file://0017-board-renesas-Add-V3MSK-board.patch \ + file://0018-arm-renesas-Add-Renesas-R8A7798-SoC-support.patch \ + file://0019-board-renesas-Add-Condor-board.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 \ diff --git a/meta-rcar-gen3-adas/recipes-kernel/kernel-module-mmngr/kernel-module-mmngr.bbappend b/meta-rcar-gen3-adas/recipes-kernel/kernel-module-mmngr/kernel-module-mmngr.bbappend index 6abdc7d..7118d46 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/kernel-module-mmngr/kernel-module-mmngr.bbappend +++ b/meta-rcar-gen3-adas/recipes-kernel/kernel-module-mmngr/kernel-module-mmngr.bbappend @@ -2,5 +2,6 @@ FILESEXTRAPATHS_prepend := "${THISDIR}/files:" MMNGR_CFG_eagle = "MMNGR_V3MSK" MMNGR_CFG_v3msk = "MMNGR_V3MSK" +MMNGR_CFG_condor = "MMNGR_V3MSK" SRC_URI_append = " file://0002-mmngr-Add-V3MSK-board.patch" diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch index ffaf796..483ba45 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch @@ -26,10 +26,11 @@ Videobox Mini board on R8A7795 SoC Videobox Mini board on R8A7797 SoC Videobox2 board on R8A7795 ES1.x SoC Videobox2 board on R8A7795 SoC +Condor board on R8A7798 SoC Signed-off-by: Vladimir Barinov --- - arch/arm64/boot/dts/renesas/Makefile | 20 + + arch/arm64/boot/dts/renesas/Makefile | 21 + arch/arm64/boot/dts/renesas/legacy/Makefile | 8 + .../renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts | 1710 +++++++++++++++++++ .../renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts | 441 +++++ @@ -67,6 +68,7 @@ Signed-off-by: Vladimir Barinov arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts | 518 ++++++ arch/arm64/boot/dts/renesas/r8a7797-v3msk-view.dts | 298 ++++ arch/arm64/boot/dts/renesas/r8a7797-v3msk.dts | 314 ++++ + arch/arm64/boot/dts/renesas/r8a7798-condor.dts | 939 +++++++++++ arch/arm64/boot/dts/renesas/ulcb-kf-cn11.dtsi | 545 ++++++ arch/arm64/boot/dts/renesas/ulcb-kf-most.dtsi | 30 + arch/arm64/boot/dts/renesas/ulcb-kf-sd3.dtsi | 46 + @@ -75,7 +77,7 @@ Signed-off-by: Vladimir Barinov arch/arm64/boot/dts/renesas/ulcb-vb.dtsi | 1726 +++++++++++++++++++ arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi | 1772 ++++++++++++++++++++ arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi | 578 +++++++ - 46 files changed, 19159 insertions(+) + 47 files changed, 20099 insertions(+) create mode 100644 arch/arm64/boot/dts/renesas/legacy/Makefile create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts @@ -113,6 +115,7 @@ Signed-off-by: Vladimir Barinov create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-v3msk-view.dts create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-v3msk.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7798-condor.dts create mode 100644 arch/arm64/boot/dts/renesas/ulcb-kf-cn11.dtsi create mode 100644 arch/arm64/boot/dts/renesas/ulcb-kf-most.dtsi create mode 100644 arch/arm64/boot/dts/renesas/ulcb-kf-sd3.dtsi @@ -123,10 +126,10 @@ Signed-off-by: Vladimir Barinov create mode 100644 arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile -index f9c71df..1c63893 100644 +index f9c71df..3b5cff6 100644 --- a/arch/arm64/boot/dts/renesas/Makefile +++ b/arch/arm64/boot/dts/renesas/Makefile -@@ -6,5 +6,25 @@ dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-xs.dtb +@@ -6,5 +6,26 @@ dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-xs.dtb dtb-$(CONFIG_ARCH_R8A77965) += r8a77965-salvator-x.dtb dtb-$(CONFIG_ARCH_R8A77965) += r8a77965-salvator-xs.dtb @@ -146,6 +149,7 @@ index f9c71df..1c63893 100644 +dtb-$(CONFIG_ARCH_R8A7797) += r8a7797-v3msk-view.dtb +dtb-$(CONFIG_ARCH_R8A7797) += r8a7797-v3msk-kf.dtb +dtb-$(CONFIG_ARCH_R8A7797) += r8a7797-v3msk-vbm.dtb ++dtb-$(CONFIG_ARCH_R8A7798) += r8a7798-condor.dtb + +# ADAS legacy boards +subdir-y := legacy @@ -12759,6 +12763,952 @@ index 0000000..91d10c5 + non-removable; + status = "okay"; +}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7798-condor.dts b/arch/arm64/boot/dts/renesas/r8a7798-condor.dts +new file mode 100644 +index 0000000..ed9cc28 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7798-condor.dts +@@ -0,0 +1,940 @@ ++/* ++ * Device Tree Source for the Condor board ++ * ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++/dts-v1/; ++#include "r8a7798.dtsi" ++#include ++ ++/ { ++ model = "Renesas Condor board based on r8a7798"; ++ compatible = "renesas,condor", "renesas,r8a7798"; ++ ++ aliases { ++ serial0 = &scif0; ++ ethernet0 = &avb; ++ }; ++ ++ chosen { ++ bootargs = "ignore_loglevel rw root=/dev/nfs ip=dhcp"; ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ ++ memory@48000000 { ++ device_type = "memory"; ++ /* first 128MB is reserved for secure area. */ ++ reg = <0x0 0x48000000 0x0 0x38000000>; ++ }; ++ ++ reserved-memory { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ /* device specific region for Lossy Decompression */ ++ lossy_decompress: linux,lossy_decompress { ++ no-map; ++ reg = <0x00000000 0x6c000000 0x0 0x03000000>; ++ }; ++ ++ /* global autoconfigured region for contiguous allocations */ ++ linux,cma { ++ compatible = "shared-dma-pool"; ++ reusable; ++ reg = <0x00000000 0x6f000000 0x0 0x10000000>; ++ linux,cma-default; ++ }; ++ ++ /* device specific region for contiguous allocations */ ++ linux,multimedia { ++ compatible = "shared-dma-pool"; ++ reusable; ++ reg = <0x00000000 0x7f000000 0x0 0x01000000>; ++ }; ++ }; ++ ++ mmngr { ++ compatible = "renesas,mmngr"; ++ memory-region = <&lossy_decompress>; ++ }; ++ ++ mmngrbuf { ++ compatible = "renesas,mmngrbuf"; ++ }; ++ ++ vspm_if { ++ compatible = "renesas,vspm_if"; ++ }; ++ ++ lvds-encoder { ++ compatible = "thine,thc63lvdm83d"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ lvds_enc_in: endpoint { ++ remote-endpoint = <&du_out_lvds0>; ++ }; ++ }; ++ port@1 { ++ reg = <1>; ++ lvds_enc_out: endpoint { ++ remote-endpoint = <&lvds_in>; ++ }; ++ }; ++ }; ++ }; ++ ++ lvds { ++ compatible = "lvds-connector"; ++ ++ width-mm = <210>; ++ height-mm = <158>; ++ ++ panel-timing { ++ clock-frequency = <138000000>; ++ hactive = <1920>; ++ vactive = <1080>; ++ hsync-len = <32>; ++ hfront-porch = <20>; ++ hback-porch = <160>; ++ vfront-porch = <3>; ++ vback-porch = <31>; ++ vsync-len = <5>; ++ }; ++ ++ port { ++ lvds_in: endpoint { ++ remote-endpoint = <&lvds_enc_out>; ++ }; ++ }; ++ }; ++ ++ hdmi-out { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi_con: endpoint { ++ remote-endpoint = <&adv7511_out>; ++ }; ++ }; ++ }; ++ ++ dclkin_p0: clock-out0 { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <148500000>; ++ }; ++ ++ msiof_ref_clk: msiof-ref-clock { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <66666666>; ++ }; ++ ++ vcc_3v3: regulator0 { ++ compatible = "regulator-fixed"; ++ regulator-name = "fixed-VCC3V3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ vcc_vddq_vin0: regulator1 { ++ compatible = "regulator-fixed"; ++ regulator-name = "VCC-VDDQ-VIN0"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++}; ++ ++&du { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ endpoint { ++ remote-endpoint = <&adv7511_in>; ++ }; ++ }; ++ }; ++}; ++ ++&extal_clk { ++ clock-frequency = <16666666>; ++}; ++ ++&extalr_clk { ++ clock-frequency = <32768>; ++}; ++ ++&pfc { ++ pinctrl-0 = <&scif_clk_pins>; ++ pinctrl-names = "default"; ++ ++ canfd0_pins: canfd0 { ++ groups = "canfd0_data_a"; ++ function = "canfd0"; ++ }; ++ ++ scif0_pins: scif0 { ++ groups = "scif0_data"; ++ function = "scif0"; ++ }; ++ ++ scif_clk_pins: scif_clk { ++ groups = "scif_clk_b"; ++ function = "scif_clk"; ++ }; ++ ++ i2c0_pins: i2c0 { ++ groups = "i2c0"; ++ function = "i2c0"; ++ }; ++ ++ i2c1_pins: i2c1 { ++ groups = "i2c1"; ++ function = "i2c1"; ++ }; ++ ++ avb_pins: avb { ++ groups = "avb_mdc"; ++ function = "avb"; ++ }; ++ ++ sdhi2_pins_1v8: sdhi2_1v8 { ++ groups = "mmc_data8", "mmc_ctrl", "mmc_ds"; ++ function = "mmc"; ++ power-source = <1800>; ++ }; ++ ++ sdhi2_pins_3v3: sdhi2_3v3 { ++ groups = "mmc_data8", "mmc_ctrl", "mmc_ds"; ++ function = "mmc"; ++ power-source = <3300>; ++ }; ++ ++ tpu_pins: tpu { ++ /* GP1_19 pin; CP4 test point */ ++ groups = "tpu_to0"; ++ function = "tpu"; ++ }; ++}; ++ ++&scif0 { ++ pinctrl-0 = <&scif0_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&scif_clk { ++ clock-frequency = <14745600>; ++ status = "okay"; ++}; ++ ++&sdhi2 { ++ /* used for on-board eMMC */ ++ pinctrl-0 = <&sdhi2_pins_3v3>; ++ pinctrl-1 = <&sdhi2_pins_1v8>; ++ pinctrl-names = "default", "state_uhs"; ++ ++ vmmc-supply = <&vcc_3v3>; ++ vqmmc-supply = <&vcc_vddq_vin0>; ++ mmc-hs200-1_8v; ++ mmc-hs400-1_8v; ++ bus-width = <8>; ++ non-removable; ++ status = "okay"; ++}; ++ ++&i2c0 { ++ pinctrl-0 = <&i2c0_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++ clock-frequency = <400000>; ++ ++ hdmi@39{ ++ compatible = "adi,adv7511w"; ++ #sound-dai-cells = <0>; ++ reg = <0x39>; ++ interrupt-parent = <&gpio1>; ++ interrupts = <20 IRQ_TYPE_LEVEL_LOW>; ++ ++ adi,input-depth = <8>; ++ adi,input-colorspace = "rgb"; ++ adi,input-clock = "1x"; ++ adi,input-style = <1>; ++ adi,input-justification = "evenly"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ adv7511_in: endpoint { ++ remote-endpoint = <&lvds_enc_out>; ++ }; ++ }; ++ port@1 { ++ reg = <1>; ++ adv7511_out: endpoint { ++ remote-endpoint = <&hdmi_con>; ++ }; ++ }; ++ }; ++ }; ++ ++ gpio_exp_20: gpio@20 { ++ compatible = "onsemi,pca9654"; ++ reg = <0x20>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ }; ++ ++ gpio_exp_21: gpio@21 { ++ compatible = "onsemi,pca9654"; ++ reg = <0x21>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ }; ++}; ++ ++&i2c1 { ++ pinctrl-0 = <&i2c1_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++ clock-frequency = <400000>; ++ ++ ov106xx@0 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x60>; ++ ++ port@0 { ++ ov106xx_in0: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin0ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@1 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x61>; ++ ++ port@0 { ++ ov106xx_in1: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin1ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@2 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x62>; ++ ++ port@0 { ++ ov106xx_in2: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin2ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@3 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x63>; ++ ++ port@0 { ++ ov106xx_in3: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin3ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_des0ep3: endpoint { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ }; ++ }; ++ ++ 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@0 { ++ compatible = "maxim,max9286"; ++ reg = <0x48>; ++ gpios = <&gpio_exp_20 0 GPIO_ACTIVE_LOW>; /* MAX9286 PWDN */ ++ maxim,gpio0 = <0>; ++ maxim,sensor_delay = <100>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ ++ port@0 { ++ max9286_des0ep0: endpoint@0 { ++ max9271-addr = <0x50>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ max9286_des0ep1: endpoint@1 { ++ max9271-addr = <0x51>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ max9286_des0ep2: endpoint@2 { ++ max9271-addr = <0x52>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ max9286_des0ep3: endpoint@3 { ++ max9271-addr = <0x53>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ max9286_csi0ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ }; ++ ++ max9286@1 { ++ compatible = "maxim,max9286"; ++ reg = <0x4a>; ++ gpios = <&gpio_exp_21 0 GPIO_ACTIVE_LOW>; /* MAX9286 PWDN */ ++ maxim,gpio0 = <0>; ++ maxim,sensor_delay = <100>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ ++ port@0 { ++ max9286_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_csi1ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ }; ++}; ++ ++&pcie_bus_clk { ++ clock-frequency = <100000000>; ++ status = "okay"; ++}; ++ ++&pciec { ++ status = "okay"; ++}; ++ ++&wdt0 { ++ timeout-sec = <60>; ++ status = "okay"; ++}; ++ ++&cmt0 { ++ status = "okay"; ++}; ++ ++&cmt1 { ++ status = "okay"; ++}; ++ ++&cmt2 { ++ status = "okay"; ++}; ++ ++&cmt3 { ++ status = "okay"; ++}; ++ ++&tpu { ++ pinctrl-0 = <&tpu_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++}; ++ ++&tmu0 { ++ status = "okay"; ++}; ++ ++&tmu1 { ++ status = "okay"; ++}; ++ ++&tmu2 { ++ status = "okay"; ++}; ++ ++&tmu3 { ++ status = "okay"; ++}; ++ ++&tmu4 { ++ status = "okay"; ++}; ++ ++&avb { ++ pinctrl-0 = <&avb_pins>; ++ pinctrl-names = "default"; ++ renesas,no-ether-link; ++ phy-handle = <&phy0>; ++ status = "okay"; ++ phy-int-gpio = <&gpio1 17 GPIO_ACTIVE_LOW>; ++ ++ phy0: ethernet-phy@0 { ++ rxc-skew-ps = <1500>; ++ rxdv-skew-ps = <420>; /* default */ ++ rxd0-skew-ps = <420>; /* default */ ++ rxd1-skew-ps = <420>; /* default */ ++ rxd2-skew-ps = <420>; /* default */ ++ rxd3-skew-ps = <420>; /* default */ ++ txc-skew-ps = <900>; /* default */ ++ txen-skew-ps = <420>; /* default */ ++ txd0-skew-ps = <420>; /* default */ ++ txd1-skew-ps = <420>; /* default */ ++ txd2-skew-ps = <420>; /* default */ ++ txd3-skew-ps = <420>; /* default */ ++ reg = <0>; ++ interrupt-parent = <&gpio1>; ++ interrupts = <17 IRQ_TYPE_LEVEL_LOW>; ++ max-speed = <1000>; ++ }; ++}; ++ ++&vin0 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin0ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ }; ++ port@1 { ++ csi0ep0: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin0_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin1 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin1ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <1>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ }; ++ port@1 { ++ csi0ep1: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin1_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin2 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin2ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <2>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ }; ++ port@1 { ++ csi0ep2: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin2_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin3 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin3ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <3>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ csi0ep3: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ vin3_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ }; ++ }; ++}; ++ ++&vin4 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin4ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in4>; ++ }; ++ }; ++ port@1 { ++ csi1ep0: 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 { ++ csi,select = "csi41"; ++ virtual,channel = <1>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in5>; ++ }; ++ }; ++ port@1 { ++ csi1ep1: 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 { ++ csi,select = "csi41"; ++ virtual,channel = <2>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in6>; ++ }; ++ }; ++ port@1 { ++ csi1ep2: 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 { ++ csi,select = "csi41"; ++ virtual,channel = <3>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in7>; ++ }; ++ }; ++ port@1 { ++ csi1ep3: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ vin7_max9286_des1ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des1ep3>; ++ }; ++ }; ++ }; ++}; ++ ++&canfd { ++ pinctrl-0 = <&canfd0_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ channel0 { ++ status = "okay"; ++ }; ++}; ++ ++&csi2_40 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi2_40_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; ++ ++&csi2_41 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi2_41_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf-cn11.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf-cn11.dtsi new file mode 100644 index 0000000..b469ca6 diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch new file mode 100644 index 0000000..a4763d4 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch @@ -0,0 +1,6197 @@ +From e8fd03e53c50c67a2aebf19f39a9f14b583f0e2d Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Sun, 14 May 2017 14:48:08 +0300 +Subject: [PATCH] arm64: renesas: r8a7798: Add Renesas R8A7798 SoC support + +This adds Renesas R8A7798 SoC support + +Signed-off-by: Vladimir Barinov +Signed-off-by: Mikhail Ulyanov +--- + arch/arm64/Kconfig.platforms | 8 + + arch/arm64/boot/dts/renesas/r8a7798.dtsi | 1584 +++++++++++++ + drivers/clk/renesas/Kconfig | 1 + + drivers/clk/renesas/Makefile | 1 + + drivers/clk/renesas/r8a7798-cpg-mssr.c | 284 +++ + drivers/clk/renesas/rcar-gen3-cpg.c | 13 +- + drivers/clk/renesas/renesas-cpg-mssr.c | 8 + + drivers/clk/renesas/renesas-cpg-mssr.h | 3 + + drivers/cpufreq/cpufreq-dt-platdev.c | 1 + + drivers/gpio/gpio-rcar.c | 7 +- + drivers/gpu/drm/rcar-du/rcar_du_drv.c | 4 +- + drivers/gpu/drm/rcar-du/rcar_du_group.c | 8 +- + drivers/i2c/busses/i2c-rcar.c | 1 + + drivers/iommu/ipmmu-vmsa.c | 6 +- + drivers/media/platform/soc_camera/Kconfig | 2 +- + drivers/media/platform/soc_camera/rcar_csi2.c | 15 +- + drivers/media/platform/soc_camera/rcar_vin.c | 97 +- + drivers/media/platform/vsp1/vsp1_lif.c | 10 +- + drivers/mmc/host/sh_mobile_sdhi.c | 4 +- + drivers/net/ethernet/renesas/ravb_main.c | 4 +- + drivers/pci/host/pcie-rcar.c | 62 +- + drivers/pinctrl/sh-pfc/Kconfig | 5 + + drivers/pinctrl/sh-pfc/Makefile | 1 + + drivers/pinctrl/sh-pfc/core.c | 9 +- + drivers/pinctrl/sh-pfc/pfc-r8a7798.c | 3151 +++++++++++++++++++++++++ + drivers/pinctrl/sh-pfc/sh_pfc.h | 11 +- + drivers/soc/renesas/Makefile | 4 + + drivers/soc/renesas/r8a7798-sysc.c | 57 + + drivers/soc/renesas/rcar-rst.c | 3 + + drivers/soc/renesas/rcar-sysc.c | 5 + + drivers/soc/renesas/rcar-sysc.h | 3 + + drivers/soc/renesas/rcar_ems_ctrl.c | 8 +- + drivers/soc/renesas/renesas-soc.c | 10 + + drivers/spi/spi-sh-msiof.c | 7 +- + drivers/thermal/rcar_gen3_thermal.c | 13 +- + include/dt-bindings/clock/r8a7798-cpg-mssr.h | 56 + + include/dt-bindings/power/r8a7798-sysc.h | 46 + + 37 files changed, 5470 insertions(+), 42 deletions(-) + create mode 100644 arch/arm64/boot/dts/renesas/r8a7798.dtsi + create mode 100644 drivers/clk/renesas/r8a7798-cpg-mssr.c + create mode 100644 drivers/pinctrl/sh-pfc/pfc-r8a7798.c + create mode 100644 drivers/soc/renesas/r8a7798-sysc.c + create mode 100644 include/dt-bindings/clock/r8a7798-cpg-mssr.h + create mode 100644 include/dt-bindings/power/r8a7798-sysc.h + +diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms +index d3b6771..119a7e3 100644 +--- a/arch/arm64/Kconfig.platforms ++++ b/arch/arm64/Kconfig.platforms +@@ -172,6 +172,14 @@ config ARCH_R8A7797 + help + This enables support for the Renesas R-Car V3M SoC. + ++config ARCH_R8A7798 ++ bool "Renesas R-Car V3H SoC Platform" ++ select SYS_SUPPORTS_SH_TMU ++ select SYS_SUPPORTS_SH_CMT ++ depends on ARCH_RENESAS ++ help ++ This enables support for the Renesas R-Car V3H SoC. ++ + config ARCH_STRATIX10 + bool "Altera's Stratix 10 SoCFPGA Family" + help +diff --git a/arch/arm64/boot/dts/renesas/r8a7798.dtsi b/arch/arm64/boot/dts/renesas/r8a7798.dtsi +new file mode 100644 +index 0000000..ee8e282 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7798.dtsi +@@ -0,0 +1,1584 @@ ++/* ++ * Device Tree Source for the r8a7798 SoC ++ * ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 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 ++#include ++#include ++ ++/ { ++ compatible = "renesas,r8a7798"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ++ aliases { ++ csi2_40 = &csi2_40; ++ csi2_41 = &csi2_41; ++ i2c0 = &i2c0; ++ i2c1 = &i2c1; ++ i2c2 = &i2c2; ++ i2c3 = &i2c3; ++ i2c4 = &i2c4; ++ i2c5 = &i2c5; ++ spi1 = &msiof0; ++ spi2 = &msiof1; ++ spi3 = &msiof2; ++ spi4 = &msiof3; ++ vin0 = &vin0; ++ vin1 = &vin1; ++ vin2 = &vin2; ++ vin3 = &vin3; ++ vin4 = &vin4; ++ vin5 = &vin5; ++ vin6 = &vin6; ++ vin7 = &vin7; ++ vin8 = &vin8; ++ vin9 = &vin9; ++ vin10 = &vin10; ++ vin11 = &vin11; ++ vin12 = &vin12; ++ vin13 = &vin13; ++ vin14 = &vin14; ++ vin15 = &vin15; ++ tsc0 = &tsc1; ++ tsc1 = &tsc2; ++ }; ++ ++ 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 R8A7798_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 R8A7798_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 R8A7798_PD_CA53_CPU1>; ++ next-level-cache = <&L2_CA53>; ++ enable-method = "psci"; ++ cpu-idle-states = <&CPU_SLEEP_0>; ++ operating-points-v2 = <&cluster0_opp_tb0>; ++ }; ++ ++ a53_2: cpu@2 { ++ compatible = "arm,cortex-a53","arm,armv8"; ++ reg = <0x2>; ++ device_type = "cpu"; ++ power-domains = <&sysc R8A7798_PD_CA53_CPU2>; ++ next-level-cache = <&L2_CA53>; ++ enable-method = "psci"; ++ cpu-idle-states = <&CPU_SLEEP_0>; ++ operating-points-v2 = <&cluster0_opp_tb0>; ++ }; ++ ++ a53_3: cpu@3 { ++ compatible = "arm,cortex-a53","arm,armv8"; ++ reg = <0x3>; ++ device_type = "cpu"; ++ power-domains = <&sysc R8A7798_PD_CA53_CPU3>; ++ 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 R8A7798_PD_CA53_SCU>; ++ cache-unified; ++ cache-level = <2>; ++ }; ++ ++ cluster0_opp_tb0: opp_table0 { ++ compatible = "operating-points-v2"; ++ opp-shared; ++ ++ opp@1000000000 { ++ opp-hz = /bits/ 64 <1000000000>; ++ opp-microvolt = <850000>; /* TBD; section 87.2 */ ++ 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>; ++ }; ++ ++ can_clk: can { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <0>; ++ }; ++ ++ /* MSIOF reference clock - to be overridden by boards that provide it */ ++ msiof_ref_clk: msiof-ref-clock { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <0>; ++ }; ++ ++ /* External PCIe clock - can be overridden by the board */ ++ pcie_bus_clk: pcie_bus { ++ 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 provide 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 = ; ++ }; ++ ++ gpio0: gpio@e6050000 { ++ compatible = "renesas,gpio-r8a7798", ++ "renesas,gpio-rcar"; ++ reg = <0 0xe6050000 0 0x50>; ++ interrupts = ; ++ #gpio-cells = <2>; ++ gpio-controller; ++ gpio-ranges = <&pfc 0 0 22>; ++ #interrupt-cells = <2>; ++ interrupt-controller; ++ clocks = <&cpg CPG_MOD 912>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ }; ++ ++ gpio1: gpio@e6051000 { ++ compatible = "renesas,gpio-r8a7798", ++ "renesas,gpio-rcar"; ++ reg = <0 0xe6051000 0 0x50>; ++ interrupts = ; ++ #gpio-cells = <2>; ++ gpio-controller; ++ gpio-ranges = <&pfc 0 32 28>; ++ #interrupt-cells = <2>; ++ interrupt-controller; ++ clocks = <&cpg CPG_MOD 911>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ }; ++ ++ gpio2: gpio@e6052000 { ++ compatible = "renesas,gpio-r8a7798", ++ "renesas,gpio-rcar"; ++ reg = <0 0xe6052000 0 0x50>; ++ interrupts = ; ++ #gpio-cells = <2>; ++ gpio-controller; ++ gpio-ranges = <&pfc 0 64 29>; ++ #interrupt-cells = <2>; ++ interrupt-controller; ++ clocks = <&cpg CPG_MOD 910>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ }; ++ ++ gpio3: gpio@e6053000 { ++ compatible = "renesas,gpio-r8a7798", ++ "renesas,gpio-rcar"; ++ reg = <0 0xe6053000 0 0x50>; ++ interrupts = ; ++ #gpio-cells = <2>; ++ gpio-controller; ++ gpio-ranges = <&pfc 0 96 17>; ++ #interrupt-cells = <2>; ++ interrupt-controller; ++ clocks = <&cpg CPG_MOD 909>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ }; ++ ++ gpio4: gpio@e6054000 { ++ compatible = "renesas,gpio-r8a7798", ++ "renesas,gpio-rcar"; ++ reg = <0 0xe6054000 0 0x50>; ++ interrupts = ; ++ #gpio-cells = <2>; ++ gpio-controller; ++ gpio-ranges = <&pfc 0 128 25>; ++ #interrupt-cells = <2>; ++ interrupt-controller; ++ clocks = <&cpg CPG_MOD 908>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ }; ++ ++ gpio5: gpio@e6055000 { ++ compatible = "renesas,gpio-r8a7798", ++ "renesas,gpio-rcar"; ++ reg = <0 0xe6055000 0 0x50>; ++ interrupts = ; ++ #gpio-cells = <2>; ++ gpio-controller; ++ gpio-ranges = <&pfc 0 160 15>; ++ #interrupt-cells = <2>; ++ interrupt-controller; ++ clocks = <&cpg CPG_MOD 907>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ }; ++ ++ pmu_a53 { ++ compatible = "arm,cortex-a53-pmu"; ++ interrupts = , ++ , ++ , ++ ; ++ interrupt-affinity = <&a53_0>, ++ <&a53_1>, ++ <&a53_2>, ++ <&a53_3>; ++ }; ++ ++ timer { ++ compatible = "arm,armv8-timer"; ++ interrupts = , ++ , ++ , ++ ; ++ }; ++ ++ wdt0: wdt@e6020000 { ++ compatible = "renesas,r8a7798-wdt", "renesas,rcar-gen3-wdt"; ++ reg = <0 0xe6020000 0 0x0c>; ++ clocks = <&cpg CPG_MOD 402>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ cpg: clock-controller@e6150000 { ++ compatible = "renesas,r8a7798-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,r8a7798-csi2"; ++ reg = <0 0xfeaa0000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 716>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ csi2_41: csi2@feab0000 { ++ compatible = "renesas,r8a7798-csi2"; ++ reg = <0 0xfeab0000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 715>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ prr: chipid@fff00044 { ++ compatible = "renesas,prr"; ++ reg = <0 0xfff00044 0 4>; ++ }; ++ ++ rst: reset-controller@e6160000 { ++ compatible = "renesas,r8a7798-rst"; ++ reg = <0 0xe6160000 0 0x0200>; ++ }; ++ ++ sysc: system-controller@e6180000 { ++ compatible = "renesas,r8a7798-sysc"; ++ reg = <0 0xe6180000 0 0x0440>; ++ #power-domain-cells = <1>; ++ }; ++ ++ pfc: pfc@e6060000 { ++ compatible = "renesas,pfc-r8a7798"; ++ reg = <0 0xe6060000 0 0x50c>; ++ }; ++ ++ intc_ex: interrupt-controller@e61c0000 { ++ compatible = "renesas,intc-ex-r8a7798", "renesas,irqc"; ++ #interrupt-cells = <2>; ++ interrupt-controller; ++ reg = <0 0xe61c0000 0 0x200>; ++ interrupts = ; /* SPI1:IRQ1, SPI2:IRQ2, SPI3:IRQ3, SPI18:IRQ4, SPI161:IRQ5 */ ++ clocks = <&cpg CPG_MOD 407>; /* RMSTPCR4/bit7:INTC-EX */ ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ }; ++ ++ ipmmu_vi: mmu@febd0000 { ++ compatible = "renesas,ipmmu-r8a7798"; ++ reg = <0 0xfebd0000 0 0x1000>; /* IPMMU-VI */ ++ renesas,ipmmu-main = <&ipmmu_mm 14>; ++ #iommu-cells = <1>; ++ status = "disabled"; ++ }; ++ ++ ipmmu_vc: mmu@fe6b0000 { ++ compatible = "renesas,ipmmu-r8a7798"; ++ reg = <0 0xfe6b0000 0 0x1000>; /* IPMMU-VC */ ++ renesas,ipmmu-main = <&ipmmu_mm 12>; ++ #iommu-cells = <1>; ++ status = "disabled"; ++ }; ++ ++ ipmmu_ir: mmu@ff8b0000 { ++ compatible = "renesas,ipmmu-r8a7798"; ++ 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-r8a7798"; ++ reg = <0 0xffc80000 0 0x1000>; /* IPMMU-RT */ ++ renesas,ipmmu-main = <&ipmmu_mm 10>; ++ #iommu-cells = <1>; ++ status = "disabled"; ++ }; ++ ++ ipmmu_ds0: mmu@e6740000 { ++ compatible = "renesas,ipmmu-r8a7798"; ++ reg = <0 0xe6740000 0 0x1000>; /* IPMMU-DS1 */ ++ renesas,ipmmu-main = <&ipmmu_mm 0>; ++ #iommu-cells = <1>; ++ status = "disabled"; ++ }; ++ ++ ipmmu_vip0: mmu@e7b00000 { ++ compatible = "renesas,ipmmu-r8a7798"; ++ reg = <0 0xe7b00000 0 0x1000>; /* IPMMU-VIP0 */ ++ renesas,ipmmu-main = <&ipmmu_mm 0>; /* FIXME missing in datasheet */ ++ #iommu-cells = <1>; ++ status = "disabled"; ++ }; ++ ++ ipmmu_vip1: mmu@e7960000 { ++ compatible = "renesas,ipmmu-r8a7798"; ++ reg = <0 0xe7960000 0 0x1000>; /* IPMMU-VIP1 */ ++ renesas,ipmmu-main = <&ipmmu_mm 0>; /* FIXME missing in datasheet */ ++ #iommu-cells = <1>; ++ status = "disabled"; ++ }; ++ ++ ipmmu_mm: mmu@e67b0000 { ++ compatible = "renesas,ipmmu-r8a7798"; ++ reg = <0 0xe67b0000 0 0x1000>; /* IPMMU-MM */ ++ interrupts = , ++ ; ++ #iommu-cells = <1>; ++ status = "disabled"; ++ }; ++ ++ dmac1: dma-controller@e7300000 { ++ compatible = "renesas,dmac-r8a7798", ++ "renesas,rcar-dmac"; ++ reg = <0 0xe7300000 0 0x10000>; ++ interrupts = ; ++ ++ ++ interrupt-names = "error", ++ "ch0", "ch1", "ch2", "ch3", ++ "ch4", "ch5", "ch6", "ch7", ++ "ch8", "ch9", "ch10", "ch11", ++ "ch12", "ch13", "ch14", "ch15"; ++ clocks = <&cpg CPG_MOD 218>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ #dma-cells = <1>; ++ dma-channels = <16>; ++ 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>, ++ <&ipmmu_ds0 8>, <&ipmmu_ds0 9>, ++ <&ipmmu_ds0 10>, <&ipmmu_ds0 11>, ++ <&ipmmu_ds0 12>, <&ipmmu_ds0 13>, ++ <&ipmmu_ds0 14>, <&ipmmu_ds0 15>; ++ }; ++ ++ dmac2: dma-controller@e7310000 { ++ compatible = "renesas,dmac-r8a7798", ++ "renesas,rcar-dmac"; ++ reg = <0 0xe7310000 0 0x10000>; ++ interrupts = ; /* SPI307::SYS-DMAC2 err, ++ SPI312~319:SYS-DMAC2.ch0~SYS-DMAC1.ch7 */ ++ interrupt-names = "error", ++ "ch0", "ch1", "ch2", "ch3", ++ "ch4", "ch5", "ch6", "ch7", ++ "ch8", "ch9", "ch10", "ch11", ++ "ch12", "ch13", "ch14", "ch15"; ++ clocks = <&cpg CPG_MOD 217>; /* RMSTPCR2/bit17:SYS-DMAC2 */ ++ clock-names = "fck"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ #dma-cells = <1>; ++ dma-channels = <16>; ++ 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>, ++ <&ipmmu_ds0 24>, <&ipmmu_ds0 25>, ++ <&ipmmu_ds0 26>, <&ipmmu_ds0 27>, ++ <&ipmmu_ds0 28>, <&ipmmu_ds0 29>, ++ <&ipmmu_ds0 30>, <&ipmmu_ds0 31>; ++ }; ++ ++ avb: ethernet@e6800000 { ++ compatible = "renesas,etheravb-r8a7798", ++ "renesas,etheravb-rcar-gen3"; ++ reg = <0 0xe6800000 0 0x800>, <0 0xe6a00000 0 0x10000>; ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; /* 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 R8A7798_PD_ALWAYS_ON>; ++ phy-mode = "rgmii-id"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ canfd: canfd@e66c0000 { ++ compatible = "renesas,r8a7798-canfd", ++ "renesas,rcar-gen3-canfd"; ++ reg = <0 0xe66c0000 0 0x8000>; ++ interrupts = , ++ ; ++ clocks = <&cpg CPG_MOD 914>, ++ <&cpg CPG_CORE R8A7798_CLK_CANFD>, ++ <&can_clk>; ++ clock-names = "fck", "canfd", "can_clk"; ++ assigned-clocks = <&cpg CPG_CORE R8A7798_CLK_CANFD>; ++ assigned-clock-rates = <40000000>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ ++ channel0 { ++ status = "disabled"; ++ }; ++ ++ channel1 { ++ status = "disabled"; ++ }; ++ }; ++ ++ ++ cmt0: timer@ffca0000 { ++ compatible = "renesas,cmt-48-r8a7798", "renesas,cmt-48-gen2"; ++ reg = <0 0xffca0000 0 0x1004>; ++ interrupts = , ++ ; ++ clocks = <&cpg CPG_MOD 303>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ ++ renesas,channels-mask = <0x60>; ++ ++ status = "disabled"; ++ }; ++ ++ cmt1: timer@e6130000 { ++ compatible = "renesas,cmt-48-r8a7798", "renesas,cmt-48-gen2"; ++ reg = <0 0xe6130000 0 0x1004>; ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 302>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ ++ renesas,channels-mask = <0xff>; ++ ++ status = "disabled"; ++ }; ++ ++ cmt2: timer@e6140000 { ++ compatible = "renesas,cmt-48-r8a7798", "renesas,cmt-48-gen2"; ++ reg = <0 0xe6140000 0 0x1004>; ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 301>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ ++ renesas,channels-mask = <0xff>; ++ ++ status = "disabled"; ++ }; ++ ++ cmt3: timer@e6148000 { ++ compatible = "renesas,cmt-48-r8a7798", "renesas,cmt-48-gen2"; ++ reg = <0 0xe6148000 0 0x1004>; ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 300>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ ++ renesas,channels-mask = <0xff>; ++ ++ status = "disabled"; ++ }; ++ ++ tpu: pwm@e6e80000 { ++ compatible = "renesas,tpu-r8a7798", "renesas,tpu"; ++ reg = <0 0xe6e80000 0 0x100>; ++ clocks = <&cpg CPG_MOD 304>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ #pwm-cells = <4>; ++ }; ++ ++ tmu0: timer@e61e0000 { ++ compatible = "renesas,tmu-r8a7798", "renesas,tmu"; ++ reg = <0 0xe61e0000 0 0x30>; ++ interrupts = , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 125>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ #renesas,channels = <3>; ++ status = "disabled"; ++ }; ++ ++ tmu1: timer@e6fc0000 { ++ compatible = "renesas,tmu-r8a7798", "renesas,tmu"; ++ reg = <0 0xe6fc0000 0 0x30>; ++ interrupts = , ++ , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 124>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ #renesas,channels = <3>; ++ status = "disabled"; ++ }; ++ ++ tmu2: timer@e6fd0000 { ++ compatible = "renesas,tmu-r8a7798", "renesas,tmu"; ++ reg = <0 0xe6fd0000 0 0x30>; ++ interrupts = , ++ , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 123>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ #renesas,channels = <3>; ++ status = "disabled"; ++ }; ++ ++ tmu3: timer@e6fe0000 { ++ compatible = "renesas,tmu-r8a7798", "renesas,tmu"; ++ reg = <0 0xe6fe0000 0 0x30>; ++ interrupts = , ++ , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 122>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ #renesas,channels = <3>; ++ status = "disabled"; ++ }; ++ ++ tmu4: timer@ffc00000 { ++ compatible = "renesas,tmu-r8a7798", "renesas,tmu"; ++ reg = <0 0xffc00000 0 0x30>; ++ interrupts = , ++ , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 121>; ++ clock-names = "fck"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ #renesas,channels = <3>; ++ status = "disabled"; ++ }; ++ ++ pwm0: pwm@e6e30000 { ++ compatible = "renesas,pwm-r8a7798", "renesas,pwm-rcar"; ++ reg = <0 0xe6e30000 0 0x10>; ++ #pwm-cells = <2>; ++ clocks = <&cpg CPG_MOD 523>; /* RMSTPCR5/bit23:PWM */ ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ pwm1: pwm@e6e31000 { ++ compatible = "renesas,pwm-r8a7798", "renesas,pwm-rcar"; ++ reg = <0 0xe6e31000 0 0x10>; ++ #pwm-cells = <2>; ++ clocks = <&cpg CPG_MOD 523>; /* RMSTPCR5/bit23:PWM */ ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ pwm2: pwm@e6e32000 { ++ compatible = "renesas,pwm-r8a7798", "renesas,pwm-rcar"; ++ reg = <0 0xe6e32000 0 0x10>; ++ #pwm-cells = <2>; ++ clocks = <&cpg CPG_MOD 523>; /* RMSTPCR5/bit23:PWM */ ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ pwm3: pwm@e6e33000 { ++ compatible = "renesas,pwm-r8a7798", "renesas,pwm-rcar"; ++ reg = <0 0xe6e33000 0 0x10>; ++ #pwm-cells = <2>; ++ clocks = <&cpg CPG_MOD 523>; /* RMSTPCR5/bit23:PWM */ ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ pwm4: pwm@e6e34000 { ++ compatible = "renesas,pwm-r8a7798", "renesas,pwm-rcar"; ++ reg = <0 0xe6e34000 0 0x10>; ++ #pwm-cells = <2>; ++ clocks = <&cpg CPG_MOD 523>; /* RMSTPCR5/bit23:PWM */ ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ hscif0: serial@e6540000 { ++ compatible = "renesas,hscif-r8a7798", ++ "renesas,rcar-gen3-hscif", ++ "renesas,hscif"; ++ reg = <0 0xe6540000 0 96>; ++ interrupts = ; /* SPI154:HSCIF.ch0 */ ++ clocks = <&cpg CPG_MOD 520>, ++ <&cpg CPG_CORE R8A7798_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 R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ hscif1: serial@e6550000 { ++ compatible = "renesas,hscif-r8a7798", ++ "renesas,rcar-gen3-hscif", ++ "renesas,hscif"; ++ reg = <0 0xe6550000 0 96>; ++ interrupts = ; /* SPI155:HSCIF.ch1 */ ++ clocks = <&cpg CPG_MOD 519>, ++ <&cpg CPG_CORE R8A7798_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 R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ hscif2: serial@e6560000 { ++ compatible = "renesas,hscif-r8a7798", ++ "renesas,rcar-gen3-hscif", ++ "renesas,hscif"; ++ reg = <0 0xe6560000 0 96>; ++ interrupts = ; /* SPI144:HSCIF.ch2 */ ++ clocks = <&cpg CPG_MOD 518>, ++ <&cpg CPG_CORE R8A7798_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 R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ hscif3: serial@e66a0000 { ++ compatible = "renesas,hscif-r8a7798", ++ "renesas,rcar-gen3-hscif", ++ "renesas,hscif"; ++ reg = <0 0xe66a0000 0 96>; ++ //interrupts = ; /* SPI145:HSCIF.ch3 */ ++ clocks = <&cpg CPG_MOD 517>, ++ <&cpg CPG_CORE R8A7798_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 R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ scif0: serial@e6e60000 { ++ compatible = "renesas,scif-r8a7798", ++ "renesas,rcar-gen3-scif", "renesas,scif"; ++ reg = <0 0xe6e60000 0 64>; ++ interrupts = ; /* SPI152:SCIF.ch0 */ ++ clocks = <&cpg CPG_MOD 207>, ++ <&cpg CPG_CORE R8A7798_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 R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ scif1: serial@e6e68000 { ++ compatible = "renesas,scif-r8a7798", ++ "renesas,rcar-gen3-scif", "renesas,scif"; ++ reg = <0 0xe6e68000 0 64>; ++ interrupts = ; /* SPI153:SCIF.ch1 */ ++ clocks = <&cpg CPG_MOD 206>, ++ <&cpg CPG_CORE R8A7798_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 R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ scif3: serial@e6c50000 { ++ compatible = "renesas,scif-r8a7798", ++ "renesas,rcar-gen3-scif", "renesas,scif"; ++ reg = <0 0xe6c50000 0 64>; ++ interrupts = ; /* SPI23:SCIF.ch3 */ ++ clocks = <&cpg CPG_MOD 204>, ++ <&cpg CPG_CORE R8A7798_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 R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ scif4: serial@e6c40000 { ++ compatible = "renesas,scif-r8a7798", ++ "renesas,rcar-gen3-scif", "renesas,scif"; ++ reg = <0 0xe6c40000 0 64>; ++ interrupts = ; /* SPI16:SCIF.ch4 */ ++ clocks = <&cpg CPG_MOD 203>, ++ <&cpg CPG_CORE R8A7798_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 R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ i2c0: i2c@e6500000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "renesas,i2c-r8a7798"; ++ reg = <0 0xe6500000 0 0x40>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 931>; ++ power-domains = <&sysc R8A7798_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-r8a7798"; ++ reg = <0 0xe6508000 0 0x40>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 930>; ++ power-domains = <&sysc R8A7798_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-r8a7798"; ++ reg = <0 0xe6510000 0 0x40>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 929>; ++ power-domains = <&sysc R8A7798_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-r8a7798"; ++ reg = <0 0xe66d0000 0 0x40>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 928>; ++ power-domains = <&sysc R8A7798_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-r8a7798"; ++ reg = <0 0xe66d8000 0 0x40>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 927>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ dmas = <&dmac1 0x99>, <&dmac1 0x98>; ++ dma-names = "tx", "rx"; ++ i2c-scl-internal-delay-ns = <6>; ++ status = "disabled"; ++ }; ++ ++ i2c5: i2c@e66e0000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "renesas,i2c-r8a7798"; ++ reg = <0 0xe66e0000 0 0x40>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 00>; /* FIXME missing entry in MSSR */ ++ power-domains = <&sysc R8A7798_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-r8a7798"; ++ reg = <0 0xe6e90000 0 0x64>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 211>, <&msiof_ref_clk>; ++ clock-names = "msiof_clk", "msiof_ref_clk"; ++ dmas = <&dmac1 0x41>, <&dmac1 0x40>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ msiof1: spi@e6ea0000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "renesas,msiof-r8a7798"; ++ reg = <0 0xe6ea0000 0 0x0064>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 210>, <&msiof_ref_clk>; ++ clock-names = "msiof_clk", "msiof_ref_clk"; ++ dmas = <&dmac1 0x43>, <&dmac1 0x42>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ msiof2: spi@e6c00000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "renesas,msiof-r8a7798"; ++ reg = <0 0xe6c00000 0 0x0064>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 209>, <&msiof_ref_clk>; ++ clock-names = "msiof_clk", "msiof_ref_clk"; ++ dmas = <&dmac1 0x45>, <&dmac1 0x44>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ msiof3: spi@e6c10000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "renesas,msiof-r8a7798"; ++ reg = <0 0xe6c10000 0 0x0064>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 208>, <&msiof_ref_clk>; ++ clock-names = "msiof_clk", "msiof_ref_clk"; ++ dmas = <&dmac1 0x47>, <&dmac1 0x46>; ++ dma-names = "tx", "rx"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ ++ pciec: pcie@fe000000 { ++ compatible = "renesas,pcie-r8a7798", ++ "renesas,pcie-rcar-gen3"; ++ reg = <0 0xfe000000 0 0x80000>, ++ <0 0xe65d0000 0 0x8000>; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ bus-range = <0x00 0xff>; ++ device_type = "pci"; ++ ranges = <0x01000000 0 0x00000000 0 0xfe100000 0 0x00100000 ++ 0x02000000 0 0xfe200000 0 0xfe200000 0 0x00200000 ++ 0x02000000 0 0x30000000 0 0x30000000 0 0x08000000 ++ 0x42000000 0 0x38000000 0 0x38000000 0 0x08000000>; ++ dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x80000000>; ++ interrupts = , ++ , ++ ; ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0 0 0 0>; ++ interrupt-map = <0 0 0 0 &gic GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>; ++ clocks = <&cpg CPG_MOD 319>, <&pcie_bus_clk>; ++ clock-names = "pcie", "pcie_bus"; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin0: video@e6ef0000 { ++ compatible = "renesas,vin-r8a7798"; ++ reg = <0 0xe6ef0000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 811>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin1: video@e6ef1000 { ++ compatible = "renesas,vin-r8a7798"; ++ reg = <0 0xe6ef1000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 810>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin2: video@e6ef2000 { ++ compatible = "renesas,vin-r8a7798"; ++ reg = <0 0xe6ef2000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 809>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin3: video@e6ef3000 { ++ compatible = "renesas,vin-r8a7798"; ++ reg = <0 0xe6ef3000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 808>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin4: video@e6ef4000 { ++ compatible = "renesas,vin-r8a7798"; ++ reg = <0 0xe6ef4000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 807>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin5: video@e6ef5000 { ++ compatible = "renesas,vin-r8a7798"; ++ reg = <0 0xe6ef5000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 806>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin6: video@e6ef6000 { ++ compatible = "renesas,vin-r8a7798"; ++ reg = <0 0xe6ef6000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 805>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin7: video@e6ef7000 { ++ compatible = "renesas,vin-r8a7798"; ++ reg = <0 0xe6ef7000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 804>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin8: video@e6ef8000 { ++ compatible = "renesas,vin-r8a7798"; ++ reg = <0 0xe6ef8000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 628>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin9: video@e6ef9000 { ++ compatible = "renesas,vin-r8a7798"; ++ reg = <0 0xe6ef9000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 625>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin10: video@e6efa000 { ++ compatible = "renesas,vin-r8a7798"; ++ reg = <0 0xe6efa000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 808>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin11: video@e6efb000 { ++ compatible = "renesas,vin-r8a7798"; ++ reg = <0 0xe6efb000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 618>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin12: video@e6efc000 { ++ compatible = "renesas,vin-r8a7798"; ++ reg = <0 0xe6efc000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 612>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin13: video@e6efd000 { ++ compatible = "renesas,vin-r8a7798"; ++ reg = <0 0xe6efd000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 608>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin14: video@e6efe000 { ++ compatible = "renesas,vin-r8a7798"; ++ reg = <0 0xe6efe000 0 0x1000>; ++ interrupts = ; /* FIXME no info in datasheet */ ++ clocks = <&cpg CPG_MOD 605>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ vin15: video@e6eff000 { ++ compatible = "renesas,vin-r8a7798"; ++ reg = <0 0xe6eff000 0 0x1000>; ++ interrupts = ; /* FIXME no info in datasheet */ ++ clocks = <&cpg CPG_MOD 604>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ sdhi2: sd@ee140000 { ++ compatible = "renesas,sdhi-r8a7798"; ++ reg = <0 0xee140000 0 0x2000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 314>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ renesas,clk-rate = <200000000>; ++ status = "disabled"; ++ }; ++ ++ qos@e67e0000 { ++ compatible = "renesas,qos"; ++ }; ++ ++ vspd0: vsp@fea20000 { ++ compatible = "renesas,vsp2"; ++ reg = <0 0xfea20000 0 0x4000>; ++ ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 623>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ ++ renesas,fcp = <&fcpvd0>; ++ }; ++ ++ fcpvd0: fcp@fea27000 { ++ compatible = "renesas,r8a7798-fcpv", "renesas,fcpv"; ++ reg = <0 0xfea27000 0 0x200>; ++ clocks = <&cpg CPG_MOD 603>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ }; ++ ++ du: display@feb00000 { ++ compatible = "renesas,du-r8a7798"; ++ reg = <0 0xfeb00000 0 0x80000>, ++ <0 0xfeb90000 0 0x14>; ++ reg-names = "du", "lvds.0"; ++ interrupts = ; ++ 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@0xe6198000 { ++ compatible = "renesas,thermal-r8a7798"; ++ reg = <0 0xe6198000 0 0x5c>; ++ interrupts = , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 522>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ #thermal-sensor-cells = <0>; ++ status = "okay"; ++ }; ++ ++ tsc2: thermal@0xe61a0000 { ++ compatible = "renesas,thermal-r8a7798"; ++ reg = <0 0xe61a0000 0 0x5c>; ++ interrupts = , ++ , ++ ; ++ clocks = <&cpg CPG_MOD 522>; ++ power-domains = <&sysc R8A7798_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>, ++ <&a53_2>, ++ <&a53_3>; ++ status = "disabled"; ++ }; ++ ++ sensor_thermal1: sensor-thermal1 { ++ polling-delay-passive = <250>; ++ polling-delay = <0>; ++ sustainable-power = <0>; /* TBD; HWM 87.4 */ ++ ++ thermal-sensors = <&tsc1>; ++ ++ trips { ++ sensor1_crit: sensor1-crit { ++ temperature = <120000>; ++ hysteresis = <2000>; ++ type = "critical"; ++ }; ++ }; ++ }; ++ ++ sensor_thermal2: sensor-thermal2 { ++ polling-delay-passive = <250>; ++ polling-delay = <0>; ++ sustainable-power = <0>; /* TBD; HWM 87.4 */ ++ ++ thermal-sensors = <&tsc2>; ++ ++ trips { ++ sensor2_crit: sensor2-crit { ++ temperature = <120000>; ++ hysteresis = <2000>; ++ type = "critical"; ++ }; ++ }; ++ }; ++ }; ++ ++ mfis: mfis@e6260000 { ++ compatible = "renesas,mfis-r8a7798", "renesas,mfis"; ++ reg = <0 0xe6260000 0 0x0200>; ++ clocks = <&cpg CPG_MOD 213>; ++ clock-names = "mfis"; ++ interrupts = ; ++ interrupt-names = "eicr0"; ++ status = "okay"; ++ }; ++ ++ mfis_lock: mfis-lock@e62600c0 { ++ compatible = "renesas,mfis-lock-r8a7798", ++ "renesas,mfis-lock"; ++ reg = <0 0xe62600c0 0 0x0020>; ++ status = "okay"; ++ }; ++ ++ imp_distributer: impdes0 { ++ compatible = "renesas,impx5+-distributer"; ++ reg = <0 0xffa00000 0 0x4000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 830>; ++ power-domains = <&sysc R8A7798_PD_A3IR>; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ }; ++ ++ imp0 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff900000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <0>; ++ clocks = <&cpg CPG_MOD 827>; ++ power-domains = <&sysc R8A7798_PD_A2IR0>; ++ }; ++ ++ imp1 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff920000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <1>; ++ clocks = <&cpg CPG_MOD 826>; ++ power-domains = <&sysc R8A7798_PD_A2IR1>; ++ }; ++ ++ imp2 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff940000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <2>; ++ clocks = <&cpg CPG_MOD 825>; ++ power-domains = <&sysc R8A7798_PD_A2IR2>; ++ }; ++ ++ imp3 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff960000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <3>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7798_PD_A2IR3>; ++ }; ++ ++ imp4 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xffa80000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <4>; ++ clocks = <&cpg CPG_MOD 521>; ++ power-domains = <&sysc R8A7798_PD_A2IR4>; ++ }; ++ ++ imp5 { ++ compatible = "renesas,impslc0"; ++ reg = <0 0xff9c0000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <5>; ++ clocks = <&cpg CPG_MOD 500>; ++ power-domains = <&sysc R8A7798_PD_A2IR4>; ++ }; ++ ++ impsc0 { ++ compatible = "renesas,impx4-shader"; ++ reg = <0 0xff980000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <6>; ++ clocks = <&cpg CPG_MOD 829>; ++ power-domains = <&sysc R8A7798_PD_A2SC0>; ++ }; ++ ++ impsc1 { ++ compatible = "renesas,impx4-shader"; ++ reg = <0 0xff990000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <7>; ++ clocks = <&cpg CPG_MOD 828>; ++ power-domains = <&sysc R8A7798_PD_A2SC1>; ++ }; ++ ++ impsc2 { ++ compatible = "renesas,impx4-shader"; ++ reg = <0 0xff9a0000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <8>; ++ clocks = <&cpg CPG_MOD 531>; ++ power-domains = <&sysc R8A7798_PD_A2SC2>; ++ }; ++ ++ impsc3 { ++ compatible = "renesas,impx4-shader"; ++ reg = <0 0xff9b0000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <9>; ++ clocks = <&cpg CPG_MOD 529>; ++ power-domains = <&sysc R8A7798_PD_A2SC3>; ++ }; ++ ++ impsc4 { ++ compatible = "renesas,impx4-shader"; ++ reg = <0 0xffa40000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <10>; ++ clocks = <&cpg CPG_MOD 528>; ++ power-domains = <&sysc R8A7798_PD_A2SC4>; ++ }; ++ ++ impdm0 { ++ compatible = "renesas,impx5-dmac"; ++ reg = <0 0xffa10000 0 0x1000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <11>; ++ clocks = <&cpg CPG_MOD 527>; ++ power-domains = <&sysc R8A7798_PD_A2PD0>; ++ }; ++ ++ impdm1 { ++ compatible = "renesas,impx5-dmac"; ++ reg = <0 0xffa14000 0 0x1000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <13>; ++ clocks = <&cpg CPG_MOD 526>; ++ power-domains = <&sysc R8A7798_PD_A2PD1>; ++ }; ++ ++ imppsc0 { ++ compatible = "renesas,impx5+-psc"; ++ reg = <0 0xffa20000 0 0x4000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <15>; ++ clocks = <&cpg CPG_MOD 525>; ++ power-domains = <&sysc R8A7798_PD_A2PD0>; ++ }; ++ ++ imppsc1 { ++ compatible = "renesas,impx5+-psc"; ++ reg = <0 0xffa24000 0 0x4000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <16>; ++ clocks = <&cpg CPG_MOD 524>; ++ power-domains = <&sysc R8A7798_PD_A2PD1>; ++ }; ++ ++ impcnn0 { ++ compatible = "renesas,impx5+-cnn"; ++ reg = <0 0xff9e0000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <17>; ++ clocks = <&cpg CPG_MOD 831>; ++ power-domains = <&sysc R8A7798_PD_A2CN>; ++ }; ++ ++ impc0 { ++ compatible = "renesas,impx4-memory"; ++ reg = <0 0xed000000 0 0x100000>; ++ clocks = <&cpg CPG_MOD 830>; ++ power-domains = <&sysc R8A7798_PD_A3IR>; ++ }; ++ ++ imrlx4_ch0: imr-lx4@fe860000 { ++ compatible = "renesas,imr-lx4"; ++ reg = <0 0xfe860000 0 0x2000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 823>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ }; ++ ++ imrlx4_ch1: imr-lx4@fe870000 { ++ compatible = "renesas,imr-lx4"; ++ reg = <0 0xfe870000 0 0x2000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 822>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ }; ++ ++ imrlx4_ch2: imr-lx4@fe880000 { ++ compatible = "renesas,imr-lx4"; ++ reg = <0 0xfe880000 0 0x2000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 821>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ }; ++ ++ imrlx4_ch3: imr-lx4@fe890000 { ++ compatible = "renesas,imr-lx4"; ++ reg = <0 0xfe890000 0 0x2000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 820>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ }; ++ }; ++}; +diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig +index b52e907..4e6d24d 100644 +--- a/drivers/clk/renesas/Kconfig ++++ b/drivers/clk/renesas/Kconfig +@@ -6,6 +6,7 @@ config CLK_RENESAS_CPG_MSSR + default y if ARCH_R8A7796 + default y if ARCH_R8A77965 + default y if ARCH_R8A7797 ++ default y if ARCH_R8A7798 + + config CLK_RENESAS_CPG_MSTP + bool +diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile +index c2ef11e..9f659d5 100644 +--- a/drivers/clk/renesas/Makefile ++++ b/drivers/clk/renesas/Makefile +@@ -15,6 +15,7 @@ obj-$(CONFIG_ARCH_R8A7795) += r8a7795-cpg-mssr.o rcar-gen3-cpg.o + obj-$(CONFIG_ARCH_R8A7796) += r8a7796-cpg-mssr.o rcar-gen3-cpg.o + obj-$(CONFIG_ARCH_R8A77965) += r8a77965-cpg-mssr.o rcar-gen3-cpg.o + obj-$(CONFIG_ARCH_R8A7797) += r8a7797-cpg-mssr.o rcar-gen3-cpg.o ++obj-$(CONFIG_ARCH_R8A7798) += r8a7798-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/r8a7798-cpg-mssr.c b/drivers/clk/renesas/r8a7798-cpg-mssr.c +new file mode 100644 +index 0000000..c7b68ac +--- /dev/null ++++ b/drivers/clk/renesas/r8a7798-cpg-mssr.c +@@ -0,0 +1,284 @@ ++/* ++ * r8a7798 Clock Pulse Generator / Module Standby and Software Reset ++ * ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 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; version 2 of the License. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "renesas-cpg-mssr.h" ++#include "rcar-gen3-cpg.h" ++ ++enum clk_ids { ++ /* Core Clock Outputs exported to DT */ ++ LAST_DT_CORE_CLK = R8A7798_CLK_OSC, ++ ++ /* External Input Clocks */ ++ CLK_EXTAL, ++ CLK_EXTALR, ++ ++ /* Internal Core Clocks */ ++ CLK_MAIN, ++ CLK_PLL1, ++ CLK_PLL2, ++ CLK_PLL3, ++ CLK_PLL1_DIV2, ++ CLK_PLL1_DIV4, ++ CLK_S0, ++ CLK_S1, ++ CLK_S2, ++ CLK_S3, ++ CLK_SDSRC, ++ CLK_RINT, ++ ++ /* Module Clocks */ ++ MOD_CLK_BASE ++}; ++ ++static const struct cpg_core_clk r8a7798_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(".pll1", CLK_PLL1, CLK_TYPE_GEN3_PLL1, CLK_MAIN), ++ DEF_BASE(".pll2", CLK_PLL2, CLK_TYPE_GEN3_PLL2, 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(".s0", CLK_S0, CLK_PLL1_DIV2, 2, 1), ++ DEF_FIXED(".s1", CLK_S1, CLK_PLL1_DIV2, 3, 1), ++ DEF_FIXED(".s2", CLK_S2, CLK_PLL1_DIV2, 4, 1), ++ DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 6, 1), ++ DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1_DIV2, 2, 1), ++ ++ /* Core Clock Outputs */ ++ DEF_BASE("z2", R8A7798_CLK_Z2, CLK_TYPE_GEN3_Z2, CLK_PLL2), ++ DEF_FIXED("ztr", R8A7798_CLK_ZTR, CLK_PLL1_DIV2, 6, 1), ++ DEF_FIXED("ztrd2", R8A7798_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1), ++ DEF_FIXED("zt", R8A7798_CLK_ZT, CLK_PLL1_DIV2, 4, 1), ++ DEF_FIXED("zx", R8A7798_CLK_ZX, CLK_PLL1_DIV2, 3, 1), ++ DEF_FIXED("s0d1", R8A7798_CLK_S0D1, CLK_S0, 1, 1), ++ DEF_FIXED("s0d2", R8A7798_CLK_S0D2, CLK_S0, 2, 1), ++ DEF_FIXED("s0d3", R8A7798_CLK_S0D3, CLK_S0, 3, 1), ++ DEF_FIXED("s0d4", R8A7798_CLK_S0D4, CLK_S0, 4, 1), ++ DEF_FIXED("s0d6", R8A7798_CLK_S0D6, CLK_S0, 6, 1), ++ DEF_FIXED("s0d12", R8A7798_CLK_S0D12, CLK_S0, 12, 1), ++ DEF_FIXED("s0d24", R8A7798_CLK_S0D24, CLK_S0, 24, 1), ++ DEF_FIXED("s1d1", R8A7798_CLK_S1D1, CLK_S1, 1, 1), ++ DEF_FIXED("s1d2", R8A7798_CLK_S1D2, CLK_S1, 2, 1), ++ DEF_FIXED("s1d4", R8A7798_CLK_S1D4, CLK_S1, 4, 1), ++ DEF_FIXED("s2d1", R8A7798_CLK_S2D1, CLK_S2, 1, 1), ++ DEF_FIXED("s2d2", R8A7798_CLK_S2D2, CLK_S2, 2, 1), ++ DEF_FIXED("s2d4", R8A7798_CLK_S2D4, CLK_S2, 4, 1), ++ DEF_FIXED("s3d1", R8A7798_CLK_S3D1, CLK_S3, 1, 1), ++ DEF_FIXED("s3d2", R8A7798_CLK_S3D2, CLK_S3, 2, 1), ++ DEF_FIXED("s3d4", R8A7798_CLK_S3D4, CLK_S3, 4, 1), ++ ++ DEF_GEN3_SD("sd0", R8A7798_CLK_SD0, CLK_SDSRC, 0x0074), /* OK? */ ++ ++ DEF_FIXED("cl", R8A7798_CLK_CL, CLK_PLL1_DIV2, 48, 1), ++ DEF_FIXED("cp", R8A7798_CLK_CP, CLK_EXTAL, 2, 1), ++ ++ DEF_DIV6P1("canfd", R8A7798_CLK_CANFD, CLK_PLL1_DIV4, 0x244), ++ DEF_DIV6P1("csi0", R8A7798_CLK_CSI0, CLK_PLL1_DIV4, 0x00c), ++ DEF_DIV6P1("mso", R8A7798_CLK_MSO, CLK_PLL1_DIV4, 0x014), ++ ++ DEF_BASE("osc", R8A7798_CLK_OSC, CLK_TYPE_GEN3_OSC, CLK_EXTAL), ++ DEF_BASE("r_int", CLK_RINT, CLK_TYPE_GEN3_RINT, CLK_EXTAL), ++ ++ DEF_BASE("r", R8A7798_CLK_R, CLK_TYPE_GEN3_R, CLK_RINT), ++}; ++ ++static const struct mssr_mod_clk r8a7798_mod_clks[] __initconst = { ++ /*... skip crc, umf, disp, rt-sram, cle, smd_ */ ++ DEF_MOD("tmu4", 121, R8A7798_CLK_S0D6), ++ DEF_MOD("tmu3", 122, R8A7798_CLK_S0D6), ++ DEF_MOD("tmu2", 123, R8A7798_CLK_S0D6), ++ DEF_MOD("tmu1", 124, R8A7798_CLK_S0D6), ++ DEF_MOD("tmu0", 125, R8A7798_CLK_CP), ++ DEF_MOD("ivcp1e", 127, R8A7798_CLK_S3D1), /* FIXME parent clk? */ ++ DEF_MOD("scif4", 203, R8A7798_CLK_S3D4), ++ DEF_MOD("scif3", 204, R8A7798_CLK_S3D4), ++ DEF_MOD("scif1", 206, R8A7798_CLK_S3D4), ++ DEF_MOD("scif0", 207, R8A7798_CLK_S3D4), ++ DEF_MOD("msiof3", 208, R8A7798_CLK_MSO), ++ DEF_MOD("msiof2", 209, R8A7798_CLK_MSO), ++ DEF_MOD("msiof1", 210, R8A7798_CLK_MSO), ++ DEF_MOD("msiof0", 211, R8A7798_CLK_MSO), ++ DEF_MOD("mfis", 213, R8A7798_CLK_S2D2), /* FIXME parent clk? */ ++ DEF_MOD("sys-dmac2", 217, R8A7798_CLK_S0D3), /* OK? */ ++ DEF_MOD("sys-dmac1", 218, R8A7798_CLK_S0D3), /* OK? */ ++ DEF_MOD("cmt3", 300, R8A7798_CLK_R), ++ DEF_MOD("cmt2", 301, R8A7798_CLK_R), ++ DEF_MOD("cmt1", 302, R8A7798_CLK_R), ++ DEF_MOD("cmt0", 303, R8A7798_CLK_R), ++ DEF_MOD("tpu", 304, R8A7798_CLK_S3D4), ++ DEF_MOD("sdif", 314, R8A7798_CLK_SD0), /* OK */ ++ DEF_MOD("pciec", 319, R8A7798_CLK_S3D1), ++ DEF_MOD("rwdt0", 402, R8A7798_CLK_R), ++ DEF_MOD("intc-ex", 407, R8A7798_CLK_CP), /* OK */ ++ DEF_MOD("intc-ap", 408, R8A7798_CLK_S0D3), ++ DEF_MOD("simp", 500, R8A7798_CLK_S1D1), ++ DEF_MOD("hscif3", 517, R8A7798_CLK_S3D1), ++ DEF_MOD("hscif2", 518, R8A7798_CLK_S3D1), ++ DEF_MOD("hscif1", 519, R8A7798_CLK_S3D1), ++ DEF_MOD("hscif0", 520, R8A7798_CLK_S3D1), ++ DEF_MOD("imp4", 521, R8A7798_CLK_S1D1), /* OK? */ ++ DEF_MOD("thermal", 522, R8A7798_CLK_CP), ++ DEF_MOD("pwm", 523, R8A7798_CLK_S0D12), ++ DEF_MOD("imppsc1", 524, R8A7798_CLK_S1D1), ++ DEF_MOD("imppsc0", 525, R8A7798_CLK_S1D1), ++ DEF_MOD("impdma1", 526, R8A7798_CLK_S1D1), /* OK? */ ++ DEF_MOD("impdma0", 527, R8A7798_CLK_S1D1), /* OK? */ ++ DEF_MOD("imp-ocv4", 528, R8A7798_CLK_S1D1), /* OK? */ ++ DEF_MOD("imp-ocv3", 529, R8A7798_CLK_S1D1), /* OK? */ ++ DEF_MOD("imp-ocv2", 531, R8A7798_CLK_S1D1), /* OK? */ ++ DEF_MOD("fcpvd0", 603, R8A7798_CLK_S3D1), ++ DEF_MOD("vin15", 604, R8A7798_CLK_S2D1), /* FIXME parent clk? */ ++ DEF_MOD("vin14", 605, R8A7798_CLK_S2D1), /* FIXME parent clk? */ ++ DEF_MOD("vin13", 608, R8A7798_CLK_S2D1), /* FIXME parent clk? */ ++ DEF_MOD("vin12", 612, R8A7798_CLK_S2D1), /* FIXME parent clk? */ ++ DEF_MOD("vin11", 618, R8A7798_CLK_S2D1), /* FIXME parent clk? */ ++ DEF_MOD("vspd0", 623, R8A7798_CLK_S3D1), ++ DEF_MOD("vin10", 625, R8A7798_CLK_S2D1), /* FIXME parent clk? */ ++ DEF_MOD("vin9", 627, R8A7798_CLK_S2D1), /* FIXME parent clk? */ ++ DEF_MOD("vin8", 628, R8A7798_CLK_S2D1), /* FIXME parent clk? */ ++#if 0 /* FIXME what is this? duplicated with 822,823 */ ++ DEF_MOD("imr1", 706, R8A7798_CLK_S2D1), /* FIXME parent clk? */ ++ DEF_MOD("imr0", 707, R8A7798_CLK_S2D1), /* FIXME parent clk? */ ++#endif ++ DEF_MOD("csi41", 715, R8A7798_CLK_CSI0), ++ DEF_MOD("csi40", 716, R8A7798_CLK_CSI0), ++ DEF_MOD("du0", 724, R8A7798_CLK_S2D1), ++ DEF_MOD("lvds", 727, R8A7798_CLK_S2D1), ++ DEF_MOD("vin7", 804, R8A7798_CLK_S0D2), /* FIXME parent clk? */ ++ DEF_MOD("vin6", 805, R8A7798_CLK_S0D2), /* FIXME parent clk? */ ++ DEF_MOD("vin5", 806, R8A7798_CLK_S0D2), /* FIXME parent clk? */ ++ DEF_MOD("vin4", 807, R8A7798_CLK_S0D2), /* FIXME parent clk? */ ++ DEF_MOD("vin3", 808, R8A7798_CLK_S0D2), /* FIXME parent clk? */ ++ DEF_MOD("vin2", 809, R8A7798_CLK_S0D2), /* FIXME parent clk? */ ++ DEF_MOD("vin1", 810, R8A7798_CLK_S0D2), /* FIXME parent clk? */ ++ DEF_MOD("vin0", 811, R8A7798_CLK_S0D2), /* FIXME parent clk? */ ++ DEF_MOD("etheravb", 812, R8A7798_CLK_S3D2), /* OK */ ++ DEF_MOD("gether", 813, R8A7798_CLK_S3D2), /* OK */ ++ DEF_MOD("isp1", 814, R8A7798_CLK_S3D1), /* FIXME parent clk? */ ++ DEF_MOD("isp0", 817, R8A7798_CLK_S3D1), /* FIXME parent clk? */ ++ DEF_MOD("imr3", 820, R8A7798_CLK_S2D1), /* FIXME check clk? */ ++ DEF_MOD("imr2", 821, R8A7798_CLK_S2D1), /* FIXME check clk? */ ++ DEF_MOD("imr1", 822, R8A7798_CLK_S2D1), /* FIXME check clk? */ ++ DEF_MOD("imr0", 823, R8A7798_CLK_S2D1), /* FIXME check clk? */ ++ DEF_MOD("imp3", 824, R8A7798_CLK_S1D1), /* OK? figure 8.1e CPG block diag */ ++ DEF_MOD("imp2", 825, R8A7798_CLK_S1D1), /* OK? */ ++ DEF_MOD("imp1", 826, R8A7798_CLK_S1D1), /* OK? */ ++ DEF_MOD("imp0", 827, R8A7798_CLK_S1D1), /* OK? */ ++ DEF_MOD("imp-ocv1", 828, R8A7798_CLK_S1D1), /* OK? */ ++ DEF_MOD("imp-ocv0", 829, R8A7798_CLK_S1D1), /* OK? */ ++ DEF_MOD("impram", 830, R8A7798_CLK_S1D1), /* OK? */ ++ DEF_MOD("impcnn", 831, R8A7798_CLK_S1D1), /* OK? */ ++ DEF_MOD("gpio5", 907, R8A7798_CLK_CP), ++ DEF_MOD("gpio4", 908, R8A7798_CLK_CP), ++ DEF_MOD("gpio3", 909, R8A7798_CLK_CP), ++ DEF_MOD("gpio2", 910, R8A7798_CLK_CP), ++ DEF_MOD("gpio1", 911, R8A7798_CLK_CP), ++ DEF_MOD("gpio0", 912, R8A7798_CLK_CP), ++ DEF_MOD("can-fd", 914, R8A7798_CLK_S3D2), ++ /* FIXME missing MSSR for i2c5; should it be 919 as in H3/M3? */ ++ /* DEF_MOD("i2c4", 919, R8A7798_CLK_S3D2), */ ++ DEF_MOD("i2c4", 927, R8A7798_CLK_S0D6), ++ DEF_MOD("i2c3", 928, R8A7798_CLK_S0D6), ++ DEF_MOD("i2c2", 929, R8A7798_CLK_S3D2), ++ DEF_MOD("i2c1", 930, R8A7798_CLK_S3D2), ++ DEF_MOD("i2c0", 931, R8A7798_CLK_S3D2), ++}; ++ ++static const unsigned int r8a7798_crit_mod_clks[] __initconst = { ++ MOD_CLK_ID(408), /* INTC-AP (GIC) */ ++}; ++ ++ ++/* ++ * CPG Clock Data ++ */ ++ ++/* ++ * MD EXTAL PLL2 PLL1 PLL3 ++ * 14 13 19 (MHz) ++ *------------------------------------------------- ++ * 0 0 0 16.66 x 1 x240 x192 x192 ++ * 0 0 1 16.66 x 1 x240 x192 x192 ++ * 0 1 0 20 x 1 x200 x160 x160 ++ * 0 1 1 20 x 1 x200 x160 x160 ++ * 1 0 0 27 x 1 x148 x118 x118 ++ * 1 0 1 27 x 1 x148 x118 x118 ++ * 1 1 0 33.33 / 2 x240 x192 x192 ++ * 1 1 1 33.33 / 2 x240 x192 x192 ++ */ ++#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, 192,}, ++ { 1, 192, 192,}, ++ { 1, 160, 160,}, ++ { 1, 160, 160,}, ++ { 1, 118, 118,}, ++ { 1, 118, 118,}, ++ { 2, 192, 192,}, ++ { 2, 192, 192,}, ++}; ++ ++static int __init r8a7798_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 r8a7798_cpg_mssr_info __initconst = { ++ /* Core Clocks */ ++ .core_clks = r8a7798_core_clks, ++ .num_core_clks = ARRAY_SIZE(r8a7798_core_clks), ++ .last_dt_core_clk = LAST_DT_CORE_CLK, ++ .num_total_core_clks = MOD_CLK_BASE, ++ ++ /* Module Clocks */ ++ .mod_clks = r8a7798_mod_clks, ++ .num_mod_clks = ARRAY_SIZE(r8a7798_mod_clks), ++ .num_hw_mod_clks = 12 * 32, ++ ++ /* Critical Module Clocks */ ++ .crit_mod_clks = r8a7798_crit_mod_clks, ++ .num_crit_mod_clks = ARRAY_SIZE(r8a7798_crit_mod_clks), ++ ++ /* Callbacks */ ++ .init = r8a7798_cpg_mssr_init, ++ .cpg_clk_register = rcar_gen3_cpg_clk_register, ++}; +diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c +index b145f14..aa4f5ce 100644 +--- a/drivers/clk/renesas/rcar-gen3-cpg.c ++++ b/drivers/clk/renesas/rcar-gen3-cpg.c +@@ -33,6 +34,11 @@ + { /* sentinel */ } + }; + ++static const struct soc_device_attribute r8a7798[] = { ++ { .soc_id = "r8a7798" }, ++ { } ++}; ++ + #define CPG_PLL0CR 0x00d8 + #define CPG_PLL2CR 0x002c + #define CPG_PLL4CR 0x01f4 +@@ -916,6 +922,11 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, + if (cpg_quirks & RCLK_CKSEL_RESEVED) + break; + ++ if (soc_device_match(r8a7798) && (cpg_mode ^ BIT(29))) { ++ parent = clks[cpg_clk_extalr]; ++ break; ++ } ++ + /* Select parent clock of RCLK by MD28 */ + if (cpg_mode & BIT(28)) + parent = clks[cpg_clk_extalr]; +diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c +index bd901a6..759facd 100644 +--- a/drivers/clk/renesas/renesas-cpg-mssr.c ++++ b/drivers/clk/renesas/renesas-cpg-mssr.c +@@ -600,6 +602,12 @@ static int __init cpg_mssr_add_clk_domain(struct device *dev, + .data = &r8a7797_cpg_mssr_info, + }, + #endif ++#ifdef CONFIG_ARCH_R8A7798 ++ { ++ .compatible = "renesas,r8a7798-cpg-mssr", ++ .data = &r8a7798_cpg_mssr_info, ++ }, ++#endif + { /* sentinel */ } + }; + +diff --git a/drivers/clk/renesas/renesas-cpg-mssr.h b/drivers/clk/renesas/renesas-cpg-mssr.h +index ce3546a..d5aaf50 100644 +--- a/drivers/clk/renesas/renesas-cpg-mssr.h ++++ b/drivers/clk/renesas/renesas-cpg-mssr.h +@@ -136,6 +138,7 @@ struct cpg_mssr_info { + extern const struct cpg_mssr_info r8a7796_cpg_mssr_info; + extern const struct cpg_mssr_info r8a77965_cpg_mssr_info; + extern const struct cpg_mssr_info r8a7797_cpg_mssr_info; ++extern const struct cpg_mssr_info r8a7798_cpg_mssr_info; + + + /* +diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c +index 5a2ec23..2d7d41c 100644 +--- a/drivers/cpufreq/cpufreq-dt-platdev.c ++++ b/drivers/cpufreq/cpufreq-dt-platdev.c +@@ -61,6 +61,7 @@ + { .compatible = "renesas,r8a7796", }, + { .compatible = "renesas,r8a77965", }, + { .compatible = "renesas,r8a7797", }, ++ { .compatible = "renesas,r8a7798", }, + { .compatible = "renesas,sh73a0", }, + + { .compatible = "rockchip,rk2928", }, +diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c +index fd15649..d4549a0 100644 +--- a/drivers/gpio/gpio-rcar.c ++++ b/drivers/gpio/gpio-rcar.c +@@ -371,6 +372,10 @@ struct gpio_rcar_info { + /* Gen3 GPIO is identical to Gen2. */ + .data = &gpio_rcar_info_gen2, + }, { ++ .compatible = "renesas,gpio-r8a7798", ++ /* 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 f74f264..8700e13 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c ++++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c +@@ -360,6 +361,7 @@ + { .compatible = "renesas,du-r8a7796", .data = &rcar_du_r8a7796_info }, + { .compatible = "renesas,du-r8a77965", .data = &rcar_du_r8a77965_info }, + { .compatible = "renesas,du-r8a7797", .data = &rcar_du_r8a7797_info }, ++ { .compatible = "renesas,du-r8a7798", .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 3916b63..f236103 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_du_group.c ++++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c +@@ -35,8 +36,9 @@ + #include "rcar_du_group.h" + #include "rcar_du_regs.h" + +-static const struct soc_device_attribute r8a7797[] = { ++static const struct soc_device_attribute r8a7797_8[] = { + { .soc_id = "r8a7797" }, ++ { .soc_id = "r8a7798" }, + { } + }; + +@@ -161,7 +163,7 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp) + + /* Apply planes to CRTCs association. */ + mutex_lock(&rgrp->lock); +- if (!soc_device_match(r8a7797)) ++ if (!soc_device_match(r8a7797_8)) + rcar_du_group_write(rgrp, DPTSR, (rgrp->dptsr_planes << 16) | + rgrp->dptsr_planes); + +diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c +index 149c107..0ad583a 100644 +--- a/drivers/i2c/busses/i2c-rcar.c ++++ b/drivers/i2c/busses/i2c-rcar.c +@@ -808,6 +808,7 @@ static u32 rcar_i2c_func(struct i2c_adapter *adap) + { .compatible = "renesas,i2c-r8a7796", .data = (void *)I2C_RCAR_GEN3 }, + { .compatible = "renesas,i2c-r8a77965", .data = (void *)I2C_RCAR_GEN3 }, + { .compatible = "renesas,i2c-r8a7797", .data = (void *)I2C_RCAR_GEN3 }, ++ { .compatible = "renesas,i2c-r8a7798", .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 1ae9174..add0cd1 100644 +--- a/drivers/iommu/ipmmu-vmsa.c ++++ b/drivers/iommu/ipmmu-vmsa.c +@@ -1280,6 +1281,9 @@ static void ipmmu_device_reset(struct ipmmu_vmsa_device *mmu) + .compatible = "renesas,ipmmu-r8a7797", + .data = &ipmmu_features_rcar_gen3, + }, { ++ .compatible = "renesas,ipmmu-r8a7798", ++ .data = &ipmmu_features_rcar_gen3, ++ }, { + /* Terminator */ + }, + }; +diff --git a/drivers/media/platform/soc_camera/Kconfig b/drivers/media/platform/soc_camera/Kconfig +index 5539c5d..fc7d829 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 || ARCH_R8A7797 || COMPILE_TEST ++ depends on ARCH_R8A7795 || ARCH_R8A7796 || ARCH_R8A7797 || ARCH_R8A7798 || 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 2ef27e8..98f271f 100644 +--- a/drivers/media/platform/soc_camera/rcar_csi2.c ++++ b/drivers/media/platform/soc_camera/rcar_csi2.c +@@ -163,6 +163,11 @@ + #define RCAR_CSI2_INTSTATE_ERRSYNCESC (1 << 1) + #define RCAR_CSI2_INTSTATE_ERRCONTROL (1 << 0) + ++static const struct soc_device_attribute r8a7798[] = { ++ { .soc_id = "r8a7798" }, ++ { } ++}; ++ + static const struct soc_device_attribute r8a7797[] = { + { .soc_id = "r8a7797" }, + { } +@@ -410,7 +415,7 @@ static int rcar_csi2_set_phy_freq(struct rcar_csi2 *priv) + iowrite32((hs_freq_range_v3m[bps_per_lane] << 16) | + RCAR_CSI2_PHTW_DWEN | RCAR_CSI2_PHTW_CWEN | 0x44, + priv->base + RCAR_CSI2_PHTW); +- else if (soc_device_match(r8a7795)) ++ else if (soc_device_match(r8a7795) || soc_device_match(r8a7798)) + iowrite32(hs_freq_range_h3[bps_per_lane] << 16, + priv->base + RCAR_CSI2_PHYPLL); + else +@@ -497,8 +502,8 @@ static int rcar_csi2_hwinit(struct rcar_csi2 *priv) + return -EINVAL; + } + +- if (soc_device_match(r8a7795)) { +- /* Set PHY Test Interface Write Register in R-Car H3(ES2.0) */ ++ if (soc_device_match(r8a7795) || soc_device_match(r8a7798)) { ++ /* Set PHY Test Interface Write Register in R-Car H3(ES2.0)/V3H */ + iowrite32(0x01cc01e2, priv->base + RCAR_CSI2_PHTW); + iowrite32(0x010101e3, priv->base + RCAR_CSI2_PHTW); + iowrite32(0x010101e4, priv->base + RCAR_CSI2_PHTW); +@@ -515,7 +520,7 @@ static int rcar_csi2_hwinit(struct rcar_csi2 *priv) + /* Set CSI0CLK Frequency Configuration Preset Register + * in R-Car H3(ES2.0) + */ +- if (soc_device_match(r8a7795)) ++ if (soc_device_match(r8a7795) || soc_device_match(r8a7798)) + iowrite32(CSI0CLKFREQRANGE(32), priv->base + RCAR_CSI2_CSI0CLKFCPR); + + /* Enable lanes */ +@@ -609,6 +614,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,r8a7798-csi2", .data = (void *)RCAR_GEN3 }, + { .compatible = "renesas,r8a7797-csi2", .data = (void *)RCAR_GEN3 }, + { .compatible = "renesas,r8a7796-csi2", .data = (void *)RCAR_GEN3 }, + { .compatible = "renesas,r8a7795-csi2", .data = (void *)RCAR_GEN3 }, +@@ -618,6 +624,7 @@ static int rcar_csi2_s_power(struct v4l2_subdev *sd, int on) + #endif + + static struct platform_device_id rcar_csi2_id_table[] = { ++ { "r8a7798-csi2", RCAR_GEN3 }, + { "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 7bd8a77..1e098ef 100644 +--- a/drivers/media/platform/soc_camera/rcar_vin.c ++++ b/drivers/media/platform/soc_camera/rcar_vin.c +@@ -162,7 +162,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, V3M:CSI40 */ ++#define VNCSI_IFMD_DES0 (1 << 25) /* H3,V3H:CSI40/41, M3:CSI40, V3M:CSI40 */ + + #define VNCSI_IFMD_CSI_CHSEL(n) (n << 0) + #define VNCSI_IFMD_SEL_NUMBER 5 +@@ -197,6 +197,7 @@ + + enum chip_id { + RCAR_GEN3, ++ RCAR_V3H, + RCAR_V3M, + RCAR_M3, + RCAR_H3, +@@ -416,6 +417,69 @@ struct vin_gen3_ifmd { + }, + }; + ++static const struct vin_gen3_ifmd vin_v3h_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}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH1}, ++ } ++ }, ++ { 0x0001, ++ { ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ } ++ }, ++ { 0x0002, ++ { ++ {RCAR_CSI40, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI40, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI_CH_NONE, RCAR_VIN_CH_NONE}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI41, 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}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH0}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH1}, ++ {RCAR_CSI41, RCAR_VIRTUAL_CH2}, ++ {RCAR_CSI41, 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}, ++ {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, +@@ -911,7 +975,7 @@ static int rcar_vin_videobuf_setup(struct vb2_queue *vq, + struct rcar_vin_cam *cam = icd->host_priv; + + if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_V3M) { ++ priv->chip == RCAR_V3M || priv->chip == RCAR_V3H) { + if ((priv->ratio_h > 0x10000) || (priv->ratio_v > 0x10000)) { + dev_err(icd->parent, "Scaling rate parameter error\n"); + return -EINVAL; +@@ -1020,7 +1084,7 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) + switch (icd->current_fmt->host_fmt->fourcc) { + case V4L2_PIX_FMT_NV12: + if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_V3M) { ++ priv->chip == RCAR_V3M || priv->chip == RCAR_V3H) { + iowrite32(ALIGN((cam->out_width * cam->out_height), + 0x80), priv->base + VNUVAOF_REG); + dmr = VNDMR_DTMD_YCSEP_YCBCR420; +@@ -1056,7 +1120,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_V3M && priv->chip != RCAR_V3H && + priv->chip != RCAR_GEN2 && priv->chip != RCAR_H1 && + priv->chip != RCAR_E1) + goto e_format; +@@ -1065,7 +1129,7 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) + break; + case V4L2_PIX_FMT_ABGR32: + if (priv->chip != RCAR_H3 && priv->chip != RCAR_M3 && +- priv->chip != RCAR_V3M) ++ priv->chip != RCAR_V3M && priv->chip != RCAR_V3H) + goto e_format; + + dmr = VNDMR_EXRGB | VNDMR_DTMD_ARGB; +@@ -1086,7 +1150,7 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) + vnmc |= VNMC_BPS; + + if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_V3M) { ++ priv->chip == RCAR_V3M || priv->chip == RCAR_V3H) { + if (priv->pdata_flags & RCAR_VIN_CSI2) + vnmc &= ~VNMC_DPINE; + else +@@ -1462,7 +1526,7 @@ 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 || +- priv->chip == RCAR_V3M) { ++ priv->chip == RCAR_V3M || priv->chip == RCAR_V3H) { + struct v4l2_subdev *csi2_sd = find_csi2(priv); + struct v4l2_subdev *deser_sd = find_deser(priv); + int ret = 0; +@@ -1725,7 +1789,7 @@ static int rcar_vin_set_rect(struct soc_camera_device *icd) + } + + if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_V3M) { ++ priv->chip == RCAR_V3M || priv->chip == RCAR_V3H) { + if ((icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_NV12) && + (icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_SBGGR8) && + (icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_SBGGR12) +@@ -1883,7 +1947,7 @@ static int rcar_vin_set_bus_param(struct soc_camera_device *icd) + return ret; + + if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_V3M) { ++ priv->chip == RCAR_V3M || priv->chip == RCAR_V3H) { + if (cfg.type == V4L2_MBUS_CSI2) + vnmc &= ~VNMC_DPINE; + else +@@ -1891,7 +1955,7 @@ static int rcar_vin_set_bus_param(struct soc_camera_device *icd) + } + + if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_V3M) ++ priv->chip == RCAR_V3M || priv->chip == RCAR_V3H) + val = VNDMR2_FTEV; + else + val = VNDMR2_FTEV | VNDMR2_VLV(1); +@@ -2489,7 +2553,7 @@ static int rcar_vin_try_fmt(struct soc_camera_device *icd, + return ret; + + if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_V3M) { ++ priv->chip == RCAR_V3M || priv->chip == RCAR_V3H) { + /* Adjust max scaling size for Gen3 */ + if (pix->width > 4096) + pix->width = priv->max_width; +@@ -2668,6 +2732,7 @@ static int rcar_vin_get_edid(struct soc_camera_device *icd, + + #ifdef CONFIG_OF + static const struct of_device_id rcar_vin_of_table[] = { ++ { .compatible = "renesas,vin-r8a7798", .data = (void *)RCAR_V3H }, + { .compatible = "renesas,vin-r8a7797", .data = (void *)RCAR_V3M }, + { .compatible = "renesas,vin-r8a7796", .data = (void *)RCAR_M3 }, + { .compatible = "renesas,vin-r8a7795", .data = (void *)RCAR_H3 }, +@@ -2989,7 +3054,7 @@ static int rcar_vin_probe(struct platform_device *pdev) + } + + if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_V3M) { ++ priv->chip == RCAR_V3M || priv->chip == RCAR_V3H) { + priv->max_width = 4096; + priv->max_height = 4096; + } else { +@@ -2998,7 +3063,8 @@ static int rcar_vin_probe(struct platform_device *pdev) + } + + if ((priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || +- priv->chip == RCAR_V3M) && !of_property_read_string(np, "csi,select", &str)) { ++ priv->chip == RCAR_V3M || priv->chip == RCAR_V3H) && ++ !of_property_read_string(np, "csi,select", &str)) { + u32 ifmd = 0; + bool match_flag = false; + const struct vin_gen3_ifmd *gen3_ifmd_table = NULL; +@@ -3073,6 +3139,8 @@ static int rcar_vin_probe(struct platform_device *pdev) + gen3_ifmd_table = vin_m3_vc_ifmd; + else if (priv->chip == RCAR_V3M) + gen3_ifmd_table = vin_v3_vc_ifmd; ++ else if (priv->chip == RCAR_V3H) ++ gen3_ifmd_table = vin_v3h_vc_ifmd; + + for (i = 0; i < num; i++) { + if ((gen3_ifmd_table[i].v_sel[priv->index].csi2_ch +@@ -3236,6 +3304,9 @@ static int rcar_vin_resume(struct device *dev) + } else if (priv->chip == RCAR_V3M) { + ifmd = VNCSI_IFMD_DES1; + gen3_ifmd_table = vin_v3_vc_ifmd; ++ } else if (priv->chip == RCAR_V3H) { ++ ifmd = VNCSI_IFMD_DES0; ++ gen3_ifmd_table = vin_v3h_vc_ifmd; + } + + for (i = 0; i < num; i++) { +diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c +index e79f9e6..948e88c 100644 +--- a/drivers/media/platform/vsp1/vsp1_lif.c ++++ b/drivers/media/platform/vsp1/vsp1_lif.c +@@ -24,8 +25,9 @@ + #define LIF_MIN_SIZE 2U + #define LIF_MAX_SIZE 8190U + +-static const struct soc_device_attribute r8a7797[] = { ++static const struct soc_device_attribute r8a7797_8[] = { + { .soc_id = "r8a7797" }, ++ { .soc_id = "r8a7798" }, + { } + }; + +@@ -151,7 +153,7 @@ static void lif_configure(struct vsp1_entity *entity, + format = vsp1_entity_get_pad_format(&lif->entity, lif->entity.config, + LIF_PAD_SOURCE); + +- if (vsp1_gen3_vspdl_check(vsp1) || soc_device_match(r8a7797)) ++ if (vsp1_gen3_vspdl_check(vsp1) || soc_device_match(r8a7797_8)) + obth = 1500; + else + obth = 3000; +@@ -165,7 +167,7 @@ static void lif_configure(struct vsp1_entity *entity, + (format->code == 0 ? VI6_LIF_CTRL_CFMT : 0) | + VI6_LIF_CTRL_REQSEL | VI6_LIF_CTRL_LIF_EN); + +- if (soc_device_match(r8a7797)) ++ if (soc_device_match(r8a7797_8)) + vsp1_lif_write(lif, dl, VI6_LIF_LBA, VI6_LIF_LBA_LBA0 | + VI6_LIF_LBA_LBA1); + } +diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c +index 040f474..bee1116 100644 +--- a/drivers/mmc/host/sh_mobile_sdhi.c ++++ b/drivers/mmc/host/sh_mobile_sdhi.c +@@ -141,6 +142,7 @@ struct sh_mobile_sdhi_of_data { + { .compatible = "renesas,sdhi-r8a77965", + .data = &of_rcar_gen3_compatible, }, + { .compatible = "renesas,sdhi-r8a7797", .data = &of_rcar_gen3_compatible, }, ++ { .compatible = "renesas,sdhi-r8a7798", .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 73fa286..9943197 100644 +--- a/drivers/net/ethernet/renesas/ravb_main.c ++++ b/drivers/net/ethernet/renesas/ravb_main.c +@@ -1921,6 +1922,7 @@ static int ravb_mdio_release(struct ravb_private *priv) + { .compatible = "renesas,etheravb-r8a7796", .data = (void *)RCAR_GEN3 }, + { .compatible = "renesas,etheravb-r8a77965", .data = (void *)RCAR_GEN3 }, + { .compatible = "renesas,etheravb-r8a7797", .data = (void *)RCAR_GEN3 }, ++ { .compatible = "renesas,etheravb-r8a7798", .data = (void *)RCAR_GEN3 }, + { .compatible = "renesas,etheravb-rcar-gen3", .data = (void *)RCAR_GEN3 }, + { } + }; +diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c +index ccc29b3..2eb13c6 100644 +--- a/drivers/pci/host/pcie-rcar.c ++++ b/drivers/pci/host/pcie-rcar.c +@@ -30,6 +31,7 @@ + #include + #include + #include ++#include + + #define PCIECAR 0x000010 + #define PCIECCTLR 0x000018 +@@ -41,6 +43,8 @@ + #define PCIEINTXR 0x000400 + #define PCIEMSITXR 0x000840 + ++#define GEN3_PCIEPHYSR 0x07f0 ++ + /* Transfer control */ + #define PCIETCTLR 0x02000 + #define DL_DOWN (1 << 3) +@@ -118,6 +122,9 @@ + #define GEN2_PCIEPHYDATA 0x784 + #define GEN2_PCIEPHYCTRL 0x78c + ++/* R-Car Gen3 R8A7798 */ ++#define R8A7798_PCIEPHYCTL 0x4000 ++ + #define INT_PCI_MSI_NR 32 + + #define RCONF(x) (PCICONF(0)+(x)) +@@ -132,6 +139,11 @@ + #define RCAR_PCI_MAX_RESOURCES 4 + #define MAX_NR_INBOUND_MAPS 6 + ++static const struct soc_device_attribute r8a7798[] = { ++ { .soc_id = "r8a7798" }, ++ { } ++}; ++ + struct rcar_msi { + DECLARE_BITMAP(used, INT_PCI_MSI_NR); + struct irq_domain *domain; +@@ -151,6 +163,7 @@ static inline struct rcar_msi *to_rcar_msi(struct msi_controller *chip) + struct rcar_pcie { + struct device *dev; + void __iomem *base; ++ void __iomem *phy_base; + struct list_head resources; + int root_bus_nr; + struct clk *clk; +@@ -160,6 +173,18 @@ struct rcar_pcie { + + static int rcar_pcie_wait_for_dl(struct rcar_pcie *pcie); + ++static void rcar_pci_phy_write_reg(struct rcar_pcie *pcie, unsigned long val, ++ unsigned long reg) ++{ ++ writel(val, pcie->phy_base + reg); ++} ++ ++static unsigned long rcar_pci_phy_read_reg(struct rcar_pcie *pcie, ++ unsigned long reg) ++{ ++ return readl(pcie->phy_base + reg); ++} ++ + static void rcar_pci_write_reg(struct rcar_pcie *pcie, unsigned long val, + unsigned long reg) + { +@@ -672,6 +697,22 @@ static int rcar_pcie_hw_init(struct rcar_pcie *pcie) + return 0; + } + ++static int rcar_pcie_hw_init_r8a7798(struct rcar_pcie *pcie) ++{ ++ unsigned int timeout = 10; ++ ++ rcar_pci_phy_write_reg(pcie, 0, R8A7798_PCIEPHYCTL); ++ ++ while (timeout--) { ++ if (rcar_pci_read_reg(pcie, GEN3_PCIEPHYSR)) ++ return rcar_pcie_hw_init(pcie); ++ ++ msleep(5); ++ } ++ ++ return -ETIMEDOUT; ++} ++ + static int rcar_pcie_hw_init_h1(struct rcar_pcie *pcie) + { + unsigned int timeout = 10; +@@ -998,6 +1039,16 @@ static int rcar_pcie_get_resources(struct rcar_pcie *pcie) + if (IS_ERR(pcie->base)) + return PTR_ERR(pcie->base); + ++ if (soc_device_match(r8a7798)) { ++ err = of_address_to_resource(dev->of_node, 1, &res); ++ if (err) ++ return err; ++ ++ pcie->phy_base = devm_ioremap_resource(dev, &res); ++ if (IS_ERR(pcie->phy_base)) ++ return PTR_ERR(pcie->base); ++ } ++ + pcie->bus_clk = devm_clk_get(dev, "pcie_bus"); + if (IS_ERR(pcie->bus_clk)) { + dev_err(dev, "cannot get pcie bus clock\n"); +@@ -1153,6 +1204,7 @@ static int rcar_pcie_parse_map_dma_ranges(struct rcar_pcie *pcie, + { .compatible = "renesas,pcie-r8a7795", .data = rcar_pcie_hw_init }, + { .compatible = "renesas,pcie-r8a7796", .data = rcar_pcie_hw_init }, + { .compatible = "renesas,pcie-r8a77965", .data = rcar_pcie_hw_init }, ++ { .compatible = "renesas,pcie-r8a7798", .data = rcar_pcie_hw_init_r8a7798 }, + {}, + }; + +@@ -1347,7 +1399,13 @@ static SIMPLE_DEV_PM_OPS(rcar_pcie_pm_ops, + }, + .probe = rcar_pcie_probe, + }; +-builtin_platform_driver(rcar_pcie_driver); ++/* builtin_platform_driver(rcar_pcie_driver); */ ++ ++static int __init rcar_pcie_init(void) ++{ ++ return platform_driver_register(&rcar_pcie_driver); ++} ++late_initcall(rcar_pcie_init); + + static int rcar_pcie_pci_notifier(struct notifier_block *nb, + unsigned long action, void *data) +diff --git a/drivers/pinctrl/sh-pfc/Kconfig b/drivers/pinctrl/sh-pfc/Kconfig +index 4aaf0be..6ae17af 100644 +--- a/drivers/pinctrl/sh-pfc/Kconfig ++++ b/drivers/pinctrl/sh-pfc/Kconfig +@@ -89,6 +89,11 @@ config PINCTRL_PFC_R8A7797 + depends on ARCH_R8A7797 + select PINCTRL_SH_PFC + ++config PINCTRL_PFC_R8A7798 ++ def_bool y ++ depends on ARCH_R8A7798 ++ 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 e263c14..5f2f619 100644 +--- a/drivers/pinctrl/sh-pfc/Makefile ++++ b/drivers/pinctrl/sh-pfc/Makefile +@@ -15,6 +15,7 @@ obj-$(CONFIG_PINCTRL_PFC_R8A7795) += pfc-r8a7795-es1.o + obj-$(CONFIG_PINCTRL_PFC_R8A7796) += pfc-r8a7796.o + obj-$(CONFIG_PINCTRL_PFC_R8A77965) += pfc-r8a77965.o + obj-$(CONFIG_PINCTRL_PFC_R8A7797) += pfc-r8a7797.o ++obj-$(CONFIG_PINCTRL_PFC_R8A7798) += pfc-r8a7798.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 9aba933..a75293f 100644 +--- a/drivers/pinctrl/sh-pfc/core.c ++++ b/drivers/pinctrl/sh-pfc/core.c +@@ -552,6 +553,12 @@ static int sh_pfc_init_ranges(struct sh_pfc *pfc) + .data = &r8a7797_pinmux_info, + }, + #endif ++#ifdef CONFIG_PINCTRL_PFC_R8A7798 ++ { ++ .compatible = "renesas,pfc-r8a7798", ++ .data = &r8a7798_pinmux_info, ++ }, ++#endif + #ifdef CONFIG_PINCTRL_PFC_SH73A0 + { + .compatible = "renesas,pfc-sh73a0", +diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7798.c b/drivers/pinctrl/sh-pfc/pfc-r8a7798.c +new file mode 100644 +index 0000000..740bf4e +--- /dev/null ++++ b/drivers/pinctrl/sh-pfc/pfc-r8a7798.c +@@ -0,0 +1,3151 @@ ++/* ++ * R8A7798 processor support - PFC hardware block. ++ * ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * 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 ++#include ++#include ++ ++#include "core.h" ++#include "sh_pfc.h" ++ ++/* mmc in gpsr3, so do POC; check if any other reg needs it */ ++#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_30(2, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \ ++ PORT_GP_CFG_17(3, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH | \ ++ SH_PFC_PIN_CFG_IO_VOLTAGE), \ ++ PORT_GP_CFG_25(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_31_28) ++#define GPSR1_26 F_(DIGRF_CLKIN, IP8_27_24) ++#define GPSR1_25 F_(CANFD_CLK_A, IP8_23_20) /* OK? */ ++#define GPSR1_24 F_(CANFD1_RX, IP8_19_16) ++#define GPSR1_23 F_(CANFD1_TX, IP8_15_12) ++#define GPSR1_22 F_(CANFD0_RX_A, IP8_11_8) ++#define GPSR1_21 F_(CANFD0_TX_A, IP8_7_4) ++#define GPSR1_20 F_(AVB_AVTP_CAPTURE, IP8_3_0) ++#define GPSR1_19 F_(AVB_AVTP_MATCH, IP7_31_28) ++#define GPSR1_18 FM(AVB_LINK) ++#define GPSR1_17 FM(AVB_PHY_INT) ++#define GPSR1_16 FM(AVB_MAGIC) ++#define GPSR1_15 FM(AVB_MDC) ++#define GPSR1_14 FM(AVB_MDIO) ++#define GPSR1_13 FM(AVB_TXCREFCLK) ++#define GPSR1_12 FM(AVB_TD3) ++#define GPSR1_11 FM(AVB_TD2) ++#define GPSR1_10 FM(AVB_TD1) ++#define GPSR1_9 FM(AVB_TD0) ++#define GPSR1_8 FM(AVB_TXC) ++#define GPSR1_7 FM(AVB_TX_CTL) ++#define GPSR1_6 FM(AVB_RD3) ++#define GPSR1_5 FM(AVB_RD2) ++#define GPSR1_4 FM(AVB_RD1) ++#define GPSR1_3 FM(AVB_RD0) ++#define GPSR1_2 FM(AVB_RXC) ++#define GPSR1_1 FM(AVB_RX_CTL) ++#define GPSR1_0 F_(IRQ0, IP2_27_24) ++ ++/* GPSR2 */ ++#define GPSR2_29 F_(FSO_TOE_N, IP10_19_16) ++#define GPSR2_28 F_(FSO_CFE_1_N, IP10_15_12) ++#define GPSR2_27 F_(FSO_CFE_0_N, IP10_11_8) ++#define GPSR2_26 F_(SDA3, IP10_7_4) ++#define GPSR2_25 F_(SCL3, IP10_3_0) ++#define GPSR2_24 F_(MSIOF0_SS2, IP9_31_28) ++#define GPSR2_23 F_(MSIOF0_SS1, IP9_27_24) ++#define GPSR2_22 F_(MSIOF0_SYNC, IP9_23_20) ++#define GPSR2_21 F_(MSIOF0_SCK, IP9_19_16) ++#define GPSR2_20 F_(MSIOF0_TXD, IP9_15_12) ++#define GPSR2_19 F_(MSIOF0_RXD, IP9_11_8) ++#define GPSR2_18 F_(IRQ5, IP9_7_4) ++#define GPSR2_17 F_(IRQ4, IP9_3_0) ++#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_24 FM(GETHER_LINK_A) ++#define GPSR4_23 FM(GETHER_PHY_INT_A) ++#define GPSR4_22 FM(GETHER_MAGIC) ++#define GPSR4_21 FM(GETHER_MDC_A) ++#define GPSR4_20 FM(GETHER_MDIO_A) ++#define GPSR4_19 FM(GETHER_TXCREFCLK_MEGA) ++#define GPSR4_18 FM(GETHER_TXCREFCLK) ++#define GPSR4_17 FM(GETHER_TD3) ++#define GPSR4_16 FM(GETHER_TD2) ++#define GPSR4_15 FM(GETHER_TD1) ++#define GPSR4_14 FM(GETHER_TD0) ++#define GPSR4_13 FM(GETHER_TXC) ++#define GPSR4_12 FM(GETHER_TX_CTL) ++#define GPSR4_11 FM(GETHER_RD3) ++#define GPSR4_10 FM(GETHER_RD2) ++#define GPSR4_9 FM(GETHER_RD1) ++#define GPSR4_8 FM(GETHER_RD0) ++#define GPSR4_7 FM(GETHER_RXC) ++#define GPSR4_6 FM(GETHER_RX_CTL) ++#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(SCK4) FM(GETHER_RMII_CRS_DV) 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(RX4) FM(GETHER_RMII_RX_ER) 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(TX4) FM(GETHER_RMII_RXD0) 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(CTS4_N) FM(GETHER_RMII_RXD1) 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(RTS4_N_TANS) FM(GETHER_RMII_TXD_EN) 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) F_(0, 0) FM(GETHER_RMII_TXD0) 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) F_(0, 0) FM(GETHER_RMII_TXD1) 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(CPG_CPCKOUT) FM(GETHER_RMII_REFCLK) 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) FM(SCL5) F_(0, 0) FM(A8) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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) FM(SDA5) FM(GETHER_MDC_B) FM(A9) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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) FM(SCIF_CLK_A) FM(GETHER_MDIO_B) FM(A10) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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) FM(HRX0_A) F_(0, 0) FM(A11) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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) FM(HSCK0_A) F_(0, 0) FM(A12) 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_23_20 FM(DU_DB3) FM(HRTS0_N_A) F_(0, 0) FM(A13) 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_27_24 FM(DU_DB4) FM(HCTS0_N_A) F_(0, 0) FM(A14) 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 IP1_31_28 FM(DU_DB5) FM(HTX0_A) FM(PWM0_A) FM(A15) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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) FM(MSIOF3_RXD) F_(0, 0) FM(A16) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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) FM(MSIOF3_TXD) F_(0, 0) FM(A17) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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(MSIOF3_SS1) FM(GETHER_LINK_B) 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(MSIOF3_SS2) FM(GETHER_PHY_INT_B) FM(A19) 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_19_16 FM(DU_EXVSYNC_DU_VSYNC) FM(MSIOF3_SCK) F_(0, 0) F_(0, 0) 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_23_20 FM(DU_EXODDF_DU_ODDF_DISP_CDE) FM(MSIOF3_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) 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(AVB_AVTP_PPS) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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) 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 IP5_23_20 FM(VI1_DATA1) FM(MSIOF1_SS2) F_(0, 0) FM(D4) 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 IP5_27_24 FM(VI1_DATA2) FM(CANFD0_TX_B) F_(0, 0) FM(D5) FM(MMC_DS) F_(0, 0) F_(0, 0) F_(0, 0) 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_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 IP6_3_0 FM(VI1_DATA4) FM(CANFD_CLK_B) F_(0, 0) FM(D7) 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 IP6_7_4 FM(VI1_DATA5) F_(0, 0) F_(0, 0) FM(D8) 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_11_8 FM(VI1_DATA6) F_(0, 0) F_(0, 0) FM(D9) 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_15_12 FM(VI1_DATA7) F_(0, 0) F_(0, 0) FM(D10) 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_19_16 FM(VI1_DATA8) F_(0, 0) F_(0, 0) FM(D11) 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_23_20 FM(VI1_DATA9) FM(TCLK1_A) F_(0, 0) FM(D12) 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_27_24 FM(VI1_DATA10) FM(TCLK2_A) F_(0, 0) FM(D13) 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_31_28 FM(VI1_DATA11) FM(SCL4) F_(0, 0) FM(D14) FM(MMC_D6) F_(0, 0) F_(0, 0) F_(0, 0) 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) F_(0, 0) FM(D15) FM(MMC_D7) F_(0, 0) F_(0, 0) F_(0, 0) 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) F_(0, 0) F_(0, 0) FM(CLKOUT) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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) F_(0, 0) F_(0, 0) FM(BS_N) FM(SCK0) FM(HSCK0_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 IP7_15_12 FM(SCL1) F_(0, 0) FM(TPU0TO2) FM(RD_N) FM(CTS0_N) FM(HCTS0_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) ++#define IP7_19_16 FM(SDA1) F_(0, 0) FM(TPU0TO3) FM(WE0_N) FM(RTS0_N_TANS) FM(HRTS0_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) ++#define IP7_23_20 FM(SCL2) F_(0, 0) F_(0, 0) FM(WE1_N) FM(RX0) FM(HRX0_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 IP7_27_24 FM(SDA2) F_(0, 0) F_(0, 0) FM(EX_WAIT0) FM(TX0) FM(HTX0_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 IP7_31_28 FM(AVB_AVTP_MATCH) FM(TPU0TO0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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(AVB_AVTP_CAPTURE) FM(TPU0TO1) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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_TX_A) FM(FXR_TXDA) FM(PWM0_B) FM(DU_DISP) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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(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_15_12 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_19_16 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_23_20 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_27_24 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_31_28 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 IP9_3_0 FM(IRQ4) F_(0, 0) F_(0, 0) FM(VI0_DATA12) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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 IP9_7_4 FM(IRQ5) F_(0, 0) F_(0, 0) FM(VI0_DATA13) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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 IP9_11_8 FM(MSIOF0_RXD) FM(DU_DR0) F_(0, 0) FM(VI0_DATA14) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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 IP9_15_12 FM(MSIOF0_TXD) FM(DU_DR1) F_(0, 0) FM(VI0_DATA15) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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 IP9_19_16 FM(MSIOF0_SCK) FM(DU_DG0) F_(0, 0) FM(VI0_DATA16) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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 IP9_23_20 FM(MSIOF0_SYNC) FM(DU_DG1) F_(0, 0) FM(VI0_DATA17) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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 IP9_27_24 FM(MSIOF0_SS1) FM(DU_DB0) FM(TCLK3) FM(VI0_DATA18) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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 IP9_31_28 FM(MSIOF0_SS2) FM(DU_DB1) FM(TCLK4) FM(VI0_DATA19) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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 IP10_3_0 FM(SCL3) F_(0, 0) F_(0, 0) FM(VI0_DATA20) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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 IP10_7_4 FM(SDA3) F_(0, 0) F_(0, 0) FM(VI0_DATA21) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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 IP10_11_8 FM(FSO_CFE_0_N) F_(0, 0) F_(0, 0) FM(VI0_DATA22) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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 IP10_15_12 FM(FSO_CFE_1_N) F_(0, 0) F_(0, 0) FM(VI0_DATA23) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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 IP10_19_16 FM(FSO_TOE_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) F_(0, 0) F_(0, 0) ++#define IP10_23_20 F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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 IP10_27_24 F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0) 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 IP10_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 \ ++\ ++ GPSR2_29 \ ++ GPSR2_28 \ ++ GPSR1_27 GPSR2_27 \ ++ GPSR1_26 GPSR2_26 \ ++ GPSR1_25 GPSR2_25 \ ++ GPSR1_24 GPSR2_24 GPSR4_24 \ ++ GPSR1_23 GPSR2_23 GPSR4_23 \ ++ GPSR1_22 GPSR2_22 GPSR4_22 \ ++GPSR0_21 GPSR1_21 GPSR2_21 GPSR4_21 \ ++GPSR0_20 GPSR1_20 GPSR2_20 GPSR4_20 \ ++GPSR0_19 GPSR1_19 GPSR2_19 GPSR4_19 \ ++GPSR0_18 GPSR1_18 GPSR2_18 GPSR4_18 \ ++GPSR0_17 GPSR1_17 GPSR2_17 GPSR4_17 \ ++GPSR0_16 GPSR1_16 GPSR2_16 GPSR3_16 GPSR4_16 \ ++GPSR0_15 GPSR1_15 GPSR2_15 GPSR3_15 GPSR4_15 \ ++GPSR0_14 GPSR1_14 GPSR2_14 GPSR3_14 GPSR4_14 GPSR5_14 \ ++GPSR0_13 GPSR1_13 GPSR2_13 GPSR3_13 GPSR4_13 GPSR5_13 \ ++GPSR0_12 GPSR1_12 GPSR2_12 GPSR3_12 GPSR4_12 GPSR5_12 \ ++GPSR0_11 GPSR1_11 GPSR2_11 GPSR3_11 GPSR4_11 GPSR5_11 \ ++GPSR0_10 GPSR1_10 GPSR2_10 GPSR3_10 GPSR4_10 GPSR5_10 \ ++GPSR0_9 GPSR1_9 GPSR2_9 GPSR3_9 GPSR4_9 GPSR5_9 \ ++GPSR0_8 GPSR1_8 GPSR2_8 GPSR3_8 GPSR4_8 GPSR5_8 \ ++GPSR0_7 GPSR1_7 GPSR2_7 GPSR3_7 GPSR4_7 GPSR5_7 \ ++GPSR0_6 GPSR1_6 GPSR2_6 GPSR3_6 GPSR4_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(IP9_3_0) IP9_3_0 FM(IP10_3_0) IP10_3_0 \ ++FM(IP8_7_4) IP8_7_4 FM(IP9_7_4) IP9_7_4 FM(IP10_7_4) IP10_7_4 \ ++FM(IP8_11_8) IP8_11_8 FM(IP9_11_8) IP9_11_8 FM(IP10_11_8) IP10_11_8 \ ++FM(IP8_15_12) IP8_15_12 FM(IP9_15_12) IP9_15_12 FM(IP10_15_12) IP10_15_12 \ ++FM(IP8_19_16) IP8_19_16 FM(IP9_19_16) IP9_19_16 FM(IP10_19_16) IP10_19_16 \ ++FM(IP8_23_20) IP8_23_20 FM(IP9_23_20) IP9_23_20 FM(IP10_23_20) IP10_23_20 \ ++FM(IP8_27_24) IP8_27_24 FM(IP9_27_24) IP9_27_24 FM(IP10_27_24) IP10_27_24 \ ++FM(IP8_31_28) IP8_31_28 FM(IP9_31_28) IP9_31_28 FM(IP10_31_28) IP10_31_28 ++ ++/* ++ Set Value = H'0 Set Value = H'1 ++Register Function Pin Function Pin ++------------------------------------------------------------ ++sel_canfd0 CANFD0_TX_A CANFD0_TX_A CANFD0_TX_B VI1_DATA2 ++ CANFD0_RX_A CANFD0_RX_A CANFD0_TX_B VI1_DATA3 ++ CANFD_CLK_A CANFD_CLK_A CANFD_CLK_B VI1_DATA4 ++sel_gether GETHER_MDC_A GETHER_MDC_A GETHER_MDC_B DU_DG5 ++ GETHER_MDIO_A GETHER_MDIO_A GETHER_MDIO_B DU_DG6 ++ GETHER_LINK_A GETHER_LINK_A GETHER_LINK_B DU_DOTCLKOUT ++ GETHER_PHY_INT_A GETHER_PHY_INT_A GETHER_PHY_INT_B DU_EXHSYNC_DU_HSYNC ++sel_hscif0 HSCK0_A DU_DB2 HSCK0_B SDA0 ++ HCTS0_N_A DU_DB4 HCTS_N_B SCL1 ++ HRTS0_N_A DU_DB3 HRTS_N_B SDA1 ++ HRX0_A DU_DG7 HRX0_B SCL2 ++ HTX0_A DU_DB5 HTX0_B SDA2 ++ SCIF_CLK_A DU_DG6 SCIF_CLK_B CANFD_CLK_A ++sel_pwm0 PWM0_A DU_DB5 PWM0_B CANFD0_TX_A ++sel_pwm1 PWM1_A VI0_DATA9 PWM1_B CANFD0_RX_A ++sel_pwm2 PWM2_A VI0_DATA10 PWM2_B CANFD1_TX ++sel_pwm3 PWM3_A VI0_DATA11 PWM3_B CANFD1_RX ++sel_pwm4 PWM4_A VI0_FIELD PWM4_B CANFD_CLK_A ++sel_rsp SPEEDIN_A VI0_DATA1 SPEEDIN_B CANFD_CLK_A ++sel_scif1 RX1_A VI0_DATA4 RX1_B CANFD1_RX ++ TX1_A VI0_DATA5 TX1_B CANFD1_TX ++sel_tmu TCLK1_A VI1_DATA9 TCLK1_B CANFD1_TX ++ TCLK2_A VI1_DATA10 TCLK2_B CANFD1_RX ++*/ ++/* MOD_SEL0 */ /* 0 */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 */ /* 7 */ ++#define MOD_SEL0_11 FM(SEL_CANFD0_0) FM(SEL_CANFD0_1) ++#define MOD_SEL0_10 FM(SEL_GETHER_0) FM(SEL_GETHER_1) ++#define MOD_SEL0_9 FM(SEL_HSCIF0_0) FM(SEL_HSCIF0_1) ++#define MOD_SEL0_8 FM(SEL_PWM0_0) FM(SEL_PWM0_1) ++#define MOD_SEL0_7 FM(SEL_PWM1_0) FM(SEL_PWM1_1) ++#define MOD_SEL0_6 FM(SEL_PWM2_0) FM(SEL_PWM2_1) ++#define MOD_SEL0_5 FM(SEL_PWM3_0) FM(SEL_PWM3_1) ++#define MOD_SEL0_4 FM(SEL_PWM4_0) FM(SEL_PWM4_1) ++#define MOD_SEL0_2 FM(SEL_RSP_0) FM(SEL_RSP_1) ++#define MOD_SEL0_1 FM(SEL_SCIF1_0) FM(SEL_SCIF1_1) ++#define MOD_SEL0_0 FM(SEL_TMU1_0) FM(SEL_TMU1_1) ++ ++#define PINMUX_MOD_SELS \ ++\ ++MOD_SEL0_11 \ ++MOD_SEL0_10 \ ++MOD_SEL0_9 \ ++MOD_SEL0_8 \ ++MOD_SEL0_7 \ ++MOD_SEL0_6 \ ++MOD_SEL0_5 \ ++MOD_SEL0_4 \ ++MOD_SEL0_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(AVB_RX_CTL), ++ PINMUX_SINGLE(AVB_RXC), ++ PINMUX_SINGLE(AVB_RD0), ++ PINMUX_SINGLE(AVB_RD1), ++ PINMUX_SINGLE(AVB_RD2), ++ PINMUX_SINGLE(AVB_RD3), ++ PINMUX_SINGLE(AVB_TX_CTL), ++ PINMUX_SINGLE(AVB_TXC), ++ PINMUX_SINGLE(AVB_TD0), ++ PINMUX_SINGLE(AVB_TD1), ++ PINMUX_SINGLE(AVB_TD2), ++ PINMUX_SINGLE(AVB_TD3), ++ PINMUX_SINGLE(AVB_TXCREFCLK), ++ PINMUX_SINGLE(AVB_MDIO), ++ PINMUX_SINGLE(AVB_MDC), ++ PINMUX_SINGLE(AVB_MAGIC), ++ PINMUX_SINGLE(AVB_PHY_INT), ++ PINMUX_SINGLE(AVB_LINK), ++ ++ PINMUX_SINGLE(GETHER_RX_CTL), ++ PINMUX_SINGLE(GETHER_RXC), ++ PINMUX_SINGLE(GETHER_RD0), ++ PINMUX_SINGLE(GETHER_RD1), ++ PINMUX_SINGLE(GETHER_RD2), ++ PINMUX_SINGLE(GETHER_RD3), ++ PINMUX_SINGLE(GETHER_TX_CTL), ++ PINMUX_SINGLE(GETHER_TXC), ++ PINMUX_SINGLE(GETHER_TD0), ++ PINMUX_SINGLE(GETHER_TD1), ++ PINMUX_SINGLE(GETHER_TD2), ++ PINMUX_SINGLE(GETHER_TD3), ++ PINMUX_SINGLE(GETHER_TXCREFCLK), ++ PINMUX_SINGLE(GETHER_TXCREFCLK_MEGA), ++ PINMUX_SINGLE(GETHER_MDIO_A), ++ PINMUX_SINGLE(GETHER_MDC_A), ++ PINMUX_SINGLE(GETHER_MAGIC), ++ PINMUX_SINGLE(GETHER_PHY_INT_A), ++ PINMUX_SINGLE(GETHER_LINK_A), ++ ++ 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, SCK4), ++ PINMUX_IPSR_GPSR(IP0_3_0, GETHER_RMII_CRS_DV), ++ PINMUX_IPSR_GPSR(IP0_3_0, A0), ++ ++ PINMUX_IPSR_GPSR(IP0_7_4, DU_DR3), ++ PINMUX_IPSR_GPSR(IP0_7_4, RX4), ++ PINMUX_IPSR_GPSR(IP0_7_4, GETHER_RMII_RX_ER), ++ PINMUX_IPSR_GPSR(IP0_7_4, A1), ++ ++ PINMUX_IPSR_GPSR(IP0_11_8, DU_DR4), ++ PINMUX_IPSR_GPSR(IP0_11_8, TX4), ++ PINMUX_IPSR_GPSR(IP0_11_8, GETHER_RMII_RXD0), ++ PINMUX_IPSR_GPSR(IP0_11_8, A2), ++ ++ PINMUX_IPSR_GPSR(IP0_15_12, DU_DR5), ++ PINMUX_IPSR_GPSR(IP0_15_12, CTS4_N), ++ PINMUX_IPSR_GPSR(IP0_15_12, GETHER_RMII_RXD1), ++ PINMUX_IPSR_GPSR(IP0_15_12, A3), ++ ++ PINMUX_IPSR_GPSR(IP0_19_16, DU_DR6), ++ PINMUX_IPSR_GPSR(IP0_19_16, RTS4_N_TANS), ++ PINMUX_IPSR_GPSR(IP0_19_16, GETHER_RMII_TXD_EN), ++ PINMUX_IPSR_GPSR(IP0_19_16, A4), ++ ++ PINMUX_IPSR_GPSR(IP0_23_20, DU_DR7), ++ PINMUX_IPSR_GPSR(IP0_23_20, GETHER_RMII_TXD0), ++ PINMUX_IPSR_GPSR(IP0_23_20, A5), ++ ++ PINMUX_IPSR_GPSR(IP0_27_24, DU_DG2), ++ PINMUX_IPSR_GPSR(IP0_27_24, GETHER_RMII_TXD1), ++ PINMUX_IPSR_GPSR(IP0_27_24, A6), ++ ++ PINMUX_IPSR_GPSR(IP0_31_28, DU_DG3), ++ PINMUX_IPSR_GPSR(IP0_31_28, CPG_CPCKOUT), ++ PINMUX_IPSR_GPSR(IP0_31_28, GETHER_RMII_REFCLK), ++ 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, SCL5), ++ PINMUX_IPSR_GPSR(IP1_3_0, A8), ++ ++ PINMUX_IPSR_GPSR(IP1_7_4, DU_DG5), ++ PINMUX_IPSR_GPSR(IP1_7_4, SDA5), ++ PINMUX_IPSR_MSEL(IP1_7_4, GETHER_MDC_B, SEL_GETHER_1), ++ PINMUX_IPSR_GPSR(IP1_7_4, A9), ++ ++ PINMUX_IPSR_GPSR(IP1_11_8, DU_DG6), ++ PINMUX_IPSR_MSEL(IP1_11_8, SCIF_CLK_A, SEL_HSCIF0_0), ++ PINMUX_IPSR_MSEL(IP1_11_8, GETHER_MDIO_B, SEL_GETHER_1), ++ PINMUX_IPSR_GPSR(IP1_11_8, A10), ++ ++ PINMUX_IPSR_GPSR(IP1_15_12, DU_DG7), ++ PINMUX_IPSR_MSEL(IP1_15_12, HRX0_A, SEL_HSCIF0_0), ++ PINMUX_IPSR_GPSR(IP1_15_12, A11), ++ ++ PINMUX_IPSR_GPSR(IP1_19_16, DU_DB2), ++ PINMUX_IPSR_MSEL(IP1_19_16, HSCK0_A, SEL_HSCIF0_0), ++ PINMUX_IPSR_GPSR(IP1_19_16, A12), ++ PINMUX_IPSR_GPSR(IP1_19_16, IRQ1), ++ ++ PINMUX_IPSR_GPSR(IP1_23_20, DU_DB3), ++ PINMUX_IPSR_MSEL(IP1_23_20, HRTS0_N_A, SEL_HSCIF0_0), ++ PINMUX_IPSR_GPSR(IP1_23_20, A13), ++ PINMUX_IPSR_GPSR(IP1_23_20, IRQ2), ++ ++ PINMUX_IPSR_GPSR(IP1_27_24, DU_DB4), ++ PINMUX_IPSR_MSEL(IP1_27_24, HCTS0_N_A, SEL_HSCIF0_0), ++ PINMUX_IPSR_GPSR(IP1_27_24, A14), ++ PINMUX_IPSR_GPSR(IP1_27_24, IRQ3), ++ ++ PINMUX_IPSR_GPSR(IP1_31_28, DU_DB5), ++ PINMUX_IPSR_MSEL(IP1_31_28, HTX0_A, SEL_HSCIF0_0), ++ PINMUX_IPSR_MSEL(IP1_31_28, PWM0_A, SEL_PWM0_0), ++ PINMUX_IPSR_GPSR(IP1_31_28, A15), ++ ++ /* IPSR2 */ ++ PINMUX_IPSR_GPSR(IP2_3_0, DU_DB6), ++ PINMUX_IPSR_GPSR(IP2_3_0, MSIOF3_RXD), ++ PINMUX_IPSR_GPSR(IP2_3_0, A16), ++ ++ PINMUX_IPSR_GPSR(IP2_7_4, DU_DB7), ++ PINMUX_IPSR_GPSR(IP2_7_4, MSIOF3_TXD), ++ PINMUX_IPSR_GPSR(IP2_7_4, A17), ++ ++ PINMUX_IPSR_GPSR(IP2_11_8, DU_DOTCLKOUT), ++ PINMUX_IPSR_GPSR(IP2_11_8, MSIOF3_SS1), ++ PINMUX_IPSR_MSEL(IP2_11_8, GETHER_LINK_B, SEL_GETHER_1), ++ PINMUX_IPSR_GPSR(IP2_11_8, A18), ++ ++ PINMUX_IPSR_GPSR(IP2_15_12, DU_EXHSYNC_DU_HSYNC), ++ PINMUX_IPSR_GPSR(IP2_15_12, MSIOF3_SS2), ++ PINMUX_IPSR_MSEL(IP2_15_12, GETHER_PHY_INT_B, SEL_GETHER_1), ++ PINMUX_IPSR_GPSR(IP2_15_12, A19), ++ PINMUX_IPSR_GPSR(IP2_15_12, FXR_TXENA_N), ++ ++ PINMUX_IPSR_GPSR(IP2_19_16, DU_EXVSYNC_DU_VSYNC), ++ PINMUX_IPSR_GPSR(IP2_19_16, MSIOF3_SCK), ++ PINMUX_IPSR_GPSR(IP2_19_16, FXR_TXENB_N), ++ ++ PINMUX_IPSR_GPSR(IP2_23_20, DU_EXODDF_DU_ODDF_DISP_CDE), ++ PINMUX_IPSR_GPSR(IP2_23_20, MSIOF3_SYNC), ++ ++ 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_0), ++ ++ PINMUX_IPSR_GPSR(IP3_23_20, VI0_DATA2), ++ PINMUX_IPSR_GPSR(IP3_23_20, AVB_AVTP_PPS), ++ ++ PINMUX_IPSR_GPSR(IP3_27_24, VI0_DATA3), ++ PINMUX_IPSR_GPSR(IP3_27_24, HSCK1), ++ ++ 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_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_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_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_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), ++ ++ /* 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_19_16, MMC_WP), ++ ++ 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_CD), ++ ++ 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_DS), ++ ++ 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_CMD), ++ ++ /* 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_D0), ++ ++ PINMUX_IPSR_GPSR(IP6_7_4, VI1_DATA5), ++ PINMUX_IPSR_GPSR(IP6_7_4, D8), ++ PINMUX_IPSR_GPSR(IP6_7_4, MMC_D1), ++ ++ PINMUX_IPSR_GPSR(IP6_11_8, VI1_DATA6), ++ PINMUX_IPSR_GPSR(IP6_11_8, D9), ++ PINMUX_IPSR_GPSR(IP6_11_8, MMC_D2), ++ ++ PINMUX_IPSR_GPSR(IP6_15_12, VI1_DATA7), ++ PINMUX_IPSR_GPSR(IP6_15_12, D10), ++ PINMUX_IPSR_GPSR(IP6_15_12, MMC_D3), ++ ++ PINMUX_IPSR_GPSR(IP6_19_16, VI1_DATA8), ++ PINMUX_IPSR_GPSR(IP6_19_16, D11), ++ PINMUX_IPSR_GPSR(IP6_19_16, MMC_CLK), ++ ++ PINMUX_IPSR_GPSR(IP6_23_20, VI1_DATA9), ++ PINMUX_IPSR_MSEL(IP6_23_20, TCLK1_A, SEL_TMU1_0), ++ PINMUX_IPSR_GPSR(IP6_23_20, D12), ++ PINMUX_IPSR_GPSR(IP6_23_20, MMC_D4), ++ ++ PINMUX_IPSR_GPSR(IP6_27_24, VI1_DATA10), ++ PINMUX_IPSR_MSEL(IP6_27_24, TCLK2_A, SEL_TMU1_0), ++ PINMUX_IPSR_GPSR(IP6_27_24, D13), ++ PINMUX_IPSR_GPSR(IP6_27_24, MMC_D5), ++ ++ PINMUX_IPSR_GPSR(IP6_31_28, VI1_DATA11), ++ PINMUX_IPSR_GPSR(IP6_31_28, SCL4), ++ PINMUX_IPSR_GPSR(IP6_31_28, D14), ++ PINMUX_IPSR_GPSR(IP6_31_28, MMC_D6), ++ ++ /* IPSR7 */ ++ PINMUX_IPSR_GPSR(IP7_3_0, VI1_FIELD), ++ PINMUX_IPSR_GPSR(IP7_3_0, SDA4), ++ PINMUX_IPSR_GPSR(IP7_3_0, D15), ++ PINMUX_IPSR_GPSR(IP7_3_0, MMC_D7), ++ ++ PINMUX_IPSR_GPSR(IP7_7_4, SCL0), ++ PINMUX_IPSR_GPSR(IP7_7_4, CLKOUT), ++ ++ PINMUX_IPSR_GPSR(IP7_11_8, SDA0), ++ PINMUX_IPSR_GPSR(IP7_11_8, BS_N), ++ PINMUX_IPSR_GPSR(IP7_11_8, SCK0), ++ PINMUX_IPSR_MSEL(IP7_11_8, HSCK0_B, SEL_HSCIF0_1), ++ ++ PINMUX_IPSR_GPSR(IP7_15_12, SCL1), ++ 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, HCTS0_N_B), ++ ++ PINMUX_IPSR_GPSR(IP7_19_16, SDA1), ++ 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, HRTS0_N_B), ++ ++ PINMUX_IPSR_GPSR(IP7_23_20, SCL2), ++ PINMUX_IPSR_GPSR(IP7_23_20, WE1_N), ++ PINMUX_IPSR_GPSR(IP7_23_20, RX0), ++ PINMUX_IPSR_MSEL(IP7_23_20, HRX0_B, SEL_HSCIF0_1), ++ ++ PINMUX_IPSR_GPSR(IP7_27_24, SDA2), ++ PINMUX_IPSR_GPSR(IP7_27_24, EX_WAIT0), ++ PINMUX_IPSR_GPSR(IP7_27_24, TX0), ++ PINMUX_IPSR_MSEL(IP7_27_24, HTX0_B, SEL_HSCIF0_1), ++ ++ PINMUX_IPSR_GPSR(IP7_31_28, AVB_AVTP_MATCH), ++ PINMUX_IPSR_GPSR(IP7_31_28, TPU0TO0), ++ ++ /* IPSR8 */ ++ PINMUX_IPSR_GPSR(IP8_3_0, AVB_AVTP_CAPTURE), ++ PINMUX_IPSR_GPSR(IP8_3_0, TPU0TO1), ++ ++ PINMUX_IPSR_MSEL(IP8_7_4, CANFD0_TX_A, SEL_CANFD0_0), ++ PINMUX_IPSR_GPSR(IP8_7_4, FXR_TXDA), ++ PINMUX_IPSR_MSEL(IP8_7_4, PWM0_B, SEL_PWM0_1), ++ PINMUX_IPSR_GPSR(IP8_7_4, DU_DISP), ++ ++ PINMUX_IPSR_MSEL(IP8_11_8, CANFD0_RX_A, SEL_CANFD0_0), ++ PINMUX_IPSR_GPSR(IP8_11_8, RXDA_EXTFXR), ++ PINMUX_IPSR_MSEL(IP8_11_8, PWM1_B, SEL_PWM1_1), ++ PINMUX_IPSR_GPSR(IP8_11_8, DU_CDE), ++ ++ PINMUX_IPSR_GPSR(IP8_15_12, CANFD1_TX), ++ PINMUX_IPSR_GPSR(IP8_15_12, FXR_TXDB), ++ PINMUX_IPSR_MSEL(IP8_15_12, PWM2_B, SEL_PWM2_1), ++ PINMUX_IPSR_MSEL(IP8_15_12, TCLK1_B, SEL_TMU1_1), ++ PINMUX_IPSR_MSEL(IP8_15_12, TX1_B, SEL_SCIF1_1), ++ ++ PINMUX_IPSR_GPSR(IP8_19_16, CANFD1_RX), ++ PINMUX_IPSR_GPSR(IP8_19_16, RXDB_EXTFXR), ++ PINMUX_IPSR_MSEL(IP8_19_16, PWM3_B, SEL_PWM3_1), ++ PINMUX_IPSR_MSEL(IP8_19_16, TCLK2_B, SEL_TMU1_1), ++ PINMUX_IPSR_MSEL(IP8_19_16, RX1_B, SEL_SCIF1_1), ++ ++ PINMUX_IPSR_MSEL(IP8_23_20, CANFD_CLK_A, SEL_CANFD0_0), ++ PINMUX_IPSR_GPSR(IP8_23_20, CLK_EXTFXR), ++ PINMUX_IPSR_MSEL(IP8_23_20, PWM4_B, SEL_PWM4_1), ++ PINMUX_IPSR_MSEL(IP8_23_20, SPEEDIN_B, SEL_RSP_1), ++ PINMUX_IPSR_MSEL(IP8_23_20, SCIF_CLK_B, SEL_HSCIF0_1), ++ ++ PINMUX_IPSR_GPSR(IP8_27_24, DIGRF_CLKIN), ++ PINMUX_IPSR_GPSR(IP8_27_24, DIGRF_CLKEN_IN), ++ ++ PINMUX_IPSR_GPSR(IP8_31_28, DIGRF_CLKOUT), ++ PINMUX_IPSR_GPSR(IP8_31_28, DIGRF_CLKEN_OUT), ++ ++ /* IPSR9 */ ++ PINMUX_IPSR_GPSR(IP9_3_0, IRQ4), ++ PINMUX_IPSR_GPSR(IP9_3_0, VI0_DATA12), ++ ++ PINMUX_IPSR_GPSR(IP9_7_4, IRQ5), ++ PINMUX_IPSR_GPSR(IP9_7_4, VI0_DATA13), ++ ++ PINMUX_IPSR_GPSR(IP9_11_8, MSIOF0_RXD), ++ PINMUX_IPSR_GPSR(IP9_11_8, DU_DR0), ++ PINMUX_IPSR_GPSR(IP9_11_8, VI0_DATA14), ++ ++ PINMUX_IPSR_GPSR(IP9_15_12, MSIOF0_TXD), ++ PINMUX_IPSR_GPSR(IP9_15_12, DU_DR1), ++ PINMUX_IPSR_GPSR(IP9_15_12, VI0_DATA15), ++ ++ PINMUX_IPSR_GPSR(IP9_19_16, MSIOF0_SCK), ++ PINMUX_IPSR_GPSR(IP9_19_16, DU_DG0), ++ PINMUX_IPSR_GPSR(IP9_19_16, VI0_DATA16), ++ ++ PINMUX_IPSR_GPSR(IP9_23_20, MSIOF0_SYNC), ++ PINMUX_IPSR_GPSR(IP9_23_20, DU_DG1), ++ PINMUX_IPSR_GPSR(IP9_23_20, VI0_DATA17), ++ ++ PINMUX_IPSR_GPSR(IP9_27_24, MSIOF0_SS1), ++ PINMUX_IPSR_GPSR(IP9_27_24, DU_DB0), ++ PINMUX_IPSR_GPSR(IP9_27_24, TCLK3), ++ PINMUX_IPSR_GPSR(IP9_27_24, VI0_DATA18), ++ ++ PINMUX_IPSR_GPSR(IP9_31_28, MSIOF0_SS2), ++ PINMUX_IPSR_GPSR(IP9_31_28, DU_DB1), ++ PINMUX_IPSR_GPSR(IP9_31_28, TCLK4), ++ PINMUX_IPSR_GPSR(IP9_31_28, VI0_DATA19), ++ ++ /* IPSR10 */ ++ PINMUX_IPSR_GPSR(IP10_3_0, SCL3), ++ PINMUX_IPSR_GPSR(IP10_3_0, VI0_DATA20), ++ ++ PINMUX_IPSR_GPSR(IP10_7_4, SDA3), ++ PINMUX_IPSR_GPSR(IP10_7_4, VI0_DATA21), ++ ++ PINMUX_IPSR_GPSR(IP10_11_8, FSO_CFE_0_N), ++ PINMUX_IPSR_GPSR(IP10_11_8, VI0_DATA22), ++ ++ PINMUX_IPSR_GPSR(IP10_15_12, FSO_CFE_1_N), ++ PINMUX_IPSR_GPSR(IP10_15_12, VI0_DATA23), ++ ++ PINMUX_IPSR_GPSR(IP10_19_16, FSO_TOE_N), ++}; ++ ++static const struct sh_pfc_pin pinmux_pins[] = { ++ PINMUX_GPIO_GP_ALL(), ++}; ++ ++/* - EtherAVB --------------------------------------------------------------- */ ++static const unsigned int avb_rx_ctrl_pins[] = { ++ /* AVB_RX_CTL */ ++ RCAR_GP_PIN(1, 1), ++}; ++static const unsigned int avb_rx_ctrl_mux[] = { ++ AVB_RX_CTL_MARK, ++}; ++static const unsigned int avb_rxc_pins[] = { ++ /* AVB_RXC */ ++ RCAR_GP_PIN(1, 2), ++}; ++static const unsigned int avb_rxc_mux[] = { ++ AVB_RXC_MARK, ++}; ++static const unsigned int avb_rd0_pins[] = { ++ /* AVB_RD[0] */ ++ RCAR_GP_PIN(1, 3), ++}; ++static const unsigned int avb_rd0_mux[] = { ++ AVB_RD0_MARK, ++}; ++static const unsigned int avb_rd1_pins[] = { ++ /* AVB_RD[1] */ ++ RCAR_GP_PIN(1, 4), ++}; ++static const unsigned int avb_rd1_mux[] = { ++ AVB_RD1_MARK, ++}; ++static const unsigned int avb_rd2_pins[] = { ++ /* AVB_RD[2] */ ++ RCAR_GP_PIN(1, 5), ++}; ++static const unsigned int avb_rd2_mux[] = { ++ AVB_RD2_MARK, ++}; ++static const unsigned int avb_rd3_pins[] = { ++ /* AVB_RD[3] */ ++ RCAR_GP_PIN(1, 6), ++}; ++static const unsigned int avb_rd3_mux[] = { ++ AVB_RD3_MARK, ++}; ++static const unsigned int avb_rd4_pins[] = { ++ /* AVB_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 avb_rd4_mux[] = { ++ AVB_RD0_MARK, AVB_RD1_MARK, ++ AVB_RD2_MARK, AVB_RD3_MARK, ++}; ++static const unsigned int avb_tx_ctrl_pins[] = { ++ /* AVB_TX_CTL */ ++ RCAR_GP_PIN(1, 7), ++}; ++static const unsigned int avb_tx_ctrl_mux[] = { ++ AVB_TX_CTL_MARK, ++}; ++static const unsigned int avb_txc_pins[] = { ++ /* AVB_TXC */ ++ RCAR_GP_PIN(1, 8), ++}; ++static const unsigned int avb_txc_mux[] = { ++ AVB_TXC_MARK, ++}; ++static const unsigned int avb_td0_pins[] = { ++ /* AVB_TD[0] */ ++ RCAR_GP_PIN(1, 9), ++}; ++static const unsigned int avb_td0_mux[] = { ++ AVB_TD0_MARK, ++}; ++static const unsigned int avb_td1_pins[] = { ++ /* AVB_TD[1] */ ++ RCAR_GP_PIN(1, 10), ++}; ++static const unsigned int avb_td1_mux[] = { ++ AVB_TD1_MARK, ++}; ++static const unsigned int avb_td2_pins[] = { ++ /* AVB_TD[2] */ ++ RCAR_GP_PIN(1, 11), ++}; ++static const unsigned int avb_td2_mux[] = { ++ AVB_TD2_MARK, ++}; ++static const unsigned int avb_td3_pins[] = { ++ /* AVB_TD[3] */ ++ RCAR_GP_PIN(1, 12), ++}; ++static const unsigned int avb_td3_mux[] = { ++ AVB_TD3_MARK, ++}; ++static const unsigned int avb_td4_pins[] = { ++ /* AVB_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 avb_td4_mux[] = { ++ AVB_TD0_MARK, AVB_TD1_MARK, ++ AVB_TD2_MARK, AVB_TD3_MARK, ++}; ++static const unsigned int avb_txcrefclk_pins[] = { ++ /* AVB_TXCREFCLK */ ++ RCAR_GP_PIN(1, 13), ++}; ++static const unsigned int avb_txcrefclk_mux[] = { ++ AVB_TXCREFCLK_MARK, ++}; ++static const unsigned int avb_mdio_pins[] = { ++ /* AVB_MDIO */ ++ RCAR_GP_PIN(1, 14), ++}; ++static const unsigned int avb_mdio_mux[] = { ++ AVB_MDIO_MARK, ++}; ++static const unsigned int avb_mdc_pins[] = { ++ /* AVB_MDC */ ++ RCAR_GP_PIN(1, 15), ++}; ++static const unsigned int avb_mdc_mux[] = { ++ AVB_MDC_MARK, ++}; ++static const unsigned int avb_magic_pins[] = { ++ /* AVB_MAGIC */ ++ RCAR_GP_PIN(1, 16), ++}; ++static const unsigned int avb_magic_mux[] = { ++ AVB_MAGIC_MARK, ++}; ++static const unsigned int avb_phy_int_pins[] = { ++ /* AVB_PHY_INT */ ++ RCAR_GP_PIN(1, 17), ++}; ++static const unsigned int avb_phy_int_mux[] = { ++ AVB_PHY_INT_MARK, ++}; ++static const unsigned int avb_link_pins[] = { ++ /* AVB_LINK */ ++ RCAR_GP_PIN(1, 18), ++}; ++static const unsigned int avb_link_mux[] = { ++ AVB_LINK_MARK, ++}; ++static const unsigned int avb_avtp_match_pins[] = { ++ /* AVB_AVTP_MATCH */ ++ RCAR_GP_PIN(1, 19), ++}; ++static const unsigned int avb_avtp_match_mux[] = { ++ AVB_AVTP_MATCH_MARK, ++}; ++static const unsigned int avb_avtp_capture_pins[] = { ++ /* AVB_AVTP_CAPTURE */ ++ RCAR_GP_PIN(1, 20), ++}; ++static const unsigned int avb_avtp_capture_mux[] = { ++ AVB_AVTP_CAPTURE_MARK, ++}; ++static const unsigned int avb_avtp_pps_pins[] = { ++ /* AVB_AVTP_PPS */ ++ RCAR_GP_PIN(2, 6), ++}; ++static const unsigned int avb_avtp_pps_mux[] = { ++ AVB_AVTP_PPS_MARK, ++}; ++ ++/* - GETHER ----------------------------------------------------------------- */ ++static const unsigned int gether_rx_ctrl_pins[] = { ++ /* GETHER_RX_CTL */ ++ RCAR_GP_PIN(4, 6), ++}; ++static const unsigned int gether_rx_ctrl_mux[] = { ++ GETHER_RX_CTL_MARK, ++}; ++static const unsigned int gether_rxc_pins[] = { ++ /* GETHER_RXC */ ++ RCAR_GP_PIN(4, 7), ++}; ++static const unsigned int gether_rxc_mux[] = { ++ GETHER_RXC_MARK, ++}; ++static const unsigned int gether_rd0_pins[] = { ++ /* GETHER_RD[0] */ ++ RCAR_GP_PIN(4, 8), ++}; ++static const unsigned int gether_rd0_mux[] = { ++ GETHER_RD0_MARK, ++}; ++static const unsigned int gether_rd1_pins[] = { ++ /* GETHER_RD[1] */ ++ RCAR_GP_PIN(4, 9), ++}; ++static const unsigned int gether_rd1_mux[] = { ++ GETHER_RD1_MARK, ++}; ++static const unsigned int gether_rd2_pins[] = { ++ /* GETHER_RD[2] */ ++ RCAR_GP_PIN(4, 10), ++}; ++static const unsigned int gether_rd2_mux[] = { ++ GETHER_RD2_MARK, ++}; ++static const unsigned int gether_rd3_pins[] = { ++ /* GETHER_RD[3] */ ++ RCAR_GP_PIN(4, 11), ++}; ++static const unsigned int gether_rd3_mux[] = { ++ GETHER_RD3_MARK, ++}; ++static const unsigned int gether_rd4_pins[] = { ++ /* GETHER_RD[3:0] */ ++ RCAR_GP_PIN(4, 8), RCAR_GP_PIN(4, 9), ++ RCAR_GP_PIN(4, 10), RCAR_GP_PIN(4, 11), ++}; ++static const unsigned int gether_rd4_mux[] = { ++ GETHER_RD0_MARK, AVB_RD1_MARK, ++ GETHER_RD2_MARK, AVB_RD3_MARK, ++}; ++static const unsigned int gether_tx_ctrl_pins[] = { ++ /* GETHER_TX_CTL */ ++ RCAR_GP_PIN(4, 12), ++}; ++static const unsigned int gether_tx_ctrl_mux[] = { ++ GETHER_TX_CTL_MARK, ++}; ++static const unsigned int gether_txc_pins[] = { ++ /* GETHER_TXC */ ++ RCAR_GP_PIN(4, 13), ++}; ++static const unsigned int gether_txc_mux[] = { ++ GETHER_TXC_MARK, ++}; ++static const unsigned int gether_td0_pins[] = { ++ /* GETHER_TD[0] */ ++ RCAR_GP_PIN(4, 14), ++}; ++static const unsigned int gether_td0_mux[] = { ++ GETHER_TD0_MARK, ++}; ++static const unsigned int gether_td1_pins[] = { ++ /* GETHER_TD[1] */ ++ RCAR_GP_PIN(4, 15), ++}; ++static const unsigned int gether_td1_mux[] = { ++ GETHER_TD1_MARK, ++}; ++static const unsigned int gether_td2_pins[] = { ++ /* GETHER_TD[2] */ ++ RCAR_GP_PIN(4, 16), ++}; ++static const unsigned int gether_td2_mux[] = { ++ GETHER_TD2_MARK, ++}; ++static const unsigned int gether_td3_pins[] = { ++ /* GETHER_TD[3] */ ++ RCAR_GP_PIN(4, 17), ++}; ++static const unsigned int gether_td3_mux[] = { ++ GETHER_TD3_MARK, ++}; ++static const unsigned int gether_td4_pins[] = { ++ /* GETHER_TD[3:0] */ ++ RCAR_GP_PIN(4, 14), RCAR_GP_PIN(4, 15), ++ RCAR_GP_PIN(4, 16), RCAR_GP_PIN(1, 17), ++}; ++static const unsigned int gether_td4_mux[] = { ++ GETHER_TD0_MARK, GETHER_TD1_MARK, ++ GETHER_TD2_MARK, GETHER_TD3_MARK, ++}; ++static const unsigned int gether_txcrefclk_pins[] = { ++ /* GETHER_TXCREFCLK */ ++ RCAR_GP_PIN(4, 18), ++}; ++static const unsigned int gether_txcrefclk_mux[] = { ++ GETHER_TXCREFCLK_MARK, ++}; ++static const unsigned int gether_txcrefclk_mega_pins[] = { ++ /* GETHER_TXCREFCLK_MEGA */ ++ RCAR_GP_PIN(4, 19), ++}; ++static const unsigned int gether_txcrefclk_mega_mux[] = { ++ GETHER_TXCREFCLK_MEGA_MARK, ++}; ++static const unsigned int gether_mdio_a_pins[] = { ++ /* GETHER_MDIO_A */ ++ RCAR_GP_PIN(4, 20), ++}; ++static const unsigned int gether_mdio_a_mux[] = { ++ GETHER_MDIO_A_MARK, ++}; ++static const unsigned int gether_mdc_a_pins[] = { ++ /* GETHER_MDC_A */ ++ RCAR_GP_PIN(4, 21), ++}; ++static const unsigned int gether_mdc_a_mux[] = { ++ GETHER_MDC_A_MARK, ++}; ++static const unsigned int gether_magic_pins[] = { ++ /* GETHER_MAGIC */ ++ RCAR_GP_PIN(4, 22), ++}; ++static const unsigned int gether_magic_mux[] = { ++ GETHER_MAGIC_MARK, ++}; ++static const unsigned int gether_phy_int_a_pins[] = { ++ /* GETHER_PHY_INT_A */ ++ RCAR_GP_PIN(4, 23), ++}; ++static const unsigned int gether_phy_int_a_mux[] = { ++ GETHER_PHY_INT_A_MARK, ++}; ++static const unsigned int gether_link_a_pins[] = { ++ /* GETHER_LINK_A */ ++ RCAR_GP_PIN(4, 24), ++}; ++static const unsigned int gether_link_a_mux[] = { ++ GETHER_LINK_A_MARK, ++}; ++ ++static const unsigned int gether_mdio_b_pins[] = { ++ /* GETHER_MDIO_B */ ++ RCAR_GP_PIN(0, 10), ++}; ++static const unsigned int gether_mdio_b_mux[] = { ++ GETHER_MDIO_B_MARK, ++}; ++static const unsigned int gether_mdc_b_pins[] = { ++ /* GETHER_MDC_B */ ++ RCAR_GP_PIN(0, 9), ++}; ++static const unsigned int gether_mdc_b_mux[] = { ++ GETHER_MDC_B_MARK, ++}; ++static const unsigned int gether_phy_int_b_pins[] = { ++ /* GETHER_PHY_INT_B */ ++ RCAR_GP_PIN(0, 19), ++}; ++static const unsigned int gether_phy_int_b_mux[] = { ++ GETHER_PHY_INT_B_MARK, ++}; ++static const unsigned int gether_link_b_pins[] = { ++ /* GETHER_LINK_B */ ++ RCAR_GP_PIN(0, 18), ++}; ++static const unsigned int gether_link_b_mux[] = { ++ GETHER_LINK_B_MARK, ++}; ++ ++/* OK? */ ++static const unsigned int gether_rmii_pins[] = { ++ /* GETHER_RMII_CRS_DV GETHER_RMII_RX_ER GETHER_RMII_RXD0 GETHER_RMII_RXD1 */ ++ /* GETHER_RMII_TXD_EN GETHER_RMII_TXD0 GETHER_RMII_TXD1 GETHER_RMII_REFCLK */ ++ RCAR_GP_PIN(0, 0), RCAR_GP_PIN(0, 1), ++ RCAR_GP_PIN(0, 2), RCAR_GP_PIN(0, 3), ++ RCAR_GP_PIN(0, 4), RCAR_GP_PIN(0, 5), ++ RCAR_GP_PIN(0, 6), RCAR_GP_PIN(0, 7), ++}; ++static const unsigned int gether_rmii_mux[] = { ++ GETHER_RMII_CRS_DV_MARK, GETHER_RMII_RX_ER_MARK, ++ GETHER_RMII_RXD0_MARK, GETHER_RMII_RXD1_MARK, ++ GETHER_RMII_TXD_EN_MARK, GETHER_RMII_TXD0_MARK, ++ GETHER_RMII_TXD1_MARK, GETHER_RMII_REFCLK_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 --------------------------------------------------------------------- */ ++/* D_[1:0] ??? */ ++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_a_pins[] = { ++ /* HRX0_A, HTX0_A */ ++ RCAR_GP_PIN(0, 11), RCAR_GP_PIN(0, 15), ++}; ++static const unsigned int hscif0_data_a_mux[] = { ++ HRX0_A_MARK, HTX0_A_MARK, ++}; ++static const unsigned int hscif0_clk_a_pins[] = { ++ /* HSCK0_A */ ++ RCAR_GP_PIN(0, 12), ++}; ++static const unsigned int hscif0_clk_a_mux[] = { ++ HSCK0_A_MARK, ++}; ++static const unsigned int hscif0_ctrl_a_pins[] = { ++ /* HRTS0#_A, HCTS0#_A */ ++ RCAR_GP_PIN(0, 13), RCAR_GP_PIN(0, 14), ++}; ++static const unsigned int hscif0_ctrl_a_mux[] = { ++ HRTS0_N_A_MARK, HCTS0_N_A_MARK, ++}; ++ ++static const unsigned int hscif0_data_b_pins[] = { ++ /* HRX0_B, HTX0_B */ ++ RCAR_GP_PIN(0, 11), RCAR_GP_PIN(0, 15), ++}; ++static const unsigned int hscif0_data_b_mux[] = { ++ HRX0_B_MARK, HTX0_B_MARK, ++}; ++static const unsigned int hscif0_clk_b_pins[] = { ++ /* HSCK0_B */ ++ RCAR_GP_PIN(0, 12), ++}; ++static const unsigned int hscif0_clk_b_mux[] = { ++ HSCK0_B_MARK, ++}; ++static const unsigned int hscif0_ctrl_b_pins[] = { ++ /* HRTS0#_B, HCTS0#_B */ ++ RCAR_GP_PIN(0, 13), RCAR_GP_PIN(0, 14), ++}; ++static const unsigned int hscif0_ctrl_b_mux[] = { ++ HRTS0_N_B_MARK, HCTS0_N_B_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, 10), ++}; ++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, SCL3 */ ++ RCAR_GP_PIN(2, 26), RCAR_GP_PIN(2, 25), ++}; ++static const unsigned int i2c3_mux[] = { ++ SDA3_MARK, SCL3_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, ++}; ++static const unsigned int i2c5_pins[] = { ++ /* SDA5, SCL5 */ ++ RCAR_GP_PIN(0, 9), RCAR_GP_PIN(0, 8), ++}; ++static const unsigned int i2c5_mux[] = { ++ SDA5_MARK, SCL5_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, 12), ++}; ++static const unsigned int intc_ex_irq1_mux[] = { ++ IRQ1_MARK, ++}; ++static const unsigned int intc_ex_irq2_pins[] = { ++ /* IRQ2 */ ++ RCAR_GP_PIN(0, 13), ++}; ++static const unsigned int intc_ex_irq2_mux[] = { ++ IRQ2_MARK, ++}; ++static const unsigned int intc_ex_irq3_pins[] = { ++ /* IRQ3 */ ++ RCAR_GP_PIN(0, 14), ++}; ++static const unsigned int intc_ex_irq3_mux[] = { ++ IRQ3_MARK, ++}; ++static const unsigned int intc_ex_irq4_pins[] = { ++ /* IRQ4 */ ++ RCAR_GP_PIN(2, 17), ++}; ++static const unsigned int intc_ex_irq4_mux[] = { ++ IRQ4_MARK, ++}; ++static const unsigned int intc_ex_irq5_pins[] = { ++ /* IRQ5 */ ++ RCAR_GP_PIN(2, 18), ++}; ++static const unsigned int intc_ex_irq5_mux[] = { ++ IRQ5_MARK, ++}; ++ ++/* - MSIOF0 ----------------------------------------------------------------- */ ++static const unsigned int msiof0_clk_pins[] = { ++ /* SCK */ ++ RCAR_GP_PIN(2, 21), ++}; ++static const unsigned int msiof0_clk_mux[] = { ++ MSIOF0_SCK_MARK, ++}; ++static const unsigned int msiof0_sync_pins[] = { ++ /* SYNC */ ++ RCAR_GP_PIN(2, 22), ++}; ++static const unsigned int msiof0_sync_mux[] = { ++ MSIOF0_SYNC_MARK, ++}; ++static const unsigned int msiof0_ss1_pins[] = { ++ /* SS1 */ ++ RCAR_GP_PIN(2, 23), ++}; ++static const unsigned int msiof0_ss1_mux[] = { ++ MSIOF0_SS1_MARK, ++}; ++static const unsigned int msiof0_ss2_pins[] = { ++ /* SS2 */ ++ RCAR_GP_PIN(2, 24), ++}; ++static const unsigned int msiof0_ss2_mux[] = { ++ MSIOF0_SS2_MARK, ++}; ++static const unsigned int msiof0_txd_pins[] = { ++ /* TXD */ ++ RCAR_GP_PIN(2, 20), ++}; ++static const unsigned int msiof0_txd_mux[] = { ++ MSIOF0_TXD_MARK, ++}; ++static const unsigned int msiof0_rxd_pins[] = { ++ /* RXD */ ++ RCAR_GP_PIN(2, 19), ++}; ++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, 18), ++}; ++static const unsigned int msiof3_ss1_mux[] = { ++ MSIOF3_SS1_MARK, ++}; ++static const unsigned int msiof3_ss2_pins[] = { ++ /* SS2 */ ++ RCAR_GP_PIN(0, 19), ++}; ++static const unsigned int msiof3_ss2_mux[] = { ++ MSIOF3_SS2_MARK, ++}; ++static const unsigned int msiof3_txd_pins[] = { ++ /* TXD */ ++ RCAR_GP_PIN(0, 17), ++}; ++static const unsigned int msiof3_txd_mux[] = { ++ MSIOF3_TXD_MARK, ++}; ++static const unsigned int msiof3_rxd_pins[] = { ++ /* RXD */ ++ RCAR_GP_PIN(0, 16), ++}; ++static const unsigned int msiof3_rxd_mux[] = { ++ MSIOF3_RXD_MARK, ++}; ++ ++/* - TPU ------------------------------------------------------------------- */ ++static const unsigned int tpu_to0_pins[] = { ++ /* TPU0TO0 */ ++ RCAR_GP_PIN(1, 19), ++}; ++static const unsigned int tpu_to0_mux[] = { ++ TPU0TO0_MARK, ++}; ++static const unsigned int tpu_to1_pins[] = { ++ /* TPU0TO1 */ ++ RCAR_GP_PIN(1, 20), ++}; ++static const unsigned int tpu_to1_mux[] = { ++ TPU0TO1_MARK, ++}; ++static const unsigned int tpu_to2_pins[] = { ++ /* TPU0TO2 */ ++ RCAR_GP_PIN(4, 2), ++}; ++static const unsigned int tpu_to2_mux[] = { ++ TPU0TO2_MARK, ++}; ++static const unsigned int tpu_to3_pins[] = { ++ /* TPU0TO3 */ ++ RCAR_GP_PIN(4, 3), ++}; ++static const unsigned int tpu_to3_mux[] = { ++ TPU0TO3_MARK, ++}; ++ ++/* - PWM0 ------------------------------------------------------------------- */ ++static const unsigned int pwm0_a_pins[] = { ++ /* PWM0 */ ++ RCAR_GP_PIN(0, 15), ++}; ++static const unsigned int pwm0_a_mux[] = { ++ PWM0_A_MARK, ++}; ++static const unsigned int pwm0_b_pins[] = { ++ /* PWM0 */ ++ RCAR_GP_PIN(1, 21), ++}; ++static const unsigned int pwm0_b_mux[] = { ++ PWM0_B_MARK, ++}; ++ ++/* - PWM1 ------------------------------------------------------------------- */ ++static const unsigned int pwm1_a_pins[] = { ++ /* PWM1 */ ++ RCAR_GP_PIN(2, 13), ++}; ++static const unsigned int pwm1_a_mux[] = { ++ PWM1_A_MARK, ++}; ++static const unsigned int pwm1_b_pins[] = { ++ /* PWM1 */ ++ RCAR_GP_PIN(1, 22), ++}; ++static const unsigned int pwm1_b_mux[] = { ++ PWM1_B_MARK, ++}; ++ ++/* - PWM2 ------------------------------------------------------------------- */ ++static const unsigned int pwm2_a_pins[] = { ++ /* PWM2 */ ++ RCAR_GP_PIN(2, 14), ++}; ++static const unsigned int pwm2_a_mux[] = { ++ PWM2_A_MARK, ++}; ++static const unsigned int pwm2_b_pins[] = { ++ /* PWM2 */ ++ RCAR_GP_PIN(1, 23), ++}; ++static const unsigned int pwm2_b_mux[] = { ++ PWM2_B_MARK, ++}; ++ ++/* - PWM3 ------------------------------------------------------------------- */ ++static const unsigned int pwm3_a_pins[] = { ++ /* PWM3 */ ++ RCAR_GP_PIN(2, 15), ++}; ++static const unsigned int pwm3_a_mux[] = { ++ PWM3_A_MARK, ++}; ++static const unsigned int pwm3_b_pins[] = { ++ /* PWM3 */ ++ RCAR_GP_PIN(1, 24), ++}; ++static const unsigned int pwm3_b_mux[] = { ++ PWM3_B_MARK, ++}; ++ ++/* - PWM4 ------------------------------------------------------------------- */ ++static const unsigned int pwm4_a_pins[] = { ++ /* PWM4 */ ++ RCAR_GP_PIN(2, 16), ++}; ++static const unsigned int pwm4_a_mux[] = { ++ PWM4_A_MARK, ++}; ++static const unsigned int pwm4_b_pins[] = { ++ /* PWM4 */ ++ RCAR_GP_PIN(1, 25), ++}; ++static const unsigned int pwm4_b_mux[] = { ++ PWM4_B_MARK, ++}; ++ ++/* - SCIF0 ------------------------------------------------------------------ */ ++static const unsigned int scif0_data_pins[] = { ++ /* RX, TX */ ++ RCAR_GP_PIN(4, 4), RCAR_GP_PIN(4, 5), ++}; ++static const unsigned int scif0_data_mux[] = { ++ RX0_MARK, TX0_MARK, ++}; ++static const unsigned int scif0_clk_pins[] = { ++ /* SCK */ ++ RCAR_GP_PIN(4, 1), ++}; ++static const unsigned int scif0_clk_mux[] = { ++ SCK0_MARK, ++}; ++static const unsigned int scif0_ctrl_pins[] = { ++ /* RTS, CTS */ ++ RCAR_GP_PIN(4, 3), RCAR_GP_PIN(4, 2), ++}; ++static const unsigned int scif0_ctrl_mux[] = { ++ RTS0_N_TANS_MARK, CTS0_N_MARK, ++}; ++ ++/* - SCIF1 ------------------------------------------------------------------ */ ++static const unsigned int scif1_data_a_pins[] = { ++ /* RX, TX */ ++ RCAR_GP_PIN(2, 8), RCAR_GP_PIN(2, 9), ++}; ++static const unsigned int scif1_data_a_mux[] = { ++ RX1_A_MARK, TX1_A_MARK, ++}; ++static const unsigned int scif1_clk_pins[] = { ++ /* SCK */ ++ RCAR_GP_PIN(2, 5), ++}; ++static const unsigned int scif1_clk_mux[] = { ++ SCK1_MARK, ++}; ++static const unsigned int scif1_ctrl_pins[] = { ++ /* RTS, CTS */ ++ RCAR_GP_PIN(2, 11), RCAR_GP_PIN(2, 10), ++}; ++static const unsigned int scif1_ctrl_mux[] = { ++ RTS1_N_TANS_MARK, CTS1_N_MARK, ++}; ++static const unsigned int scif1_data_b_pins[] = { ++ /* RX, TX */ ++ RCAR_GP_PIN(1, 24), RCAR_GP_PIN(1, 23), ++}; ++static const unsigned int scif1_data_b_mux[] = { ++ RX1_B_MARK, TX1_B_MARK, ++}; ++ ++/* - SCIF3 ------------------------------------------------------------------ */ ++static const unsigned int scif3_data_pins[] = { ++ /* RX, TX */ ++ RCAR_GP_PIN(2, 1), RCAR_GP_PIN(2, 2), ++}; ++static const unsigned int scif3_data_mux[] = { ++ RX3_MARK, TX3_MARK, ++}; ++static const unsigned int scif3_clk_pins[] = { ++ /* SCK */ ++ RCAR_GP_PIN(2, 0), ++}; ++static const unsigned int scif3_clk_mux[] = { ++ SCK3_MARK, ++}; ++static const unsigned int scif3_ctrl_pins[] = { ++ /* RTS, CTS */ ++ RCAR_GP_PIN(2, 4), RCAR_GP_PIN(2, 3), ++}; ++static const unsigned int scif3_ctrl_mux[] = { ++ RTS3_N_TANS_MARK, CTS3_N_MARK, ++}; ++ ++/* - SCIF4 ------------------------------------------------------------------ */ ++static const unsigned int scif4_data_pins[] = { ++ /* RX, TX */ ++ RCAR_GP_PIN(0, 1), RCAR_GP_PIN(0, 2), ++}; ++static const unsigned int scif4_data_mux[] = { ++ RX4_MARK, TX4_MARK, ++}; ++static const unsigned int scif4_clk_pins[] = { ++ /* SCK */ ++ RCAR_GP_PIN(0, 0), ++}; ++static const unsigned int scif4_clk_mux[] = { ++ SCK4_MARK, ++}; ++static const unsigned int scif4_ctrl_pins[] = { ++ /* RTS, CTS */ ++ RCAR_GP_PIN(0, 4), RCAR_GP_PIN(0, 3), ++}; ++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, 8), ++}; ++static const unsigned int mmc_data1_mux[] = { ++ MMC_D0_MARK, ++}; ++static const unsigned int mmc_data4_pins[] = { ++ /* D[0:3] */ ++ RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9), ++ RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 11), ++}; ++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, 8), RCAR_GP_PIN(3, 9), ++ RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 11), ++ RCAR_GP_PIN(3, 13), RCAR_GP_PIN(3, 14), ++ RCAR_GP_PIN(3, 15), RCAR_GP_PIN(3, 16), ++}; ++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, 12), RCAR_GP_PIN(3, 7), ++}; ++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, 5), ++}; ++static const unsigned int mmc_cd_mux[] = { ++ MMC_CD_MARK, ++}; ++static const unsigned int mmc_wp_pins[] = { ++ /* WP */ ++ RCAR_GP_PIN(3, 4), ++}; ++static const unsigned int mmc_wp_mux[] = { ++ MMC_WP_MARK, ++}; ++static const unsigned int mmc_ds_pins[] = { ++ /* DS */ ++ RCAR_GP_PIN(3, 6), ++}; ++static const unsigned int mmc_ds_mux[] = { ++ MMC_DS_MARK, ++}; ++ ++/* - TMU -------------------------------------------------------------------- */ ++static const unsigned int tmu_tclk1_a_pins[] = { ++ /* TCLK1 */ ++ RCAR_GP_PIN(3, 13), ++}; ++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(3, 14), ++}; ++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_data16_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), ++ RCAR_GP_PIN(2, 17), RCAR_GP_PIN(2, 18), ++ RCAR_GP_PIN(2, 19), RCAR_GP_PIN(2, 20), ++}; ++static const unsigned int vin0_data16_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, ++ VI0_DATA12_MARK, VI0_DATA13_MARK, ++ VI0_DATA14_MARK, VI0_DATA15_MARK, ++}; ++static const unsigned int vin0_data20_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), ++ RCAR_GP_PIN(2, 17), RCAR_GP_PIN(2, 18), ++ RCAR_GP_PIN(2, 19), RCAR_GP_PIN(2, 20), ++ RCAR_GP_PIN(2, 21), RCAR_GP_PIN(2, 22), ++ RCAR_GP_PIN(2, 23), RCAR_GP_PIN(2, 24), ++}; ++static const unsigned int vin0_data20_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, ++ VI0_DATA12_MARK, VI0_DATA13_MARK, ++ VI0_DATA14_MARK, VI0_DATA15_MARK, ++ VI0_DATA16_MARK, VI0_DATA17_MARK, ++ VI0_DATA18_MARK, VI0_DATA19_MARK, ++}; ++static const unsigned int vin0_data24_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), ++ RCAR_GP_PIN(2, 17), RCAR_GP_PIN(2, 18), ++ RCAR_GP_PIN(2, 19), RCAR_GP_PIN(2, 20), ++ RCAR_GP_PIN(2, 21), RCAR_GP_PIN(2, 22), ++ RCAR_GP_PIN(2, 23), RCAR_GP_PIN(2, 24), ++ RCAR_GP_PIN(2, 25), RCAR_GP_PIN(2, 26), ++ RCAR_GP_PIN(2, 27), RCAR_GP_PIN(2, 28), ++}; ++static const unsigned int vin0_data24_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, ++ VI0_DATA12_MARK, VI0_DATA13_MARK, ++ VI0_DATA14_MARK, VI0_DATA15_MARK, ++ VI0_DATA16_MARK, VI0_DATA17_MARK, ++ VI0_DATA18_MARK, VI0_DATA19_MARK, ++ VI0_DATA20_MARK, VI0_DATA21_MARK, ++ VI0_DATA22_MARK, VI0_DATA23_MARK, ++}; ++static const unsigned int vin0_sync_pins[] = { ++ /* VSYNC_N, HSYNC_N */ ++ RCAR_GP_PIN(2, 3), RCAR_GP_PIN(2, 2), ++}; ++static const unsigned int vin0_sync_mux[] = { ++ VI0_HSYNC_N_MARK, VI0_VSYNC_N_MARK, ++}; ++static const unsigned int vin0_field_pins[] = { ++ /* FIELD */ ++ RCAR_GP_PIN(2, 16), ++}; ++static const unsigned int vin0_field_mux[] = { ++ VI0_FIELD_MARK, ++}; ++static const unsigned int vin0_clkenb_pins[] = { ++ /* CLKENB */ ++ RCAR_GP_PIN(2, 1), ++}; ++static const unsigned int vin0_clkenb_mux[] = { ++ VI0_CLKENB_MARK, ++}; ++static const unsigned int vin0_clk_pins[] = { ++ /* CLK */ ++ RCAR_GP_PIN(2, 0), ++}; ++static const unsigned int vin0_clk_mux[] = { ++ VI0_CLK_MARK, ++}; ++/* - VIN1 ------------------------------------------------------------------- */ ++static const unsigned int vin1_data8_pins[] = { ++ RCAR_GP_PIN(3, 4), RCAR_GP_PIN(3, 5), ++ RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7), ++ RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9), ++ RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 11), ++}; ++static const unsigned int vin1_data8_mux[] = { ++ VI1_DATA0_MARK, VI1_DATA1_MARK, ++ VI1_DATA2_MARK, VI1_DATA3_MARK, ++ VI1_DATA4_MARK, VI1_DATA5_MARK, ++ VI1_DATA6_MARK, VI1_DATA7_MARK, ++}; ++static const unsigned int vin1_data10_pins[] = { ++ RCAR_GP_PIN(3, 4), RCAR_GP_PIN(3, 5), ++ RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7), ++ RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9), ++ RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 11), ++ RCAR_GP_PIN(3, 12), RCAR_GP_PIN(3, 13), ++}; ++static const unsigned int vin1_data10_mux[] = { ++ VI1_DATA0_MARK, VI1_DATA1_MARK, ++ VI1_DATA2_MARK, VI1_DATA3_MARK, ++ VI1_DATA4_MARK, VI1_DATA5_MARK, ++ VI1_DATA6_MARK, VI1_DATA7_MARK, ++ VI1_DATA8_MARK, VI1_DATA9_MARK, ++}; ++static const unsigned int vin1_data12_pins[] = { ++ RCAR_GP_PIN(3, 4), RCAR_GP_PIN(3, 5), ++ RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7), ++ RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9), ++ RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 11), ++ RCAR_GP_PIN(3, 12), RCAR_GP_PIN(3, 13), ++ RCAR_GP_PIN(3, 14), RCAR_GP_PIN(3, 15), ++}; ++static const unsigned int vin1_data12_mux[] = { ++ VI1_DATA0_MARK, VI1_DATA1_MARK, ++ VI1_DATA2_MARK, VI1_DATA3_MARK, ++ VI1_DATA4_MARK, VI1_DATA5_MARK, ++ VI1_DATA6_MARK, VI1_DATA7_MARK, ++ VI1_DATA8_MARK, VI1_DATA9_MARK, ++ VI1_DATA10_MARK, VI1_DATA11_MARK, ++}; ++static const unsigned int vin1_sync_pins[] = { ++ /* VSYNC_N, HSYNC_N */ ++ RCAR_GP_PIN(3, 3), RCAR_GP_PIN(3, 2), ++}; ++static const unsigned int vin1_sync_mux[] = { ++ VI1_HSYNC_N_MARK, VI1_VSYNC_N_MARK, ++}; ++static const unsigned int vin1_field_pins[] = { ++ /* FIELD */ ++ RCAR_GP_PIN(3, 16), ++}; ++static const unsigned int vin1_field_mux[] = { ++ VI1_FIELD_MARK, ++}; ++static const unsigned int vin1_clkenb_pins[] = { ++ /* CLKENB */ ++ RCAR_GP_PIN(3, 1), ++}; ++static const unsigned int vin1_clkenb_mux[] = { ++ VI1_CLKENB_MARK, ++}; ++static const unsigned int vin1_clk_pins[] = { ++ /* CLK */ ++ RCAR_GP_PIN(3, 0), ++}; ++static const unsigned int vin1_clk_mux[] = { ++ VI1_CLK_MARK, ++}; ++ ++static const struct sh_pfc_pin_group pinmux_groups[] = { ++ SH_PFC_PIN_GROUP(avb_rx_ctrl), ++ SH_PFC_PIN_GROUP(avb_rxc), ++ SH_PFC_PIN_GROUP(avb_rd0), ++ SH_PFC_PIN_GROUP(avb_rd1), ++ SH_PFC_PIN_GROUP(avb_rd2), ++ SH_PFC_PIN_GROUP(avb_rd3), ++ SH_PFC_PIN_GROUP(avb_rd4), ++ SH_PFC_PIN_GROUP(avb_tx_ctrl), ++ SH_PFC_PIN_GROUP(avb_txc), ++ SH_PFC_PIN_GROUP(avb_td0), ++ SH_PFC_PIN_GROUP(avb_td1), ++ SH_PFC_PIN_GROUP(avb_td2), ++ SH_PFC_PIN_GROUP(avb_td3), ++ SH_PFC_PIN_GROUP(avb_td4), ++ SH_PFC_PIN_GROUP(avb_txcrefclk), ++ SH_PFC_PIN_GROUP(avb_mdio), ++ SH_PFC_PIN_GROUP(avb_mdc), ++ SH_PFC_PIN_GROUP(avb_magic), ++ SH_PFC_PIN_GROUP(avb_phy_int), ++ SH_PFC_PIN_GROUP(avb_link), ++ SH_PFC_PIN_GROUP(avb_avtp_match), ++ SH_PFC_PIN_GROUP(avb_avtp_capture), ++ SH_PFC_PIN_GROUP(avb_avtp_pps), ++ SH_PFC_PIN_GROUP(gether_rx_ctrl), ++ SH_PFC_PIN_GROUP(gether_rxc), ++ SH_PFC_PIN_GROUP(gether_rd0), ++ SH_PFC_PIN_GROUP(gether_rd1), ++ SH_PFC_PIN_GROUP(gether_rd2), ++ SH_PFC_PIN_GROUP(gether_rd3), ++ SH_PFC_PIN_GROUP(gether_rd4), ++ SH_PFC_PIN_GROUP(gether_tx_ctrl), ++ SH_PFC_PIN_GROUP(gether_txc), ++ SH_PFC_PIN_GROUP(gether_td0), ++ SH_PFC_PIN_GROUP(gether_td1), ++ SH_PFC_PIN_GROUP(gether_td2), ++ SH_PFC_PIN_GROUP(gether_td3), ++ SH_PFC_PIN_GROUP(gether_td4), ++ SH_PFC_PIN_GROUP(gether_txcrefclk), ++ SH_PFC_PIN_GROUP(gether_txcrefclk_mega), ++ SH_PFC_PIN_GROUP(gether_mdio_a), ++ SH_PFC_PIN_GROUP(gether_mdio_b), ++ SH_PFC_PIN_GROUP(gether_mdc_a), ++ SH_PFC_PIN_GROUP(gether_mdc_b), ++ SH_PFC_PIN_GROUP(gether_magic), ++ SH_PFC_PIN_GROUP(gether_phy_int_a), ++ SH_PFC_PIN_GROUP(gether_phy_int_b), ++ SH_PFC_PIN_GROUP(gether_link_a), ++ SH_PFC_PIN_GROUP(gether_link_b), ++ SH_PFC_PIN_GROUP(gether_rmii), ++ 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_a), ++ SH_PFC_PIN_GROUP(hscif0_clk_a), ++ SH_PFC_PIN_GROUP(hscif0_ctrl_a), ++ SH_PFC_PIN_GROUP(hscif0_data_b), ++ SH_PFC_PIN_GROUP(hscif0_clk_b), ++ SH_PFC_PIN_GROUP(hscif0_ctrl_b), ++ 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(i2c5), ++ 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(tpu_to0), ++ SH_PFC_PIN_GROUP(tpu_to1), ++ SH_PFC_PIN_GROUP(tpu_to2), ++ SH_PFC_PIN_GROUP(tpu_to3), ++ 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(mmc_ds), ++ 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_data16), ++ SH_PFC_PIN_GROUP(vin0_data20), ++ SH_PFC_PIN_GROUP(vin0_data24), ++ 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 avb_groups[] = { ++ "avb_rx_ctrl", ++ "avb_rxc", ++ "avb_rd1", ++ "avb_rd4", ++ "avb_tx_ctrl", ++ "avb_txc", ++ "avb_td1", ++ "avb_td4", ++ "avb_txcrefclk", ++ "avb_mdio", ++ "avb_mdc", ++ "avb_magic", ++ "avb_phy_int", ++ "avb_link", ++ "avb_avtp_match", ++ "avb_avtp_capture", ++ "avb_avtp_pps", ++}; ++ ++static const char * const gether_groups[] = { ++ "gether_rx_ctrl", ++ "gether_rxc", ++ "gether_rd1", ++ "gether_rd4", ++ "gether_tx_ctrl", ++ "gether_txc", ++ "gether_td1", ++ "gether_td4", ++ "gether_txcrefclk", ++ "gether_txcrefclk_mega", ++ "gether_mdio_a", ++ "gether_mdc_a", ++ "gether_mdio_b", ++ "gether_mdc_b", ++ "gether_magic", ++ "gether_phy_int_a", ++ "gether_link_a", ++ "gether_phy_int_b", ++ "gether_link_b", ++ "gether_rmii", ++}; ++ ++static const char * const canfd0_groups[] = { ++ "canfd0_data_a", ++ "canfd_clk_a", ++ "canfd0_data_b", ++ "canfd_clk_b", ++}; ++ ++static const char * const canfd1_groups[] = { ++ "canfd1_data", ++}; ++ ++static const char * const du_groups[] = { ++ "du_rgb666", ++ "du_clk_out_0", ++ "du_clk_out_1", ++ "du_sync", ++ "du_oddf", ++ "du_cde", ++ "du_disp", ++}; ++ ++static const char * const hscif0_groups[] = { ++ "hscif0_data_a", ++ "hscif0_clk_a", ++ "hscif0_ctrl_a", ++ "hscif0_data_b", ++ "hscif0_clk_b", ++ "hscif0_ctrl_b", ++}; ++ ++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 i2c5_groups[] = { ++ "i2c5", ++}; ++ ++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 tpu_groups[] = { ++ "tpu_to0", ++ "tpu_to1", ++ "tpu_to2", ++ "tpu_to3", ++}; ++ ++static const char * const pwm0_groups[] = { ++ "pwm0_a", ++ "pwm0_b", ++}; ++ ++static const char * const pwm1_groups[] = { ++ "pwm1_a", ++ "pwm1_b", ++}; ++ ++static const char * const pwm2_groups[] = { ++ "pwm2_a", ++ "pwm2_b", ++}; ++ ++static const char * const pwm3_groups[] = { ++ "pwm3_a", ++ "pwm3_b", ++}; ++ ++static const char * const pwm4_groups[] = { ++ "pwm4_a", ++ "pwm4_b", ++}; ++ ++static const char * const scif0_groups[] = { ++ "scif0_data", ++// "scif0_clk", ++// "scif0_ctrl", ++}; ++ ++static const char * const scif1_groups[] = { ++ "scif1_data_a", ++ "scif1_clk", ++ "scif1_ctrl", ++ "scif1_data_b", ++}; ++ ++static const char * const scif3_groups[] = { ++ "scif3_data", ++ "scif3_clk", ++ "scif3_ctrl", ++}; ++ ++static const char * const scif4_groups[] = { ++ "scif4_data", ++ "scif4_clk", ++ "scif4_ctrl", ++}; ++ ++static const char * const mmc_groups[] = { ++ "mmc_data1", ++ "mmc_data4", ++ "mmc_data8", ++ "mmc_ctrl", ++ "mmc_cd", ++ "mmc_wp", ++ "mmc_ds", ++}; ++ ++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_data16", ++ "vin0_data20", ++ "vin0_data24", ++ "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", ++}; ++ ++static const struct sh_pfc_function pinmux_functions[] = { ++ SH_PFC_FUNCTION(avb), ++ SH_PFC_FUNCTION(gether), ++ 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(i2c5), ++ SH_PFC_FUNCTION(intc_ex), ++ SH_PFC_FUNCTION(msiof0), ++ SH_PFC_FUNCTION(msiof1), ++ SH_PFC_FUNCTION(msiof2), ++ SH_PFC_FUNCTION(msiof3), ++ SH_PFC_FUNCTION(tpu), ++ 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, ++ GP_2_29_FN, GPSR2_29, ++ GP_2_28_FN, GPSR2_28, ++ GP_2_27_FN, GPSR2_27, ++ GP_2_26_FN, GPSR2_26, ++ GP_2_25_FN, GPSR2_25, ++ GP_2_24_FN, GPSR2_24, ++ GP_2_23_FN, GPSR2_23, ++ GP_2_22_FN, GPSR2_22, ++ GP_2_21_FN, GPSR2_21, ++ GP_2_20_FN, GPSR2_20, ++ GP_2_19_FN, GPSR2_19, ++ GP_2_18_FN, GPSR2_18, ++ GP_2_17_FN, GPSR2_17, ++ 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, ++ GP_4_24_FN, GPSR4_24, ++ GP_4_23_FN, GPSR4_23, ++ GP_4_22_FN, GPSR4_22, ++ GP_4_21_FN, GPSR4_21, ++ GP_4_20_FN, GPSR4_20, ++ GP_4_19_FN, GPSR4_19, ++ GP_4_18_FN, GPSR4_18, ++ GP_4_17_FN, GPSR4_17, ++ GP_4_16_FN, GPSR4_16, ++ GP_4_15_FN, GPSR4_15, ++ GP_4_14_FN, GPSR4_14, ++ GP_4_13_FN, GPSR4_13, ++ GP_4_12_FN, GPSR4_12, ++ GP_4_11_FN, GPSR4_11, ++ GP_4_10_FN, GPSR4_10, ++ GP_4_9_FN, GPSR4_9, ++ GP_4_8_FN, GPSR4_8, ++ GP_4_7_FN, GPSR4_7, ++ GP_4_6_FN, GPSR4_6, ++ 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 } ++ }, ++ { PINMUX_CFG_REG("IPSR9", 0xe6060224, 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 } ++ }, ++ { PINMUX_CFG_REG("IPSR10", 0xe6060228, 32, 4) { ++ IP8_31_28 ++ IP8_27_24 ++ IP8_23_20 ++ IP8_19_16 ++ IP8_15_12 ++ IP8_11_8 ++ IP8_7_4 ++ IP8_3_0 } ++ }, ++#undef F_ ++#undef FM ++ ++#define F_(x, y) x, ++#define FM(x) FN_##x, ++ { PINMUX_CFG_REG("MOD_SEL0", 0xe6060500, 32, 1) { ++ /* RESERVED 31..12 */ ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ 0, 0, ++ MOD_SEL0_11 ++ MOD_SEL0_10 ++ MOD_SEL0_9 ++ MOD_SEL0_8 ++ MOD_SEL0_7 ++ MOD_SEL0_6 ++ MOD_SEL0_5 ++ MOD_SEL0_4 ++ 0, 0, ++ MOD_SEL0_2 ++ MOD_SEL0_1 ++ MOD_SEL0_0 } ++ }, ++ { }, ++}; ++ ++#define POC0 0xe6060380 ++#define POC1 0xe6060384 ++#define POC2 0xe6060388 ++ ++/* TODO make it nice */ ++static int r8a7798_pin_to_pocctrl(struct sh_pfc *pfc, unsigned int pin, u32 *pocctrl) ++{ ++ int bit = -EINVAL; ++ ++ *pocctrl = POC0; ++ ++ if (pin >= RCAR_GP_PIN(0, 0) && pin <= RCAR_GP_PIN(0, 21)) ++ bit = pin & 0x1f; ++ else if (pin >= RCAR_GP_PIN(2, 0) && pin <= RCAR_GP_PIN(2, 9)) ++ bit = (pin & 0x1f) + 22; ++ ++ if (bit != -EINVAL) ++ goto out; ++ ++ *pocctrl = POC1; ++ ++ if (pin >= RCAR_GP_PIN(2, 10) && pin <= RCAR_GP_PIN(2, 16)) ++ bit = (pin & 0x1f) - 10; ++ else if (pin >= RCAR_GP_PIN(3, 0) && pin <= RCAR_GP_PIN(3, 16)) ++ bit = (pin & 0x1f) + 7; ++ else if (pin >= RCAR_GP_PIN(2, 17) && pin <= RCAR_GP_PIN(2, 24)) ++ bit = (pin & 0x1f) + 7; ++ ++ if (bit != -EINVAL) ++ goto out; ++ ++ *pocctrl = POC2; ++ ++ if (pin >= RCAR_GP_PIN(2, 25) && pin <= RCAR_GP_PIN(2, 29)) ++ bit = (pin & 0x1f) - 25; ++ ++out: ++ return bit; ++} ++ ++static const struct sh_pfc_soc_operations pinmux_ops = { ++ .pin_to_pocctrl = r8a7798_pin_to_pocctrl, ++}; ++ ++const struct sh_pfc_soc_info r8a7798_pinmux_info = { ++ .name = "r8a77980_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 062af89..31df6d4 100644 +--- a/drivers/pinctrl/sh-pfc/sh_pfc.h ++++ b/drivers/pinctrl/sh-pfc/sh_pfc.h +@@ -289,6 +291,7 @@ struct sh_pfc_soc_info { + extern const struct sh_pfc_soc_info r8a7796_pinmux_info; + extern const struct sh_pfc_soc_info r8a77965_pinmux_info; + extern const struct sh_pfc_soc_info r8a7797_pinmux_info; ++extern const struct sh_pfc_soc_info r8a7798_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; +@@ -465,9 +468,13 @@ struct sh_pfc_soc_info { + PORT_GP_CFG_1(bank, 23, fn, sfx, cfg) + #define PORT_GP_24(bank, fn, sfx) PORT_GP_CFG_24(bank, fn, sfx, 0) + +-#define PORT_GP_CFG_26(bank, fn, sfx, cfg) \ ++#define PORT_GP_CFG_25(bank, fn, sfx, cfg) \ + PORT_GP_CFG_24(bank, fn, sfx, cfg), \ +- PORT_GP_CFG_1(bank, 24, fn, sfx, cfg), \ ++ PORT_GP_CFG_1(bank, 24, fn, sfx, cfg) ++#define PORT_GP_24(bank, fn, sfx) PORT_GP_CFG_24(bank, fn, sfx, 0) ++ ++#define PORT_GP_CFG_26(bank, fn, sfx, cfg) \ ++ PORT_GP_CFG_25(bank, fn, sfx, cfg), \ + PORT_GP_CFG_1(bank, 25, fn, sfx, cfg) + #define PORT_GP_26(bank, fn, sfx) PORT_GP_CFG_26(bank, fn, sfx, 0) + +diff --git a/drivers/soc/renesas/Makefile b/drivers/soc/renesas/Makefile +index 2ba6a76..164b3e7 100644 +--- a/drivers/soc/renesas/Makefile ++++ b/drivers/soc/renesas/Makefile +@@ -6,6 +6,7 @@ obj-$(CONFIG_ARCH_R8A7795) += rcar-rst.o + obj-$(CONFIG_ARCH_R8A7796) += rcar-rst.o + obj-$(CONFIG_ARCH_R8A77965) += rcar-rst.o + obj-$(CONFIG_ARCH_R8A7797) += rcar-rst.o ++obj-$(CONFIG_ARCH_R8A7798) += rcar-rst.o + + obj-$(CONFIG_ARCH_R8A7743) += rcar-sysc.o r8a7743-sysc.o + obj-$(CONFIG_ARCH_R8A7745) += rcar-sysc.o r8a7745-sysc.o +@@ -20,15 +21,18 @@ obj-$(CONFIG_ARCH_R8A7795) += rcar-sysc.o r8a7795-sysc.o + obj-$(CONFIG_ARCH_R8A7796) += rcar-sysc.o r8a7796-sysc.o + obj-$(CONFIG_ARCH_R8A77965) += rcar-sysc.o r8a77965-sysc.o + obj-$(CONFIG_ARCH_R8A7797) += rcar-sysc.o r8a7797-sysc.o ++obj-$(CONFIG_ARCH_R8A7798) += rcar-sysc.o r8a7798-sysc.o + + obj-$(CONFIG_ARCH_R8A7795) += rcar-avs.o + obj-$(CONFIG_ARCH_R8A7796) += rcar-avs.o + obj-$(CONFIG_ARCH_R8A77965) += rcar-avs.o + obj-$(CONFIG_ARCH_R8A7797) += rcar-avs.o ++obj-$(CONFIG_ARCH_R8A7798) += rcar-avs.o + # EMS for R-Car Gen3 + obj-$(CONFIG_ARCH_R8A7795) += rcar_ems_ctrl.o + obj-$(CONFIG_ARCH_R8A7796) += rcar_ems_ctrl.o + obj-$(CONFIG_ARCH_R8A77965) += rcar_ems_ctrl.o + obj-$(CONFIG_ARCH_R8A7797) += rcar_ems_ctrl.o ++obj-$(CONFIG_ARCH_R8A7798) += rcar_ems_ctrl.o + + obj-$(CONFIG_RCAR_DDR_BACKUP) += s2ram_ddr_backup.o +diff --git a/drivers/soc/renesas/r8a7798-sysc.c b/drivers/soc/renesas/r8a7798-sysc.c +new file mode 100644 +index 0000000..d530488 +--- /dev/null ++++ b/drivers/soc/renesas/r8a7798-sysc.c +@@ -0,0 +1,57 @@ ++/* ++ * Renesas R-Car V3H System Controller ++ * ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 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; version 2 of the License. ++ */ ++ ++#include ++#include ++ ++#include ++ ++#include "rcar-sysc.h" ++ ++static const struct rcar_sysc_area r8a7798_areas[] __initconst = { ++ { "always-on", 0, 0, R8A7798_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, ++ { "ca53-scu", 0x140, 0, R8A7798_PD_CA53_SCU, R8A7798_PD_ALWAYS_ON, ++ PD_SCU }, ++ { "ca53-cpu0", 0x200, 0, R8A7798_PD_CA53_CPU0, R8A7798_PD_CA53_SCU, ++ PD_CPU_NOCR }, ++ { "ca53-cpu1", 0x200, 1, R8A7798_PD_CA53_CPU1, R8A7798_PD_CA53_SCU, ++ PD_CPU_NOCR }, ++ { "ca53-cpu2", 0x200, 2, R8A7798_PD_CA53_CPU2, R8A7798_PD_CA53_SCU, ++ PD_CPU_NOCR }, ++ { "ca53-cpu3", 0x200, 3, R8A7798_PD_CA53_CPU3, R8A7798_PD_CA53_SCU, ++ PD_CPU_NOCR }, ++ { "cr7", 0x240, 0, R8A7798_PD_CR7, R8A7798_PD_ALWAYS_ON }, ++ ++ { "a3ir", 0x180, 0, R8A7798_PD_A3IR, R8A7798_PD_ALWAYS_ON }, ++ { "a2ir0", 0x400, 0, R8A7798_PD_A2IR0, R8A7798_PD_ALWAYS_ON }, ++ { "a2ir1", 0x400, 1, R8A7798_PD_A2IR1, R8A7798_PD_A2IR0 }, ++ { "a2ir2", 0x400, 2, R8A7798_PD_A2IR2, R8A7798_PD_A2IR0 }, ++ { "a2ir3", 0x400, 3, R8A7798_PD_A2IR3, R8A7798_PD_A2IR0 }, ++ { "a2ir4", 0x400, 4, R8A7798_PD_A2IR4, R8A7798_PD_A2IR0 }, ++ { "a2ir5", 0x400, 5, R8A7798_PD_A2IR5, R8A7798_PD_A2IR0 }, ++ { "a2sc0", 0x400, 6, R8A7798_PD_A2SC0, R8A7798_PD_ALWAYS_ON }, ++ { "a2sc1", 0x400, 7, R8A7798_PD_A2SC1, R8A7798_PD_A2SC0 }, ++ { "a2sc2", 0x400, 8, R8A7798_PD_A2SC2, R8A7798_PD_A2SC0 }, ++ { "a2sc3", 0x400, 9, R8A7798_PD_A2SC3, R8A7798_PD_A2SC0 }, ++ { "a2sc4", 0x400, 10, R8A7798_PD_A2SC4, R8A7798_PD_A2SC0 }, ++ { "a2pd0", 0x400, 11, R8A7798_PD_A2PD0, R8A7798_PD_ALWAYS_ON }, /* OK? */ ++ { "a2pd1", 0x400, 12, R8A7798_PD_A2PD1, R8A7798_PD_A2PD0 }, /* OK? */ ++ { "a2cn", 0x400, 13, R8A7798_PD_A2CN, R8A7798_PD_ALWAYS_ON }, /* OK? */ ++ ++ { "a3vip", 0x2c0, 0, R8A7798_PD_A3VIP, R8A7798_PD_ALWAYS_ON }, /* OK? */ ++ { "a3vip1", 0x300, 0, R8A7798_PD_A3VIP1, R8A7798_PD_A3VIP }, /* OK? */ ++ { "a3vip2", 0x280, 0, R8A7798_PD_A3VIP2, R8A7798_PD_A3VIP }, /* OK? */ ++}; ++ ++const struct rcar_sysc_info r8a7798_sysc_info __initconst = { ++ .areas = r8a7798_areas, ++ .num_areas = ARRAY_SIZE(r8a7798_areas), ++}; +diff --git a/drivers/soc/renesas/rcar-rst.c b/drivers/soc/renesas/rcar-rst.c +index bc3632b..19b441b 100644 +--- a/drivers/soc/renesas/rcar-rst.c ++++ b/drivers/soc/renesas/rcar-rst.c +@@ -43,6 +45,7 @@ struct rst_config { + { .compatible = "renesas,r8a7796-rst", .data = &rcar_rst_gen2 }, + { .compatible = "renesas,r8a77965-rst", .data = &rcar_rst_gen2 }, + { .compatible = "renesas,r8a7797-rst", .data = &rcar_rst_gen2 }, ++ { .compatible = "renesas,r8a7798-rst", .data = &rcar_rst_gen2 }, + { /* sentinel */ } + }; + +diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c +index 1d5d440..87d5c21 100644 +--- a/drivers/soc/renesas/rcar-sysc.c ++++ b/drivers/soc/renesas/rcar-sysc.c +@@ -327,6 +329,9 @@ static void __init rcar_sysc_pd_setup(struct rcar_sysc_pd *pd) + #ifdef CONFIG_ARCH_R8A7797 + { .compatible = "renesas,r8a7797-sysc", .data = &r8a7797_sysc_info }, + #endif ++#ifdef CONFIG_ARCH_R8A7798 ++ { .compatible = "renesas,r8a7798-sysc", .data = &r8a7798_sysc_info }, ++#endif + { /* sentinel */ } + }; + +diff --git a/drivers/soc/renesas/rcar-sysc.h b/drivers/soc/renesas/rcar-sysc.h +index 1eb4e6d..c3b5bce 100644 +--- a/drivers/soc/renesas/rcar-sysc.h ++++ b/drivers/soc/renesas/rcar-sysc.h +@@ -62,4 +64,5 @@ struct rcar_sysc_info { + extern const struct rcar_sysc_info r8a7796_sysc_info; + extern const struct rcar_sysc_info r8a77965_sysc_info; + extern const struct rcar_sysc_info r8a7797_sysc_info; ++extern const struct rcar_sysc_info r8a7798_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 388c570..007e203 100644 +--- a/drivers/soc/renesas/rcar_ems_ctrl.c ++++ b/drivers/soc/renesas/rcar_ems_ctrl.c +@@ -30,8 +31,9 @@ + + #define EMS_THERMAL_ZONE_MAX 10 + +-static const struct soc_device_attribute r8a7797[] = { ++static const struct soc_device_attribute r8a7797_8[] = { + { .soc_id = "r8a7797" }, ++ { .soc_id = "r8a7798" }, + { } + }; + +@@ -274,7 +276,7 @@ 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 (soc_device_match(r8a7797_8)) { + if (!of_device_is_compatible(tmp_node, "arm,cortex-a53")) + continue; + } +diff --git a/drivers/soc/renesas/renesas-soc.c b/drivers/soc/renesas/renesas-soc.c +index 63f943d..c107f7c 100644 +--- a/drivers/soc/renesas/renesas-soc.c ++++ b/drivers/soc/renesas/renesas-soc.c +@@ -144,6 +146,11 @@ struct renesas_soc { + .id = 0x54, + }; + ++static const struct renesas_soc soc_rcar_v3h __initconst __maybe_unused = { ++ .family = &fam_rcar_gen3, ++ .id = 0x56, ++}; ++ + static const struct renesas_soc soc_shmobile_ag5 __initconst __maybe_unused = { + .family = &fam_shmobile, + .id = 0x37, +@@ -199,6 +206,9 @@ struct renesas_soc { + #ifdef CONFIG_ARCH_R8A7797 + { .compatible = "renesas,r8a7797", .data = &soc_rcar_v3m }, + #endif ++#ifdef CONFIG_ARCH_R8A7798 ++ { .compatible = "renesas,r8a7798", .data = &soc_rcar_v3h }, ++#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 a2606fe..bbe2526 100644 +--- a/drivers/spi/spi-sh-msiof.c ++++ b/drivers/spi/spi-sh-msiof.c +@@ -217,7 +218,8 @@ static int msiof_rcar_is_gen3(struct device *dev) + return of_device_is_compatible(node, "renesas,msiof-r8a7795") || + of_device_is_compatible(node, "renesas,msiof-r8a7796") || + of_device_is_compatible(node, "renesas,msiof-r8a77965") || +- of_device_is_compatible(node, "renesas,msiof-r8a7797"); ++ of_device_is_compatible(node, "renesas,msiof-r8a7797") || ++ of_device_is_compatible(node, "renesas,msiof-r8a7798"); + } + + static u32 sh_msiof_read(struct sh_msiof_spi_priv *p, int reg_offs) +@@ -1192,6 +1194,7 @@ static int sh_msiof_transfer_one(struct spi_master *master, + { .compatible = "renesas,msiof-r8a7796", .data = &r8a779x_data }, + { .compatible = "renesas,msiof-r8a77965", .data = &r8a779x_data }, + { .compatible = "renesas,msiof-r8a7797", .data = &r8a779x_data }, ++ { .compatible = "renesas,msiof-r8a7798", .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 a23dd44..44bc4fd 100644 +--- a/drivers/thermal/rcar_gen3_thermal.c ++++ b/drivers/thermal/rcar_gen3_thermal.c +@@ -415,6 +416,11 @@ static int rcar_gen3_r8a7797_thermal_init(struct rcar_thermal_priv *priv) + return 0; + } + ++static int rcar_gen3_r8a7798_thermal_init(struct rcar_thermal_priv *priv) ++{ ++ return rcar_gen3_r8a7796_thermal_init(priv); ++} ++ + /* + * Interrupt + */ +@@ -500,11 +506,16 @@ static int rcar_gen3_thermal_remove(struct platform_device *pdev) + .thermal_init = rcar_gen3_r8a7797_thermal_init, + }; + ++static const struct rcar_thermal_data r8a7798_data = { ++ .thermal_init = rcar_gen3_r8a7798_thermal_init, ++}; ++ + static const struct of_device_id rcar_thermal_dt_ids[] = { + { .compatible = "renesas,thermal-r8a7795", .data = &r8a7795_data}, + { .compatible = "renesas,thermal-r8a7796", .data = &r8a7796_data}, + { .compatible = "renesas,thermal-r8a77965", .data = &r8a7796_data}, + { .compatible = "renesas,thermal-r8a7797", .data = &r8a7797_data}, ++ { .compatible = "renesas,thermal-r8a7798", .data = &r8a7798_data}, + {}, + }; + MODULE_DEVICE_TABLE(of, rcar_thermal_dt_ids); +diff --git a/include/dt-bindings/clock/r8a7798-cpg-mssr.h b/include/dt-bindings/clock/r8a7798-cpg-mssr.h +new file mode 100644 +index 0000000..6c2d97a +--- /dev/null ++++ b/include/dt-bindings/clock/r8a7798-cpg-mssr.h +@@ -0,0 +1,56 @@ ++/* ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 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 __DT_BINDINGS_CLOCK_R8A7798_CPG_MSSR_H__ ++#define __DT_BINDINGS_CLOCK_R8A7798_CPG_MSSR_H__ ++ ++#include ++ ++/* r8a7798 CPG Core Clocks */ ++#define R8A7798_CLK_Z2 0 ++#define R8A7798_CLK_ZR 1 ++#define R8A7798_CLK_ZTR 2 ++#define R8A7798_CLK_ZTRD2 3 ++#define R8A7798_CLK_ZT 4 ++#define R8A7798_CLK_ZX 5 ++#define R8A7798_CLK_S0D1 6 ++#define R8A7798_CLK_S0D2 7 ++#define R8A7798_CLK_S0D3 8 ++#define R8A7798_CLK_S0D4 9 ++#define R8A7798_CLK_S0D6 10 ++#define R8A7798_CLK_S0D12 11 ++#define R8A7798_CLK_S0D24 12 ++#define R8A7798_CLK_S1D1 13 ++#define R8A7798_CLK_S1D2 14 ++#define R8A7798_CLK_S1D4 15 ++#define R8A7798_CLK_S2D1 16 ++#define R8A7798_CLK_S2D2 17 ++#define R8A7798_CLK_S2D4 18 ++#define R8A7798_CLK_S3D1 19 ++#define R8A7798_CLK_S3D2 20 ++#define R8A7798_CLK_S3D4 21 ++#define R8A7798_CLK_LB 22 ++#define R8A7798_CLK_CL 23 ++#define R8A7798_CLK_ZB3 24 ++#define R8A7798_CLK_ZB3D2 25 ++#define R8A7798_CLK_ZB3D4 26 ++#define R8A7798_CLK_SD0H 27 ++#define R8A7798_CLK_SD0 28 ++#define R8A7798_CLK_RPC 29 ++#define R8A7798_CLK_RPCD2 30 ++#define R8A7798_CLK_MSO 31 ++#define R8A7798_CLK_CANFD 32 ++#define R8A7798_CLK_CSI0 33 ++#define R8A7798_CLK_CSIREF 34 ++#define R8A7798_CLK_CP 35 ++#define R8A7798_CLK_CPEX 36 ++#define R8A7798_CLK_R 37 ++#define R8A7798_CLK_OSC 38 ++ ++#endif /* __DT_BINDINGS_CLOCK_R8A7798_CPG_MSSR_H__ */ +diff --git a/include/dt-bindings/power/r8a7798-sysc.h b/include/dt-bindings/power/r8a7798-sysc.h +new file mode 100644 +index 0000000..2451b16 +--- /dev/null ++++ b/include/dt-bindings/power/r8a7798-sysc.h +@@ -0,0 +1,46 @@ ++/* ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 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; version 2 of the License. ++ */ ++#ifndef __DT_BINDINGS_POWER_R8A7798_SYSC_H__ ++#define __DT_BINDINGS_POWER_R8A7798_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 R8A7798_PD_A2SC2 0 ++#define R8A7798_PD_A2SC3 1 ++#define R8A7798_PD_A2SC4 2 ++#define R8A7798_PD_A2PD0 3 ++#define R8A7798_PD_A2PD1 4 ++#define R8A7798_PD_CA53_CPU0 5 ++#define R8A7798_PD_CA53_CPU1 6 ++#define R8A7798_PD_CA53_CPU2 7 ++#define R8A7798_PD_CA53_CPU3 8 ++#define R8A7798_PD_A2CN 10 ++#define R8A7798_PD_A3VIP 11 ++#define R8A7798_PD_A2IR5 12 ++#define R8A7798_PD_CR7 13 ++#define R8A7798_PD_A2IR4 15 ++#define R8A7798_PD_CA53_SCU 21 ++#define R8A7798_PD_A2IR0 23 ++#define R8A7798_PD_A3IR 24 ++#define R8A7798_PD_A3VIP1 25 ++#define R8A7798_PD_A3VIP2 26 ++#define R8A7798_PD_A2IR1 27 ++#define R8A7798_PD_A2IR2 28 ++#define R8A7798_PD_A2IR3 29 ++#define R8A7798_PD_A2SC0 30 ++#define R8A7798_PD_A2SC1 31 ++ ++/* Always-on power area */ ++#define R8A7798_PD_ALWAYS_ON 32 ++ ++#endif /* __DT_BINDINGS_POWER_R8A7798_SYSC_H__ */ +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0104-media-vsp1-extend-DRM-VSP1-interface.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0104-media-vsp1-extend-DRM-VSP1-interface.patch index 2f6fa35..ecd0fd5 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0104-media-vsp1-extend-DRM-VSP1-interface.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0104-media-vsp1-extend-DRM-VSP1-interface.patch @@ -198,7 +198,7 @@ index e79f9e6..753763d 100644 + (format->code != MEDIA_BUS_FMT_ARGB8888_1X32 ? VI6_LIF_CTRL_CFMT : 0) | VI6_LIF_CTRL_REQSEL | VI6_LIF_CTRL_LIF_EN); - if (soc_device_match(r8a7797)) + if (soc_device_match(r8a7797_8)) diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c index 8379962..86d4a85 100644 --- a/drivers/media/platform/vsp1/vsp1_pipe.c diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/condor.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/condor.cfg new file mode 100644 index 0000000..46f8879 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/condor.cfg @@ -0,0 +1,29 @@ +CONFIG_ARCH_R8A7798=y +CONFIG_CAN=y +CONFIG_CAN_BCM=y +CONFIG_CAN_RAW=y +CONFIG_CAN_DEV=y +CONFIG_CAN_CALC_BITTIMING=y +CONFIG_CAN_RCAR=y +CONFIG_CAN_RCAR_CANFD=y +CONFIG_DUMMY=y +CONFIG_DRM_I2C_ADV7511=y +CONFIG_GPIO_PCA953X=y +CONFIG_GPIO_PCA953X_IRQ=y +CONFIG_VIDEO_ADV_DEBUG=y +CONFIG_VIDEO_RCAR_VIN_LEGACY=y +CONFIG_VIDEO_RCAR_CSI2_LEGACY=y +# CONFIG_VIDEO_RCAR_VIN is not set +# CONFIG_VIDEO_RCAR_CSI2 is not set +CONFIG_SOC_CAMERA=y +CONFIG_SOC_CAMERA_SCALE_CROP=y +CONFIG_SOC_CAMERA_PLATFORM=y +CONFIG_SOC_CAMERA_MAX9286_MAX9271=y +CONFIG_SOC_CAMERA_OV106XX=y +CONFIG_VIDEO_RENESAS_IMR=y +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_INPUT_UINPUT=y +CONFIG_TOUCHSCREEN_PROPERTIES=y +CONFIG_HID_MULTITOUCH=y +CONFIG_SERIAL_SH_SCI_DMA=y +CONFIG_UIO=y diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas_4.9.bbappend b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas_4.9.bbappend index 110d8bb..f21ad58 100644 --- 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 @@ -2,6 +2,7 @@ FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" COMPATIBLE_MACHINE_eagle = "eagle" COMPATIBLE_MACHINE_v3msk = "v3msk" +COMPATIBLE_MACHINE_condor = "condor" SRC_URI_append = " \ ${@bb.utils.contains('MACHINE_FEATURES', 'h3ulcb-had', ' file://hyperflash.cfg', '', d)} \ @@ -51,6 +52,7 @@ SRC_URI_append = " \ ${@base_conditional("KF_ENABLE_MOST", "1", " file://0048-arm64-dts-renesas-ulcb-kf-enable-most.patch", "", d)} \ file://0049-clk-r8a779x-add-IMP-clock.patch \ file://0050-arm64-dts-renesas-r8a779x-add-IMP-nodes.patch \ + file://0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.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)} \ @@ -71,9 +73,6 @@ SRC_URI_append = " \ file://0078-MOST-aim-fix-null-pointer-crash.patch \ file://0079-Revert-dmaengine-rcar-dmac-use-TCRB-instead-of-TCR-f.patch \ file://0082-gpio-pca953x-fix-interrupt-trigger.patch \ -" - -SRC_URI_append_r8a7797 = " \ file://0103-gpu-drm-rcar-du-Extend-VSP1-DRM-interface.patch \ file://0104-media-vsp1-extend-DRM-VSP1-interface.patch \ file://0105-media-rcar-imr-IMR-driver-updates-for-raw-DL.patch \ @@ -84,6 +83,7 @@ SRC_URI_append_m3ulcb = " file://ulcb.cfg" SRC_URI_append_salvator-x = " file://salvator-x.cfg" SRC_URI_append_eagle = " file://eagle.cfg" SRC_URI_append_v3msk = " file://v3msk.cfg" +SRC_URI_append_condor = " file://condor.cfg" KERNEL_DEVICETREE_append_h3ulcb = " \ renesas/r8a7795-es1-h3ulcb-view.dtb \ @@ -124,3 +124,7 @@ KERNEL_DEVICETREE_append_v3msk = " \ renesas/r8a7797-v3msk-vbm.dtb \ renesas/r8a7797-v3msk-view.dtb \ " + +KERNEL_DEVICETREE_append_condor = " \ + renesas/r8a7798-condor.dtb \ +" -- cgit 1.2.3-korg From a94b208793023660c3aa1fcbce38bf8a6767920a Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Mon, 22 Jan 2018 18:43:47 +0300 Subject: V3M/V3H: fix CMT0 timer offset --- .../0018-arm64-renesas-r8a7797-Add-Renesas-R8A7797-SoC-suppor.patch | 4 ++-- .../0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') 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 index dc80f98..88d2a52 100644 --- 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 @@ -579,9 +579,9 @@ index 0000000..0dd374f + }; + }; + -+ cmt0: timer@ffca0000 { ++ cmt0: timer@e60f0000 { + compatible = "renesas,cmt-48-r8a7797", "renesas,cmt-48-gen2"; -+ reg = <0 0xffca0000 0 0x1004>; ++ reg = <0 0xe60f0000 0 0x1004>; + interrupts = , + ; + clocks = <&cpg CPG_MOD 303>; diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch index a4763d4..effd7e2 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch @@ -690,9 +690,9 @@ index 0000000..ee8e282 + }; + + -+ cmt0: timer@ffca0000 { ++ cmt0: timer@e60f0000 { + compatible = "renesas,cmt-48-r8a7798", "renesas,cmt-48-gen2"; -+ reg = <0 0xffca0000 0 0x1004>; ++ reg = <0 0xe60f0000 0 0x1004>; + interrupts = , + ; + clocks = <&cpg CPG_MOD 303>; -- cgit 1.2.3-korg From 7f4eccd38eb4222c4795894b64e150cd1d96c2c5 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Tue, 23 Jan 2018 12:39:37 +0300 Subject: MSIOF: add SPIDEV function 1) add spidev function on MSIOF 2) set MSOIF1 master and MSIOF slave on V3MSK VideoBoxMini --- .../0040-arm64-dts-renesas-add-ADAS-boards.patch | 44 +- ...t-DT-bindings-for-SPI-controllers-in-slav.patch | 118 + ...d-support-for-registering-SPI-slave-contr.patch | 445 +++ ...spi-Document-SPI-slave-controller-support.patch | 66 + .../0086-spi-sh-msiof-Add-slave-mode-support.patch | 209 ++ ...dd-SPI-slave-handler-reporting-uptime-at-.patch | 182 ++ ...dd-SPI-slave-handler-controlling-system-s.patch | 205 ++ ...9-spi-Generalize-SPI-master-to-controller.patch | 3048 ++++++++++++++++++++ ...ot-automatically-bind-to-MSIOF-spi-may-be.patch | 26 + .../recipes-kernel/linux/linux-renesas/v3msk.cfg | 3 + .../linux/linux-renesas_4.9.bbappend | 8 + 11 files changed, 4348 insertions(+), 6 deletions(-) create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0083-spi-Document-DT-bindings-for-SPI-controllers-in-slav.patch create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0084-spi-core-Add-support-for-registering-SPI-slave-contr.patch create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0085-spi-Document-SPI-slave-controller-support.patch create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0086-spi-sh-msiof-Add-slave-mode-support.patch create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0087-spi-slave-Add-SPI-slave-handler-reporting-uptime-at-.patch create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0088-spi-slave-Add-SPI-slave-handler-controlling-system-s.patch create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0089-spi-Generalize-SPI-master-to-controller.patch create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0090-spidev-Do-not-automatically-bind-to-MSIOF-spi-may-be.patch (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch index 483ba45..4d914f1 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch @@ -65,10 +65,10 @@ Signed-off-by: Vladimir Barinov .../boot/dts/renesas/r8a7797-eagle-function.dts | 62 + arch/arm64/boot/dts/renesas/r8a7797-eagle.dts | 575 +++++++ arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts | 578 +++++++ - arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts | 518 ++++++ + arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts | 550 ++++++ arch/arm64/boot/dts/renesas/r8a7797-v3msk-view.dts | 298 ++++ arch/arm64/boot/dts/renesas/r8a7797-v3msk.dts | 314 ++++ - arch/arm64/boot/dts/renesas/r8a7798-condor.dts | 939 +++++++++++ + arch/arm64/boot/dts/renesas/r8a7798-condor.dts | 940 +++++++++++ arch/arm64/boot/dts/renesas/ulcb-kf-cn11.dtsi | 545 ++++++ arch/arm64/boot/dts/renesas/ulcb-kf-most.dtsi | 30 + arch/arm64/boot/dts/renesas/ulcb-kf-sd3.dtsi | 46 + @@ -77,7 +77,7 @@ Signed-off-by: Vladimir Barinov arch/arm64/boot/dts/renesas/ulcb-vb.dtsi | 1726 +++++++++++++++++++ arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi | 1772 ++++++++++++++++++++ arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi | 578 +++++++ - 47 files changed, 20099 insertions(+) + 47 files changed, 20132 insertions(+) create mode 100644 arch/arm64/boot/dts/renesas/legacy/Makefile create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts @@ -11617,10 +11617,10 @@ index 0000000..b92fe83 +}; diff --git a/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts new file mode 100644 -index 0000000..26f8c70 +index 0000000..8612f64 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts -@@ -0,0 +1,518 @@ +@@ -0,0 +1,550 @@ +/* + * Device Tree Source for the V3MSK Videobox Mini board on r8a7797 + * @@ -11987,6 +11987,28 @@ index 0000000..26f8c70 + }; +}; + ++&msiof1 { ++ pinctrl-0 = <&msiof1_pins>; ++ pinctrl-names = "default"; ++ cs-gpios = <&gpio3 3 0>; ++ ++ status = "okay"; ++ spidev@0 { ++ compatible = "spidev"; ++ reg = <0>; ++ spi-max-frequency = <66666666>; ++ }; ++ ++}; ++ ++&msiof3 { ++ pinctrl-0 = <&msiof3_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++ slave; ++}; ++ +&pfc { + canfd0_pins: canfd0 { + groups = "canfd0_data_a"; @@ -12003,6 +12025,16 @@ index 0000000..26f8c70 + function = "i2c1"; + }; + ++ msiof1_pins: msiof1 { ++ groups = "msiof1_clk", "msiof1_txd", "msiof1_rxd"; ++ function = "msiof1"; ++ }; ++ ++ msiof3_pins: msiof3 { ++ groups = "msiof3_clk", "msiof3_txd", "msiof3_rxd", "msiof3_sync"; ++ function = "msiof3"; ++ }; ++ + scif3_pins: scif3 { + groups = "scif3_data"; + function = "scif3"; @@ -12765,7 +12797,7 @@ index 0000000..91d10c5 +}; diff --git a/arch/arm64/boot/dts/renesas/r8a7798-condor.dts b/arch/arm64/boot/dts/renesas/r8a7798-condor.dts new file mode 100644 -index 0000000..ed9cc28 +index 0000000..b236d66 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7798-condor.dts @@ -0,0 +1,940 @@ diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0083-spi-Document-DT-bindings-for-SPI-controllers-in-slav.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0083-spi-Document-DT-bindings-for-SPI-controllers-in-slav.patch new file mode 100644 index 0000000..0266378 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0083-spi-Document-DT-bindings-for-SPI-controllers-in-slav.patch @@ -0,0 +1,118 @@ +From c71da12ba9738ac1441fb431100cb03662ba9ac1 Mon Sep 17 00:00:00 2001 +From: Geert Uytterhoeven +Date: Fri, 17 Jun 2016 18:05:32 +0200 +Subject: [PATCH 1/7] spi: Document DT bindings for SPI controllers in slave + mode + +Signed-off-by: Geert Uytterhoeven +Reviewed-by: Rob Herring +--- + Documentation/devicetree/bindings/spi/spi-bus.txt | 76 ++++++++++++--------- + 1 file changed, 45 insertions(+), 31 deletions(-) + +diff --git a/Documentation/devicetree/bindings/spi/spi-bus.txt b/Documentation/devicetree/bindings/spi/spi-bus.txt +index 4b1d6e7..1f6e86f 100644 +--- a/Documentation/devicetree/bindings/spi/spi-bus.txt ++++ b/Documentation/devicetree/bindings/spi/spi-bus.txt +@@ -1,17 +1,23 @@ + SPI (Serial Peripheral Interface) busses + +-SPI busses can be described with a node for the SPI master device +-and a set of child nodes for each SPI slave on the bus. For this +-discussion, it is assumed that the system's SPI controller is in +-SPI master mode. This binding does not describe SPI controllers +-in slave mode. ++SPI busses can be described with a node for the SPI controller device ++and a set of child nodes for each SPI slave on the bus. The system's SPI ++controller may be described for use in SPI master mode or in SPI slave mode, ++but not for both at the same time. + +-The SPI master node requires the following properties: ++The SPI controller node requires the following properties: ++- compatible - Name of SPI bus controller following generic names ++ recommended practice. ++ ++In master mode, the SPI controller node requires the following additional ++properties: + - #address-cells - number of cells required to define a chip select + address on the SPI bus. + - #size-cells - should be zero. +-- compatible - name of SPI bus controller following generic names +- recommended practice. ++ ++In slave mode, the SPI controller node requires one additional property: ++- spi-slave - Empty property. ++ + No other properties are required in the SPI bus node. It is assumed + that a driver for an SPI bus device will understand that it is an SPI bus. + However, the binding does not attempt to define the specific method for +@@ -21,7 +27,7 @@ assumption that board specific platform code will be used to manage + chip selects. Individual drivers can define additional properties to + support describing the chip select layout. + +-Optional properties: ++Optional properties (master mode only): + - cs-gpios - gpios chip select. + - num-cs - total number of chipselects. + +@@ -41,28 +47,36 @@ cs1 : native + cs2 : &gpio1 1 0 + cs3 : &gpio1 2 0 + +-SPI slave nodes must be children of the SPI master node and can +-contain the following properties. +-- reg - (required) chip select address of device. +-- compatible - (required) name of SPI device following generic names +- recommended practice. +-- spi-max-frequency - (required) Maximum SPI clocking speed of device in Hz. +-- spi-cpol - (optional) Empty property indicating device requires +- inverse clock polarity (CPOL) mode. +-- spi-cpha - (optional) Empty property indicating device requires +- shifted clock phase (CPHA) mode. +-- spi-cs-high - (optional) Empty property indicating device requires +- chip select active high. +-- spi-3wire - (optional) Empty property indicating device requires +- 3-wire mode. +-- spi-lsb-first - (optional) Empty property indicating device requires +- LSB first mode. +-- spi-tx-bus-width - (optional) The bus width (number of data wires) that is +- used for MOSI. Defaults to 1 if not present. +-- spi-rx-bus-width - (optional) The bus width (number of data wires) that is +- used for MISO. Defaults to 1 if not present. +-- spi-rx-delay-us - (optional) Microsecond delay after a read transfer. +-- spi-tx-delay-us - (optional) Microsecond delay after a write transfer. ++ ++SPI slave nodes must be children of the SPI controller node. ++ ++In master mode, one or more slave nodes (up to the number of chip selects) can ++be present. Required properties are: ++- compatible - Name of SPI device following generic names recommended ++ practice. ++- reg - Chip select address of device. ++- spi-max-frequency - Maximum SPI clocking speed of device in Hz. ++ ++In slave mode, the (single) slave node is optional. ++If present, it must be called "slave". Required properties are: ++- compatible - Name of SPI device following generic names recommended ++ practice. ++ ++All slave nodes can contain the following optional properties: ++- spi-cpol - Empty property indicating device requires inverse clock ++ polarity (CPOL) mode. ++- spi-cpha - Empty property indicating device requires shifted clock ++ phase (CPHA) mode. ++- spi-cs-high - Empty property indicating device requires chip select ++ active high. ++- spi-3wire - Empty property indicating device requires 3-wire mode. ++- spi-lsb-first - Empty property indicating device requires LSB first mode. ++- spi-tx-bus-width - The bus width (number of data wires) that is used for MOSI. ++ Defaults to 1 if not present. ++- spi-rx-bus-width - The bus width (number of data wires) that is used for MISO. ++ Defaults to 1 if not present. ++- spi-rx-delay-us - Microsecond delay after a read transfer. ++- spi-tx-delay-us - Microsecond delay after a write transfer. + + Some SPI controllers and devices support Dual and Quad SPI transfer mode. + It allows data in the SPI system to be transferred using 2 wires (DUAL) or 4 +-- +1.7.10.4 diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0084-spi-core-Add-support-for-registering-SPI-slave-contr.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0084-spi-core-Add-support-for-registering-SPI-slave-contr.patch new file mode 100644 index 0000000..780459c --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0084-spi-core-Add-support-for-registering-SPI-slave-contr.patch @@ -0,0 +1,445 @@ +From 069206bafab71d97d2c427ed664e7cbacbe0678c Mon Sep 17 00:00:00 2001 +From: Geert Uytterhoeven +Date: Fri, 17 Jun 2016 16:45:37 +0200 +Subject: [PATCH 2/7] spi: core: Add support for registering SPI slave + controllers + +Add support for registering SPI slave controllers using the existing SPI +master framework: + - SPI slave controllers must use spi_alloc_slave() instead of + spi_alloc_master(), and should provide an additional callback + "slave_abort" to abort an ongoing SPI transfer request, + - SPI slave controllers are added to a new "spi_slave" device class, + - SPI slave handlers can be bound to the SPI slave device represented + by an SPI slave controller using a DT child node named "slave", + - Alternatively, (un)binding an SPI slave handler to the SPI slave + device represented by an SPI slave controller can be done by + (un)registering the slave device through a sysfs virtual file named + "slave". + +From the point of view of an SPI slave protocol handler, an SPI slave +controller looks almost like an ordinary SPI master controller. The only +exception is that a transfer request will block on the remote SPI +master, and may be cancelled using spi_slave_abort(). + +Signed-off-by: Geert Uytterhoeven +--- + drivers/spi/Kconfig | 14 +++- + drivers/spi/Makefile | 2 + + drivers/spi/spi.c | 179 ++++++++++++++++++++++++++++++++++++++++------- + include/linux/spi/spi.h | 35 +++++++-- + 4 files changed, 201 insertions(+), 29 deletions(-) + +diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig +index fb418d5..8c97790 100644 +--- a/drivers/spi/Kconfig ++++ b/drivers/spi/Kconfig +@@ -781,6 +781,18 @@ config SPI_TLE62X0 + + endif # SPI_MASTER + +-# (slave support would go here) ++# ++# SLAVE side ... listening to other SPI masters ++# ++ ++config SPI_SLAVE ++ bool "SPI slave protocol handlers" ++ help ++ If your system has a slave-capable SPI controller, you can enable ++ slave protocol handlers. ++ ++if SPI_SLAVE ++ ++endif # SPI_SLAVE + + endif # SPI +diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile +index aa939d9..2428b0f 100644 +--- a/drivers/spi/Makefile ++++ b/drivers/spi/Makefile +@@ -102,3 +102,5 @@ obj-$(CONFIG_SPI_XILINX) += spi-xilinx.o + obj-$(CONFIG_SPI_XLP) += spi-xlp.o + obj-$(CONFIG_SPI_XTENSA_XTFPGA) += spi-xtensa-xtfpga.o + obj-$(CONFIG_SPI_ZYNQMP_GQSPI) += spi-zynqmp-gqspi.o ++ ++# SPI slave protocol handlers +diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c +index 838783c..a403e3a 100644 +--- a/drivers/spi/spi.c ++++ b/drivers/spi/spi.c +@@ -1513,15 +1513,6 @@ static int spi_master_initialize_queue(struct spi_master *master) + goto err_out; + } + +- /* Device address */ +- rc = of_property_read_u32(nc, "reg", &value); +- if (rc) { +- dev_err(&master->dev, "%s has no valid 'reg' property (%d)\n", +- nc->full_name, rc); +- goto err_out; +- } +- spi->chip_select = value; +- + /* Mode (clock phase/polarity/etc.) */ + if (of_find_property(nc, "spi-cpha", NULL)) + spi->mode |= SPI_CPHA; +@@ -1571,6 +1562,24 @@ static int spi_master_initialize_queue(struct spi_master *master) + } + } + ++ if (spi_controller_is_slave(master)) { ++ if (strcmp(nc->name, "slave")) { ++ dev_err(&master->dev, "%s is not called 'slave'\n", ++ nc->full_name); ++ return -EINVAL; ++ } ++ return 0; ++ } ++ ++ /* Device address */ ++ rc = of_property_read_u32(nc, "reg", &value); ++ if (rc) { ++ dev_err(&master->dev, "%s has no valid 'reg' property (%d)\n", ++ nc->full_name, rc); ++ return rc; ++ } ++ spi->chip_select = value; ++ + /* Device speed */ + rc = of_property_read_u32(nc, "spi-max-frequency", &value); + if (rc) { +@@ -1603,8 +1612,8 @@ static int spi_master_initialize_queue(struct spi_master *master) + * of_register_spi_devices() - Register child devices onto the SPI bus + * @master: Pointer to spi_master device + * +- * Registers an spi_device for each child node of master node which has a 'reg' +- * property. ++ * Registers an spi_device for each child node of controller node which ++ * represents a valid SPI slave. + */ + static void of_register_spi_devices(struct spi_master *master) + { +@@ -1771,28 +1780,129 @@ static void spi_master_release(struct device *dev) + .dev_groups = spi_master_groups, + }; + ++#ifdef CONFIG_SPI_SLAVE ++/** ++ * spi_slave_abort - abort the ongoing transfer request on an SPI slave ++ * controller ++ * @spi: device used for the current transfer ++ */ ++int spi_slave_abort(struct spi_device *spi) ++{ ++ struct spi_master *master = spi->master; ++ ++ if (spi_controller_is_slave(master) && master->slave_abort) ++ return master->slave_abort(master); ++ ++ return -ENOTSUPP; ++} ++EXPORT_SYMBOL_GPL(spi_slave_abort); ++ ++static int match_true(struct device *dev, void *data) ++{ ++ return 1; ++} ++ ++static ssize_t spi_slave_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct spi_master *ctlr = container_of(dev, struct spi_master, dev); ++ struct device *child; ++ ++ child = device_find_child(&ctlr->dev, NULL, match_true); ++ return sprintf(buf, "%s\n", ++ child ? to_spi_device(child)->modalias : NULL); ++} ++ ++static ssize_t spi_slave_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, ++ size_t count) ++{ ++ struct spi_master *ctlr = container_of(dev, struct spi_master, dev); ++ struct spi_device *spi; ++ struct device *child; ++ char name[32]; ++ int rc; ++ ++ rc = sscanf(buf, "%31s", name); ++ if (rc != 1 || !name[0]) ++ return -EINVAL; ++ ++ child = device_find_child(&ctlr->dev, NULL, match_true); ++ if (child) { ++ /* Remove registered slave */ ++ device_unregister(child); ++ put_device(child); ++ } ++ ++ if (strcmp(name, "(null)")) { ++ /* Register new slave */ ++ spi = spi_alloc_device(ctlr); ++ if (!spi) ++ return -ENOMEM; ++ ++ strlcpy(spi->modalias, name, sizeof(spi->modalias)); ++ ++ rc = spi_add_device(spi); ++ if (rc) { ++ spi_dev_put(spi); ++ return rc; ++ } ++ } ++ ++ return count; ++} ++ ++static DEVICE_ATTR(slave, 0644, spi_slave_show, spi_slave_store); ++ ++static struct attribute *spi_slave_attrs[] = { ++ &dev_attr_slave.attr, ++ NULL, ++}; ++ ++static const struct attribute_group spi_slave_group = { ++ .attrs = spi_slave_attrs, ++}; ++ ++static const struct attribute_group *spi_slave_groups[] = { ++ &spi_master_statistics_group, ++ &spi_slave_group, ++ NULL, ++}; ++ ++static struct class spi_slave_class = { ++ .name = "spi_slave", ++ .owner = THIS_MODULE, ++ .dev_release = spi_master_release, ++ .dev_groups = spi_slave_groups, ++}; ++#else ++extern struct class spi_slave_class; /* dummy */ ++#endif + + /** +- * spi_alloc_master - allocate SPI master controller ++ * __spi_alloc_controller - allocate an SPI master or slave controller + * @dev: the controller, possibly using the platform_bus + * @size: how much zeroed driver-private data to allocate; the pointer to this + * memory is in the driver_data field of the returned device, + * accessible with spi_master_get_devdata(). ++ * @slave: flag indicating whether to allocate an SPI master (false) or SPI ++ * slave (true) controller + * Context: can sleep + * +- * This call is used only by SPI master controller drivers, which are the ++ * This call is used only by SPI controller drivers, which are the + * only ones directly touching chip registers. It's how they allocate + * an spi_master structure, prior to calling spi_register_master(). + * + * This must be called from context that can sleep. + * +- * The caller is responsible for assigning the bus number and initializing +- * the master's methods before calling spi_register_master(); and (after errors ++ * The caller is responsible for assigning the bus number and initializing the ++ * controller's methods before calling spi_register_master(); and (after errors + * adding the device) calling spi_master_put() to prevent a memory leak. + * +- * Return: the SPI master structure on success, else NULL. ++ * Return: the SPI controller structure on success, else NULL. + */ +-struct spi_master *spi_alloc_master(struct device *dev, unsigned size) ++struct spi_master *__spi_alloc_controller(struct device *dev, ++ unsigned int size, bool slave) + { + struct spi_master *master; + +@@ -1806,14 +1916,18 @@ struct spi_master *spi_alloc_master(struct device *dev, unsigned size) + device_initialize(&master->dev); + master->bus_num = -1; + master->num_chipselect = 1; +- master->dev.class = &spi_master_class; ++ master->slave = slave; ++ if (IS_ENABLED(CONFIG_SPI_SLAVE) && slave) ++ master->dev.class = &spi_slave_class; ++ else ++ master->dev.class = &spi_master_class; + master->dev.parent = dev; + pm_suspend_ignore_children(&master->dev, true); + spi_master_set_devdata(master, &master[1]); + + return master; + } +-EXPORT_SYMBOL_GPL(spi_alloc_master); ++EXPORT_SYMBOL_GPL(__spi_alloc_controller); + + #ifdef CONFIG_OF + static int of_spi_register_master(struct spi_master *master) +@@ -1889,9 +2003,11 @@ int spi_register_master(struct spi_master *master) + if (!dev) + return -ENODEV; + +- status = of_spi_register_master(master); +- if (status) +- return status; ++ if (!spi_controller_is_slave(master)) { ++ status = of_spi_register_master(master); ++ if (status) ++ return status; ++ } + + /* even if it's just one always-selected device, there must + * be at least one chipselect +@@ -1928,8 +2044,9 @@ int spi_register_master(struct spi_master *master) + status = device_add(&master->dev); + if (status < 0) + goto done; +- dev_dbg(dev, "registered master %s%s\n", dev_name(&master->dev), +- dynamic ? " (dynamic)" : ""); ++ dev_dbg(dev, "registered %s %s%s\n", ++ spi_controller_is_slave(master) ? "slave" : "master", ++ dev_name(&master->dev), dynamic ? " (dynamic)" : ""); + + /* If we're using a queued driver, start the queue */ + if (master->transfer) +@@ -3102,6 +3219,9 @@ static struct spi_master *of_find_spi_master_by_node(struct device_node *node) + + dev = class_find_device(&spi_master_class, NULL, node, + __spi_of_master_match); ++ if (!dev && IS_ENABLED(CONFIG_SPI_SLAVE)) ++ dev = class_find_device(&spi_slave_class, NULL, node, ++ __spi_of_master_match); + if (!dev) + return NULL; + +@@ -3183,6 +3303,9 @@ static struct spi_master *acpi_spi_find_master_by_adev(struct acpi_device *adev) + + dev = class_find_device(&spi_master_class, NULL, adev, + spi_acpi_master_match); ++ if (!dev && IS_ENABLED(CONFIG_SPI_SLAVE)) ++ dev = class_find_device(&spi_slave_class, NULL, adev, ++ spi_acpi_master_match); + if (!dev) + return NULL; + +@@ -3255,6 +3378,12 @@ static int __init spi_init(void) + if (status < 0) + goto err2; + ++ if (IS_ENABLED(CONFIG_SPI_SLAVE)) { ++ status = class_register(&spi_slave_class); ++ if (status < 0) ++ goto err3; ++ } ++ + if (IS_ENABLED(CONFIG_OF_DYNAMIC)) + WARN_ON(of_reconfig_notifier_register(&spi_of_notifier)); + if (IS_ENABLED(CONFIG_ACPI)) +@@ -3262,6 +3391,8 @@ static int __init spi_init(void) + + return 0; + ++err3: ++ class_unregister(&spi_master_class); + err2: + bus_unregister(&spi_bus_type); + err1: +diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h +index 4b743ac..f9bbd33 100644 +--- a/include/linux/spi/spi.h ++++ b/include/linux/spi/spi.h +@@ -28,8 +28,8 @@ + struct spi_flash_read_message; + + /* +- * INTERFACES between SPI master-side drivers and SPI infrastructure. +- * (There's no SPI slave support for Linux yet...) ++ * INTERFACES between SPI master-side drivers and SPI slave protocol handlers, ++ * and SPI infrastructure. + */ + extern struct bus_type spi_bus_type; + +@@ -310,6 +310,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) + * @min_speed_hz: Lowest supported transfer speed + * @max_speed_hz: Highest supported transfer speed + * @flags: other constraints relevant to this driver ++ * @slave: indicates that this is an SPI slave controller + * @max_transfer_size: function that returns the max transfer size for + * a &spi_device; may be %NULL, so the default %SIZE_MAX will be used. + * @max_message_size: function that returns the max message size for +@@ -373,6 +374,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) + * @handle_err: the subsystem calls the driver to handle an error that occurs + * in the generic implementation of transfer_one_message(). + * @unprepare_message: undo any work done by prepare_message(). ++ * @slave_abort: abort the ongoing transfer request on an SPI slave controller + * @spi_flash_read: to support spi-controller hardwares that provide + * accelerated interface to read from flash devices. + * @flash_read_supported: spi device supports flash read +@@ -443,6 +445,9 @@ struct spi_master { + #define SPI_MASTER_MUST_RX BIT(3) /* requires rx */ + #define SPI_MASTER_MUST_TX BIT(4) /* requires tx */ + ++ /* flag indicating this is an SPI slave controller */ ++ bool slave; ++ + /* + * on some hardware transfer / message size may be constrained + * the limit may depend on device transfer settings +@@ -535,6 +540,7 @@ struct spi_master { + struct spi_message *message); + int (*unprepare_message)(struct spi_master *master, + struct spi_message *message); ++ int (*slave_abort)(struct spi_master *spi); + int (*spi_flash_read)(struct spi_device *spi, + struct spi_flash_read_message *msg); + bool (*flash_read_supported)(struct spi_device *spi); +@@ -589,6 +595,11 @@ static inline void spi_master_put(struct spi_master *master) + put_device(&master->dev); + } + ++static inline bool spi_controller_is_slave(struct spi_master *ctlr) ++{ ++ return IS_ENABLED(CONFIG_SPI_SLAVE) && ctlr->slave; ++} ++ + /* PM calls that need to be issued by the driver */ + extern int spi_master_suspend(struct spi_master *master); + extern int spi_master_resume(struct spi_master *master); +@@ -599,8 +610,23 @@ static inline void spi_master_put(struct spi_master *master) + extern void spi_finalize_current_transfer(struct spi_master *master); + + /* the spi driver core manages memory for the spi_master classdev */ +-extern struct spi_master * +-spi_alloc_master(struct device *host, unsigned size); ++extern struct spi_master *__spi_alloc_controller(struct device *host, ++ unsigned int size, bool slave); ++ ++static inline struct spi_master *spi_alloc_master(struct device *host, ++ unsigned int size) ++{ ++ return __spi_alloc_controller(host, size, false); ++} ++ ++static inline struct spi_master *spi_alloc_slave(struct device *host, ++ unsigned int size) ++{ ++ if (!IS_ENABLED(CONFIG_SPI_SLAVE)) ++ return NULL; ++ ++ return __spi_alloc_controller(host, size, true); ++} + + extern int spi_register_master(struct spi_master *master); + extern int devm_spi_register_master(struct device *dev, +@@ -906,6 +932,7 @@ static inline void spi_message_free(struct spi_message *m) + extern int spi_async(struct spi_device *spi, struct spi_message *message); + extern int spi_async_locked(struct spi_device *spi, + struct spi_message *message); ++extern int spi_slave_abort(struct spi_device *spi); + + static inline size_t + spi_max_message_size(struct spi_device *spi) +-- +1.7.10.4 diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0085-spi-Document-SPI-slave-controller-support.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0085-spi-Document-SPI-slave-controller-support.patch new file mode 100644 index 0000000..57436d2 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0085-spi-Document-SPI-slave-controller-support.patch @@ -0,0 +1,66 @@ +From 0be2c71f293e8c8423e5378cc73f71e10205ad54 Mon Sep 17 00:00:00 2001 +From: Geert Uytterhoeven +Date: Thu, 8 Sep 2016 15:01:48 +0200 +Subject: [PATCH 3/7] spi: Document SPI slave controller support + +Signed-off-by: Geert Uytterhoeven +--- + Documentation/spi/spi-summary | 27 ++++++++++++++++++++------- + 1 file changed, 20 insertions(+), 7 deletions(-) + +diff --git a/Documentation/spi/spi-summary b/Documentation/spi/spi-summary +index d1824b3..1721c1b 100644 +--- a/Documentation/spi/spi-summary ++++ b/Documentation/spi/spi-summary +@@ -62,8 +62,8 @@ chips described as using "three wire" signaling: SCK, data, nCSx. + (That data line is sometimes called MOMI or SISO.) + + Microcontrollers often support both master and slave sides of the SPI +-protocol. This document (and Linux) currently only supports the master +-side of SPI interactions. ++protocol. This document (and Linux) supports both the master and slave ++sides of SPI interactions. + + + Who uses it? On what kinds of systems? +@@ -154,9 +154,8 @@ control audio interfaces, present touchscreen sensors as input interfaces, + or monitor temperature and voltage levels during industrial processing. + And those might all be sharing the same controller driver. + +-A "struct spi_device" encapsulates the master-side interface between +-those two types of driver. At this writing, Linux has no slave side +-programming interface. ++A "struct spi_device" encapsulates the controller-side interface between ++those two types of drivers. + + There is a minimal core of SPI programming interfaces, focussing on + using the driver model to connect controller and protocol drivers using +@@ -177,10 +176,24 @@ shows up in sysfs in several locations: + /sys/bus/spi/drivers/D ... driver for one or more spi*.* devices + + /sys/class/spi_master/spiB ... symlink (or actual device node) to +- a logical node which could hold class related state for the +- controller managing bus "B". All spiB.* devices share one ++ a logical node which could hold class related state for the SPI ++ master controller managing bus "B". All spiB.* devices share one + physical SPI bus segment, with SCLK, MOSI, and MISO. + ++ /sys/devices/.../CTLR/slave ... virtual file for (un)registering the ++ slave device for an SPI slave controller. ++ Writing the driver name of an SPI slave handler to this file ++ registers the slave device; writing "(null)" unregisters the slave ++ device. ++ Reading from this file shows the name of the slave device ("(null)" ++ if not registered). ++ ++ /sys/class/spi_slave/spiB ... symlink (or actual device node) to ++ a logical node which could hold class related state for the SPI ++ slave controller on bus "B". When registered, a single spiB.* ++ device is present here, possible sharing the physical SPI bus ++ segment with other SPI slave devices. ++ + Note that the actual location of the controller's class state depends + on whether you enabled CONFIG_SYSFS_DEPRECATED or not. At this time, + the only class-specific state is the bus number ("B" in "spiB"), so +-- +1.7.10.4 diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0086-spi-sh-msiof-Add-slave-mode-support.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0086-spi-sh-msiof-Add-slave-mode-support.patch new file mode 100644 index 0000000..af15bae --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0086-spi-sh-msiof-Add-slave-mode-support.patch @@ -0,0 +1,209 @@ +From 383d0d23b9292dab56a2fdf5f6fecf898be6d142 Mon Sep 17 00:00:00 2001 +From: Hisashi Nakamura +Date: Mon, 28 Jul 2014 14:47:56 +0900 +Subject: [PATCH 4/7] spi: sh-msiof: Add slave mode support + +Add slave mode support to the MSIOF driver, in both PIO and DMA mode. + +For now this only supports the transmission of messages with a size +that is known in advance. + +Signed-off-by: Hisashi Nakamura +Signed-off-by: Hiromitsu Yamasaki +[geert: Timeout handling cleanup, spi core integration, cancellation, + rewording] +Signed-off-by: Geert Uytterhoeven +Acked-by: Rob Herring +--- + Documentation/devicetree/bindings/spi/sh-msiof.txt | 2 + + drivers/spi/spi-sh-msiof.c | 79 ++++++++++++++------ + 2 files changed, 60 insertions(+), 21 deletions(-) + +diff --git a/Documentation/devicetree/bindings/spi/sh-msiof.txt b/Documentation/devicetree/bindings/spi/sh-msiof.txt +index c2b6251..74ee3cd 100644 +--- a/Documentation/devicetree/bindings/spi/sh-msiof.txt ++++ b/Documentation/devicetree/bindings/spi/sh-msiof.txt +@@ -33,6 +33,8 @@ Optional properties: + specifiers, one for transmission, and one for + reception. + - dma-names : Must contain a list of two DMA names, "tx" and "rx". ++- spi-slave : Empty property indicating the SPI controller is used ++ in slave mode. + - renesas,dtdl : delay sync signal (setup) in transmit mode. + Must contain one of the following values: + 0 (no bit delay) +diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c +index 3281dc7..3b87024 100644 +--- a/drivers/spi/spi-sh-msiof.c ++++ b/drivers/spi/spi-sh-msiof.c +@@ -3,7 +3,7 @@ + * + * Copyright (C) 2016-2017 Renesas Electronics Corporation + * Copyright (c) 2009 Magnus Damm +- * Copyright (C) 2014 Glider bvba ++ * Copyright (C) 2014-2017 Glider bvba + * + * 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 +@@ -35,7 +35,6 @@ + + #include + +- + struct sh_msiof_chipdata { + u16 tx_fifo_size; + u16 rx_fifo_size; +@@ -62,6 +61,7 @@ struct sh_msiof_spi_priv { + void *rx_dma_page; + dma_addr_t tx_dma_addr; + dma_addr_t rx_dma_addr; ++ bool slave_aborted; + unsigned int quirks; + }; + +@@ -712,6 +712,33 @@ static int sh_msiof_spi_stop(struct sh_msiof_spi_priv *p, void *rx_buf) + return ret; + } + ++static int sh_msiof_slave_abort(struct spi_master *master) ++{ ++ struct sh_msiof_spi_priv *p = spi_master_get_devdata(master); ++ ++ p->slave_aborted = true; ++ complete(&p->done); ++ return 0; ++} ++ ++static int sh_msiof_wait_for_completion(struct sh_msiof_spi_priv *p) ++{ ++ if (spi_controller_is_slave(p->master)) { ++ if (wait_for_completion_interruptible(&p->done) || ++ p->slave_aborted) { ++ dev_dbg(&p->pdev->dev, "interrupted\n"); ++ return -EINTR; ++ } ++ } else { ++ if (!wait_for_completion_timeout(&p->done, HZ)) { ++ dev_err(&p->pdev->dev, "timeout\n"); ++ return -ETIMEDOUT; ++ } ++ } ++ ++ return 0; ++} ++ + static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p, + void (*tx_fifo)(struct sh_msiof_spi_priv *, + const void *, int, int), +@@ -747,6 +774,7 @@ static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p, + tx_fifo(p, tx_buf, words, fifo_shift); + + reinit_completion(&p->done); ++ p->slave_aborted = false; + + ret = sh_msiof_spi_start(p, rx_buf); + if (ret) { +@@ -867,6 +895,7 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, + reinit_completion(&p->done); + reinit_completion(&p->done_dma_tx); + reinit_completion(&p->done_dma_rx); ++ p->slave_aborted = false; + + /* Now start DMA */ + if (rx) +@@ -1205,8 +1234,14 @@ static struct sh_msiof_spi_info *sh_msiof_spi_parse_dt(struct device *dev) + if (!info) + return NULL; + ++ if (of_property_read_bool(np, "slave")) ++ info->mode = SPI_MSIOF_SLAVE; ++ else ++ info->mode = SPI_MSIOF_MASTER; ++ + /* Parse the MSIOF properties */ +- of_property_read_u32(np, "num-cs", &num_cs); ++ if (info->mode == SPI_MSIOF_MASTER) ++ of_property_read_u32(np, "num-cs", &num_cs); + of_property_read_u32(np, "renesas,tx-fifo-size", + &info->tx_fifo_override); + of_property_read_u32(np, "renesas,rx-fifo-size", +@@ -1214,10 +1249,6 @@ static struct sh_msiof_spi_info *sh_msiof_spi_parse_dt(struct device *dev) + of_property_read_u32(np, "renesas,dtdl", &info->dtdl); + of_property_read_u32(np, "renesas,syncdl", &info->syncdl); + +- if (of_property_read_bool(np, "slave")) +- info->mode = SPI_MSIOF_SLAVE; +- else +- info->mode = SPI_MSIOF_MASTER; + + info->num_chipselect = num_cs; + +@@ -1368,6 +1399,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) + struct spi_master *master; + const struct sh_msiof_chipdata *chipdata; + const struct of_device_id *of_id; ++ struct sh_msiof_spi_info *info; + struct sh_msiof_spi_priv *p; + struct clk *ref_clk; + u32 clk_rate = 0; +@@ -1375,32 +1407,36 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) + int ret; + const struct soc_device_attribute *attr; + +- master = spi_alloc_master(&pdev->dev, sizeof(struct sh_msiof_spi_priv)); +- if (master == NULL) { +- dev_err(&pdev->dev, "failed to allocate spi master\n"); +- return -ENOMEM; +- } +- +- p = spi_master_get_devdata(master); +- +- platform_set_drvdata(pdev, p); +- p->master = master; +- + of_id = of_match_device(sh_msiof_match, &pdev->dev); + if (of_id) { + chipdata = of_id->data; +- p->info = sh_msiof_spi_parse_dt(&pdev->dev); ++ info = sh_msiof_spi_parse_dt(&pdev->dev); + } else { + chipdata = (const void *)pdev->id_entry->driver_data; +- p->info = dev_get_platdata(&pdev->dev); ++ info = dev_get_platdata(&pdev->dev); + } + +- if (!p->info) { ++ if (!info) { + dev_err(&pdev->dev, "failed to obtain device info\n"); + ret = -ENXIO; + goto err1; + } + ++ if (info->mode == SPI_MSIOF_SLAVE) ++ master = spi_alloc_slave(&pdev->dev, ++ sizeof(struct sh_msiof_spi_priv)); ++ else ++ master = spi_alloc_master(&pdev->dev, ++ sizeof(struct sh_msiof_spi_priv)); ++ if (master == NULL) ++ return -ENOMEM; ++ ++ p = spi_master_get_devdata(master); ++ ++ platform_set_drvdata(pdev, p); ++ p->master = master; ++ p->info = info; ++ + attr = soc_device_match(rcar_quirks_match); + if (attr) + p->quirks = (uintptr_t)attr->data; +@@ -1458,6 +1494,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) + master->num_chipselect = p->info->num_chipselect; + master->setup = sh_msiof_spi_setup; + master->prepare_message = sh_msiof_prepare_message; ++ master->slave_abort = sh_msiof_slave_abort; + master->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 32); + master->auto_runtime_pm = true; + master->transfer_one = sh_msiof_transfer_one; +-- +1.7.10.4 diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0087-spi-slave-Add-SPI-slave-handler-reporting-uptime-at-.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0087-spi-slave-Add-SPI-slave-handler-reporting-uptime-at-.patch new file mode 100644 index 0000000..1c9be85 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0087-spi-slave-Add-SPI-slave-handler-reporting-uptime-at-.patch @@ -0,0 +1,182 @@ +From 8b3a09269db92be56455d98bc8cb01f779733f0a Mon Sep 17 00:00:00 2001 +From: Geert Uytterhoeven +Date: Fri, 17 Jun 2016 17:00:25 +0200 +Subject: [PATCH 5/7] spi: slave: Add SPI slave handler reporting uptime at + previous message + +Add an example SPI slave handler responding with the uptime at the time +of reception of the last SPI message. + +This can be used by an external microcontroller as a dead man's switch. + +Signed-off-by: Geert Uytterhoeven +--- + drivers/spi/Kconfig | 6 ++ + drivers/spi/Makefile | 1 + + drivers/spi/spi-slave-time.c | 129 ++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 136 insertions(+) + create mode 100644 drivers/spi/spi-slave-time.c + +diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig +index 8c97790..267bedf 100644 +--- a/drivers/spi/Kconfig ++++ b/drivers/spi/Kconfig +@@ -793,6 +793,12 @@ config SPI_SLAVE + + if SPI_SLAVE + ++config SPI_SLAVE_TIME ++ tristate "SPI slave handler reporting boot up time" ++ help ++ SPI slave handler responding with the time of reception of the last ++ SPI message. ++ + endif # SPI_SLAVE + + endif # SPI +diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile +index 2428b0f..5e2e537 100644 +--- a/drivers/spi/Makefile ++++ b/drivers/spi/Makefile +@@ -104,3 +104,4 @@ obj-$(CONFIG_SPI_XTENSA_XTFPGA) += spi-xtensa-xtfpga.o + obj-$(CONFIG_SPI_ZYNQMP_GQSPI) += spi-zynqmp-gqspi.o + + # SPI slave protocol handlers ++obj-$(CONFIG_SPI_SLAVE_TIME) += spi-slave-time.o +diff --git a/drivers/spi/spi-slave-time.c b/drivers/spi/spi-slave-time.c +new file mode 100644 +index 0000000..fbeaa5b +--- /dev/null ++++ b/drivers/spi/spi-slave-time.c +@@ -0,0 +1,129 @@ ++/* ++ * SPI slave handler reporting uptime at reception of previous SPI message ++ * ++ * This SPI slave handler sends the time of reception of the last SPI message ++ * as two 32-bit unsigned integers in binary format and in network byte order, ++ * representing the number of seconds and fractional seconds (in microseconds) ++ * since boot up. ++ * ++ * Copyright (C) 2016-2017 Glider bvba ++ * ++ * 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 ++ * for more details. ++ * ++ * Usage (assuming /dev/spidev2.0 corresponds to the SPI master on the remote ++ * system): ++ * ++ * # spidev_test -D /dev/spidev2.0 -p dummy-8B ++ * spi mode: 0x0 ++ * bits per word: 8 ++ * max speed: 500000 Hz (500 KHz) ++ * RX | 00 00 04 6D 00 09 5B BB ... ++ * ^^^^^ ^^^^^^^^ ++ * seconds microseconds ++ */ ++ ++#include ++#include ++#include ++#include ++ ++ ++struct spi_slave_time_priv { ++ struct spi_device *spi; ++ struct completion finished; ++ struct spi_transfer xfer; ++ struct spi_message msg; ++ __be32 buf[2]; ++}; ++ ++static int spi_slave_time_submit(struct spi_slave_time_priv *priv); ++ ++static void spi_slave_time_complete(void *arg) ++{ ++ struct spi_slave_time_priv *priv = arg; ++ int ret; ++ ++ ret = priv->msg.status; ++ if (ret) ++ goto terminate; ++ ++ ret = spi_slave_time_submit(priv); ++ if (ret) ++ goto terminate; ++ ++ return; ++ ++terminate: ++ dev_info(&priv->spi->dev, "Terminating\n"); ++ complete(&priv->finished); ++} ++ ++static int spi_slave_time_submit(struct spi_slave_time_priv *priv) ++{ ++ u32 rem_us; ++ int ret; ++ u64 ts; ++ ++ ts = local_clock(); ++ rem_us = do_div(ts, 1000000000) / 1000; ++ ++ priv->buf[0] = cpu_to_be32(ts); ++ priv->buf[1] = cpu_to_be32(rem_us); ++ ++ spi_message_init_with_transfers(&priv->msg, &priv->xfer, 1); ++ ++ priv->msg.complete = spi_slave_time_complete; ++ priv->msg.context = priv; ++ ++ ret = spi_async(priv->spi, &priv->msg); ++ if (ret) ++ dev_err(&priv->spi->dev, "spi_async() failed %d\n", ret); ++ ++ return ret; ++} ++ ++static int spi_slave_time_probe(struct spi_device *spi) ++{ ++ struct spi_slave_time_priv *priv; ++ int ret; ++ ++ priv = devm_kzalloc(&spi->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->spi = spi; ++ init_completion(&priv->finished); ++ priv->xfer.tx_buf = priv->buf; ++ priv->xfer.len = sizeof(priv->buf); ++ ++ ret = spi_slave_time_submit(priv); ++ if (ret) ++ return ret; ++ ++ spi_set_drvdata(spi, priv); ++ return 0; ++} ++ ++static int spi_slave_time_remove(struct spi_device *spi) ++{ ++ struct spi_slave_time_priv *priv = spi_get_drvdata(spi); ++ ++ spi_slave_abort(spi); ++ wait_for_completion(&priv->finished); ++ return 0; ++} ++ ++static struct spi_driver spi_slave_time_driver = { ++ .driver = { ++ .name = "spi-slave-time", ++ }, ++ .probe = spi_slave_time_probe, ++ .remove = spi_slave_time_remove, ++}; ++module_spi_driver(spi_slave_time_driver); ++ ++MODULE_AUTHOR("Geert Uytterhoeven "); ++MODULE_DESCRIPTION("SPI slave reporting uptime at previous SPI message"); ++MODULE_LICENSE("GPL v2"); +-- +1.7.10.4 diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0088-spi-slave-Add-SPI-slave-handler-controlling-system-s.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0088-spi-slave-Add-SPI-slave-handler-controlling-system-s.patch new file mode 100644 index 0000000..3752e98 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0088-spi-slave-Add-SPI-slave-handler-controlling-system-s.patch @@ -0,0 +1,205 @@ +From 6acf67e94cbd406b57315f03937a8d4d37a2952c Mon Sep 17 00:00:00 2001 +From: Geert Uytterhoeven +Date: Fri, 17 Jun 2016 17:05:45 +0200 +Subject: [PATCH 6/7] spi: slave: Add SPI slave handler controlling system + state + +Add an example SPI slave handler to allow remote control of system +reboot, power off, halt, and suspend. + +Signed-off-by: Geert Uytterhoeven +--- + drivers/spi/Kconfig | 6 ++ + drivers/spi/Makefile | 1 + + drivers/spi/spi-slave-system-control.c | 154 ++++++++++++++++++++++++++++++++ + 3 files changed, 161 insertions(+) + create mode 100644 drivers/spi/spi-slave-system-control.c + +diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig +index 267bedf..45208ec 100644 +--- a/drivers/spi/Kconfig ++++ b/drivers/spi/Kconfig +@@ -799,6 +799,12 @@ config SPI_SLAVE_TIME + SPI slave handler responding with the time of reception of the last + SPI message. + ++config SPI_SLAVE_SYSTEM_CONTROL ++ tristate "SPI slave handler controlling system state" ++ help ++ SPI slave handler to allow remote control of system reboot, power ++ off, halt, and suspend. ++ + endif # SPI_SLAVE + + endif # SPI +diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile +index 5e2e537..d4d5050 100644 +--- a/drivers/spi/Makefile ++++ b/drivers/spi/Makefile +@@ -105,3 +105,4 @@ obj-$(CONFIG_SPI_ZYNQMP_GQSPI) += spi-zynqmp-gqspi.o + + # SPI slave protocol handlers + obj-$(CONFIG_SPI_SLAVE_TIME) += spi-slave-time.o ++obj-$(CONFIG_SPI_SLAVE_SYSTEM_CONTROL) += spi-slave-system-control.o +diff --git a/drivers/spi/spi-slave-system-control.c b/drivers/spi/spi-slave-system-control.c +new file mode 100644 +index 0000000..c0257e9 +--- /dev/null ++++ b/drivers/spi/spi-slave-system-control.c +@@ -0,0 +1,154 @@ ++/* ++ * SPI slave handler controlling system state ++ * ++ * This SPI slave handler allows remote control of system reboot, power off, ++ * halt, and suspend. ++ * ++ * Copyright (C) 2016-2017 Glider bvba ++ * ++ * 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 ++ * for more details. ++ * ++ * Usage (assuming /dev/spidev2.0 corresponds to the SPI master on the remote ++ * system): ++ * ++ * # reboot='\x7c\x50' ++ * # poweroff='\x71\x3f' ++ * # halt='\x38\x76' ++ * # suspend='\x1b\x1b' ++ * # spidev_test -D /dev/spidev2.0 -p $suspend # or $reboot, $poweroff, $halt ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++/* ++ * The numbers are chosen to display something human-readable on two 7-segment ++ * displays connected to two 74HC595 shift registers ++ */ ++#define CMD_REBOOT 0x7c50 /* rb */ ++#define CMD_POWEROFF 0x713f /* OF */ ++#define CMD_HALT 0x3876 /* HL */ ++#define CMD_SUSPEND 0x1b1b /* ZZ */ ++ ++struct spi_slave_system_control_priv { ++ struct spi_device *spi; ++ struct completion finished; ++ struct spi_transfer xfer; ++ struct spi_message msg; ++ __be16 cmd; ++}; ++ ++static ++int spi_slave_system_control_submit(struct spi_slave_system_control_priv *priv); ++ ++static void spi_slave_system_control_complete(void *arg) ++{ ++ struct spi_slave_system_control_priv *priv = arg; ++ u16 cmd; ++ int ret; ++ ++ if (priv->msg.status) ++ goto terminate; ++ ++ cmd = be16_to_cpu(priv->cmd); ++ switch (cmd) { ++ case CMD_REBOOT: ++ dev_info(&priv->spi->dev, "Rebooting system...\n"); ++ kernel_restart(NULL); ++ ++ case CMD_POWEROFF: ++ dev_info(&priv->spi->dev, "Powering off system...\n"); ++ kernel_power_off(); ++ break; ++ ++ case CMD_HALT: ++ dev_info(&priv->spi->dev, "Halting system...\n"); ++ kernel_halt(); ++ break; ++ ++ case CMD_SUSPEND: ++ dev_info(&priv->spi->dev, "Suspending system...\n"); ++ pm_suspend(PM_SUSPEND_MEM); ++ break; ++ ++ default: ++ dev_warn(&priv->spi->dev, "Unknown command 0x%x\n", cmd); ++ break; ++ } ++ ++ ret = spi_slave_system_control_submit(priv); ++ if (ret) ++ goto terminate; ++ ++ return; ++ ++terminate: ++ dev_info(&priv->spi->dev, "Terminating\n"); ++ complete(&priv->finished); ++} ++ ++static ++int spi_slave_system_control_submit(struct spi_slave_system_control_priv *priv) ++{ ++ int ret; ++ ++ spi_message_init_with_transfers(&priv->msg, &priv->xfer, 1); ++ ++ priv->msg.complete = spi_slave_system_control_complete; ++ priv->msg.context = priv; ++ ++ ret = spi_async(priv->spi, &priv->msg); ++ if (ret) ++ dev_err(&priv->spi->dev, "spi_async() failed %d\n", ret); ++ ++ return ret; ++} ++ ++static int spi_slave_system_control_probe(struct spi_device *spi) ++{ ++ struct spi_slave_system_control_priv *priv; ++ int ret; ++ ++ priv = devm_kzalloc(&spi->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->spi = spi; ++ init_completion(&priv->finished); ++ priv->xfer.rx_buf = &priv->cmd; ++ priv->xfer.len = sizeof(priv->cmd); ++ ++ ret = spi_slave_system_control_submit(priv); ++ if (ret) ++ return ret; ++ ++ spi_set_drvdata(spi, priv); ++ return 0; ++} ++ ++static int spi_slave_system_control_remove(struct spi_device *spi) ++{ ++ struct spi_slave_system_control_priv *priv = spi_get_drvdata(spi); ++ ++ spi_slave_abort(spi); ++ wait_for_completion(&priv->finished); ++ return 0; ++} ++ ++static struct spi_driver spi_slave_system_control_driver = { ++ .driver = { ++ .name = "spi-slave-system-control", ++ }, ++ .probe = spi_slave_system_control_probe, ++ .remove = spi_slave_system_control_remove, ++}; ++module_spi_driver(spi_slave_system_control_driver); ++ ++MODULE_AUTHOR("Geert Uytterhoeven "); ++MODULE_DESCRIPTION("SPI slave handler controlling system state"); ++MODULE_LICENSE("GPL v2"); +-- +1.7.10.4 diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0089-spi-Generalize-SPI-master-to-controller.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0089-spi-Generalize-SPI-master-to-controller.patch new file mode 100644 index 0000000..2c1e0eb --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0089-spi-Generalize-SPI-master-to-controller.patch @@ -0,0 +1,3048 @@ +From 5767a2cd113534b904593d143175e1ba71ea6555 Mon Sep 17 00:00:00 2001 +From: Geert Uytterhoeven +Date: Wed, 3 May 2017 17:28:39 +0200 +Subject: [PATCH 7/7] spi: Generalize SPI "master" to "controller" + +Now struct spi_master is used for both SPI master and slave controllers, +it makes sense to rename it to struct spi_controller, and replace +"master" by "controller" where appropriate. + +For now this conversion is done for SPI core infrastructure only. +Wrappers are provided for backwards compatibility, until all SPI drivers +have been converted. + +Noteworthy details: + - SPI_MASTER_GPIO_SS is retained, as it only makes sense for SPI + master controllers, + - spi_busnum_to_master() is kept, as it looks up masters only, + - A new field spi_device.controller is added, but spi_device.master is + retained for compatibility (both are always initialized by + spi_alloc_device()), + - spi_flash_read() is used by SPI masters only. + +Signed-off-by: Geert Uytterhoeven +--- + drivers/spi/spi.c | 1073 ++++++++++++++++++++++---------------------- + include/linux/spi/spi.h | 197 ++++---- + include/trace/events/spi.h | 26 +- + 3 files changed, 664 insertions(+), 632 deletions(-) + +diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c +index a403e3a..cd2e271 100644 +--- a/drivers/spi/spi.c ++++ b/drivers/spi/spi.c +@@ -46,11 +46,11 @@ static void spidev_release(struct device *dev) + { + struct spi_device *spi = to_spi_device(dev); + +- /* spi masters may cleanup for released devices */ +- if (spi->master->cleanup) +- spi->master->cleanup(spi); ++ /* spi controllers may cleanup for released devices */ ++ if (spi->controller->cleanup) ++ spi->controller->cleanup(spi); + +- spi_master_put(spi->master); ++ spi_controller_put(spi->controller); + kfree(spi); + } + +@@ -69,17 +69,17 @@ static void spidev_release(struct device *dev) + static DEVICE_ATTR_RO(modalias); + + #define SPI_STATISTICS_ATTRS(field, file) \ +-static ssize_t spi_master_##field##_show(struct device *dev, \ +- struct device_attribute *attr, \ +- char *buf) \ ++static ssize_t spi_controller_##field##_show(struct device *dev, \ ++ struct device_attribute *attr, \ ++ char *buf) \ + { \ +- struct spi_master *master = container_of(dev, \ +- struct spi_master, dev); \ +- return spi_statistics_##field##_show(&master->statistics, buf); \ ++ struct spi_controller *ctlr = container_of(dev, \ ++ struct spi_controller, dev); \ ++ return spi_statistics_##field##_show(&ctlr->statistics, buf); \ + } \ +-static struct device_attribute dev_attr_spi_master_##field = { \ ++static struct device_attribute dev_attr_spi_controller_##field = { \ + .attr = { .name = file, .mode = S_IRUGO }, \ +- .show = spi_master_##field##_show, \ ++ .show = spi_controller_##field##_show, \ + }; \ + static ssize_t spi_device_##field##_show(struct device *dev, \ + struct device_attribute *attr, \ +@@ -199,51 +199,51 @@ static void spidev_release(struct device *dev) + NULL, + }; + +-static struct attribute *spi_master_statistics_attrs[] = { +- &dev_attr_spi_master_messages.attr, +- &dev_attr_spi_master_transfers.attr, +- &dev_attr_spi_master_errors.attr, +- &dev_attr_spi_master_timedout.attr, +- &dev_attr_spi_master_spi_sync.attr, +- &dev_attr_spi_master_spi_sync_immediate.attr, +- &dev_attr_spi_master_spi_async.attr, +- &dev_attr_spi_master_bytes.attr, +- &dev_attr_spi_master_bytes_rx.attr, +- &dev_attr_spi_master_bytes_tx.attr, +- &dev_attr_spi_master_transfer_bytes_histo0.attr, +- &dev_attr_spi_master_transfer_bytes_histo1.attr, +- &dev_attr_spi_master_transfer_bytes_histo2.attr, +- &dev_attr_spi_master_transfer_bytes_histo3.attr, +- &dev_attr_spi_master_transfer_bytes_histo4.attr, +- &dev_attr_spi_master_transfer_bytes_histo5.attr, +- &dev_attr_spi_master_transfer_bytes_histo6.attr, +- &dev_attr_spi_master_transfer_bytes_histo7.attr, +- &dev_attr_spi_master_transfer_bytes_histo8.attr, +- &dev_attr_spi_master_transfer_bytes_histo9.attr, +- &dev_attr_spi_master_transfer_bytes_histo10.attr, +- &dev_attr_spi_master_transfer_bytes_histo11.attr, +- &dev_attr_spi_master_transfer_bytes_histo12.attr, +- &dev_attr_spi_master_transfer_bytes_histo13.attr, +- &dev_attr_spi_master_transfer_bytes_histo14.attr, +- &dev_attr_spi_master_transfer_bytes_histo15.attr, +- &dev_attr_spi_master_transfer_bytes_histo16.attr, +- &dev_attr_spi_master_transfers_split_maxsize.attr, ++static struct attribute *spi_controller_statistics_attrs[] = { ++ &dev_attr_spi_controller_messages.attr, ++ &dev_attr_spi_controller_transfers.attr, ++ &dev_attr_spi_controller_errors.attr, ++ &dev_attr_spi_controller_timedout.attr, ++ &dev_attr_spi_controller_spi_sync.attr, ++ &dev_attr_spi_controller_spi_sync_immediate.attr, ++ &dev_attr_spi_controller_spi_async.attr, ++ &dev_attr_spi_controller_bytes.attr, ++ &dev_attr_spi_controller_bytes_rx.attr, ++ &dev_attr_spi_controller_bytes_tx.attr, ++ &dev_attr_spi_controller_transfer_bytes_histo0.attr, ++ &dev_attr_spi_controller_transfer_bytes_histo1.attr, ++ &dev_attr_spi_controller_transfer_bytes_histo2.attr, ++ &dev_attr_spi_controller_transfer_bytes_histo3.attr, ++ &dev_attr_spi_controller_transfer_bytes_histo4.attr, ++ &dev_attr_spi_controller_transfer_bytes_histo5.attr, ++ &dev_attr_spi_controller_transfer_bytes_histo6.attr, ++ &dev_attr_spi_controller_transfer_bytes_histo7.attr, ++ &dev_attr_spi_controller_transfer_bytes_histo8.attr, ++ &dev_attr_spi_controller_transfer_bytes_histo9.attr, ++ &dev_attr_spi_controller_transfer_bytes_histo10.attr, ++ &dev_attr_spi_controller_transfer_bytes_histo11.attr, ++ &dev_attr_spi_controller_transfer_bytes_histo12.attr, ++ &dev_attr_spi_controller_transfer_bytes_histo13.attr, ++ &dev_attr_spi_controller_transfer_bytes_histo14.attr, ++ &dev_attr_spi_controller_transfer_bytes_histo15.attr, ++ &dev_attr_spi_controller_transfer_bytes_histo16.attr, ++ &dev_attr_spi_controller_transfers_split_maxsize.attr, + NULL, + }; + +-static const struct attribute_group spi_master_statistics_group = { ++static const struct attribute_group spi_controller_statistics_group = { + .name = "statistics", +- .attrs = spi_master_statistics_attrs, ++ .attrs = spi_controller_statistics_attrs, + }; + + static const struct attribute_group *spi_master_groups[] = { +- &spi_master_statistics_group, ++ &spi_controller_statistics_group, + NULL, + }; + + void spi_statistics_add_transfer_stats(struct spi_statistics *stats, + struct spi_transfer *xfer, +- struct spi_master *master) ++ struct spi_controller *ctlr) + { + unsigned long flags; + int l2len = min(fls(xfer->len), SPI_STATISTICS_HISTO_SIZE) - 1; +@@ -258,10 +258,10 @@ void spi_statistics_add_transfer_stats(struct spi_statistics *stats, + + stats->bytes += xfer->len; + if ((xfer->tx_buf) && +- (xfer->tx_buf != master->dummy_tx)) ++ (xfer->tx_buf != ctlr->dummy_tx)) + stats->bytes_tx += xfer->len; + if ((xfer->rx_buf) && +- (xfer->rx_buf != master->dummy_rx)) ++ (xfer->rx_buf != ctlr->dummy_rx)) + stats->bytes_rx += xfer->len; + + spin_unlock_irqrestore(&stats->lock, flags); +@@ -403,7 +403,7 @@ int __spi_register_driver(struct module *owner, struct spi_driver *sdrv) + /*-------------------------------------------------------------------------*/ + + /* SPI devices should normally not be created by SPI device drivers; that +- * would make them board-specific. Similarly with SPI master drivers. ++ * would make them board-specific. Similarly with SPI controller drivers. + * Device registration normally goes into like arch/.../mach.../board-YYY.c + * with other readonly (flashable) information about mainboard devices. + */ +@@ -414,17 +414,17 @@ struct boardinfo { + }; + + static LIST_HEAD(board_list); +-static LIST_HEAD(spi_master_list); ++static LIST_HEAD(spi_controller_list); + + /* + * Used to protect add/del opertion for board_info list and +- * spi_master list, and their matching process ++ * spi_controller list, and their matching process + */ + static DEFINE_MUTEX(board_lock); + + /** + * spi_alloc_device - Allocate a new SPI device +- * @master: Controller to which device is connected ++ * @ctlr: Controller to which device is connected + * Context: can sleep + * + * Allows a driver to allocate and initialize a spi_device without +@@ -433,27 +433,27 @@ struct boardinfo { + * spi_add_device() on it. + * + * Caller is responsible to call spi_add_device() on the returned +- * spi_device structure to add it to the SPI master. If the caller ++ * spi_device structure to add it to the SPI controller. If the caller + * needs to discard the spi_device without adding it, then it should + * call spi_dev_put() on it. + * + * Return: a pointer to the new device, or NULL. + */ +-struct spi_device *spi_alloc_device(struct spi_master *master) ++struct spi_device *spi_alloc_device(struct spi_controller *ctlr) + { + struct spi_device *spi; + +- if (!spi_master_get(master)) ++ if (!spi_controller_get(ctlr)) + return NULL; + + spi = kzalloc(sizeof(*spi), GFP_KERNEL); + if (!spi) { +- spi_master_put(master); ++ spi_controller_put(ctlr); + return NULL; + } + +- spi->master = master; +- spi->dev.parent = &master->dev; ++ spi->master = spi->controller = ctlr; ++ spi->dev.parent = &ctlr->dev; + spi->dev.bus = &spi_bus_type; + spi->dev.release = spidev_release; + spi->cs_gpio = -ENOENT; +@@ -474,7 +474,7 @@ static void spi_dev_set_name(struct spi_device *spi) + return; + } + +- dev_set_name(&spi->dev, "%s.%u", dev_name(&spi->master->dev), ++ dev_set_name(&spi->dev, "%s.%u", dev_name(&spi->controller->dev), + spi->chip_select); + } + +@@ -483,7 +483,7 @@ static int spi_dev_check(struct device *dev, void *data) + struct spi_device *spi = to_spi_device(dev); + struct spi_device *new_spi = data; + +- if (spi->master == new_spi->master && ++ if (spi->controller == new_spi->controller && + spi->chip_select == new_spi->chip_select) + return -EBUSY; + return 0; +@@ -501,15 +501,14 @@ static int spi_dev_check(struct device *dev, void *data) + int spi_add_device(struct spi_device *spi) + { + static DEFINE_MUTEX(spi_add_lock); +- struct spi_master *master = spi->master; +- struct device *dev = master->dev.parent; ++ struct spi_controller *ctlr = spi->controller; ++ struct device *dev = ctlr->dev.parent; + int status; + + /* Chipselects are numbered 0..max; validate. */ +- if (spi->chip_select >= master->num_chipselect) { +- dev_err(dev, "cs%d >= max %d\n", +- spi->chip_select, +- master->num_chipselect); ++ if (spi->chip_select >= ctlr->num_chipselect) { ++ dev_err(dev, "cs%d >= max %d\n", spi->chip_select, ++ ctlr->num_chipselect); + return -EINVAL; + } + +@@ -529,8 +528,8 @@ int spi_add_device(struct spi_device *spi) + goto done; + } + +- if (master->cs_gpios) +- spi->cs_gpio = master->cs_gpios[spi->chip_select]; ++ if (ctlr->cs_gpios) ++ spi->cs_gpio = ctlr->cs_gpios[spi->chip_select]; + + /* Drivers may modify this initial i/o setup, but will + * normally rely on the device being setup. Devices +@@ -559,7 +558,7 @@ int spi_add_device(struct spi_device *spi) + + /** + * spi_new_device - instantiate one new SPI device +- * @master: Controller to which device is connected ++ * @ctlr: Controller to which device is connected + * @chip: Describes the SPI device + * Context: can sleep + * +@@ -571,7 +570,7 @@ int spi_add_device(struct spi_device *spi) + * + * Return: the new device, or NULL. + */ +-struct spi_device *spi_new_device(struct spi_master *master, ++struct spi_device *spi_new_device(struct spi_controller *ctlr, + struct spi_board_info *chip) + { + struct spi_device *proxy; +@@ -584,7 +583,7 @@ struct spi_device *spi_new_device(struct spi_master *master, + * suggests syslogged diagnostics are best here (ugh). + */ + +- proxy = spi_alloc_device(master); ++ proxy = spi_alloc_device(ctlr); + if (!proxy) + return NULL; + +@@ -614,7 +613,7 @@ struct spi_device *spi_new_device(struct spi_master *master, + * @spi: spi_device to unregister + * + * Start making the passed SPI device vanish. Normally this would be handled +- * by spi_unregister_master(). ++ * by spi_unregister_controller(). + */ + void spi_unregister_device(struct spi_device *spi) + { +@@ -629,17 +628,17 @@ void spi_unregister_device(struct spi_device *spi) + } + EXPORT_SYMBOL_GPL(spi_unregister_device); + +-static void spi_match_master_to_boardinfo(struct spi_master *master, +- struct spi_board_info *bi) ++static void spi_match_controller_to_boardinfo(struct spi_controller *ctlr, ++ struct spi_board_info *bi) + { + struct spi_device *dev; + +- if (master->bus_num != bi->bus_num) ++ if (ctlr->bus_num != bi->bus_num) + return; + +- dev = spi_new_device(master, bi); ++ dev = spi_new_device(ctlr, bi); + if (!dev) +- dev_err(master->dev.parent, "can't create new device for %s\n", ++ dev_err(ctlr->dev.parent, "can't create new device for %s\n", + bi->modalias); + } + +@@ -677,13 +676,14 @@ int spi_register_board_info(struct spi_board_info const *info, unsigned n) + return -ENOMEM; + + for (i = 0; i < n; i++, bi++, info++) { +- struct spi_master *master; ++ struct spi_controller *ctlr; + + memcpy(&bi->board_info, info, sizeof(*info)); + mutex_lock(&board_lock); + list_add_tail(&bi->list, &board_list); +- list_for_each_entry(master, &spi_master_list, list) +- spi_match_master_to_boardinfo(master, &bi->board_info); ++ list_for_each_entry(ctlr, &spi_controller_list, list) ++ spi_match_controller_to_boardinfo(ctlr, ++ &bi->board_info); + mutex_unlock(&board_lock); + } + +@@ -699,12 +699,12 @@ static void spi_set_cs(struct spi_device *spi, bool enable) + + if (gpio_is_valid(spi->cs_gpio)) + gpio_set_value(spi->cs_gpio, !enable); +- else if (spi->master->set_cs) +- spi->master->set_cs(spi, !enable); ++ else if (spi->controller->set_cs) ++ spi->controller->set_cs(spi, !enable); + } + + #ifdef CONFIG_HAS_DMA +-static int spi_map_buf(struct spi_master *master, struct device *dev, ++static int spi_map_buf(struct spi_controller *ctlr, struct device *dev, + struct sg_table *sgt, void *buf, size_t len, + enum dma_data_direction dir) + { +@@ -728,7 +728,7 @@ static int spi_map_buf(struct spi_master *master, struct device *dev, + desc_len = min_t(int, max_seg_size, PAGE_SIZE); + sgs = DIV_ROUND_UP(len + offset_in_page(buf), desc_len); + } else if (virt_addr_valid(buf)) { +- desc_len = min_t(int, max_seg_size, master->max_dma_len); ++ desc_len = min_t(int, max_seg_size, ctlr->max_dma_len); + sgs = DIV_ROUND_UP(len, desc_len); + } else { + return -EINVAL; +@@ -776,7 +776,7 @@ static int spi_map_buf(struct spi_master *master, struct device *dev, + return 0; + } + +-static void spi_unmap_buf(struct spi_master *master, struct device *dev, ++static void spi_unmap_buf(struct spi_controller *ctlr, struct device *dev, + struct sg_table *sgt, enum dma_data_direction dir) + { + if (sgt->orig_nents) { +@@ -785,31 +785,31 @@ static void spi_unmap_buf(struct spi_master *master, struct device *dev, + } + } + +-static int __spi_map_msg(struct spi_master *master, struct spi_message *msg) ++static int __spi_map_msg(struct spi_controller *ctlr, struct spi_message *msg) + { + struct device *tx_dev, *rx_dev; + struct spi_transfer *xfer; + int ret; + +- if (!master->can_dma) ++ if (!ctlr->can_dma) + return 0; + +- if (master->dma_tx) +- tx_dev = master->dma_tx->device->dev; ++ if (ctlr->dma_tx) ++ tx_dev = ctlr->dma_tx->device->dev; + else +- tx_dev = &master->dev; ++ tx_dev = &ctlr->dev; + +- if (master->dma_rx) +- rx_dev = master->dma_rx->device->dev; ++ if (ctlr->dma_rx) ++ rx_dev = ctlr->dma_rx->device->dev; + else +- rx_dev = &master->dev; ++ rx_dev = &ctlr->dev; + + list_for_each_entry(xfer, &msg->transfers, transfer_list) { +- if (!master->can_dma(master, msg->spi, xfer)) ++ if (!ctlr->can_dma(ctlr, msg->spi, xfer)) + continue; + + if (xfer->tx_buf != NULL) { +- ret = spi_map_buf(master, tx_dev, &xfer->tx_sg, ++ ret = spi_map_buf(ctlr, tx_dev, &xfer->tx_sg, + (void *)xfer->tx_buf, xfer->len, + DMA_TO_DEVICE); + if (ret != 0) +@@ -817,79 +817,78 @@ static int __spi_map_msg(struct spi_master *master, struct spi_message *msg) + } + + if (xfer->rx_buf != NULL) { +- ret = spi_map_buf(master, rx_dev, &xfer->rx_sg, ++ ret = spi_map_buf(ctlr, rx_dev, &xfer->rx_sg, + xfer->rx_buf, xfer->len, + DMA_FROM_DEVICE); + if (ret != 0) { +- spi_unmap_buf(master, tx_dev, &xfer->tx_sg, ++ spi_unmap_buf(ctlr, tx_dev, &xfer->tx_sg, + DMA_TO_DEVICE); + return ret; + } + } + } + +- master->cur_msg_mapped = true; ++ ctlr->cur_msg_mapped = true; + + return 0; + } + +-static int __spi_unmap_msg(struct spi_master *master, struct spi_message *msg) ++static int __spi_unmap_msg(struct spi_controller *ctlr, struct spi_message *msg) + { + struct spi_transfer *xfer; + struct device *tx_dev, *rx_dev; + +- if (!master->cur_msg_mapped || !master->can_dma) ++ if (!ctlr->cur_msg_mapped || !ctlr->can_dma) + return 0; + +- if (master->dma_tx) +- tx_dev = master->dma_tx->device->dev; ++ if (ctlr->dma_tx) ++ tx_dev = ctlr->dma_tx->device->dev; + else +- tx_dev = &master->dev; ++ tx_dev = &ctlr->dev; + +- if (master->dma_rx) +- rx_dev = master->dma_rx->device->dev; ++ if (ctlr->dma_rx) ++ rx_dev = ctlr->dma_rx->device->dev; + else +- rx_dev = &master->dev; ++ rx_dev = &ctlr->dev; + + list_for_each_entry(xfer, &msg->transfers, transfer_list) { +- if (!master->can_dma(master, msg->spi, xfer)) ++ if (!ctlr->can_dma(ctlr, msg->spi, xfer)) + continue; + +- spi_unmap_buf(master, rx_dev, &xfer->rx_sg, DMA_FROM_DEVICE); +- spi_unmap_buf(master, tx_dev, &xfer->tx_sg, DMA_TO_DEVICE); ++ spi_unmap_buf(ctlr, rx_dev, &xfer->rx_sg, DMA_FROM_DEVICE); ++ spi_unmap_buf(ctlr, tx_dev, &xfer->tx_sg, DMA_TO_DEVICE); + } + + return 0; + } + #else /* !CONFIG_HAS_DMA */ +-static inline int spi_map_buf(struct spi_master *master, +- struct device *dev, struct sg_table *sgt, +- void *buf, size_t len, ++static inline int spi_map_buf(struct spi_controller *ctlr, struct device *dev, ++ struct sg_table *sgt, void *buf, size_t len, + enum dma_data_direction dir) + { + return -EINVAL; + } + +-static inline void spi_unmap_buf(struct spi_master *master, ++static inline void spi_unmap_buf(struct spi_controller *ctlr, + struct device *dev, struct sg_table *sgt, + enum dma_data_direction dir) + { + } + +-static inline int __spi_map_msg(struct spi_master *master, ++static inline int __spi_map_msg(struct spi_controller *ctlr, + struct spi_message *msg) + { + return 0; + } + +-static inline int __spi_unmap_msg(struct spi_master *master, ++static inline int __spi_unmap_msg(struct spi_controller *ctlr, + struct spi_message *msg) + { + return 0; + } + #endif /* !CONFIG_HAS_DMA */ + +-static inline int spi_unmap_msg(struct spi_master *master, ++static inline int spi_unmap_msg(struct spi_controller *ctlr, + struct spi_message *msg) + { + struct spi_transfer *xfer; +@@ -899,63 +898,63 @@ static inline int spi_unmap_msg(struct spi_master *master, + * Restore the original value of tx_buf or rx_buf if they are + * NULL. + */ +- if (xfer->tx_buf == master->dummy_tx) ++ if (xfer->tx_buf == ctlr->dummy_tx) + xfer->tx_buf = NULL; +- if (xfer->rx_buf == master->dummy_rx) ++ if (xfer->rx_buf == ctlr->dummy_rx) + xfer->rx_buf = NULL; + } + +- return __spi_unmap_msg(master, msg); ++ return __spi_unmap_msg(ctlr, msg); + } + +-static int spi_map_msg(struct spi_master *master, struct spi_message *msg) ++static int spi_map_msg(struct spi_controller *ctlr, struct spi_message *msg) + { + struct spi_transfer *xfer; + void *tmp; + unsigned int max_tx, max_rx; + +- if (master->flags & (SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX)) { ++ if (ctlr->flags & (SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX)) { + max_tx = 0; + max_rx = 0; + + list_for_each_entry(xfer, &msg->transfers, transfer_list) { +- if ((master->flags & SPI_MASTER_MUST_TX) && ++ if ((ctlr->flags & SPI_CONTROLLER_MUST_TX) && + !xfer->tx_buf) + max_tx = max(xfer->len, max_tx); +- if ((master->flags & SPI_MASTER_MUST_RX) && ++ if ((ctlr->flags & SPI_CONTROLLER_MUST_RX) && + !xfer->rx_buf) + max_rx = max(xfer->len, max_rx); + } + + if (max_tx) { +- tmp = krealloc(master->dummy_tx, max_tx, ++ tmp = krealloc(ctlr->dummy_tx, max_tx, + GFP_KERNEL | GFP_DMA); + if (!tmp) + return -ENOMEM; +- master->dummy_tx = tmp; ++ ctlr->dummy_tx = tmp; + memset(tmp, 0, max_tx); + } + + if (max_rx) { +- tmp = krealloc(master->dummy_rx, max_rx, ++ tmp = krealloc(ctlr->dummy_rx, max_rx, + GFP_KERNEL | GFP_DMA); + if (!tmp) + return -ENOMEM; +- master->dummy_rx = tmp; ++ ctlr->dummy_rx = tmp; + } + + if (max_tx || max_rx) { + list_for_each_entry(xfer, &msg->transfers, + transfer_list) { + if (!xfer->tx_buf) +- xfer->tx_buf = master->dummy_tx; ++ xfer->tx_buf = ctlr->dummy_tx; + if (!xfer->rx_buf) +- xfer->rx_buf = master->dummy_rx; ++ xfer->rx_buf = ctlr->dummy_rx; + } + } + } + +- return __spi_map_msg(master, msg); ++ return __spi_map_msg(ctlr, msg); + } + + /* +@@ -965,14 +964,14 @@ static int spi_map_msg(struct spi_master *master, struct spi_message *msg) + * drivers which implement a transfer_one() operation. It provides + * standard handling of delays and chip select management. + */ +-static int spi_transfer_one_message(struct spi_master *master, ++static int spi_transfer_one_message(struct spi_controller *ctlr, + struct spi_message *msg) + { + struct spi_transfer *xfer; + bool keep_cs = false; + int ret = 0; + unsigned long long ms = 1; +- struct spi_statistics *statm = &master->statistics; ++ struct spi_statistics *statm = &ctlr->statistics; + struct spi_statistics *stats = &msg->spi->statistics; + + spi_set_cs(msg->spi, true); +@@ -983,13 +982,13 @@ static int spi_transfer_one_message(struct spi_master *master, + list_for_each_entry(xfer, &msg->transfers, transfer_list) { + trace_spi_transfer_start(msg, xfer); + +- spi_statistics_add_transfer_stats(statm, xfer, master); +- spi_statistics_add_transfer_stats(stats, xfer, master); ++ spi_statistics_add_transfer_stats(statm, xfer, ctlr); ++ spi_statistics_add_transfer_stats(stats, xfer, ctlr); + + if (xfer->tx_buf || xfer->rx_buf) { +- reinit_completion(&master->xfer_completion); ++ reinit_completion(&ctlr->xfer_completion); + +- ret = master->transfer_one(master, msg->spi, xfer); ++ ret = ctlr->transfer_one(ctlr, msg->spi, xfer); + if (ret < 0) { + SPI_STATISTICS_INCREMENT_FIELD(statm, + errors); +@@ -1009,7 +1008,7 @@ static int spi_transfer_one_message(struct spi_master *master, + if (ms > UINT_MAX) + ms = UINT_MAX; + +- ms = wait_for_completion_timeout(&master->xfer_completion, ++ ms = wait_for_completion_timeout(&ctlr->xfer_completion, + msecs_to_jiffies(ms)); + } + +@@ -1058,33 +1057,33 @@ static int spi_transfer_one_message(struct spi_master *master, + if (msg->status == -EINPROGRESS) + msg->status = ret; + +- if (msg->status && master->handle_err) +- master->handle_err(master, msg); ++ if (msg->status && ctlr->handle_err) ++ ctlr->handle_err(ctlr, msg); + +- spi_res_release(master, msg); ++ spi_res_release(ctlr, msg); + +- spi_finalize_current_message(master); ++ spi_finalize_current_message(ctlr); + + return ret; + } + + /** + * spi_finalize_current_transfer - report completion of a transfer +- * @master: the master reporting completion ++ * @ctlr: the controller reporting completion + * + * Called by SPI drivers using the core transfer_one_message() + * implementation to notify it that the current interrupt driven + * transfer has finished and the next one may be scheduled. + */ +-void spi_finalize_current_transfer(struct spi_master *master) ++void spi_finalize_current_transfer(struct spi_controller *ctlr) + { +- complete(&master->xfer_completion); ++ complete(&ctlr->xfer_completion); + } + EXPORT_SYMBOL_GPL(spi_finalize_current_transfer); + + /** + * __spi_pump_messages - function which processes spi message queue +- * @master: master to process queue for ++ * @ctlr: controller to process queue for + * @in_kthread: true if we are in the context of the message pump thread + * + * This function checks if there is any spi message in the queue that +@@ -1095,136 +1094,136 @@ void spi_finalize_current_transfer(struct spi_master *master) + * inside spi_sync(); the queue extraction handling at the top of the + * function should deal with this safely. + */ +-static void __spi_pump_messages(struct spi_master *master, bool in_kthread) ++static void __spi_pump_messages(struct spi_controller *ctlr, bool in_kthread) + { + unsigned long flags; + bool was_busy = false; + int ret; + + /* Lock queue */ +- spin_lock_irqsave(&master->queue_lock, flags); ++ spin_lock_irqsave(&ctlr->queue_lock, flags); + + /* Make sure we are not already running a message */ +- if (master->cur_msg) { +- spin_unlock_irqrestore(&master->queue_lock, flags); ++ if (ctlr->cur_msg) { ++ spin_unlock_irqrestore(&ctlr->queue_lock, flags); + return; + } + + /* If another context is idling the device then defer */ +- if (master->idling) { +- kthread_queue_work(&master->kworker, &master->pump_messages); +- spin_unlock_irqrestore(&master->queue_lock, flags); ++ if (ctlr->idling) { ++ kthread_queue_work(&ctlr->kworker, &ctlr->pump_messages); ++ spin_unlock_irqrestore(&ctlr->queue_lock, flags); + return; + } + + /* Check if the queue is idle */ +- if (list_empty(&master->queue) || !master->running) { +- if (!master->busy) { +- spin_unlock_irqrestore(&master->queue_lock, flags); ++ if (list_empty(&ctlr->queue) || !ctlr->running) { ++ if (!ctlr->busy) { ++ spin_unlock_irqrestore(&ctlr->queue_lock, flags); + return; + } + + /* Only do teardown in the thread */ + if (!in_kthread) { +- kthread_queue_work(&master->kworker, +- &master->pump_messages); +- spin_unlock_irqrestore(&master->queue_lock, flags); ++ kthread_queue_work(&ctlr->kworker, ++ &ctlr->pump_messages); ++ spin_unlock_irqrestore(&ctlr->queue_lock, flags); + return; + } + +- master->busy = false; +- master->idling = true; +- spin_unlock_irqrestore(&master->queue_lock, flags); +- +- kfree(master->dummy_rx); +- master->dummy_rx = NULL; +- kfree(master->dummy_tx); +- master->dummy_tx = NULL; +- if (master->unprepare_transfer_hardware && +- master->unprepare_transfer_hardware(master)) +- dev_err(&master->dev, ++ ctlr->busy = false; ++ ctlr->idling = true; ++ spin_unlock_irqrestore(&ctlr->queue_lock, flags); ++ ++ kfree(ctlr->dummy_rx); ++ ctlr->dummy_rx = NULL; ++ kfree(ctlr->dummy_tx); ++ ctlr->dummy_tx = NULL; ++ if (ctlr->unprepare_transfer_hardware && ++ ctlr->unprepare_transfer_hardware(ctlr)) ++ dev_err(&ctlr->dev, + "failed to unprepare transfer hardware\n"); +- if (master->auto_runtime_pm) { +- pm_runtime_mark_last_busy(master->dev.parent); +- pm_runtime_put_autosuspend(master->dev.parent); ++ if (ctlr->auto_runtime_pm) { ++ pm_runtime_mark_last_busy(ctlr->dev.parent); ++ pm_runtime_put_autosuspend(ctlr->dev.parent); + } +- trace_spi_master_idle(master); ++ trace_spi_controller_idle(ctlr); + +- spin_lock_irqsave(&master->queue_lock, flags); +- master->idling = false; +- spin_unlock_irqrestore(&master->queue_lock, flags); ++ spin_lock_irqsave(&ctlr->queue_lock, flags); ++ ctlr->idling = false; ++ spin_unlock_irqrestore(&ctlr->queue_lock, flags); + return; + } + + /* Extract head of queue */ +- master->cur_msg = +- list_first_entry(&master->queue, struct spi_message, queue); ++ ctlr->cur_msg = ++ list_first_entry(&ctlr->queue, struct spi_message, queue); + +- list_del_init(&master->cur_msg->queue); +- if (master->busy) ++ list_del_init(&ctlr->cur_msg->queue); ++ if (ctlr->busy) + was_busy = true; + else +- master->busy = true; +- spin_unlock_irqrestore(&master->queue_lock, flags); ++ ctlr->busy = true; ++ spin_unlock_irqrestore(&ctlr->queue_lock, flags); + +- mutex_lock(&master->io_mutex); ++ mutex_lock(&ctlr->io_mutex); + +- if (!was_busy && master->auto_runtime_pm) { +- ret = pm_runtime_get_sync(master->dev.parent); ++ if (!was_busy && ctlr->auto_runtime_pm) { ++ ret = pm_runtime_get_sync(ctlr->dev.parent); + if (ret < 0) { +- dev_err(&master->dev, "Failed to power device: %d\n", ++ dev_err(&ctlr->dev, "Failed to power device: %d\n", + ret); +- mutex_unlock(&master->io_mutex); ++ mutex_unlock(&ctlr->io_mutex); + return; + } + } + + if (!was_busy) +- trace_spi_master_busy(master); ++ trace_spi_controller_busy(ctlr); + +- if (!was_busy && master->prepare_transfer_hardware) { +- ret = master->prepare_transfer_hardware(master); ++ if (!was_busy && ctlr->prepare_transfer_hardware) { ++ ret = ctlr->prepare_transfer_hardware(ctlr); + if (ret) { +- dev_err(&master->dev, ++ dev_err(&ctlr->dev, + "failed to prepare transfer hardware\n"); + +- if (master->auto_runtime_pm) +- pm_runtime_put(master->dev.parent); +- mutex_unlock(&master->io_mutex); ++ if (ctlr->auto_runtime_pm) ++ pm_runtime_put(ctlr->dev.parent); ++ mutex_unlock(&ctlr->io_mutex); + return; + } + } + +- trace_spi_message_start(master->cur_msg); ++ trace_spi_message_start(ctlr->cur_msg); + +- if (master->prepare_message) { +- ret = master->prepare_message(master, master->cur_msg); ++ if (ctlr->prepare_message) { ++ ret = ctlr->prepare_message(ctlr, ctlr->cur_msg); + if (ret) { +- dev_err(&master->dev, +- "failed to prepare message: %d\n", ret); +- master->cur_msg->status = ret; +- spi_finalize_current_message(master); ++ dev_err(&ctlr->dev, "failed to prepare message: %d\n", ++ ret); ++ ctlr->cur_msg->status = ret; ++ spi_finalize_current_message(ctlr); + goto out; + } +- master->cur_msg_prepared = true; ++ ctlr->cur_msg_prepared = true; + } + +- ret = spi_map_msg(master, master->cur_msg); ++ ret = spi_map_msg(ctlr, ctlr->cur_msg); + if (ret) { +- master->cur_msg->status = ret; +- spi_finalize_current_message(master); ++ ctlr->cur_msg->status = ret; ++ spi_finalize_current_message(ctlr); + goto out; + } + +- ret = master->transfer_one_message(master, master->cur_msg); ++ ret = ctlr->transfer_one_message(ctlr, ctlr->cur_msg); + if (ret) { +- dev_err(&master->dev, ++ dev_err(&ctlr->dev, + "failed to transfer one message from queue\n"); + goto out; + } + + out: +- mutex_unlock(&master->io_mutex); ++ mutex_unlock(&ctlr->io_mutex); + + /* Prod the scheduler in case transfer_one() was busy waiting */ + if (!ret) +@@ -1233,44 +1232,43 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread) + + /** + * spi_pump_messages - kthread work function which processes spi message queue +- * @work: pointer to kthread work struct contained in the master struct ++ * @work: pointer to kthread work struct contained in the controller struct + */ + static void spi_pump_messages(struct kthread_work *work) + { +- struct spi_master *master = +- container_of(work, struct spi_master, pump_messages); ++ struct spi_controller *ctlr = ++ container_of(work, struct spi_controller, pump_messages); + +- __spi_pump_messages(master, true); ++ __spi_pump_messages(ctlr, true); + } + +-static int spi_init_queue(struct spi_master *master) ++static int spi_init_queue(struct spi_controller *ctlr) + { + struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 }; + +- master->running = false; +- master->busy = false; ++ ctlr->running = false; ++ ctlr->busy = false; + +- kthread_init_worker(&master->kworker); +- master->kworker_task = kthread_run(kthread_worker_fn, +- &master->kworker, "%s", +- dev_name(&master->dev)); +- if (IS_ERR(master->kworker_task)) { +- dev_err(&master->dev, "failed to create message pump task\n"); +- return PTR_ERR(master->kworker_task); ++ kthread_init_worker(&ctlr->kworker); ++ ctlr->kworker_task = kthread_run(kthread_worker_fn, &ctlr->kworker, ++ "%s", dev_name(&ctlr->dev)); ++ if (IS_ERR(ctlr->kworker_task)) { ++ dev_err(&ctlr->dev, "failed to create message pump task\n"); ++ return PTR_ERR(ctlr->kworker_task); + } +- kthread_init_work(&master->pump_messages, spi_pump_messages); ++ kthread_init_work(&ctlr->pump_messages, spi_pump_messages); + + /* +- * Master config will indicate if this controller should run the ++ * Controller config will indicate if this controller should run the + * message pump with high (realtime) priority to reduce the transfer + * latency on the bus by minimising the delay between a transfer + * request and the scheduling of the message pump thread. Without this + * setting the message pump thread will remain at default priority. + */ +- if (master->rt) { +- dev_info(&master->dev, ++ if (ctlr->rt) { ++ dev_info(&ctlr->dev, + "will run message pump with realtime priority\n"); +- sched_setscheduler(master->kworker_task, SCHED_FIFO, ¶m); ++ sched_setscheduler(ctlr->kworker_task, SCHED_FIFO, ¶m); + } + + return 0; +@@ -1279,23 +1277,23 @@ static int spi_init_queue(struct spi_master *master) + /** + * spi_get_next_queued_message() - called by driver to check for queued + * messages +- * @master: the master to check for queued messages ++ * @ctlr: the controller to check for queued messages + * + * If there are more messages in the queue, the next message is returned from + * this call. + * + * Return: the next message in the queue, else NULL if the queue is empty. + */ +-struct spi_message *spi_get_next_queued_message(struct spi_master *master) ++struct spi_message *spi_get_next_queued_message(struct spi_controller *ctlr) + { + struct spi_message *next; + unsigned long flags; + + /* get a pointer to the next message, if any */ +- spin_lock_irqsave(&master->queue_lock, flags); +- next = list_first_entry_or_null(&master->queue, struct spi_message, ++ spin_lock_irqsave(&ctlr->queue_lock, flags); ++ next = list_first_entry_or_null(&ctlr->queue, struct spi_message, + queue); +- spin_unlock_irqrestore(&master->queue_lock, flags); ++ spin_unlock_irqrestore(&ctlr->queue_lock, flags); + + return next; + } +@@ -1303,36 +1301,36 @@ struct spi_message *spi_get_next_queued_message(struct spi_master *master) + + /** + * spi_finalize_current_message() - the current message is complete +- * @master: the master to return the message to ++ * @ctlr: the controller to return the message to + * + * Called by the driver to notify the core that the message in the front of the + * queue is complete and can be removed from the queue. + */ +-void spi_finalize_current_message(struct spi_master *master) ++void spi_finalize_current_message(struct spi_controller *ctlr) + { + struct spi_message *mesg; + unsigned long flags; + int ret; + +- spin_lock_irqsave(&master->queue_lock, flags); +- mesg = master->cur_msg; +- spin_unlock_irqrestore(&master->queue_lock, flags); ++ spin_lock_irqsave(&ctlr->queue_lock, flags); ++ mesg = ctlr->cur_msg; ++ spin_unlock_irqrestore(&ctlr->queue_lock, flags); + +- spi_unmap_msg(master, mesg); ++ spi_unmap_msg(ctlr, mesg); + +- if (master->cur_msg_prepared && master->unprepare_message) { +- ret = master->unprepare_message(master, mesg); ++ if (ctlr->cur_msg_prepared && ctlr->unprepare_message) { ++ ret = ctlr->unprepare_message(ctlr, mesg); + if (ret) { +- dev_err(&master->dev, +- "failed to unprepare message: %d\n", ret); ++ dev_err(&ctlr->dev, "failed to unprepare message: %d\n", ++ ret); + } + } + +- spin_lock_irqsave(&master->queue_lock, flags); +- master->cur_msg = NULL; +- master->cur_msg_prepared = false; +- kthread_queue_work(&master->kworker, &master->pump_messages); +- spin_unlock_irqrestore(&master->queue_lock, flags); ++ spin_lock_irqsave(&ctlr->queue_lock, flags); ++ ctlr->cur_msg = NULL; ++ ctlr->cur_msg_prepared = false; ++ kthread_queue_work(&ctlr->kworker, &ctlr->pump_messages); ++ spin_unlock_irqrestore(&ctlr->queue_lock, flags); + + trace_spi_message_done(mesg); + +@@ -1342,66 +1340,65 @@ void spi_finalize_current_message(struct spi_master *master) + } + EXPORT_SYMBOL_GPL(spi_finalize_current_message); + +-static int spi_start_queue(struct spi_master *master) ++static int spi_start_queue(struct spi_controller *ctlr) + { + unsigned long flags; + +- spin_lock_irqsave(&master->queue_lock, flags); ++ spin_lock_irqsave(&ctlr->queue_lock, flags); + +- if (master->running || master->busy) { +- spin_unlock_irqrestore(&master->queue_lock, flags); ++ if (ctlr->running || ctlr->busy) { ++ spin_unlock_irqrestore(&ctlr->queue_lock, flags); + return -EBUSY; + } + +- master->running = true; +- master->cur_msg = NULL; +- spin_unlock_irqrestore(&master->queue_lock, flags); ++ ctlr->running = true; ++ ctlr->cur_msg = NULL; ++ spin_unlock_irqrestore(&ctlr->queue_lock, flags); + +- kthread_queue_work(&master->kworker, &master->pump_messages); ++ kthread_queue_work(&ctlr->kworker, &ctlr->pump_messages); + + return 0; + } + +-static int spi_stop_queue(struct spi_master *master) ++static int spi_stop_queue(struct spi_controller *ctlr) + { + unsigned long flags; + unsigned limit = 500; + int ret = 0; + +- spin_lock_irqsave(&master->queue_lock, flags); ++ spin_lock_irqsave(&ctlr->queue_lock, flags); + + /* + * This is a bit lame, but is optimized for the common execution path. +- * A wait_queue on the master->busy could be used, but then the common ++ * A wait_queue on the ctlr->busy could be used, but then the common + * execution path (pump_messages) would be required to call wake_up or + * friends on every SPI message. Do this instead. + */ +- while ((!list_empty(&master->queue) || master->busy) && limit--) { +- spin_unlock_irqrestore(&master->queue_lock, flags); ++ while ((!list_empty(&ctlr->queue) || ctlr->busy) && limit--) { ++ spin_unlock_irqrestore(&ctlr->queue_lock, flags); + usleep_range(10000, 11000); +- spin_lock_irqsave(&master->queue_lock, flags); ++ spin_lock_irqsave(&ctlr->queue_lock, flags); + } + +- if (!list_empty(&master->queue) || master->busy) ++ if (!list_empty(&ctlr->queue) || ctlr->busy) + ret = -EBUSY; + else +- master->running = false; ++ ctlr->running = false; + +- spin_unlock_irqrestore(&master->queue_lock, flags); ++ spin_unlock_irqrestore(&ctlr->queue_lock, flags); + + if (ret) { +- dev_warn(&master->dev, +- "could not stop message queue\n"); ++ dev_warn(&ctlr->dev, "could not stop message queue\n"); + return ret; + } + return ret; + } + +-static int spi_destroy_queue(struct spi_master *master) ++static int spi_destroy_queue(struct spi_controller *ctlr) + { + int ret; + +- ret = spi_stop_queue(master); ++ ret = spi_stop_queue(ctlr); + + /* + * kthread_flush_worker will block until all work is done. +@@ -1410,12 +1407,12 @@ static int spi_destroy_queue(struct spi_master *master) + * return anyway. + */ + if (ret) { +- dev_err(&master->dev, "problem destroying queue\n"); ++ dev_err(&ctlr->dev, "problem destroying queue\n"); + return ret; + } + +- kthread_flush_worker(&master->kworker); +- kthread_stop(master->kworker_task); ++ kthread_flush_worker(&ctlr->kworker); ++ kthread_stop(ctlr->kworker_task); + + return 0; + } +@@ -1424,23 +1421,23 @@ static int __spi_queued_transfer(struct spi_device *spi, + struct spi_message *msg, + bool need_pump) + { +- struct spi_master *master = spi->master; ++ struct spi_controller *ctlr = spi->controller; + unsigned long flags; + +- spin_lock_irqsave(&master->queue_lock, flags); ++ spin_lock_irqsave(&ctlr->queue_lock, flags); + +- if (!master->running) { +- spin_unlock_irqrestore(&master->queue_lock, flags); ++ if (!ctlr->running) { ++ spin_unlock_irqrestore(&ctlr->queue_lock, flags); + return -ESHUTDOWN; + } + msg->actual_length = 0; + msg->status = -EINPROGRESS; + +- list_add_tail(&msg->queue, &master->queue); +- if (!master->busy && need_pump) +- kthread_queue_work(&master->kworker, &master->pump_messages); ++ list_add_tail(&msg->queue, &ctlr->queue); ++ if (!ctlr->busy && need_pump) ++ kthread_queue_work(&ctlr->kworker, &ctlr->pump_messages); + +- spin_unlock_irqrestore(&master->queue_lock, flags); ++ spin_unlock_irqrestore(&ctlr->queue_lock, flags); + return 0; + } + +@@ -1456,31 +1453,31 @@ static int spi_queued_transfer(struct spi_device *spi, struct spi_message *msg) + return __spi_queued_transfer(spi, msg, true); + } + +-static int spi_master_initialize_queue(struct spi_master *master) ++static int spi_controller_initialize_queue(struct spi_controller *ctlr) + { + int ret; + +- master->transfer = spi_queued_transfer; +- if (!master->transfer_one_message) +- master->transfer_one_message = spi_transfer_one_message; ++ ctlr->transfer = spi_queued_transfer; ++ if (!ctlr->transfer_one_message) ++ ctlr->transfer_one_message = spi_transfer_one_message; + + /* Initialize and start queue */ +- ret = spi_init_queue(master); ++ ret = spi_init_queue(ctlr); + if (ret) { +- dev_err(&master->dev, "problem initializing queue\n"); ++ dev_err(&ctlr->dev, "problem initializing queue\n"); + goto err_init_queue; + } +- master->queued = true; +- ret = spi_start_queue(master); ++ ctlr->queued = true; ++ ret = spi_start_queue(ctlr); + if (ret) { +- dev_err(&master->dev, "problem starting queue\n"); ++ dev_err(&ctlr->dev, "problem starting queue\n"); + goto err_start_queue; + } + + return 0; + + err_start_queue: +- spi_destroy_queue(master); ++ spi_destroy_queue(ctlr); + err_init_queue: + return ret; + } +@@ -1489,16 +1486,16 @@ static int spi_master_initialize_queue(struct spi_master *master) + + #if defined(CONFIG_OF) + static struct spi_device * +-of_register_spi_device(struct spi_master *master, struct device_node *nc) ++of_register_spi_device(struct spi_controller *ctlr, struct device_node *nc) + { + struct spi_device *spi; + int rc; + u32 value; + + /* Alloc an spi_device */ +- spi = spi_alloc_device(master); ++ spi = spi_alloc_device(ctlr); + if (!spi) { +- dev_err(&master->dev, "spi_device alloc error for %s\n", ++ dev_err(&ctlr->dev, "spi_device alloc error for %s\n", + nc->full_name); + rc = -ENOMEM; + goto err_out; +@@ -1508,7 +1505,7 @@ static int spi_master_initialize_queue(struct spi_master *master) + rc = of_modalias_node(nc, spi->modalias, + sizeof(spi->modalias)); + if (rc < 0) { +- dev_err(&master->dev, "cannot find modalias for %s\n", ++ dev_err(&ctlr->dev, "cannot find modalias for %s\n", + nc->full_name); + goto err_out; + } +@@ -1537,7 +1534,7 @@ static int spi_master_initialize_queue(struct spi_master *master) + spi->mode |= SPI_TX_QUAD; + break; + default: +- dev_warn(&master->dev, ++ dev_warn(&ctlr->dev, + "spi-tx-bus-width %d not supported\n", + value); + break; +@@ -1555,35 +1552,36 @@ static int spi_master_initialize_queue(struct spi_master *master) + spi->mode |= SPI_RX_QUAD; + break; + default: +- dev_warn(&master->dev, ++ dev_warn(&ctlr->dev, + "spi-rx-bus-width %d not supported\n", + value); + break; + } + } + +- if (spi_controller_is_slave(master)) { ++ if (spi_controller_is_slave(ctlr)) { + if (strcmp(nc->name, "slave")) { +- dev_err(&master->dev, "%s is not called 'slave'\n", ++ dev_err(&ctlr->dev, "%s is not called 'slave'\n", + nc->full_name); +- return -EINVAL; ++ rc = -EINVAL; ++ goto err_out; + } +- return 0; + } + + /* Device address */ + rc = of_property_read_u32(nc, "reg", &value); + if (rc) { +- dev_err(&master->dev, "%s has no valid 'reg' property (%d)\n", ++ dev_err(&ctlr->dev, "%s has no valid 'reg' property (%d)\n", + nc->full_name, rc); +- return rc; ++ goto err_out; + } + spi->chip_select = value; + + /* Device speed */ + rc = of_property_read_u32(nc, "spi-max-frequency", &value); + if (rc) { +- dev_err(&master->dev, "%s has no valid 'spi-max-frequency' property (%d)\n", ++ dev_err(&ctlr->dev, ++ "%s has no valid 'spi-max-frequency' property (%d)\n", + nc->full_name, rc); + goto err_out; + } +@@ -1596,7 +1594,7 @@ static int spi_master_initialize_queue(struct spi_master *master) + /* Register the new device */ + rc = spi_add_device(spi); + if (rc) { +- dev_err(&master->dev, "spi_device register error %s\n", ++ dev_err(&ctlr->dev, "spi_device register error %s\n", + nc->full_name); + goto err_out; + } +@@ -1610,39 +1608,40 @@ static int spi_master_initialize_queue(struct spi_master *master) + + /** + * of_register_spi_devices() - Register child devices onto the SPI bus +- * @master: Pointer to spi_master device ++ * @ctlr: Pointer to spi_controller device + * + * Registers an spi_device for each child node of controller node which + * represents a valid SPI slave. + */ +-static void of_register_spi_devices(struct spi_master *master) ++static void of_register_spi_devices(struct spi_controller *ctlr) + { + struct spi_device *spi; + struct device_node *nc; + +- if (!master->dev.of_node) ++ if (!ctlr->dev.of_node) + return; + +- for_each_available_child_of_node(master->dev.of_node, nc) { ++ for_each_available_child_of_node(ctlr->dev.of_node, nc) { + if (of_node_test_and_set_flag(nc, OF_POPULATED)) + continue; +- spi = of_register_spi_device(master, nc); ++ spi = of_register_spi_device(ctlr, nc); + if (IS_ERR(spi)) { +- dev_warn(&master->dev, "Failed to create SPI device for %s\n", +- nc->full_name); ++ dev_warn(&ctlr->dev, ++ "Failed to create SPI device for %s\n", ++ nc->full_name); + of_node_clear_flag(nc, OF_POPULATED); + } + } + } + #else +-static void of_register_spi_devices(struct spi_master *master) { } ++static void of_register_spi_devices(struct spi_controller *ctlr) { } + #endif + + #ifdef CONFIG_ACPI + static int acpi_spi_add_resource(struct acpi_resource *ares, void *data) + { + struct spi_device *spi = data; +- struct spi_master *master = spi->master; ++ struct spi_controller *ctlr = spi->controller; + + if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) { + struct acpi_resource_spi_serialbus *sb; +@@ -1656,8 +1655,8 @@ static int acpi_spi_add_resource(struct acpi_resource *ares, void *data) + * 0 .. max - 1 so we need to ask the driver to + * translate between the two schemes. + */ +- if (master->fw_translate_cs) { +- int cs = master->fw_translate_cs(master, ++ if (ctlr->fw_translate_cs) { ++ int cs = ctlr->fw_translate_cs(ctlr, + sb->device_selection); + if (cs < 0) + return cs; +@@ -1686,7 +1685,7 @@ static int acpi_spi_add_resource(struct acpi_resource *ares, void *data) + return 1; + } + +-static acpi_status acpi_register_spi_device(struct spi_master *master, ++static acpi_status acpi_register_spi_device(struct spi_controller *ctlr, + struct acpi_device *adev) + { + struct list_head resource_list; +@@ -1697,9 +1696,9 @@ static acpi_status acpi_register_spi_device(struct spi_master *master, + acpi_device_enumerated(adev)) + return AE_OK; + +- spi = spi_alloc_device(master); ++ spi = spi_alloc_device(ctlr); + if (!spi) { +- dev_err(&master->dev, "failed to allocate SPI device for %s\n", ++ dev_err(&ctlr->dev, "failed to allocate SPI device for %s\n", + dev_name(&adev->dev)); + return AE_NO_MEMORY; + } +@@ -1726,7 +1725,7 @@ static acpi_status acpi_register_spi_device(struct spi_master *master, + strlcpy(spi->modalias, acpi_device_hid(adev), sizeof(spi->modalias)); + if (spi_add_device(spi)) { + adev->power.flags.ignore_parent = false; +- dev_err(&master->dev, "failed to add SPI device %s from ACPI\n", ++ dev_err(&ctlr->dev, "failed to add SPI device %s from ACPI\n", + dev_name(&adev->dev)); + spi_dev_put(spi); + } +@@ -1737,46 +1736,45 @@ static acpi_status acpi_register_spi_device(struct spi_master *master, + static acpi_status acpi_spi_add_device(acpi_handle handle, u32 level, + void *data, void **return_value) + { +- struct spi_master *master = data; ++ struct spi_controller *ctlr = data; + struct acpi_device *adev; + + if (acpi_bus_get_device(handle, &adev)) + return AE_OK; + +- return acpi_register_spi_device(master, adev); ++ return acpi_register_spi_device(ctlr, adev); + } + +-static void acpi_register_spi_devices(struct spi_master *master) ++static void acpi_register_spi_devices(struct spi_controller *ctlr) + { + acpi_status status; + acpi_handle handle; + +- handle = ACPI_HANDLE(master->dev.parent); ++ handle = ACPI_HANDLE(ctlr->dev.parent); + if (!handle) + return; + + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, +- acpi_spi_add_device, NULL, +- master, NULL); ++ acpi_spi_add_device, NULL, ctlr, NULL); + if (ACPI_FAILURE(status)) +- dev_warn(&master->dev, "failed to enumerate SPI slaves\n"); ++ dev_warn(&ctlr->dev, "failed to enumerate SPI slaves\n"); + } + #else +-static inline void acpi_register_spi_devices(struct spi_master *master) {} ++static inline void acpi_register_spi_devices(struct spi_controller *ctlr) {} + #endif /* CONFIG_ACPI */ + +-static void spi_master_release(struct device *dev) ++static void spi_controller_release(struct device *dev) + { +- struct spi_master *master; ++ struct spi_controller *ctlr; + +- master = container_of(dev, struct spi_master, dev); +- kfree(master); ++ ctlr = container_of(dev, struct spi_controller, dev); ++ kfree(ctlr); + } + + static struct class spi_master_class = { + .name = "spi_master", + .owner = THIS_MODULE, +- .dev_release = spi_master_release, ++ .dev_release = spi_controller_release, + .dev_groups = spi_master_groups, + }; + +@@ -1788,10 +1786,10 @@ static void spi_master_release(struct device *dev) + */ + int spi_slave_abort(struct spi_device *spi) + { +- struct spi_master *master = spi->master; ++ struct spi_controller *ctlr = spi->controller; + +- if (spi_controller_is_slave(master) && master->slave_abort) +- return master->slave_abort(master); ++ if (spi_controller_is_slave(ctlr) && ctlr->slave_abort) ++ return ctlr->slave_abort(ctlr); + + return -ENOTSUPP; + } +@@ -1805,7 +1803,8 @@ static int match_true(struct device *dev, void *data) + static ssize_t spi_slave_show(struct device *dev, + struct device_attribute *attr, char *buf) + { +- struct spi_master *ctlr = container_of(dev, struct spi_master, dev); ++ struct spi_controller *ctlr = container_of(dev, struct spi_controller, ++ dev); + struct device *child; + + child = device_find_child(&ctlr->dev, NULL, match_true); +@@ -1817,7 +1816,8 @@ static ssize_t spi_slave_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) + { +- struct spi_master *ctlr = container_of(dev, struct spi_master, dev); ++ struct spi_controller *ctlr = container_of(dev, struct spi_controller, ++ dev); + struct spi_device *spi; + struct device *child; + char name[32]; +@@ -1864,7 +1864,7 @@ static ssize_t spi_slave_store(struct device *dev, + }; + + static const struct attribute_group *spi_slave_groups[] = { +- &spi_master_statistics_group, ++ &spi_controller_statistics_group, + &spi_slave_group, + NULL, + }; +@@ -1872,7 +1872,7 @@ static ssize_t spi_slave_store(struct device *dev, + static struct class spi_slave_class = { + .name = "spi_slave", + .owner = THIS_MODULE, +- .dev_release = spi_master_release, ++ .dev_release = spi_controller_release, + .dev_groups = spi_slave_groups, + }; + #else +@@ -1884,62 +1884,63 @@ static ssize_t spi_slave_store(struct device *dev, + * @dev: the controller, possibly using the platform_bus + * @size: how much zeroed driver-private data to allocate; the pointer to this + * memory is in the driver_data field of the returned device, +- * accessible with spi_master_get_devdata(). ++ * accessible with spi_controller_get_devdata(). + * @slave: flag indicating whether to allocate an SPI master (false) or SPI + * slave (true) controller + * Context: can sleep + * + * This call is used only by SPI controller drivers, which are the + * only ones directly touching chip registers. It's how they allocate +- * an spi_master structure, prior to calling spi_register_master(). ++ * an spi_controller structure, prior to calling spi_register_controller(). + * + * This must be called from context that can sleep. + * + * The caller is responsible for assigning the bus number and initializing the +- * controller's methods before calling spi_register_master(); and (after errors +- * adding the device) calling spi_master_put() to prevent a memory leak. ++ * controller's methods before calling spi_register_controller(); and (after ++ * errors adding the device) calling spi_controller_put() to prevent a memory ++ * leak. + * + * Return: the SPI controller structure on success, else NULL. + */ +-struct spi_master *__spi_alloc_controller(struct device *dev, +- unsigned int size, bool slave) ++struct spi_controller *__spi_alloc_controller(struct device *dev, ++ unsigned int size, bool slave) + { +- struct spi_master *master; ++ struct spi_controller *ctlr; + + if (!dev) + return NULL; + +- master = kzalloc(size + sizeof(*master), GFP_KERNEL); +- if (!master) ++ ctlr = kzalloc(size + sizeof(*ctlr), GFP_KERNEL); ++ if (!ctlr) + return NULL; + +- device_initialize(&master->dev); +- master->bus_num = -1; +- master->num_chipselect = 1; +- master->slave = slave; ++ device_initialize(&ctlr->dev); ++ ctlr->bus_num = -1; ++ ctlr->num_chipselect = 1; ++ ctlr->slave = slave; + if (IS_ENABLED(CONFIG_SPI_SLAVE) && slave) +- master->dev.class = &spi_slave_class; ++ ctlr->dev.class = &spi_slave_class; + else +- master->dev.class = &spi_master_class; +- master->dev.parent = dev; +- pm_suspend_ignore_children(&master->dev, true); +- spi_master_set_devdata(master, &master[1]); ++ ctlr->dev.class = &spi_master_class; ++ ctlr->dev.parent = dev; ++ pm_suspend_ignore_children(&ctlr->dev, true); ++ spi_controller_set_devdata(ctlr, &ctlr[1]); + +- return master; ++ return ctlr; + } + EXPORT_SYMBOL_GPL(__spi_alloc_controller); + + #ifdef CONFIG_OF +-static int of_spi_register_master(struct spi_master *master) ++static int of_spi_register_master(struct spi_controller *ctlr) + { + int nb, i, *cs; +- struct device_node *np = master->dev.of_node; ++ struct device_node *np = ctlr->dev.of_node; + + if (!np) + return 0; + + nb = of_gpio_named_count(np, "cs-gpios"); +- master->num_chipselect = max_t(int, nb, master->num_chipselect); ++ ctlr->num_chipselect = max_t(int, nb, ctlr->num_chipselect); + + /* Return error only for an incorrectly formed cs-gpios property */ + if (nb == 0 || nb == -ENOENT) +@@ -1947,15 +1948,14 @@ static int of_spi_register_master(struct spi_master *master) + else if (nb < 0) + return nb; + +- cs = devm_kzalloc(&master->dev, +- sizeof(int) * master->num_chipselect, ++ cs = devm_kzalloc(&ctlr->dev, sizeof(int) * ctlr->num_chipselect, + GFP_KERNEL); +- master->cs_gpios = cs; ++ ctlr->cs_gpios = cs; + +- if (!master->cs_gpios) ++ if (!ctlr->cs_gpios) + return -ENOMEM; + +- for (i = 0; i < master->num_chipselect; i++) ++ for (i = 0; i < ctlr->num_chipselect; i++) + cs[i] = -ENOENT; + + for (i = 0; i < nb; i++) +@@ -1964,20 +1964,21 @@ static int of_spi_register_master(struct spi_master *master) + return 0; + } + #else +-static int of_spi_register_master(struct spi_master *master) ++static int of_spi_register_master(struct spi_controller *ctlr) + { + return 0; + } + #endif + + /** +- * spi_register_master - register SPI master controller +- * @master: initialized master, originally from spi_alloc_master() ++ * spi_register_controller - register SPI master or slave controller ++ * @ctlr: initialized master, originally from spi_alloc_master() or ++ * spi_alloc_slave() + * Context: can sleep + * +- * SPI master controllers connect to their drivers using some non-SPI bus, ++ * SPI controllers connect to their drivers using some non-SPI bus, + * such as the platform bus. The final stage of probe() in that code +- * includes calling spi_register_master() to hook up to this SPI bus glue. ++ * includes calling spi_register_controller() to hook up to this SPI bus glue. + * + * SPI controllers use board specific (often SOC specific) bus numbers, + * and board-specific addressing for SPI devices combines those numbers +@@ -1986,16 +1987,16 @@ static int of_spi_register_master(struct spi_master *master) + * chip is at which address. + * + * This must be called from context that can sleep. It returns zero on +- * success, else a negative error code (dropping the master's refcount). ++ * success, else a negative error code (dropping the controller's refcount). + * After a successful return, the caller is responsible for calling +- * spi_unregister_master(). ++ * spi_unregister_controller(). + * + * Return: zero on success, else a negative error code. + */ +-int spi_register_master(struct spi_master *master) ++int spi_register_controller(struct spi_controller *ctlr) + { + static atomic_t dyn_bus_id = ATOMIC_INIT((1<<15) - 1); +- struct device *dev = master->dev.parent; ++ struct device *dev = ctlr->dev.parent; + struct boardinfo *bi; + int status = -ENODEV; + int dynamic = 0; +@@ -2003,8 +2004,8 @@ int spi_register_master(struct spi_master *master) + if (!dev) + return -ENODEV; + +- if (!spi_controller_is_slave(master)) { +- status = of_spi_register_master(master); ++ if (!spi_controller_is_slave(ctlr)) { ++ status = of_spi_register_master(ctlr); + if (status) + return status; + } +@@ -2012,97 +2013,100 @@ int spi_register_master(struct spi_master *master) + /* even if it's just one always-selected device, there must + * be at least one chipselect + */ +- if (master->num_chipselect == 0) ++ if (ctlr->num_chipselect == 0) + return -EINVAL; + +- if ((master->bus_num < 0) && master->dev.of_node) +- master->bus_num = of_alias_get_id(master->dev.of_node, "spi"); ++ if ((ctlr->bus_num < 0) && ctlr->dev.of_node) ++ ctlr->bus_num = of_alias_get_id(ctlr->dev.of_node, "spi"); + + /* convention: dynamically assigned bus IDs count down from the max */ +- if (master->bus_num < 0) { ++ if (ctlr->bus_num < 0) { + /* FIXME switch to an IDR based scheme, something like + * I2C now uses, so we can't run out of "dynamic" IDs + */ +- master->bus_num = atomic_dec_return(&dyn_bus_id); ++ ctlr->bus_num = atomic_dec_return(&dyn_bus_id); + dynamic = 1; + } + +- INIT_LIST_HEAD(&master->queue); +- spin_lock_init(&master->queue_lock); +- spin_lock_init(&master->bus_lock_spinlock); +- mutex_init(&master->bus_lock_mutex); +- mutex_init(&master->io_mutex); +- master->bus_lock_flag = 0; +- init_completion(&master->xfer_completion); +- if (!master->max_dma_len) +- master->max_dma_len = INT_MAX; ++ INIT_LIST_HEAD(&ctlr->queue); ++ spin_lock_init(&ctlr->queue_lock); ++ spin_lock_init(&ctlr->bus_lock_spinlock); ++ mutex_init(&ctlr->bus_lock_mutex); ++ mutex_init(&ctlr->io_mutex); ++ ctlr->bus_lock_flag = 0; ++ init_completion(&ctlr->xfer_completion); ++ if (!ctlr->max_dma_len) ++ ctlr->max_dma_len = INT_MAX; + + /* register the device, then userspace will see it. + * registration fails if the bus ID is in use. + */ +- dev_set_name(&master->dev, "spi%u", master->bus_num); +- status = device_add(&master->dev); ++ dev_set_name(&ctlr->dev, "spi%u", ctlr->bus_num); ++ status = device_add(&ctlr->dev); + if (status < 0) + goto done; + dev_dbg(dev, "registered %s %s%s\n", +- spi_controller_is_slave(master) ? "slave" : "master", +- dev_name(&master->dev), dynamic ? " (dynamic)" : ""); ++ spi_controller_is_slave(ctlr) ? "slave" : "master", ++ dev_name(&ctlr->dev), dynamic ? " (dynamic)" : ""); + + /* If we're using a queued driver, start the queue */ +- if (master->transfer) ++ if (ctlr->transfer) + dev_info(dev, "master is unqueued, this is deprecated\n"); + else { +- status = spi_master_initialize_queue(master); ++ status = spi_controller_initialize_queue(ctlr); + if (status) { +- device_del(&master->dev); ++ device_del(&ctlr->dev); + goto done; + } + } + /* add statistics */ +- spin_lock_init(&master->statistics.lock); ++ spin_lock_init(&ctlr->statistics.lock); + + mutex_lock(&board_lock); +- list_add_tail(&master->list, &spi_master_list); ++ list_add_tail(&ctlr->list, &spi_controller_list); + list_for_each_entry(bi, &board_list, list) +- spi_match_master_to_boardinfo(master, &bi->board_info); ++ spi_match_controller_to_boardinfo(ctlr, &bi->board_info); + mutex_unlock(&board_lock); + + /* Register devices from the device tree and ACPI */ +- of_register_spi_devices(master); +- acpi_register_spi_devices(master); ++ of_register_spi_devices(ctlr); ++ acpi_register_spi_devices(ctlr); + done: + return status; + } +-EXPORT_SYMBOL_GPL(spi_register_master); ++EXPORT_SYMBOL_GPL(spi_register_controller); + + static void devm_spi_unregister(struct device *dev, void *res) + { +- spi_unregister_master(*(struct spi_master **)res); ++ spi_unregister_controller(*(struct spi_master **)res); + } + + /** +- * dev_spi_register_master - register managed SPI master controller +- * @dev: device managing SPI master +- * @master: initialized master, originally from spi_alloc_master() ++ * devm_spi_register_controller - register managed SPI master or slave ++ * controller ++ * @dev: device managing SPI controller ++ * @ctlr: initialized controller, originally from spi_alloc_master() or ++ * spi_alloc_slave() + * Context: can sleep + * +- * Register a SPI device as with spi_register_master() which will ++ * Register a SPI device as with spi_register_controller() which will + * automatically be unregister + * + * Return: zero on success, else a negative error code. + */ +-int devm_spi_register_master(struct device *dev, struct spi_master *master) ++int devm_spi_register_controller(struct device *dev, ++ struct spi_controller *ctlr) + { +- struct spi_master **ptr; ++ struct spi_controller **ptr; + int ret; + + ptr = devres_alloc(devm_spi_unregister, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return -ENOMEM; + +- ret = spi_register_master(master); ++ ret = spi_register_controller(ctlr); + if (!ret) { +- *ptr = master; ++ *ptr = ctlr; + devres_add(dev, ptr); + } else { + devres_free(ptr); +@@ -2110,7 +2114,7 @@ int devm_spi_register_master(struct device *dev, struct spi_master *master) + + return ret; + } +-EXPORT_SYMBOL_GPL(devm_spi_register_master); ++EXPORT_SYMBOL_GPL(devm_spi_register_controller); + + static int __unregister(struct device *dev, void *null) + { +@@ -2119,71 +2123,71 @@ static int __unregister(struct device *dev, void *null) + } + + /** +- * spi_unregister_master - unregister SPI master controller +- * @master: the master being unregistered ++ * spi_unregister_controller - unregister SPI master or slave controller ++ * @ctlr: the controller being unregistered + * Context: can sleep + * +- * This call is used only by SPI master controller drivers, which are the ++ * This call is used only by SPI controller drivers, which are the + * only ones directly touching chip registers. + * + * This must be called from context that can sleep. + */ +-void spi_unregister_master(struct spi_master *master) ++void spi_unregister_controller(struct spi_controller *ctlr) + { + int dummy; + +- if (master->queued) { +- if (spi_destroy_queue(master)) +- dev_err(&master->dev, "queue remove failed\n"); ++ if (ctlr->queued) { ++ if (spi_destroy_queue(ctlr)) ++ dev_err(&ctlr->dev, "queue remove failed\n"); + } + + mutex_lock(&board_lock); +- list_del(&master->list); ++ list_del(&ctlr->list); + mutex_unlock(&board_lock); + +- dummy = device_for_each_child(&master->dev, NULL, __unregister); +- device_unregister(&master->dev); ++ dummy = device_for_each_child(&ctlr->dev, NULL, __unregister); ++ device_unregister(&ctlr->dev); + } +-EXPORT_SYMBOL_GPL(spi_unregister_master); ++EXPORT_SYMBOL_GPL(spi_unregister_controller); + +-int spi_master_suspend(struct spi_master *master) ++int spi_controller_suspend(struct spi_controller *ctlr) + { + int ret; + +- /* Basically no-ops for non-queued masters */ +- if (!master->queued) ++ /* Basically no-ops for non-queued controllers */ ++ if (!ctlr->queued) + return 0; + +- ret = spi_stop_queue(master); ++ ret = spi_stop_queue(ctlr); + if (ret) +- dev_err(&master->dev, "queue stop failed\n"); ++ dev_err(&ctlr->dev, "queue stop failed\n"); + + return ret; + } +-EXPORT_SYMBOL_GPL(spi_master_suspend); ++EXPORT_SYMBOL_GPL(spi_controller_suspend); + +-int spi_master_resume(struct spi_master *master) ++int spi_controller_resume(struct spi_controller *ctlr) + { + int ret; + +- if (!master->queued) ++ if (!ctlr->queued) + return 0; + +- ret = spi_start_queue(master); ++ ret = spi_start_queue(ctlr); + if (ret) +- dev_err(&master->dev, "queue restart failed\n"); ++ dev_err(&ctlr->dev, "queue restart failed\n"); + + return ret; + } +-EXPORT_SYMBOL_GPL(spi_master_resume); ++EXPORT_SYMBOL_GPL(spi_controller_resume); + +-static int __spi_master_match(struct device *dev, const void *data) ++static int __spi_controller_match(struct device *dev, const void *data) + { +- struct spi_master *m; ++ struct spi_controller *ctlr; + const u16 *bus_num = data; + +- m = container_of(dev, struct spi_master, dev); +- return m->bus_num == *bus_num; ++ ctlr = container_of(dev, struct spi_controller, dev); ++ return ctlr->bus_num == *bus_num; + } + + /** +@@ -2193,22 +2197,22 @@ static int __spi_master_match(struct device *dev, const void *data) + * + * This call may be used with devices that are registered after + * arch init time. It returns a refcounted pointer to the relevant +- * spi_master (which the caller must release), or NULL if there is ++ * spi_controller (which the caller must release), or NULL if there is + * no such master registered. + * + * Return: the SPI master structure on success, else NULL. + */ +-struct spi_master *spi_busnum_to_master(u16 bus_num) ++struct spi_controller *spi_busnum_to_master(u16 bus_num) + { + struct device *dev; +- struct spi_master *master = NULL; ++ struct spi_controller *ctlr = NULL; + + dev = class_find_device(&spi_master_class, NULL, &bus_num, +- __spi_master_match); ++ __spi_controller_match); + if (dev) +- master = container_of(dev, struct spi_master, dev); ++ ctlr = container_of(dev, struct spi_controller, dev); + /* reference got in class_find_device */ +- return master; ++ return ctlr; + } + EXPORT_SYMBOL_GPL(spi_busnum_to_master); + +@@ -2228,7 +2232,7 @@ struct spi_master *spi_busnum_to_master(u16 bus_num) + * Return: the pointer to the allocated data + * + * This may get enhanced in the future to allocate from a memory pool +- * of the @spi_device or @spi_master to avoid repeated allocations. ++ * of the @spi_device or @spi_controller to avoid repeated allocations. + */ + void *spi_res_alloc(struct spi_device *spi, + spi_res_release_t release, +@@ -2280,11 +2284,10 @@ void spi_res_add(struct spi_message *message, void *res) + + /** + * spi_res_release - release all spi resources for this message +- * @master: the @spi_master ++ * @ctlr: the @spi_controller + * @message: the @spi_message + */ +-void spi_res_release(struct spi_master *master, +- struct spi_message *message) ++void spi_res_release(struct spi_controller *ctlr, struct spi_message *message) + { + struct spi_res *res; + +@@ -2293,7 +2296,7 @@ void spi_res_release(struct spi_master *master, + struct spi_res, entry); + + if (res->release) +- res->release(master, message, res->data); ++ res->release(ctlr, message, res->data); + + list_del(&res->entry); + +@@ -2306,7 +2309,7 @@ void spi_res_release(struct spi_master *master, + + /* Core methods for spi_message alterations */ + +-static void __spi_replace_transfers_release(struct spi_master *master, ++static void __spi_replace_transfers_release(struct spi_controller *ctlr, + struct spi_message *msg, + void *res) + { +@@ -2315,7 +2318,7 @@ static void __spi_replace_transfers_release(struct spi_master *master, + + /* call extra callback if requested */ + if (rxfer->release) +- rxfer->release(master, msg, res); ++ rxfer->release(ctlr, msg, res); + + /* insert replaced transfers back into the message */ + list_splice(&rxfer->replaced_transfers, rxfer->replaced_after); +@@ -2435,7 +2438,7 @@ struct spi_replaced_transfers *spi_replace_transfers( + } + EXPORT_SYMBOL_GPL(spi_replace_transfers); + +-static int __spi_split_transfer_maxsize(struct spi_master *master, ++static int __spi_split_transfer_maxsize(struct spi_controller *ctlr, + struct spi_message *msg, + struct spi_transfer **xferp, + size_t maxsize, +@@ -2497,7 +2500,7 @@ static int __spi_split_transfer_maxsize(struct spi_master *master, + *xferp = &xfers[count - 1]; + + /* increment statistics counters */ +- SPI_STATISTICS_INCREMENT_FIELD(&master->statistics, ++ SPI_STATISTICS_INCREMENT_FIELD(&ctlr->statistics, + transfers_split_maxsize); + SPI_STATISTICS_INCREMENT_FIELD(&msg->spi->statistics, + transfers_split_maxsize); +@@ -2509,14 +2512,14 @@ static int __spi_split_transfer_maxsize(struct spi_master *master, + * spi_split_tranfers_maxsize - split spi transfers into multiple transfers + * when an individual transfer exceeds a + * certain size +- * @master: the @spi_master for this transfer ++ * @ctlr: the @spi_controller for this transfer + * @msg: the @spi_message to transform + * @maxsize: the maximum when to apply this + * @gfp: GFP allocation flags + * + * Return: status of transformation + */ +-int spi_split_transfers_maxsize(struct spi_master *master, ++int spi_split_transfers_maxsize(struct spi_controller *ctlr, + struct spi_message *msg, + size_t maxsize, + gfp_t gfp) +@@ -2532,8 +2535,8 @@ int spi_split_transfers_maxsize(struct spi_master *master, + */ + list_for_each_entry(xfer, &msg->transfers, transfer_list) { + if (xfer->len > maxsize) { +- ret = __spi_split_transfer_maxsize( +- master, msg, &xfer, maxsize, gfp); ++ ret = __spi_split_transfer_maxsize(ctlr, msg, &xfer, ++ maxsize, gfp); + if (ret) + return ret; + } +@@ -2545,18 +2548,18 @@ int spi_split_transfers_maxsize(struct spi_master *master, + + /*-------------------------------------------------------------------------*/ + +-/* Core methods for SPI master protocol drivers. Some of the ++/* Core methods for SPI controller protocol drivers. Some of the + * other core methods are currently defined as inline functions. + */ + +-static int __spi_validate_bits_per_word(struct spi_master *master, u8 bits_per_word) ++static int __spi_validate_bits_per_word(struct spi_controller *ctlr, ++ u8 bits_per_word) + { +- if (master->bits_per_word_mask) { ++ if (ctlr->bits_per_word_mask) { + /* Only 32 bits fit in the mask */ + if (bits_per_word > 32) + return -EINVAL; +- if (!(master->bits_per_word_mask & +- SPI_BPW_MASK(bits_per_word))) ++ if (!(ctlr->bits_per_word_mask & SPI_BPW_MASK(bits_per_word))) + return -EINVAL; + } + +@@ -2602,9 +2605,9 @@ int spi_setup(struct spi_device *spi) + (SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD))) + return -EINVAL; + /* help drivers fail *cleanly* when they need options +- * that aren't supported with their current master ++ * that aren't supported with their current controller + */ +- bad_bits = spi->mode & ~spi->master->mode_bits; ++ bad_bits = spi->mode & ~spi->controller->mode_bits; + ugly_bits = bad_bits & + (SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD); + if (ugly_bits) { +@@ -2623,15 +2626,16 @@ int spi_setup(struct spi_device *spi) + if (!spi->bits_per_word) + spi->bits_per_word = 8; + +- status = __spi_validate_bits_per_word(spi->master, spi->bits_per_word); ++ status = __spi_validate_bits_per_word(spi->controller, ++ spi->bits_per_word); + if (status) + return status; + + if (!spi->max_speed_hz) +- spi->max_speed_hz = spi->master->max_speed_hz; ++ spi->max_speed_hz = spi->controller->max_speed_hz; + +- if (spi->master->setup) +- status = spi->master->setup(spi); ++ if (spi->controller->setup) ++ status = spi->controller->setup(spi); + + spi_set_cs(spi, false); + +@@ -2650,7 +2654,7 @@ int spi_setup(struct spi_device *spi) + + static int __spi_validate(struct spi_device *spi, struct spi_message *message) + { +- struct spi_master *master = spi->master; ++ struct spi_controller *ctlr = spi->controller; + struct spi_transfer *xfer; + int w_size; + +@@ -2662,16 +2666,16 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message) + * either MOSI or MISO is missing. They can also be caused by + * software limitations. + */ +- if ((master->flags & SPI_MASTER_HALF_DUPLEX) +- || (spi->mode & SPI_3WIRE)) { +- unsigned flags = master->flags; ++ if ((ctlr->flags & SPI_CONTROLLER_HALF_DUPLEX) || ++ (spi->mode & SPI_3WIRE)) { ++ unsigned flags = ctlr->flags; + + list_for_each_entry(xfer, &message->transfers, transfer_list) { + if (xfer->rx_buf && xfer->tx_buf) + return -EINVAL; +- if ((flags & SPI_MASTER_NO_TX) && xfer->tx_buf) ++ if ((flags & SPI_CONTROLLER_NO_TX) && xfer->tx_buf) + return -EINVAL; +- if ((flags & SPI_MASTER_NO_RX) && xfer->rx_buf) ++ if ((flags & SPI_CONTROLLER_NO_RX) && xfer->rx_buf) + return -EINVAL; + } + } +@@ -2691,13 +2695,12 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message) + if (!xfer->speed_hz) + xfer->speed_hz = spi->max_speed_hz; + if (!xfer->speed_hz) +- xfer->speed_hz = master->max_speed_hz; ++ xfer->speed_hz = ctlr->max_speed_hz; + +- if (master->max_speed_hz && +- xfer->speed_hz > master->max_speed_hz) +- xfer->speed_hz = master->max_speed_hz; ++ if (ctlr->max_speed_hz && xfer->speed_hz > ctlr->max_speed_hz) ++ xfer->speed_hz = ctlr->max_speed_hz; + +- if (__spi_validate_bits_per_word(master, xfer->bits_per_word)) ++ if (__spi_validate_bits_per_word(ctlr, xfer->bits_per_word)) + return -EINVAL; + + /* +@@ -2715,8 +2718,8 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message) + if (xfer->len % w_size) + return -EINVAL; + +- if (xfer->speed_hz && master->min_speed_hz && +- xfer->speed_hz < master->min_speed_hz) ++ if (xfer->speed_hz && ctlr->min_speed_hz && ++ xfer->speed_hz < ctlr->min_speed_hz) + return -EINVAL; + + if (xfer->tx_buf && !xfer->tx_nbits) +@@ -2761,16 +2764,16 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message) + + static int __spi_async(struct spi_device *spi, struct spi_message *message) + { +- struct spi_master *master = spi->master; ++ struct spi_controller *ctlr = spi->controller; + + message->spi = spi; + +- SPI_STATISTICS_INCREMENT_FIELD(&master->statistics, spi_async); ++ SPI_STATISTICS_INCREMENT_FIELD(&ctlr->statistics, spi_async); + SPI_STATISTICS_INCREMENT_FIELD(&spi->statistics, spi_async); + + trace_spi_message_submit(message); + +- return master->transfer(spi, message); ++ return ctlr->transfer(spi, message); + } + + /** +@@ -2806,7 +2809,7 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message) + */ + int spi_async(struct spi_device *spi, struct spi_message *message) + { +- struct spi_master *master = spi->master; ++ struct spi_controller *ctlr = spi->controller; + int ret; + unsigned long flags; + +@@ -2814,14 +2817,14 @@ int spi_async(struct spi_device *spi, struct spi_message *message) + if (ret != 0) + return ret; + +- spin_lock_irqsave(&master->bus_lock_spinlock, flags); ++ spin_lock_irqsave(&ctlr->bus_lock_spinlock, flags); + +- if (master->bus_lock_flag) ++ if (ctlr->bus_lock_flag) + ret = -EBUSY; + else + ret = __spi_async(spi, message); + +- spin_unlock_irqrestore(&master->bus_lock_spinlock, flags); ++ spin_unlock_irqrestore(&ctlr->bus_lock_spinlock, flags); + + return ret; + } +@@ -2860,7 +2863,7 @@ int spi_async(struct spi_device *spi, struct spi_message *message) + */ + int spi_async_locked(struct spi_device *spi, struct spi_message *message) + { +- struct spi_master *master = spi->master; ++ struct spi_controller *ctlr = spi->controller; + int ret; + unsigned long flags; + +@@ -2868,11 +2871,11 @@ int spi_async_locked(struct spi_device *spi, struct spi_message *message) + if (ret != 0) + return ret; + +- spin_lock_irqsave(&master->bus_lock_spinlock, flags); ++ spin_lock_irqsave(&ctlr->bus_lock_spinlock, flags); + + ret = __spi_async(spi, message); + +- spin_unlock_irqrestore(&master->bus_lock_spinlock, flags); ++ spin_unlock_irqrestore(&ctlr->bus_lock_spinlock, flags); + + return ret; + +@@ -2884,7 +2887,7 @@ int spi_flash_read(struct spi_device *spi, + struct spi_flash_read_message *msg) + + { +- struct spi_master *master = spi->master; ++ struct spi_controller *master = spi->controller; + struct device *rx_dev = NULL; + int ret; + +@@ -2938,7 +2941,7 @@ int spi_flash_read(struct spi_device *spi, + + /*-------------------------------------------------------------------------*/ + +-/* Utility methods for SPI master protocol drivers, layered on ++/* Utility methods for SPI protocol drivers, layered on + * top of the core. Some other utility methods are defined as + * inline functions. + */ +@@ -2952,7 +2955,7 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message) + { + DECLARE_COMPLETION_ONSTACK(done); + int status; +- struct spi_master *master = spi->master; ++ struct spi_controller *ctlr = spi->controller; + unsigned long flags; + + status = __spi_validate(spi, message); +@@ -2963,7 +2966,7 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message) + message->context = &done; + message->spi = spi; + +- SPI_STATISTICS_INCREMENT_FIELD(&master->statistics, spi_sync); ++ SPI_STATISTICS_INCREMENT_FIELD(&ctlr->statistics, spi_sync); + SPI_STATISTICS_INCREMENT_FIELD(&spi->statistics, spi_sync); + + /* If we're not using the legacy transfer method then we will +@@ -2971,14 +2974,14 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message) + * This code would be less tricky if we could remove the + * support for driver implemented message queues. + */ +- if (master->transfer == spi_queued_transfer) { +- spin_lock_irqsave(&master->bus_lock_spinlock, flags); ++ if (ctlr->transfer == spi_queued_transfer) { ++ spin_lock_irqsave(&ctlr->bus_lock_spinlock, flags); + + trace_spi_message_submit(message); + + status = __spi_queued_transfer(spi, message, false); + +- spin_unlock_irqrestore(&master->bus_lock_spinlock, flags); ++ spin_unlock_irqrestore(&ctlr->bus_lock_spinlock, flags); + } else { + status = spi_async_locked(spi, message); + } +@@ -2987,12 +2990,12 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message) + /* Push out the messages in the calling context if we + * can. + */ +- if (master->transfer == spi_queued_transfer) { +- SPI_STATISTICS_INCREMENT_FIELD(&master->statistics, ++ if (ctlr->transfer == spi_queued_transfer) { ++ SPI_STATISTICS_INCREMENT_FIELD(&ctlr->statistics, + spi_sync_immediate); + SPI_STATISTICS_INCREMENT_FIELD(&spi->statistics, + spi_sync_immediate); +- __spi_pump_messages(master, false); ++ __spi_pump_messages(ctlr, false); + } + + wait_for_completion(&done); +@@ -3027,9 +3030,9 @@ int spi_sync(struct spi_device *spi, struct spi_message *message) + { + int ret; + +- mutex_lock(&spi->master->bus_lock_mutex); ++ mutex_lock(&spi->controller->bus_lock_mutex); + ret = __spi_sync(spi, message); +- mutex_unlock(&spi->master->bus_lock_mutex); ++ mutex_unlock(&spi->controller->bus_lock_mutex); + + return ret; + } +@@ -3059,7 +3062,7 @@ int spi_sync_locked(struct spi_device *spi, struct spi_message *message) + + /** + * spi_bus_lock - obtain a lock for exclusive SPI bus usage +- * @master: SPI bus master that should be locked for exclusive bus access ++ * @ctlr: SPI bus master that should be locked for exclusive bus access + * Context: can sleep + * + * This call may only be used from a context that may sleep. The sleep +@@ -3072,15 +3075,15 @@ int spi_sync_locked(struct spi_device *spi, struct spi_message *message) + * + * Return: always zero. + */ +-int spi_bus_lock(struct spi_master *master) ++int spi_bus_lock(struct spi_controller *ctlr) + { + unsigned long flags; + +- mutex_lock(&master->bus_lock_mutex); ++ mutex_lock(&ctlr->bus_lock_mutex); + +- spin_lock_irqsave(&master->bus_lock_spinlock, flags); +- master->bus_lock_flag = 1; +- spin_unlock_irqrestore(&master->bus_lock_spinlock, flags); ++ spin_lock_irqsave(&ctlr->bus_lock_spinlock, flags); ++ ctlr->bus_lock_flag = 1; ++ spin_unlock_irqrestore(&ctlr->bus_lock_spinlock, flags); + + /* mutex remains locked until spi_bus_unlock is called */ + +@@ -3090,7 +3093,7 @@ int spi_bus_lock(struct spi_master *master) + + /** + * spi_bus_unlock - release the lock for exclusive SPI bus usage +- * @master: SPI bus master that was locked for exclusive bus access ++ * @ctlr: SPI bus master that was locked for exclusive bus access + * Context: can sleep + * + * This call may only be used from a context that may sleep. The sleep +@@ -3101,11 +3104,11 @@ int spi_bus_lock(struct spi_master *master) + * + * Return: always zero. + */ +-int spi_bus_unlock(struct spi_master *master) ++int spi_bus_unlock(struct spi_controller *ctlr) + { +- master->bus_lock_flag = 0; ++ ctlr->bus_lock_flag = 0; + +- mutex_unlock(&master->bus_lock_mutex); ++ mutex_unlock(&ctlr->bus_lock_mutex); + + return 0; + } +@@ -3207,48 +3210,48 @@ static struct spi_device *of_find_spi_device_by_node(struct device_node *node) + return dev ? to_spi_device(dev) : NULL; + } + +-static int __spi_of_master_match(struct device *dev, const void *data) ++static int __spi_of_controller_match(struct device *dev, const void *data) + { + return dev->of_node == data; + } + +-/* the spi masters are not using spi_bus, so we find it with another way */ +-static struct spi_master *of_find_spi_master_by_node(struct device_node *node) ++/* the spi controllers are not using spi_bus, so we find it with another way */ ++static struct spi_controller *of_find_spi_controller_by_node(struct device_node *node) + { + struct device *dev; + + dev = class_find_device(&spi_master_class, NULL, node, +- __spi_of_master_match); ++ __spi_of_controller_match); + if (!dev && IS_ENABLED(CONFIG_SPI_SLAVE)) + dev = class_find_device(&spi_slave_class, NULL, node, +- __spi_of_master_match); ++ __spi_of_controller_match); + if (!dev) + return NULL; + + /* reference got in class_find_device */ +- return container_of(dev, struct spi_master, dev); ++ return container_of(dev, struct spi_controller, dev); + } + + static int of_spi_notify(struct notifier_block *nb, unsigned long action, + void *arg) + { + struct of_reconfig_data *rd = arg; +- struct spi_master *master; ++ struct spi_controller *ctlr; + struct spi_device *spi; + + switch (of_reconfig_get_state_change(action, arg)) { + case OF_RECONFIG_CHANGE_ADD: +- master = of_find_spi_master_by_node(rd->dn->parent); +- if (master == NULL) ++ ctlr = of_find_spi_controller_by_node(rd->dn->parent); ++ if (ctlr == NULL) + return NOTIFY_OK; /* not for us */ + + if (of_node_test_and_set_flag(rd->dn, OF_POPULATED)) { +- put_device(&master->dev); ++ put_device(&ctlr->dev); + return NOTIFY_OK; + } + +- spi = of_register_spi_device(master, rd->dn); +- put_device(&master->dev); ++ spi = of_register_spi_device(ctlr, rd->dn); ++ put_device(&ctlr->dev); + + if (IS_ERR(spi)) { + pr_err("%s: failed to create for '%s'\n", +@@ -3287,7 +3290,7 @@ static int of_spi_notify(struct notifier_block *nb, unsigned long action, + #endif /* IS_ENABLED(CONFIG_OF_DYNAMIC) */ + + #if IS_ENABLED(CONFIG_ACPI) +-static int spi_acpi_master_match(struct device *dev, const void *data) ++static int spi_acpi_controller_match(struct device *dev, const void *data) + { + return ACPI_COMPANION(dev->parent) == data; + } +@@ -3297,19 +3300,19 @@ static int spi_acpi_device_match(struct device *dev, void *data) + return ACPI_COMPANION(dev) == data; + } + +-static struct spi_master *acpi_spi_find_master_by_adev(struct acpi_device *adev) ++static struct spi_controller *acpi_spi_find_controller_by_adev(struct acpi_device *adev) + { + struct device *dev; + + dev = class_find_device(&spi_master_class, NULL, adev, +- spi_acpi_master_match); ++ spi_acpi_controller_match); + if (!dev && IS_ENABLED(CONFIG_SPI_SLAVE)) + dev = class_find_device(&spi_slave_class, NULL, adev, +- spi_acpi_master_match); ++ spi_acpi_controller_match); + if (!dev) + return NULL; + +- return container_of(dev, struct spi_master, dev); ++ return container_of(dev, struct spi_controller, dev); + } + + static struct spi_device *acpi_spi_find_device_by_adev(struct acpi_device *adev) +@@ -3325,17 +3328,17 @@ static int acpi_spi_notify(struct notifier_block *nb, unsigned long value, + void *arg) + { + struct acpi_device *adev = arg; +- struct spi_master *master; ++ struct spi_controller *ctlr; + struct spi_device *spi; + + switch (value) { + case ACPI_RECONFIG_DEVICE_ADD: +- master = acpi_spi_find_master_by_adev(adev->parent); +- if (!master) ++ ctlr = acpi_spi_find_controller_by_adev(adev->parent); ++ if (!ctlr) + break; + +- acpi_register_spi_device(master, adev); +- put_device(&master->dev); ++ acpi_register_spi_device(ctlr, adev); ++ put_device(&ctlr->dev); + break; + case ACPI_RECONFIG_DEVICE_REMOVE: + if (!acpi_device_enumerated(adev)) +diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h +index f9bbd33..920cdb7 100644 +--- a/include/linux/spi/spi.h ++++ b/include/linux/spi/spi.h +@@ -23,7 +23,7 @@ + #include + + struct dma_chan; +-struct spi_master; ++struct spi_controller; + struct spi_transfer; + struct spi_flash_read_message; + +@@ -83,7 +83,7 @@ struct spi_statistics { + + void spi_statistics_add_transfer_stats(struct spi_statistics *stats, + struct spi_transfer *xfer, +- struct spi_master *master); ++ struct spi_controller *ctlr); + + #define SPI_STATISTICS_ADD_TO_FIELD(stats, field, count) \ + do { \ +@@ -97,13 +97,14 @@ void spi_statistics_add_transfer_stats(struct spi_statistics *stats, + SPI_STATISTICS_ADD_TO_FIELD(stats, field, 1) + + /** +- * struct spi_device - Master side proxy for an SPI slave device ++ * struct spi_device - Controller side proxy for an SPI slave device + * @dev: Driver model representation of the device. +- * @master: SPI controller used with the device. ++ * @controller: SPI controller used with the device. ++ * @master: Copy of controller, for backwards compatibility. + * @max_speed_hz: Maximum clock rate to be used with this chip + * (on this board); may be changed by the device's driver. + * The spi_transfer.speed_hz can override this for each transfer. +- * @chip_select: Chipselect, distinguishing chips handled by @master. ++ * @chip_select: Chipselect, distinguishing chips handled by @controller. + * @mode: The spi mode defines how data is clocked out and in. + * This may be changed by the device's driver. + * The "active low" default for chipselect mode can be overridden +@@ -139,7 +140,8 @@ void spi_statistics_add_transfer_stats(struct spi_statistics *stats, + */ + struct spi_device { + struct device dev; +- struct spi_master *master; ++ struct spi_controller *controller; ++ struct spi_controller *master; /* compatibility layer */ + u32 max_speed_hz; + u8 chip_select; + u8 bits_per_word; +@@ -197,7 +199,7 @@ static inline void spi_dev_put(struct spi_device *spi) + put_device(&spi->dev); + } + +-/* ctldata is for the bus_master driver's runtime state */ ++/* ctldata is for the bus_controller driver's runtime state */ + static inline void *spi_get_ctldata(struct spi_device *spi) + { + return spi->controller_state; +@@ -291,9 +293,9 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) + spi_unregister_driver) + + /** +- * struct spi_master - interface to SPI master controller ++ * struct spi_controller - interface to SPI master or slave controller + * @dev: device interface to this driver +- * @list: link with the global spi_master list ++ * @list: link with the global spi_controller list + * @bus_num: board-specific (and often SOC-specific) identifier for a + * given SPI controller. + * @num_chipselect: chipselects are used to distinguish individual +@@ -326,8 +328,8 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) + * the device whose settings are being modified. + * @transfer: adds a message to the controller's transfer queue. + * @cleanup: frees controller-specific state +- * @can_dma: determine whether this master supports DMA +- * @queued: whether this master is providing an internal message queue ++ * @can_dma: determine whether this controller supports DMA ++ * @queued: whether this controller is providing an internal message queue + * @kworker: thread struct for message pump + * @kworker_task: pointer to task for message pump kworker thread + * @pump_messages: work struct for scheduling work to the message pump +@@ -381,7 +383,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) + * @cs_gpios: Array of GPIOs to use as chip select lines; one per CS + * number. Any individual value may be -ENOENT for CS lines that + * are not GPIOs (driven by the SPI controller itself). +- * @statistics: statistics for the spi_master ++ * @statistics: statistics for the spi_controller + * @dma_tx: DMA transmit channel + * @dma_rx: DMA receive channel + * @dummy_rx: dummy receive buffer for full-duplex devices +@@ -390,7 +392,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) + * what Linux expects, this optional hook can be used to translate + * between the two. + * +- * Each SPI master controller can communicate with one or more @spi_device ++ * Each SPI controller can communicate with one or more @spi_device + * children. These make a small bus, sharing MOSI, MISO and SCK signals + * but not chip select signals. Each device may be configured to use a + * different clock rate, since those shared signals are ignored unless +@@ -401,7 +403,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) + * an SPI slave device. For each such message it queues, it calls the + * message's completion function when the transaction completes. + */ +-struct spi_master { ++struct spi_controller { + struct device dev; + + struct list_head list; +@@ -439,11 +441,13 @@ struct spi_master { + + /* other constraints relevant to this driver */ + u16 flags; +-#define SPI_MASTER_HALF_DUPLEX BIT(0) /* can't do full duplex */ +-#define SPI_MASTER_NO_RX BIT(1) /* can't do buffer read */ +-#define SPI_MASTER_NO_TX BIT(2) /* can't do buffer write */ +-#define SPI_MASTER_MUST_RX BIT(3) /* requires rx */ +-#define SPI_MASTER_MUST_TX BIT(4) /* requires tx */ ++#define SPI_CONTROLLER_HALF_DUPLEX BIT(0) /* can't do full duplex */ ++#define SPI_CONTROLLER_NO_RX BIT(1) /* can't do buffer read */ ++#define SPI_CONTROLLER_NO_TX BIT(2) /* can't do buffer write */ ++#define SPI_CONTROLLER_MUST_RX BIT(3) /* requires rx */ ++#define SPI_CONTROLLER_MUST_TX BIT(4) /* requires tx */ ++ ++#define SPI_MASTER_GPIO_SS BIT(5) /* GPIO CS must select slave */ + + /* flag indicating this is an SPI slave controller */ + bool slave; +@@ -481,8 +485,8 @@ struct spi_master { + * any other request management + * + To a given spi_device, message queueing is pure fifo + * +- * + The master's main job is to process its message queue, +- * selecting a chip then transferring data ++ * + The controller's main job is to process its message queue, ++ * selecting a chip (for masters), then transferring data + * + If there are multiple spi_device children, the i/o queue + * arbitration algorithm is unspecified (round robin, fifo, + * priority, reservations, preemption, etc) +@@ -495,7 +499,7 @@ struct spi_master { + int (*transfer)(struct spi_device *spi, + struct spi_message *mesg); + +- /* called on release() to free memory provided by spi_master */ ++ /* called on release() to free memory provided by spi_controller */ + void (*cleanup)(struct spi_device *spi); + + /* +@@ -505,13 +509,13 @@ struct spi_master { + * not modify or store xfer and dma_tx and dma_rx must be set + * while the device is prepared. + */ +- bool (*can_dma)(struct spi_master *master, ++ bool (*can_dma)(struct spi_controller *ctlr, + struct spi_device *spi, + struct spi_transfer *xfer); + + /* + * These hooks are for drivers that want to use the generic +- * master transfer queueing mechanism. If these are used, the ++ * controller transfer queueing mechanism. If these are used, the + * transfer() function above must NOT be specified by the driver. + * Over time we expect SPI drivers to be phased over to this API. + */ +@@ -532,15 +536,15 @@ struct spi_master { + struct completion xfer_completion; + size_t max_dma_len; + +- int (*prepare_transfer_hardware)(struct spi_master *master); +- int (*transfer_one_message)(struct spi_master *master, ++ int (*prepare_transfer_hardware)(struct spi_controller *ctlr); ++ int (*transfer_one_message)(struct spi_controller *ctlr, + struct spi_message *mesg); +- int (*unprepare_transfer_hardware)(struct spi_master *master); +- int (*prepare_message)(struct spi_master *master, ++ int (*unprepare_transfer_hardware)(struct spi_controller *ctlr); ++ int (*prepare_message)(struct spi_controller *ctlr, + struct spi_message *message); +- int (*unprepare_message)(struct spi_master *master, ++ int (*unprepare_message)(struct spi_controller *ctlr, + struct spi_message *message); +- int (*slave_abort)(struct spi_master *spi); ++ int (*slave_abort)(struct spi_controller *ctlr); + int (*spi_flash_read)(struct spi_device *spi, + struct spi_flash_read_message *msg); + bool (*flash_read_supported)(struct spi_device *spi); +@@ -550,9 +554,9 @@ struct spi_master { + * of transfer_one_message() provied by the core. + */ + void (*set_cs)(struct spi_device *spi, bool enable); +- int (*transfer_one)(struct spi_master *master, struct spi_device *spi, ++ int (*transfer_one)(struct spi_controller *ctlr, struct spi_device *spi, + struct spi_transfer *transfer); +- void (*handle_err)(struct spi_master *master, ++ void (*handle_err)(struct spi_controller *ctlr, + struct spi_message *message); + + /* gpio chip select */ +@@ -569,58 +573,59 @@ struct spi_master { + void *dummy_rx; + void *dummy_tx; + +- int (*fw_translate_cs)(struct spi_master *master, unsigned cs); ++ int (*fw_translate_cs)(struct spi_controller *ctlr, unsigned cs); + }; + +-static inline void *spi_master_get_devdata(struct spi_master *master) ++static inline void *spi_controller_get_devdata(struct spi_controller *ctlr) + { +- return dev_get_drvdata(&master->dev); ++ return dev_get_drvdata(&ctlr->dev); + } + +-static inline void spi_master_set_devdata(struct spi_master *master, void *data) ++static inline void spi_controller_set_devdata(struct spi_controller *ctlr, ++ void *data) + { +- dev_set_drvdata(&master->dev, data); ++ dev_set_drvdata(&ctlr->dev, data); + } + +-static inline struct spi_master *spi_master_get(struct spi_master *master) ++static inline struct spi_controller *spi_controller_get(struct spi_controller *ctlr) + { +- if (!master || !get_device(&master->dev)) ++ if (!ctlr || !get_device(&ctlr->dev)) + return NULL; +- return master; ++ return ctlr; + } + +-static inline void spi_master_put(struct spi_master *master) ++static inline void spi_controller_put(struct spi_controller *ctlr) + { +- if (master) +- put_device(&master->dev); ++ if (ctlr) ++ put_device(&ctlr->dev); + } + +-static inline bool spi_controller_is_slave(struct spi_master *ctlr) ++static inline bool spi_controller_is_slave(struct spi_controller *ctlr) + { + return IS_ENABLED(CONFIG_SPI_SLAVE) && ctlr->slave; + } + + /* PM calls that need to be issued by the driver */ +-extern int spi_master_suspend(struct spi_master *master); +-extern int spi_master_resume(struct spi_master *master); ++extern int spi_controller_suspend(struct spi_controller *ctlr); ++extern int spi_controller_resume(struct spi_controller *ctlr); + + /* Calls the driver make to interact with the message queue */ +-extern struct spi_message *spi_get_next_queued_message(struct spi_master *master); +-extern void spi_finalize_current_message(struct spi_master *master); +-extern void spi_finalize_current_transfer(struct spi_master *master); ++extern struct spi_message *spi_get_next_queued_message(struct spi_controller *ctlr); ++extern void spi_finalize_current_message(struct spi_controller *ctlr); ++extern void spi_finalize_current_transfer(struct spi_controller *ctlr); + +-/* the spi driver core manages memory for the spi_master classdev */ +-extern struct spi_master *__spi_alloc_controller(struct device *host, +- unsigned int size, bool slave); ++/* the spi driver core manages memory for the spi_controller classdev */ ++extern struct spi_controller *__spi_alloc_controller(struct device *host, ++ unsigned int size, bool slave); + +-static inline struct spi_master *spi_alloc_master(struct device *host, +- unsigned int size) ++static inline struct spi_controller *spi_alloc_master(struct device *host, ++ unsigned int size) + { + return __spi_alloc_controller(host, size, false); + } + +-static inline struct spi_master *spi_alloc_slave(struct device *host, +- unsigned int size) ++static inline struct spi_controller *spi_alloc_slave(struct device *host, ++ unsigned int size) + { + if (!IS_ENABLED(CONFIG_SPI_SLAVE)) + return NULL; +@@ -628,18 +633,18 @@ static inline struct spi_master *spi_alloc_slave(struct device *host, + return __spi_alloc_controller(host, size, true); + } + +-extern int spi_register_master(struct spi_master *master); +-extern int devm_spi_register_master(struct device *dev, +- struct spi_master *master); +-extern void spi_unregister_master(struct spi_master *master); ++extern int spi_register_controller(struct spi_controller *ctlr); ++extern int devm_spi_register_controller(struct device *dev, ++ struct spi_controller *ctlr); ++extern void spi_unregister_controller(struct spi_controller *ctlr); + +-extern struct spi_master *spi_busnum_to_master(u16 busnum); ++extern struct spi_controller *spi_busnum_to_master(u16 busnum); + + /* + * SPI resource management while processing a SPI message + */ + +-typedef void (*spi_res_release_t)(struct spi_master *master, ++typedef void (*spi_res_release_t)(struct spi_controller *ctlr, + struct spi_message *msg, + void *res); + +@@ -664,7 +669,7 @@ extern void *spi_res_alloc(struct spi_device *spi, + extern void spi_res_add(struct spi_message *message, void *res); + extern void spi_res_free(void *res); + +-extern void spi_res_release(struct spi_master *master, ++extern void spi_res_release(struct spi_controller *ctlr, + struct spi_message *message); + + /*---------------------------------------------------------------------------*/ +@@ -848,7 +853,7 @@ struct spi_message { + + /* for optional use by whatever driver currently owns the + * spi_message ... between calls to spi_async and then later +- * complete(), that's the spi_master controller driver. ++ * complete(), that's the spi_controller controller driver. + */ + struct list_head queue; + void *state; +@@ -937,21 +942,22 @@ extern int spi_async_locked(struct spi_device *spi, + static inline size_t + spi_max_message_size(struct spi_device *spi) + { +- struct spi_master *master = spi->master; +- if (!master->max_message_size) ++ struct spi_controller *ctlr = spi->controller; ++ ++ if (!ctlr->max_message_size) + return SIZE_MAX; +- return master->max_message_size(spi); ++ return ctlr->max_message_size(spi); + } + + static inline size_t + spi_max_transfer_size(struct spi_device *spi) + { +- struct spi_master *master = spi->master; ++ struct spi_controller *ctlr = spi->controller; + size_t tr_max = SIZE_MAX; + size_t msg_max = spi_max_message_size(spi); + +- if (master->max_transfer_size) +- tr_max = master->max_transfer_size(spi); ++ if (ctlr->max_transfer_size) ++ tr_max = ctlr->max_transfer_size(spi); + + /* transfer size limit must not be greater than messsage size limit */ + return min(tr_max, msg_max); +@@ -962,7 +968,7 @@ extern int spi_async_locked(struct spi_device *spi, + /* SPI transfer replacement methods which make use of spi_res */ + + struct spi_replaced_transfers; +-typedef void (*spi_replaced_release_t)(struct spi_master *master, ++typedef void (*spi_replaced_release_t)(struct spi_controller *ctlr, + struct spi_message *msg, + struct spi_replaced_transfers *res); + /** +@@ -1006,7 +1012,7 @@ extern struct spi_replaced_transfers *spi_replace_transfers( + + /* SPI transfer transformation methods */ + +-extern int spi_split_transfers_maxsize(struct spi_master *master, ++extern int spi_split_transfers_maxsize(struct spi_controller *ctlr, + struct spi_message *msg, + size_t maxsize, + gfp_t gfp); +@@ -1020,8 +1026,8 @@ extern int spi_split_transfers_maxsize(struct spi_master *master, + + extern int spi_sync(struct spi_device *spi, struct spi_message *message); + extern int spi_sync_locked(struct spi_device *spi, struct spi_message *message); +-extern int spi_bus_lock(struct spi_master *master); +-extern int spi_bus_unlock(struct spi_master *master); ++extern int spi_bus_lock(struct spi_controller *ctlr); ++extern int spi_bus_unlock(struct spi_controller *ctlr); + + /** + * spi_sync_transfer - synchronous SPI data transfer +@@ -1206,9 +1212,9 @@ struct spi_flash_read_message { + /* SPI core interface for flash read support */ + static inline bool spi_flash_read_supported(struct spi_device *spi) + { +- return spi->master->spi_flash_read && +- (!spi->master->flash_read_supported || +- spi->master->flash_read_supported(spi)); ++ return spi->controller->spi_flash_read && ++ (!spi->controller->flash_read_supported || ++ spi->controller->flash_read_supported(spi)); + } + + int spi_flash_read(struct spi_device *spi, +@@ -1240,7 +1246,7 @@ int spi_flash_read(struct spi_device *spi, + * @irq: Initializes spi_device.irq; depends on how the board is wired. + * @max_speed_hz: Initializes spi_device.max_speed_hz; based on limits + * from the chip datasheet and board-specific signal quality issues. +- * @bus_num: Identifies which spi_master parents the spi_device; unused ++ * @bus_num: Identifies which spi_controller parents the spi_device; unused + * by spi_new_device(), and otherwise depends on board wiring. + * @chip_select: Initializes spi_device.chip_select; depends on how + * the board is wired. +@@ -1279,7 +1285,7 @@ struct spi_board_info { + + + /* bus_num is board specific and matches the bus_num of some +- * spi_master that will probably be registered later. ++ * spi_controller that will probably be registered later. + * + * chip_select reflects how this chip is wired to that master; + * it's less than num_chipselect. +@@ -1313,7 +1319,7 @@ struct spi_board_info { + /* If you're hotplugging an adapter with devices (parport, usb, etc) + * use spi_new_device() to describe each device. You can also call + * spi_unregister_device() to start making that device vanish, but +- * normally that would be handled by spi_unregister_master(). ++ * normally that would be handled by spi_unregister_controller(). + * + * You can also use spi_alloc_device() and spi_add_device() to use a two + * stage registration sequence for each spi_device. This gives the caller +@@ -1322,13 +1328,13 @@ struct spi_board_info { + * be defined using the board info. + */ + extern struct spi_device * +-spi_alloc_device(struct spi_master *master); ++spi_alloc_device(struct spi_controller *ctlr); + + extern int + spi_add_device(struct spi_device *spi); + + extern struct spi_device * +-spi_new_device(struct spi_master *, struct spi_board_info *); ++spi_new_device(struct spi_controller *, struct spi_board_info *); + + extern void spi_unregister_device(struct spi_device *spi); + +@@ -1336,9 +1342,32 @@ struct spi_board_info { + spi_get_device_id(const struct spi_device *sdev); + + static inline bool +-spi_transfer_is_last(struct spi_master *master, struct spi_transfer *xfer) ++spi_transfer_is_last(struct spi_controller *ctlr, struct spi_transfer *xfer) + { +- return list_is_last(&xfer->transfer_list, &master->cur_msg->transfers); ++ return list_is_last(&xfer->transfer_list, &ctlr->cur_msg->transfers); + } + ++ ++/* Compatibility layer */ ++#define spi_master spi_controller ++ ++#define SPI_MASTER_HALF_DUPLEX SPI_CONTROLLER_HALF_DUPLEX ++#define SPI_MASTER_NO_RX SPI_CONTROLLER_NO_RX ++#define SPI_MASTER_NO_TX SPI_CONTROLLER_NO_TX ++#define SPI_MASTER_MUST_RX SPI_CONTROLLER_MUST_RX ++#define SPI_MASTER_MUST_TX SPI_CONTROLLER_MUST_TX ++ ++#define spi_master_get_devdata(_ctlr) spi_controller_get_devdata(_ctlr) ++#define spi_master_set_devdata(_ctlr, _data) \ ++ spi_controller_set_devdata(_ctlr, _data) ++#define spi_master_get(_ctlr) spi_controller_get(_ctlr) ++#define spi_master_put(_ctlr) spi_controller_put(_ctlr) ++#define spi_master_suspend(_ctlr) spi_controller_suspend(_ctlr) ++#define spi_master_resume(_ctlr) spi_controller_resume(_ctlr) ++ ++#define spi_register_master(_ctlr) spi_register_controller(_ctlr) ++#define devm_spi_register_master(_dev, _ctlr) \ ++ devm_spi_register_controller(_dev, _ctlr) ++#define spi_unregister_master(_ctlr) spi_unregister_controller(_ctlr) ++ + #endif /* __LINUX_SPI_H */ +diff --git a/include/trace/events/spi.h b/include/trace/events/spi.h +index 7e02c98..f9f702b 100644 +--- a/include/trace/events/spi.h ++++ b/include/trace/events/spi.h +@@ -7,37 +7,37 @@ + #include + #include + +-DECLARE_EVENT_CLASS(spi_master, ++DECLARE_EVENT_CLASS(spi_controller, + +- TP_PROTO(struct spi_master *master), ++ TP_PROTO(struct spi_controller *controller), + +- TP_ARGS(master), ++ TP_ARGS(controller), + + TP_STRUCT__entry( + __field( int, bus_num ) + ), + + TP_fast_assign( +- __entry->bus_num = master->bus_num; ++ __entry->bus_num = controller->bus_num; + ), + + TP_printk("spi%d", (int)__entry->bus_num) + + ); + +-DEFINE_EVENT(spi_master, spi_master_idle, ++DEFINE_EVENT(spi_controller, spi_controller_idle, + +- TP_PROTO(struct spi_master *master), ++ TP_PROTO(struct spi_controller *controller), + +- TP_ARGS(master) ++ TP_ARGS(controller) + + ); + +-DEFINE_EVENT(spi_master, spi_master_busy, ++DEFINE_EVENT(spi_controller, spi_controller_busy, + +- TP_PROTO(struct spi_master *master), ++ TP_PROTO(struct spi_controller *controller), + +- TP_ARGS(master) ++ TP_ARGS(controller) + + ); + +@@ -54,7 +54,7 @@ + ), + + TP_fast_assign( +- __entry->bus_num = msg->spi->master->bus_num; ++ __entry->bus_num = msg->spi->controller->bus_num; + __entry->chip_select = msg->spi->chip_select; + __entry->msg = msg; + ), +@@ -95,7 +95,7 @@ + ), + + TP_fast_assign( +- __entry->bus_num = msg->spi->master->bus_num; ++ __entry->bus_num = msg->spi->controller->bus_num; + __entry->chip_select = msg->spi->chip_select; + __entry->msg = msg; + __entry->frame = msg->frame_length; +@@ -122,7 +122,7 @@ + ), + + TP_fast_assign( +- __entry->bus_num = msg->spi->master->bus_num; ++ __entry->bus_num = msg->spi->controller->bus_num; + __entry->chip_select = msg->spi->chip_select; + __entry->xfer = xfer; + __entry->len = xfer->len; +-- +1.7.10.4 diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0090-spidev-Do-not-automatically-bind-to-MSIOF-spi-may-be.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0090-spidev-Do-not-automatically-bind-to-MSIOF-spi-may-be.patch new file mode 100644 index 0000000..de7cc2b --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0090-spidev-Do-not-automatically-bind-to-MSIOF-spi-may-be.patch @@ -0,0 +1,26 @@ +From e2fe50b628f660ef35c82b778c5d0c56b5c4487b Mon Sep 17 00:00:00 2001 +From: Andrey Dolnikov +Date: Fri, 12 Jan 2018 18:25:33 +0300 +Subject: [PATCH] spidev: Do not automatically bind to MSIOF spi (may be used + as slave). + +Signed-off-by: Andrey Dolnikov +--- + drivers/spi/spidev.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c +index 203d68c..cbd0b93 100644 +--- a/drivers/spi/spidev.c ++++ b/drivers/spi/spidev.c +@@ -697,7 +697,6 @@ static struct class *spidev_class; + static const struct of_device_id spidev_dt_ids[] = { + { .compatible = "rohm,dh2228fv" }, + { .compatible = "lineartechnology,ltc2488" }, +- { .compatible = "renesas,sh-msiof" }, + { .compatible = "spi-gpio" }, + {}, + }; +-- +2.7.4 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3msk.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3msk.cfg index 34a385b..7dea6e2 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3msk.cfg +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3msk.cfg @@ -32,3 +32,6 @@ CONFIG_TOUCHSCREEN_PROPERTIES=y CONFIG_HID_MULTITOUCH=y CONFIG_SERIAL_SH_SCI_DMA=y CONFIG_UIO=y +CONFIG_SPI_SLAVE=y +CONFIG_SPI_SLAVE_TIME=y +CONFIG_SPI_SLAVE_SYSTEM_CONTROL=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 index f21ad58..f855641 100644 --- 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 @@ -73,6 +73,14 @@ SRC_URI_append = " \ file://0078-MOST-aim-fix-null-pointer-crash.patch \ file://0079-Revert-dmaengine-rcar-dmac-use-TCRB-instead-of-TCR-f.patch \ file://0082-gpio-pca953x-fix-interrupt-trigger.patch \ + file://0083-spi-Document-DT-bindings-for-SPI-controllers-in-slav.patch \ + file://0084-spi-core-Add-support-for-registering-SPI-slave-contr.patch \ + file://0085-spi-Document-SPI-slave-controller-support.patch \ + file://0086-spi-sh-msiof-Add-slave-mode-support.patch \ + file://0087-spi-slave-Add-SPI-slave-handler-reporting-uptime-at-.patch \ + file://0088-spi-slave-Add-SPI-slave-handler-controlling-system-s.patch \ + file://0089-spi-Generalize-SPI-master-to-controller.patch \ + file://0090-spidev-Do-not-automatically-bind-to-MSIOF-spi-may-be.patch \ file://0103-gpu-drm-rcar-du-Extend-VSP1-DRM-interface.patch \ file://0104-media-vsp1-extend-DRM-VSP1-interface.patch \ file://0105-media-rcar-imr-IMR-driver-updates-for-raw-DL.patch \ -- cgit 1.2.3-korg From d2b16d8f3bbb050466c045d87c54fbcfbd88fe13 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Tue, 23 Jan 2018 17:51:53 +0300 Subject: OV490-OV10640: add module params 1) add dvp_order module parameter 2) add max_height, max_width params This will allow override default dts params using kernel command line: f.e.: " ov106xx.dvp_order=2" or " ov106xx.max_width=1280 ov106xx.max_height=966 max9286.gpio_resetb=4 max9286.active_low_resetb=1 max9286.fsync_period=3200000" --- .../linux-renesas/0030-Gen3-LVDS-cameras.patch | 66 ++++++++++++---------- 1 file changed, 35 insertions(+), 31 deletions(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') 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 index 6eb40f3..a2bfd20 100644 --- 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 @@ -21,7 +21,7 @@ Signed-off-by: Vladimir Barinov drivers/media/i2c/soc_camera/ov10635.h | 1139 +++++++++++++++++++++ drivers/media/i2c/soc_camera/ov10635_debug.h | 54 + drivers/media/i2c/soc_camera/ov106xx.c | 117 +++ - drivers/media/i2c/soc_camera/ov490_ov10640.c | 1156 ++++++++++++++++++++++ + drivers/media/i2c/soc_camera/ov490_ov10640.c | 1160 ++++++++++++++++++++++ drivers/media/i2c/soc_camera/ov490_ov10640.h | 102 ++ drivers/media/i2c/soc_camera/ov495_ov2775.c | 658 ++++++++++++ drivers/media/i2c/soc_camera/ov495_ov2775.h | 23 + @@ -34,7 +34,7 @@ Signed-off-by: Vladimir Barinov drivers/media/platform/soc_camera/soc_mediabus.c | 16 + include/media/drv-intf/soc_mediabus.h | 3 + include/media/soc_camera.h | 1 + - 25 files changed, 7816 insertions(+), 109 deletions(-) + 25 files changed, 7820 insertions(+), 109 deletions(-) create mode 100644 drivers/media/i2c/soc_camera/ap0101_ar014x.c create mode 100644 drivers/media/i2c/soc_camera/ap0101_ar014x.h create mode 100644 drivers/media/i2c/soc_camera/ar0132.c @@ -4596,10 +4596,10 @@ index 0000000..4c797f9 +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..be7098e +index 0000000..690eac0 --- /dev/null +++ b/drivers/media/i2c/soc_camera/ov490_ov10640.c -@@ -0,0 +1,1156 @@ +@@ -0,0 +1,1160 @@ +/* + * OmniVision ov490-ov10640 sensor camera driver + * @@ -4668,16 +4668,21 @@ index 0000000..be7098e + int gpio_fsin; +}; + -+static int force_conf_link; ++static int conf_link; ++module_param(conf_link, int, 0644); ++MODULE_PARM_DESC(conf_link, " Force configuration link. Used only if robust firmware flashing required (f.e. recovery)"); + -+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 int dvp_order; ++module_param(dvp_order, int, 0644); ++MODULE_PARM_DESC(dvp_order, " DVP bus bits order"); ++ ++static int max_width; ++module_param(max_width, int, 0644); ++MODULE_PARM_DESC(max_width, " Fixed sensor width"); ++ ++static int max_height; ++module_param(max_height, int, 0644); ++MODULE_PARM_DESC(max_height, " Fixed sensor height"); + +static inline struct ov490_priv *to_ov490(const struct i2c_client *client) +{ @@ -5416,7 +5421,7 @@ index 0000000..be7098e + goto err; + } + -+ if (unlikely(force_conf_link)) ++ if (unlikely(conf_link)) + goto out; + +again: @@ -5501,7 +5506,7 @@ index 0000000..be7098e +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; ++ int i; + const char *fixed_sensor; + struct device_node *endpoint = NULL, *rendpoint = NULL; + int tmp_addr = 0; @@ -5584,28 +5589,27 @@ index 0000000..be7098e + } + client->addr = tmp_addr; + -+ err = of_property_read_string(np, "maxim,fixed-sensor", &fixed_sensor); -+ if (err) -+ return 0; ++ if (!of_property_read_string(np, "maxim,fixed-sensor", &fixed_sensor) && ++ strcmp(fixed_sensor, "ov490") == 0) { ++ if (of_property_read_u32(np, "maxim,width", &priv->max_width)) ++ priv->max_width = 1280; + -+ 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; -+ } ++ if (of_property_read_u32(np, "maxim,height", &priv->max_height)) ++ priv->max_height = 966; + -+ 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; ++ } + ++ /* module params override dts */ ++ if (dvp_order) ++ priv->dvp_order = dvp_order; ++ if (max_width && max_height) { ++ priv->max_width = max_width; ++ priv->max_height = max_height; + priv->is_fixed_sensor = true; + } + -+out: -+ return err; ++ return 0; +} + +static int ov490_probe(struct i2c_client *client, -- cgit 1.2.3-korg From f2308034a208b6f8f6c480716c6fd01d3215cb63 Mon Sep 17 00:00:00 2001 From: Roman Meshkevich Date: Tue, 23 Jan 2018 18:21:25 +0300 Subject: [linux-renesas] add support MD and RAID devices into ulcb config --- meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/ulcb.cfg | 3 +++ 1 file changed, 3 insertions(+) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/ulcb.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/ulcb.cfg index 002480e..8f36675 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/ulcb.cfg +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/ulcb.cfg @@ -84,3 +84,6 @@ CONFIG_PMBUS=y CONFIG_RTC_DRV_DS1307=y CONFIG_RTC_DRV_DS1307_HWMON=y CONFIG_SENSORS_LM63=y +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_RAID0=y -- cgit 1.2.3-korg From 90e6ceff18447c3ccb6e438cbadf8096f3f91852 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Wed, 24 Jan 2018 02:44:55 +0300 Subject: SPI slave: fix WARN message This fixes warn message form spidev driver --- .../0040-arm64-dts-renesas-add-ADAS-boards.patch | 2 +- ...ot-automatically-bind-to-MSIOF-spi-may-be.patch | 26 ---------------------- .../linux/linux-renesas_4.9.bbappend | 1 - 3 files changed, 1 insertion(+), 28 deletions(-) delete mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0090-spidev-Do-not-automatically-bind-to-MSIOF-spi-may-be.patch (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch index 4d914f1..346d5dc 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch @@ -11994,7 +11994,7 @@ index 0000000..8612f64 + + status = "okay"; + spidev@0 { -+ compatible = "spidev"; ++ compatible = "renesas,sh-msiof"; + reg = <0>; + spi-max-frequency = <66666666>; + }; diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0090-spidev-Do-not-automatically-bind-to-MSIOF-spi-may-be.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0090-spidev-Do-not-automatically-bind-to-MSIOF-spi-may-be.patch deleted file mode 100644 index de7cc2b..0000000 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0090-spidev-Do-not-automatically-bind-to-MSIOF-spi-may-be.patch +++ /dev/null @@ -1,26 +0,0 @@ -From e2fe50b628f660ef35c82b778c5d0c56b5c4487b Mon Sep 17 00:00:00 2001 -From: Andrey Dolnikov -Date: Fri, 12 Jan 2018 18:25:33 +0300 -Subject: [PATCH] spidev: Do not automatically bind to MSIOF spi (may be used - as slave). - -Signed-off-by: Andrey Dolnikov ---- - drivers/spi/spidev.c | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c -index 203d68c..cbd0b93 100644 ---- a/drivers/spi/spidev.c -+++ b/drivers/spi/spidev.c -@@ -697,7 +697,6 @@ static struct class *spidev_class; - static const struct of_device_id spidev_dt_ids[] = { - { .compatible = "rohm,dh2228fv" }, - { .compatible = "lineartechnology,ltc2488" }, -- { .compatible = "renesas,sh-msiof" }, - { .compatible = "spi-gpio" }, - {}, - }; --- -2.7.4 - 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 index f855641..1ab0ac5 100644 --- 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 @@ -80,7 +80,6 @@ SRC_URI_append = " \ file://0087-spi-slave-Add-SPI-slave-handler-reporting-uptime-at-.patch \ file://0088-spi-slave-Add-SPI-slave-handler-controlling-system-s.patch \ file://0089-spi-Generalize-SPI-master-to-controller.patch \ - file://0090-spidev-Do-not-automatically-bind-to-MSIOF-spi-may-be.patch \ file://0103-gpu-drm-rcar-du-Extend-VSP1-DRM-interface.patch \ file://0104-media-vsp1-extend-DRM-VSP1-interface.patch \ file://0105-media-rcar-imr-IMR-driver-updates-for-raw-DL.patch \ -- cgit 1.2.3-korg From 2ce130f2eede986a8cfff5e1226650a6519c0be1 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Thu, 25 Jan 2018 05:03:14 +0300 Subject: V3H: Add GETHER 1) Add GETHER in uboot/kernel 2) Condor board: setup as default interface --- ...m-renesas-Add-Renesas-R8A7798-SoC-support.patch | 88 ++++-- .../0019-board-renesas-Add-Condor-board.patch | 71 ++--- .../0040-arm64-dts-renesas-add-ADAS-boards.patch | 35 ++- ...as-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch | 336 +++++++++++++++------ .../recipes-kernel/linux/linux-renesas/condor.cfg | 3 + 5 files changed, 371 insertions(+), 162 deletions(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0018-arm-renesas-Add-Renesas-R8A7798-SoC-support.patch b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0018-arm-renesas-Add-Renesas-R8A7798-SoC-support.patch index 026126e..c325687 100644 --- a/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0018-arm-renesas-Add-Renesas-R8A7798-SoC-support.patch +++ b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0018-arm-renesas-Add-Renesas-R8A7798-SoC-support.patch @@ -19,10 +19,11 @@ Signed-off-by: Mikhail Ulyanov arch/arm/include/asm/arch-rcar_gen3/r8a7798.h | 34 + arch/arm/include/asm/arch-rcar_gen3/rcar_gen3.h | 2 + drivers/mtd/spi/sf_probe.c | 2 +- - drivers/net/sh_eth.h | 5 +- + drivers/net/sh_eth.c | 11 +- + drivers/net/sh_eth.h | 7 +- drivers/serial/serial_sh.h | 2 +- - include/configs/rcar-gen3-common.h | 4 + - 14 files changed, 3701 insertions(+), 4 deletions(-) + include/configs/rcar-gen3-common.h | 6 + + 15 files changed, 3714 insertions(+), 6 deletions(-) create mode 100644 arch/arm/cpu/armv8/rcar_gen3/cpu_info-r8a7798.c create mode 100644 arch/arm/cpu/armv8/rcar_gen3/pfc-r8a7798.c create mode 100644 arch/arm/include/asm/arch-rcar_gen3/r8a7798-gpio.h @@ -3826,36 +3827,75 @@ index 4b9a61b..95129ce 100644 if (((flash->dual_flash == SF_SINGLE_FLASH) && (flash->size > SPI_FLASH_16MB_BOUN)) || ((flash->dual_flash > SF_SINGLE_FLASH) && +diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c +index 4bf493e..8226591 100644 +--- a/drivers/net/sh_eth.c ++++ b/drivers/net/sh_eth.c +@@ -380,8 +380,12 @@ static int sh_eth_config(struct sh_eth_dev *eth, bd_t *bd) + struct phy_device *phy; + + /* Configure e-dmac registers */ ++ val = EMDR_DESC | EDMR_EL; ++#if defined(CONFIG_R8A7798) ++ val |= EDMR_NBST; ++#endif + sh_eth_write(eth, (sh_eth_read(eth, EDMR) & ~EMDR_DESC_R) | +- (EMDR_DESC | EDMR_EL), EDMR); ++ val, EDMR); + + sh_eth_write(eth, 0, EESIPR); + sh_eth_write(eth, 0, TRSCER); +@@ -417,7 +421,8 @@ static int sh_eth_config(struct sh_eth_dev *eth, bd_t *bd) + #if defined(CONFIG_CPU_SH7734) || defined(CONFIG_R8A7740) + sh_eth_write(eth, CONFIG_SH_ETHER_SH7734_MII, RMII_MII); + #elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) || \ +- defined(CONFIG_R8A7793) || defined(CONFIG_R8A7794) ++ defined(CONFIG_R8A7793) || defined(CONFIG_R8A7794) || \ ++ defined(CONFIG_R8A7798) + sh_eth_write(eth, sh_eth_read(eth, RMIIMR) | 0x1, RMIIMR); + #endif + /* Configure phy */ +@@ -444,7 +449,7 @@ static int sh_eth_config(struct sh_eth_dev *eth, bd_t *bd) + sh_eth_write(eth, 1, RTRATE); + #elif defined(CONFIG_CPU_SH7724) || defined(CONFIG_R8A7790) || \ + defined(CONFIG_R8A7791) || defined(CONFIG_R8A7793) || \ +- defined(CONFIG_R8A7794) ++ defined(CONFIG_R8A7794) || defined(CONFIG_R8A7798) + val = ECMR_RTM; + #endif + } else if (phy->speed == 10) { diff --git a/drivers/net/sh_eth.h b/drivers/net/sh_eth.h -index 5cb520c..591e75d 100644 +index 5cb520c..3c30d42 100644 --- a/drivers/net/sh_eth.h +++ b/drivers/net/sh_eth.h -@@ -226,7 +226,6 @@ static const u16 sh_eth_offset_gigabit[SH_ETH_MAX_REGISTER_OFFSET] = { - [RMII_MII] = 0x0790, - }; - --#if defined(SH_ETH_TYPE_RZ) - static const u16 sh_eth_offset_rz[SH_ETH_MAX_REGISTER_OFFSET] = { - [EDSR] = 0x0000, - [EDMR] = 0x0400, -@@ -279,7 +278,6 @@ static const u16 sh_eth_offset_rz[SH_ETH_MAX_REGISTER_OFFSET] = { - [MAFCR] = 0x0778, - [RMII_MII] = 0x0790, - }; --#endif - - static const u16 sh_eth_offset_fast_sh4[SH_ETH_MAX_REGISTER_OFFSET] = { - [ECMR] = 0x0100, -@@ -361,6 +359,9 @@ static const u16 sh_eth_offset_fast_sh4[SH_ETH_MAX_REGISTER_OFFSET] = { +@@ -361,6 +361,9 @@ static const u16 sh_eth_offset_fast_sh4[SH_ETH_MAX_REGISTER_OFFSET] = { #elif defined(CONFIG_R7S72100) #define SH_ETH_TYPE_RZ #define BASE_IO_ADDR 0xE8203000 +#elif defined(CONFIG_R8A7798) -+#define SH_ETH_TYPE_RZ ++#define SH_ETH_TYPE_GETHER +#define BASE_IO_ADDR 0xE7400000 #endif /* +@@ -377,6 +380,7 @@ enum EDSR_BIT { + + /* EDMR */ + enum DMAC_M_BIT { ++ EDMR_NBST = 0x80, /* DMA transfer burst mode */ + EDMR_DL1 = 0x20, EDMR_DL0 = 0x10, + #if defined(SH_ETH_TYPE_GETHER) || defined(SH_ETH_TYPE_RZ) + EDMR_SRST = 0x03, /* Receive/Send reset */ +@@ -567,7 +571,8 @@ enum FELIC_MODE_BIT { + #ifdef CONFIG_CPU_SH7724 + ECMR_RTM = 0x00000010, + #elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) || \ +- defined(CONFIG_R8A7793) || defined(CONFIG_R8A7794) ++ defined(CONFIG_R8A7793) || defined(CONFIG_R8A7794) || \ ++ defined(CONFIG_R8A7798) + ECMR_RTM = 0x00000004, + #endif + diff --git a/drivers/serial/serial_sh.h b/drivers/serial/serial_sh.h index 478824e..ded0d3d 100644 --- a/drivers/serial/serial_sh.h @@ -3870,10 +3910,10 @@ index 478824e..ded0d3d 100644 # 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 39d86dd..8124369 100644 +index dc5560d..a3721ad 100644 --- a/include/configs/rcar-gen3-common.h +++ b/include/configs/rcar-gen3-common.h -@@ -133,6 +133,12 @@ +@@ -134,6 +134,12 @@ #endif #define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1 #define CONFIG_SYS_SDRAM_SIZE PHYS_SDRAM_1_SIZE diff --git a/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0019-board-renesas-Add-Condor-board.patch b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0019-board-renesas-Add-Condor-board.patch index 68e0ac9..ddab534 100644 --- a/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0019-board-renesas-Add-Condor-board.patch +++ b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/0019-board-renesas-Add-Condor-board.patch @@ -7,14 +7,14 @@ Condor is a board based on R-Car V3H SoC (R8A7798) Signed-off-by: Vladimir Barinov --- - arch/arm/cpu/armv8/Kconfig | 7 ++ + arch/arm/cpu/armv8/Kconfig | 4 + board/renesas/condor/Kconfig | 15 +++ board/renesas/condor/MAINTAINERS | 6 + - board/renesas/condor/Makefile | 9 ++ - board/renesas/condor/condor.c | 251 +++++++++++++++++++++++++++++++++++++++ + board/renesas/condor/Makefile | 10 ++ + board/renesas/condor/condor.c | 239 +++++++++++++++++++++++++++++++++++++++ configs/r8a7798_condor_defconfig | 10 ++ - include/configs/r8a7798_condor.h | 159 +++++++++++++++++++++++++ - 7 files changed, 457 insertions(+) + include/configs/r8a7798_condor.h | 160 ++++++++++++++++++++++++++ + 7 files changed, 444 insertions(+) create mode 100644 board/renesas/condor/Kconfig create mode 100644 board/renesas/condor/MAINTAINERS create mode 100644 board/renesas/condor/Makefile @@ -23,7 +23,7 @@ Signed-off-by: Vladimir Barinov create mode 100644 include/configs/r8a7798_condor.h diff --git a/arch/arm/cpu/armv8/Kconfig b/arch/arm/cpu/armv8/Kconfig -index 343b121..0edd5db 100644 +index 58a9259..0edd5db 100644 --- a/arch/arm/cpu/armv8/Kconfig +++ b/arch/arm/cpu/armv8/Kconfig @@ -22,6 +22,9 @@ config TARGET_EAGLE @@ -36,7 +36,7 @@ index 343b121..0edd5db 100644 endchoice config R8A7796X -@@ -53,5 +59,6 @@ source "board/renesas/salvator-x/Kconfig" +@@ -56,5 +59,6 @@ source "board/renesas/salvator-x/Kconfig" source "board/renesas/ulcb/Kconfig" source "board/renesas/eagle/Kconfig" source "board/renesas/v3msk/Kconfig" @@ -66,7 +66,7 @@ index 0000000..21ba79f +endif diff --git a/board/renesas/condor/MAINTAINERS b/board/renesas/condor/MAINTAINERS new file mode 100644 -index 0000000..d0442b8 +index 0000000..9076b24 --- /dev/null +++ b/board/renesas/condor/MAINTAINERS @@ -0,0 +1,6 @@ @@ -78,7 +78,7 @@ index 0000000..d0442b8 +F: configs/r8a7798_condor_defconfig diff --git a/board/renesas/condor/Makefile b/board/renesas/condor/Makefile new file mode 100644 -index 0000000..4c5d29b +index 0000000..d11d859 --- /dev/null +++ b/board/renesas/condor/Makefile @@ -0,0 +1,10 @@ @@ -94,10 +94,10 @@ index 0000000..4c5d29b +obj-y := condor.o ../rcar-gen3-common/common.o diff --git a/board/renesas/condor/condor.c b/board/renesas/condor/condor.c new file mode 100644 -index 0000000..d31e5fd +index 0000000..30c155b --- /dev/null +++ b/board/renesas/condor/condor.c -@@ -0,0 +1,252 @@ +@@ -0,0 +1,239 @@ +/* + * board/renesas/condor/condor.c + * This is Condor board support. @@ -160,10 +160,13 @@ index 0000000..d31e5fd + mstp_clrbits_le32(MSTPSR2, SMSTPCR2, SCIF0_MSTP207); + /* SDHI0/MMC */ + mstp_clrbits_le32(MSTPSR3, SMSTPCR3, SD0_MSTP314); -+ /* Gigabit Ethernet */ -+ mstp_clrbits_le32(MSTPSR8, SMSTPCR8, GETHER_MSTP813); ++#if defined(CONFIG_RAVB) + /* RAVB Ethernet */ + mstp_clrbits_le32(MSTPSR8, SMSTPCR8, RAVB_MSTP812); ++#elif defined(CONFIG_SH_ETHER) ++ /* Gigabit Ethernet */ ++ mstp_clrbits_le32(MSTPSR8, SMSTPCR8, GETHER_MSTP813); ++#endif + /* QSPI/RPC */ + mstp_clrbits_le32(MSTPSR9, SMSTPCR9, RPC_MSTP917); + @@ -175,17 +178,17 @@ index 0000000..d31e5fd + +int board_init(void) +{ -+ /* adress of boot parameters */ ++ /* address of boot parameters */ + gd->bd->bi_boot_params = CONFIG_SYS_TEXT_BASE + 0x50000; + + /* Init PFC controller */ + pinmux_init(); -+#ifdef CONFIG_RAVB ++#if defined(CONFIG_RAVB) + gpio_request(GPIO_GFN_AVB0_AVTP_CAPTURE, NULL); + gpio_request(GPIO_GFN_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_MAGIC, NULL); - PHY reset gpio */ + gpio_request(GPIO_FN_AVB0_MDC, NULL); + gpio_request(GPIO_FN_AVB0_MDIO, NULL); + gpio_request(GPIO_FN_AVB0_TXCREFCLK, NULL); @@ -203,11 +206,10 @@ index 0000000..d31e5fd + gpio_request(GPIO_FN_AVB0_RX_CTL, NULL); + gpio_request(GPIO_IFN_AVB0_AVTP_CAPTURE, NULL); + gpio_request(GPIO_FN_AVB0_AVTP_PPS, NULL); -+#endif -+#ifdef CONFIG_SH_ETHER ++#elif defined(CONFIG_SH_ETHER) + gpio_request(GPIO_FN_GETHER_LINK_A, NULL); + gpio_request(GPIO_FN_GETHER_PHY_INT_A, NULL); -+ /* GPIO_FN_GETHER_MAGIC: PHY reset gpio */ ++ /* gpio_request(GPIO_FN_GETHER_MAGIC, NULL); - PHY reset gpio */ + gpio_request(GPIO_FN_GETHER_MDC_A, NULL); + gpio_request(GPIO_FN_GETHER_MDIO_A, NULL); + gpio_request(GPIO_FN_GETHER_TXCREFCLK, NULL); @@ -245,18 +247,17 @@ index 0000000..d31e5fd + return 0; +} + -+#ifdef CONFIG_RAVB ++#if defined(CONFIG_RAVB) +#define MAHR 0xE68005C0 +#define MALR 0xE68005C8 -+#endif -+#ifdef CONFIG_SH_ETHER ++#elif defined(CONFIG_SH_ETHER) +#define MAHR 0xE74005C0 +#define MALR 0xE74005C8 +#endif +int board_eth_init(bd_t *bis) +{ + int ret = -ENODEV; -+#ifdef CONFIG_RAVB ++ + u32 val; + unsigned char enetaddr[6]; + @@ -270,24 +271,10 @@ index 0000000..d31e5fd + + val = enetaddr[4] << 8 | enetaddr[5]; + writel(val, MALR); -+ ++#if defined(CONFIG_RAVB) + ret = ravb_initialize(bis); -+#endif -+#ifdef CONFIG_SH_ETHER -+ u32 val; -+ unsigned char enetaddr[6]; -+ ++#elif defined(CONFIG_SH_ETHER) + ret = sh_eth_initialize(bis); -+ 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); +#endif + return ret; +} @@ -368,7 +355,7 @@ index 0000000..1cab2ae +CONFIG_SPI_FLASH_BAR=y diff --git a/include/configs/r8a7798_condor.h b/include/configs/r8a7798_condor.h new file mode 100644 -index 0000000..f0b2e0b +index 0000000..a7cc2a0 --- /dev/null +++ b/include/configs/r8a7798_condor.h @@ -0,0 +1,160 @@ @@ -421,7 +408,7 @@ index 0000000..f0b2e0b +#undef CONFIG_SPI_FLASH_SPANSION +#endif + -+#if 1 ++#if 0 +/* Ethernet RAVB */ +#define CONFIG_RAVB +#define CONFIG_RAVB_PHY_ADDR 0x0 @@ -433,7 +420,7 @@ index 0000000..f0b2e0b +#define CONFIG_BITBANGMII_MULTI +#define CONFIG_SH_ETHER_BITBANG +#else -+/* SH Ether */ ++/* GETHER */ +#define CONFIG_NET_MULTI +#define CONFIG_SH_ETHER +#define CONFIG_SH_ETHER_USE_PORT 0 diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch index 346d5dc..30dbeb8 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch @@ -68,7 +68,7 @@ Signed-off-by: Vladimir Barinov arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts | 550 ++++++ arch/arm64/boot/dts/renesas/r8a7797-v3msk-view.dts | 298 ++++ arch/arm64/boot/dts/renesas/r8a7797-v3msk.dts | 314 ++++ - arch/arm64/boot/dts/renesas/r8a7798-condor.dts | 940 +++++++++++ + arch/arm64/boot/dts/renesas/r8a7798-condor.dts | 963 +++++++++++ arch/arm64/boot/dts/renesas/ulcb-kf-cn11.dtsi | 545 ++++++ arch/arm64/boot/dts/renesas/ulcb-kf-most.dtsi | 30 + arch/arm64/boot/dts/renesas/ulcb-kf-sd3.dtsi | 46 + @@ -77,7 +77,7 @@ Signed-off-by: Vladimir Barinov arch/arm64/boot/dts/renesas/ulcb-vb.dtsi | 1726 +++++++++++++++++++ arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi | 1772 ++++++++++++++++++++ arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi | 578 +++++++ - 47 files changed, 20132 insertions(+) + 47 files changed, 20155 insertions(+) create mode 100644 arch/arm64/boot/dts/renesas/legacy/Makefile create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts @@ -11617,7 +11617,7 @@ index 0000000..b92fe83 +}; diff --git a/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts new file mode 100644 -index 0000000..8612f64 +index 0000000..25970c9 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts @@ -0,0 +1,550 @@ @@ -12797,10 +12797,10 @@ index 0000000..91d10c5 +}; diff --git a/arch/arm64/boot/dts/renesas/r8a7798-condor.dts b/arch/arm64/boot/dts/renesas/r8a7798-condor.dts new file mode 100644 -index 0000000..b236d66 +index 0000000..cdd9844 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7798-condor.dts -@@ -0,0 +1,940 @@ +@@ -0,0 +1,963 @@ +/* + * Device Tree Source for the Condor board + * @@ -12823,6 +12823,7 @@ index 0000000..b236d66 + aliases { + serial0 = &scif0; + ethernet0 = &avb; ++ ethernet1 = &gether; + }; + + chosen { @@ -13020,6 +13021,11 @@ index 0000000..b236d66 + function = "avb"; + }; + ++ gether_pins: gether { ++ groups = "gether_mdc_a"; ++ function = "gether"; ++ }; ++ + sdhi2_pins_1v8: sdhi2_1v8 { + groups = "mmc_data8", "mmc_ctrl", "mmc_ds"; + function = "mmc"; @@ -13417,7 +13423,7 @@ index 0000000..b236d66 + pinctrl-names = "default"; + renesas,no-ether-link; + phy-handle = <&phy0>; -+ status = "okay"; ++// status = "okay"; + phy-int-gpio = <&gpio1 17 GPIO_ACTIVE_LOW>; + + phy0: ethernet-phy@0 { @@ -13440,6 +13446,23 @@ index 0000000..b236d66 + }; +}; + ++&gether { ++ pinctrl-0 = <&gether_pins>; ++ pinctrl-names = "default"; ++ renesas,no-ether-link; ++ phy-handle = <&gether_phy>; ++ status = "okay"; ++ phy-gpios = <&gpio4 23 GPIO_ACTIVE_LOW>; ++ phy-reset-gpios = <&gpio4 22 GPIO_ACTIVE_LOW>; ++ ++ gether_phy: ethernet-phy@0 { ++ reg = <0>; ++ interrupt-parent = <&gpio4>; ++ interrupts = <23 IRQ_TYPE_LEVEL_LOW>; ++ max-speed = <1000>; ++ }; ++}; ++ +&vin0 { + status = "okay"; + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch index effd7e2..669f2e8 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch @@ -9,43 +9,45 @@ Signed-off-by: Vladimir Barinov Signed-off-by: Mikhail Ulyanov --- arch/arm64/Kconfig.platforms | 8 + - arch/arm64/boot/dts/renesas/r8a7798.dtsi | 1584 +++++++++++++ + arch/arm64/boot/dts/renesas/r8a7798.dtsi | 1594 +++++++++++++ drivers/clk/renesas/Kconfig | 1 + drivers/clk/renesas/Makefile | 1 + drivers/clk/renesas/r8a7798-cpg-mssr.c | 284 +++ - drivers/clk/renesas/rcar-gen3-cpg.c | 13 +- - drivers/clk/renesas/renesas-cpg-mssr.c | 8 + - drivers/clk/renesas/renesas-cpg-mssr.h | 3 + + drivers/clk/renesas/rcar-gen3-cpg.c | 10 + + drivers/clk/renesas/renesas-cpg-mssr.c | 6 + + drivers/clk/renesas/renesas-cpg-mssr.h | 1 + drivers/cpufreq/cpufreq-dt-platdev.c | 1 + - drivers/gpio/gpio-rcar.c | 7 +- - drivers/gpu/drm/rcar-du/rcar_du_drv.c | 4 +- - drivers/gpu/drm/rcar-du/rcar_du_group.c | 8 +- + drivers/gpio/gpio-rcar.c | 4 + + drivers/gpu/drm/rcar-du/rcar_du_drv.c | 1 + + drivers/gpu/drm/rcar-du/rcar_du_group.c | 5 +- drivers/i2c/busses/i2c-rcar.c | 1 + - drivers/iommu/ipmmu-vmsa.c | 6 +- + drivers/iommu/ipmmu-vmsa.c | 3 + drivers/media/platform/soc_camera/Kconfig | 2 +- drivers/media/platform/soc_camera/rcar_csi2.c | 15 +- drivers/media/platform/soc_camera/rcar_vin.c | 97 +- - drivers/media/platform/vsp1/vsp1_lif.c | 10 +- - drivers/mmc/host/sh_mobile_sdhi.c | 4 +- - drivers/net/ethernet/renesas/ravb_main.c | 4 +- - drivers/pci/host/pcie-rcar.c | 62 +- + drivers/media/platform/vsp1/vsp1_lif.c | 7 +- + drivers/mmc/host/sh_mobile_sdhi.c | 1 + + drivers/net/ethernet/renesas/ravb_main.c | 1 + + drivers/net/ethernet/renesas/sh_eth.c | 53 +- + drivers/net/ethernet/renesas/sh_eth.h | 5 +- + drivers/pci/host/pcie-rcar.c | 59 +- drivers/pinctrl/sh-pfc/Kconfig | 5 + drivers/pinctrl/sh-pfc/Makefile | 1 + - drivers/pinctrl/sh-pfc/core.c | 9 +- + drivers/pinctrl/sh-pfc/core.c | 6 + drivers/pinctrl/sh-pfc/pfc-r8a7798.c | 3151 +++++++++++++++++++++++++ - drivers/pinctrl/sh-pfc/sh_pfc.h | 11 +- + drivers/pinctrl/sh-pfc/sh_pfc.h | 9 +- drivers/soc/renesas/Makefile | 4 + drivers/soc/renesas/r8a7798-sysc.c | 57 + - drivers/soc/renesas/rcar-rst.c | 3 + - drivers/soc/renesas/rcar-sysc.c | 5 + - drivers/soc/renesas/rcar-sysc.h | 3 + - drivers/soc/renesas/rcar_ems_ctrl.c | 8 +- - drivers/soc/renesas/renesas-soc.c | 10 + - drivers/spi/spi-sh-msiof.c | 7 +- - drivers/thermal/rcar_gen3_thermal.c | 13 +- + drivers/soc/renesas/rcar-rst.c | 1 + + drivers/soc/renesas/rcar-sysc.c | 3 + + drivers/soc/renesas/rcar-sysc.h | 1 + + drivers/soc/renesas/rcar_ems_ctrl.c | 5 +- + drivers/soc/renesas/renesas-soc.c | 8 + + drivers/spi/spi-sh-msiof.c | 4 +- + drivers/thermal/rcar_gen3_thermal.c | 10 + include/dt-bindings/clock/r8a7798-cpg-mssr.h | 56 + include/dt-bindings/power/r8a7798-sysc.h | 46 + - 37 files changed, 5470 insertions(+), 42 deletions(-) + 39 files changed, 5493 insertions(+), 34 deletions(-) create mode 100644 arch/arm64/boot/dts/renesas/r8a7798.dtsi create mode 100644 drivers/clk/renesas/r8a7798-cpg-mssr.c create mode 100644 drivers/pinctrl/sh-pfc/pfc-r8a7798.c @@ -54,10 +56,10 @@ Signed-off-by: Mikhail Ulyanov create mode 100644 include/dt-bindings/power/r8a7798-sysc.h diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms -index d3b6771..119a7e3 100644 +index 9cebaad..3646b6e 100644 --- a/arch/arm64/Kconfig.platforms +++ b/arch/arm64/Kconfig.platforms -@@ -172,6 +172,14 @@ config ARCH_R8A7797 +@@ -174,6 +174,14 @@ config ARCH_R8A7797 help This enables support for the Renesas R-Car V3M SoC. @@ -74,10 +76,10 @@ index d3b6771..119a7e3 100644 help diff --git a/arch/arm64/boot/dts/renesas/r8a7798.dtsi b/arch/arm64/boot/dts/renesas/r8a7798.dtsi new file mode 100644 -index 0000000..ee8e282 +index 0000000..c0056b8 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7798.dtsi -@@ -0,0 +1,1584 @@ +@@ -0,0 +1,1594 @@ +/* + * Device Tree Source for the r8a7798 SoC + * @@ -558,7 +560,6 @@ index 0000000..ee8e282 + GIC_SPI 359 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 360 IRQ_TYPE_LEVEL_HIGH>; + -+ + interrupt-names = "error", + "ch0", "ch1", "ch2", "ch3", + "ch4", "ch5", "ch6", "ch7", @@ -665,6 +666,17 @@ index 0000000..ee8e282 + #size-cells = <0>; + }; + ++ gether: ethernet@e7400000 { ++ compatible = "renesas,gether-r8a7798"; ++ reg = <0 0xe7400000 0 0x1000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 813>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ phy-mode = "rgmii"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ + canfd: canfd@e66c0000 { + compatible = "renesas,r8a7798-canfd", + "renesas,rcar-gen3-canfd"; @@ -1688,7 +1700,7 @@ index c2ef11e..9f659d5 100644 obj-$(CONFIG_CLK_RENESAS_CPG_MSSR) += renesas-cpg-mssr.o clk-div6.o diff --git a/drivers/clk/renesas/r8a7798-cpg-mssr.c b/drivers/clk/renesas/r8a7798-cpg-mssr.c new file mode 100644 -index 0000000..c7b68ac +index 0000000..3f82003 --- /dev/null +++ b/drivers/clk/renesas/r8a7798-cpg-mssr.c @@ -0,0 +1,284 @@ @@ -1977,10 +1989,10 @@ index 0000000..c7b68ac + .cpg_clk_register = rcar_gen3_cpg_clk_register, +}; diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c -index b145f14..aa4f5ce 100644 +index b145f14..99acba2 100644 --- a/drivers/clk/renesas/rcar-gen3-cpg.c +++ b/drivers/clk/renesas/rcar-gen3-cpg.c -@@ -33,6 +34,11 @@ +@@ -33,6 +33,11 @@ { /* sentinel */ } }; @@ -1992,7 +2004,7 @@ index b145f14..aa4f5ce 100644 #define CPG_PLL0CR 0x00d8 #define CPG_PLL2CR 0x002c #define CPG_PLL4CR 0x01f4 -@@ -916,6 +922,11 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, +@@ -916,6 +921,11 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, if (cpg_quirks & RCLK_CKSEL_RESEVED) break; @@ -2005,10 +2017,10 @@ index b145f14..aa4f5ce 100644 if (cpg_mode & BIT(28)) parent = clks[cpg_clk_extalr]; diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c -index bd901a6..759facd 100644 +index bd901a6..f1a81ed 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c -@@ -600,6 +602,12 @@ static int __init cpg_mssr_add_clk_domain(struct device *dev, +@@ -600,6 +600,12 @@ static int __init cpg_mssr_add_clk_domain(struct device *dev, .data = &r8a7797_cpg_mssr_info, }, #endif @@ -2022,10 +2034,10 @@ index bd901a6..759facd 100644 }; diff --git a/drivers/clk/renesas/renesas-cpg-mssr.h b/drivers/clk/renesas/renesas-cpg-mssr.h -index ce3546a..d5aaf50 100644 +index ce3546a..70cb4cb 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.h +++ b/drivers/clk/renesas/renesas-cpg-mssr.h -@@ -136,6 +138,7 @@ struct cpg_mssr_info { +@@ -136,6 +136,7 @@ struct cpg_mssr_info { extern const struct cpg_mssr_info r8a7796_cpg_mssr_info; extern const struct cpg_mssr_info r8a77965_cpg_mssr_info; extern const struct cpg_mssr_info r8a7797_cpg_mssr_info; @@ -2046,10 +2058,10 @@ index 5a2ec23..2d7d41c 100644 { .compatible = "rockchip,rk2928", }, diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c -index fd15649..d4549a0 100644 +index fd15649..11044cd 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c -@@ -371,6 +372,10 @@ struct gpio_rcar_info { +@@ -371,6 +371,10 @@ struct gpio_rcar_info { /* Gen3 GPIO is identical to Gen2. */ .data = &gpio_rcar_info_gen2, }, { @@ -2061,10 +2073,10 @@ index fd15649..d4549a0 100644 .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 f74f264..8700e13 100644 +index f74f264..6fea1e2 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c -@@ -360,6 +361,7 @@ +@@ -360,6 +360,7 @@ { .compatible = "renesas,du-r8a7796", .data = &rcar_du_r8a7796_info }, { .compatible = "renesas,du-r8a77965", .data = &rcar_du_r8a77965_info }, { .compatible = "renesas,du-r8a7797", .data = &rcar_du_r8a7797_info }, @@ -2073,10 +2085,10 @@ index f74f264..8700e13 100644 }; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c -index 3916b63..f236103 100644 +index 3916b63..22c7713 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_group.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c -@@ -35,8 +36,9 @@ +@@ -35,8 +35,9 @@ #include "rcar_du_group.h" #include "rcar_du_regs.h" @@ -2087,7 +2099,7 @@ index 3916b63..f236103 100644 { } }; -@@ -161,7 +163,7 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp) +@@ -161,7 +162,7 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp) /* Apply planes to CRTCs association. */ mutex_lock(&rgrp->lock); @@ -2109,10 +2121,10 @@ index 149c107..0ad583a 100644 }; MODULE_DEVICE_TABLE(of, rcar_i2c_dt_ids); diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c -index 1ae9174..add0cd1 100644 +index 1ae9174..41e14fa 100644 --- a/drivers/iommu/ipmmu-vmsa.c +++ b/drivers/iommu/ipmmu-vmsa.c -@@ -1280,6 +1281,9 @@ static void ipmmu_device_reset(struct ipmmu_vmsa_device *mmu) +@@ -1280,6 +1280,9 @@ static void ipmmu_device_reset(struct ipmmu_vmsa_device *mmu) .compatible = "renesas,ipmmu-r8a7797", .data = &ipmmu_features_rcar_gen3, }, { @@ -2424,10 +2436,10 @@ index 7bd8a77..1e098ef 100644 for (i = 0; i < num; i++) { diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c -index e79f9e6..948e88c 100644 +index e79f9e6..4802899 100644 --- a/drivers/media/platform/vsp1/vsp1_lif.c +++ b/drivers/media/platform/vsp1/vsp1_lif.c -@@ -24,8 +25,9 @@ +@@ -24,8 +24,9 @@ #define LIF_MIN_SIZE 2U #define LIF_MAX_SIZE 8190U @@ -2438,7 +2450,7 @@ index e79f9e6..948e88c 100644 { } }; -@@ -151,7 +153,7 @@ static void lif_configure(struct vsp1_entity *entity, +@@ -151,7 +152,7 @@ static void lif_configure(struct vsp1_entity *entity, format = vsp1_entity_get_pad_format(&lif->entity, lif->entity.config, LIF_PAD_SOURCE); @@ -2447,7 +2459,7 @@ index e79f9e6..948e88c 100644 obth = 1500; else obth = 3000; -@@ -165,7 +167,7 @@ static void lif_configure(struct vsp1_entity *entity, +@@ -165,7 +166,7 @@ static void lif_configure(struct vsp1_entity *entity, (format->code == 0 ? VI6_LIF_CTRL_CFMT : 0) | VI6_LIF_CTRL_REQSEL | VI6_LIF_CTRL_LIF_EN); @@ -2457,10 +2469,10 @@ index e79f9e6..948e88c 100644 VI6_LIF_LBA_LBA1); } diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c -index 040f474..bee1116 100644 +index 040f474..72b46bb 100644 --- a/drivers/mmc/host/sh_mobile_sdhi.c +++ b/drivers/mmc/host/sh_mobile_sdhi.c -@@ -141,6 +142,7 @@ struct sh_mobile_sdhi_of_data { +@@ -141,6 +141,7 @@ struct sh_mobile_sdhi_of_data { { .compatible = "renesas,sdhi-r8a77965", .data = &of_rcar_gen3_compatible, }, { .compatible = "renesas,sdhi-r8a7797", .data = &of_rcar_gen3_compatible, }, @@ -2469,10 +2481,10 @@ index 040f474..bee1116 100644 }; 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 73fa286..9943197 100644 +index 73fa286..c539234 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c -@@ -1921,6 +1922,7 @@ static int ravb_mdio_release(struct ravb_private *priv) +@@ -1921,6 +1921,7 @@ static int ravb_mdio_release(struct ravb_private *priv) { .compatible = "renesas,etheravb-r8a7796", .data = (void *)RCAR_GEN3 }, { .compatible = "renesas,etheravb-r8a77965", .data = (void *)RCAR_GEN3 }, { .compatible = "renesas,etheravb-r8a7797", .data = (void *)RCAR_GEN3 }, @@ -2480,11 +2492,155 @@ index 73fa286..9943197 100644 { .compatible = "renesas,etheravb-rcar-gen3", .data = (void *)RCAR_GEN3 }, { } }; +diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c +index d18b452..f87cae6 100644 +--- a/drivers/net/ethernet/renesas/sh_eth.c ++++ b/drivers/net/ethernet/renesas/sh_eth.c +@@ -456,6 +456,9 @@ static void sh_eth_select_mii(struct net_device *ndev) + u32 value; + + switch (mdp->phy_interface) { ++ case PHY_INTERFACE_MODE_RGMII: ++ value = 0x3; ++ break; + case PHY_INTERFACE_MODE_GMII: + value = 0x2; + break; +@@ -645,6 +648,36 @@ static void sh_eth_set_rate_r8a777x(struct net_device *ndev) + .rmiimode = 1, + .magic = 1, + }; ++ ++/* R8A7798 */ ++static struct sh_eth_cpu_data r8a7798_data = { ++ .set_duplex = sh_eth_set_duplex, ++ .set_rate = sh_eth_set_rate_gether, ++ ++ .register_type = SH_ETH_REG_GIGABIT, ++ ++ .ecsr_value = ECSR_PSRTO | ECSR_LCHNG | ECSR_ICD | ECSR_MPD, ++ .ecsipr_value = ECSIPR_PSRTOIP | ECSIPR_LCHNGIP | ECSIPR_ICDIP | ++ ECSIPR_MPDIP, ++ .eesipr_value = 0x01ff009f, ++ ++ .tx_check = EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | EESR_RTO, ++ .eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | ++ EESR_RFE | EESR_RDE | EESR_RFRMER | EESR_TFE | ++ EESR_TDE | EESR_ECI, ++ .fdr_value = 0x0000070f, ++ ++ .apr = 1, ++ .mpr = 1, ++ .tpauser = 1, ++ .nbst = 1, ++ .hw_swap = 1, ++ .no_trimd = 1, ++ .no_ade = 1, ++ .select_mii = 1, ++ .shift_rd0 = 1, ++ .magic = 1, ++}; + #endif /* CONFIG_OF */ + + static void sh_eth_set_rate_sh7724(struct net_device *ndev) +@@ -1088,14 +1121,14 @@ static void sh_eth_ring_free(struct net_device *ndev) + + if (mdp->rx_ring) { + ringsize = sizeof(struct sh_eth_rxdesc) * mdp->num_rx_ring; +- dma_free_coherent(NULL, ringsize, mdp->rx_ring, ++ dma_free_coherent(&ndev->dev, ringsize, mdp->rx_ring, + mdp->rx_desc_dma); + mdp->rx_ring = NULL; + } + + if (mdp->tx_ring) { + ringsize = sizeof(struct sh_eth_txdesc) * mdp->num_tx_ring; +- dma_free_coherent(NULL, ringsize, mdp->tx_ring, ++ dma_free_coherent(&ndev->dev, ringsize, mdp->tx_ring, + mdp->tx_desc_dma); + mdp->tx_ring = NULL; + } +@@ -1209,9 +1242,16 @@ static int sh_eth_ring_init(struct net_device *ndev) + if (!mdp->tx_skbuff) + goto ring_free; + ++#ifdef CONFIG_ARM64 ++ { ++ struct device_node *np; ++ np = of_find_compatible_node(NULL, NULL, "shared-dma-pool"); ++ of_dma_configure(&ndev->dev, np); ++ } ++#endif + /* Allocate all Rx descriptors. */ + rx_ringsize = sizeof(struct sh_eth_rxdesc) * mdp->num_rx_ring; +- mdp->rx_ring = dma_alloc_coherent(NULL, rx_ringsize, &mdp->rx_desc_dma, ++ mdp->rx_ring = dma_alloc_coherent(&ndev->dev, rx_ringsize, &mdp->rx_desc_dma, + GFP_KERNEL); + if (!mdp->rx_ring) + goto ring_free; +@@ -1220,7 +1260,7 @@ static int sh_eth_ring_init(struct net_device *ndev) + + /* Allocate all Tx descriptors. */ + tx_ringsize = sizeof(struct sh_eth_txdesc) * mdp->num_tx_ring; +- mdp->tx_ring = dma_alloc_coherent(NULL, tx_ringsize, &mdp->tx_desc_dma, ++ mdp->tx_ring = dma_alloc_coherent(&ndev->dev, tx_ringsize, &mdp->tx_desc_dma, + GFP_KERNEL); + if (!mdp->tx_ring) + goto ring_free; +@@ -1261,6 +1301,10 @@ static int sh_eth_dev_init(struct net_device *ndev) + #endif + sh_eth_write(ndev, 0, EDMR); + ++ /* DMA transfer burst mode */ ++ if (mdp->cd->nbst) ++ sh_eth_modify(ndev, EDMR, EDMR_NBST, EDMR_NBST); ++ + /* FIFO size set */ + sh_eth_write(ndev, mdp->cd->fdr_value, FDR); + sh_eth_write(ndev, 0, TFTR); +@@ -3001,6 +3045,7 @@ static struct sh_eth_plat_data *sh_eth_parse_dt(struct device *dev) + { .compatible = "renesas,ether-r8a7791", .data = &r8a779x_data }, + { .compatible = "renesas,ether-r8a7793", .data = &r8a779x_data }, + { .compatible = "renesas,ether-r8a7794", .data = &r8a779x_data }, ++ { .compatible = "renesas,gether-r8a7798", .data = &r8a7798_data }, + { .compatible = "renesas,ether-r7s72100", .data = &r7s72100_data }, + { } + }; +diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h +index 4ceed00..2c4ddd6 100644 +--- a/drivers/net/ethernet/renesas/sh_eth.h ++++ b/drivers/net/ethernet/renesas/sh_eth.h +@@ -163,7 +163,8 @@ enum { + }; + + /* Driver's parameters */ +-#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE) ++#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE) || \ ++ defined(CONFIG_ARCH_R8A7798) + #define SH_ETH_RX_ALIGN 32 + #else + #define SH_ETH_RX_ALIGN 2 +@@ -184,6 +185,7 @@ enum GECMR_BIT { + + /* EDMR */ + enum DMAC_M_BIT { ++ EDMR_NBST = 0x80, + EDMR_EL = 0x40, /* Litte endian */ + EDMR_DL1 = 0x20, EDMR_DL0 = 0x10, + EDMR_SRST_GETHER = 0x03, +@@ -484,6 +486,7 @@ struct sh_eth_cpu_data { + unsigned tpauser:1; /* EtherC have TPAUSER */ + unsigned bculr:1; /* EtherC have BCULR */ + unsigned tsu:1; /* EtherC have TSU */ ++ unsigned nbst:1; /* E-DMAC have NBST bit in EDMR */ + unsigned hw_swap:1; /* E-DMAC have DE bit in EDMR */ + unsigned rpadir:1; /* E-DMAC have RPADIR */ + unsigned no_trimd:1; /* E-DMAC DO NOT have TRIMD */ diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c -index ccc29b3..2eb13c6 100644 +index ccc29b3..ebe7e92 100644 --- a/drivers/pci/host/pcie-rcar.c +++ b/drivers/pci/host/pcie-rcar.c -@@ -30,6 +31,7 @@ +@@ -30,6 +30,7 @@ #include #include #include @@ -2492,7 +2648,7 @@ index ccc29b3..2eb13c6 100644 #define PCIECAR 0x000010 #define PCIECCTLR 0x000018 -@@ -41,6 +43,8 @@ +@@ -41,6 +42,8 @@ #define PCIEINTXR 0x000400 #define PCIEMSITXR 0x000840 @@ -2501,7 +2657,7 @@ index ccc29b3..2eb13c6 100644 /* Transfer control */ #define PCIETCTLR 0x02000 #define DL_DOWN (1 << 3) -@@ -118,6 +122,9 @@ +@@ -118,6 +121,9 @@ #define GEN2_PCIEPHYDATA 0x784 #define GEN2_PCIEPHYCTRL 0x78c @@ -2511,7 +2667,7 @@ index ccc29b3..2eb13c6 100644 #define INT_PCI_MSI_NR 32 #define RCONF(x) (PCICONF(0)+(x)) -@@ -132,6 +139,11 @@ +@@ -132,6 +138,11 @@ #define RCAR_PCI_MAX_RESOURCES 4 #define MAX_NR_INBOUND_MAPS 6 @@ -2523,7 +2679,7 @@ index ccc29b3..2eb13c6 100644 struct rcar_msi { DECLARE_BITMAP(used, INT_PCI_MSI_NR); struct irq_domain *domain; -@@ -151,6 +163,7 @@ static inline struct rcar_msi *to_rcar_msi(struct msi_controller *chip) +@@ -151,6 +162,7 @@ static inline struct rcar_msi *to_rcar_msi(struct msi_controller *chip) struct rcar_pcie { struct device *dev; void __iomem *base; @@ -2531,7 +2687,7 @@ index ccc29b3..2eb13c6 100644 struct list_head resources; int root_bus_nr; struct clk *clk; -@@ -160,6 +173,18 @@ struct rcar_pcie { +@@ -160,6 +172,18 @@ struct rcar_pcie { static int rcar_pcie_wait_for_dl(struct rcar_pcie *pcie); @@ -2550,7 +2706,7 @@ index ccc29b3..2eb13c6 100644 static void rcar_pci_write_reg(struct rcar_pcie *pcie, unsigned long val, unsigned long reg) { -@@ -672,6 +697,22 @@ static int rcar_pcie_hw_init(struct rcar_pcie *pcie) +@@ -672,6 +696,22 @@ static int rcar_pcie_hw_init(struct rcar_pcie *pcie) return 0; } @@ -2573,7 +2729,7 @@ index ccc29b3..2eb13c6 100644 static int rcar_pcie_hw_init_h1(struct rcar_pcie *pcie) { unsigned int timeout = 10; -@@ -998,6 +1039,16 @@ static int rcar_pcie_get_resources(struct rcar_pcie *pcie) +@@ -998,6 +1038,16 @@ static int rcar_pcie_get_resources(struct rcar_pcie *pcie) if (IS_ERR(pcie->base)) return PTR_ERR(pcie->base); @@ -2590,7 +2746,7 @@ index ccc29b3..2eb13c6 100644 pcie->bus_clk = devm_clk_get(dev, "pcie_bus"); if (IS_ERR(pcie->bus_clk)) { dev_err(dev, "cannot get pcie bus clock\n"); -@@ -1153,6 +1204,7 @@ static int rcar_pcie_parse_map_dma_ranges(struct rcar_pcie *pcie, +@@ -1153,6 +1203,7 @@ static int rcar_pcie_parse_map_dma_ranges(struct rcar_pcie *pcie, { .compatible = "renesas,pcie-r8a7795", .data = rcar_pcie_hw_init }, { .compatible = "renesas,pcie-r8a7796", .data = rcar_pcie_hw_init }, { .compatible = "renesas,pcie-r8a77965", .data = rcar_pcie_hw_init }, @@ -2598,7 +2754,7 @@ index ccc29b3..2eb13c6 100644 {}, }; -@@ -1347,7 +1399,13 @@ static SIMPLE_DEV_PM_OPS(rcar_pcie_pm_ops, +@@ -1347,7 +1398,13 @@ static SIMPLE_DEV_PM_OPS(rcar_pcie_pm_ops, }, .probe = rcar_pcie_probe, }; @@ -2642,10 +2798,10 @@ index e263c14..5f2f619 100644 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 9aba933..a75293f 100644 +index 9aba933..d685090 100644 --- a/drivers/pinctrl/sh-pfc/core.c +++ b/drivers/pinctrl/sh-pfc/core.c -@@ -552,6 +553,12 @@ static int sh_pfc_init_ranges(struct sh_pfc *pfc) +@@ -552,6 +552,12 @@ static int sh_pfc_init_ranges(struct sh_pfc *pfc) .data = &r8a7797_pinmux_info, }, #endif @@ -2660,7 +2816,7 @@ index 9aba933..a75293f 100644 .compatible = "renesas,pfc-sh73a0", diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7798.c b/drivers/pinctrl/sh-pfc/pfc-r8a7798.c new file mode 100644 -index 0000000..740bf4e +index 0000000..39aba74 --- /dev/null +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7798.c @@ -0,0 +1,3151 @@ @@ -5816,10 +5972,10 @@ index 0000000..740bf4e + .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 062af89..31df6d4 100644 +index 062af89..eaf052d 100644 --- a/drivers/pinctrl/sh-pfc/sh_pfc.h +++ b/drivers/pinctrl/sh-pfc/sh_pfc.h -@@ -289,6 +291,7 @@ struct sh_pfc_soc_info { +@@ -289,6 +289,7 @@ struct sh_pfc_soc_info { extern const struct sh_pfc_soc_info r8a7796_pinmux_info; extern const struct sh_pfc_soc_info r8a77965_pinmux_info; extern const struct sh_pfc_soc_info r8a7797_pinmux_info; @@ -5827,7 +5983,7 @@ index 062af89..31df6d4 100644 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; -@@ -465,9 +468,13 @@ struct sh_pfc_soc_info { +@@ -465,9 +466,13 @@ struct sh_pfc_soc_info { PORT_GP_CFG_1(bank, 23, fn, sfx, cfg) #define PORT_GP_24(bank, fn, sfx) PORT_GP_CFG_24(bank, fn, sfx, 0) @@ -5876,7 +6032,7 @@ index 2ba6a76..164b3e7 100644 obj-$(CONFIG_RCAR_DDR_BACKUP) += s2ram_ddr_backup.o diff --git a/drivers/soc/renesas/r8a7798-sysc.c b/drivers/soc/renesas/r8a7798-sysc.c new file mode 100644 -index 0000000..d530488 +index 0000000..e663c74 --- /dev/null +++ b/drivers/soc/renesas/r8a7798-sysc.c @@ -0,0 +1,57 @@ @@ -5938,10 +6094,10 @@ index 0000000..d530488 + .num_areas = ARRAY_SIZE(r8a7798_areas), +}; diff --git a/drivers/soc/renesas/rcar-rst.c b/drivers/soc/renesas/rcar-rst.c -index bc3632b..19b441b 100644 +index bc3632b..8906817 100644 --- a/drivers/soc/renesas/rcar-rst.c +++ b/drivers/soc/renesas/rcar-rst.c -@@ -43,6 +45,7 @@ struct rst_config { +@@ -43,6 +43,7 @@ struct rst_config { { .compatible = "renesas,r8a7796-rst", .data = &rcar_rst_gen2 }, { .compatible = "renesas,r8a77965-rst", .data = &rcar_rst_gen2 }, { .compatible = "renesas,r8a7797-rst", .data = &rcar_rst_gen2 }, @@ -5950,10 +6106,10 @@ index bc3632b..19b441b 100644 }; diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c -index 1d5d440..87d5c21 100644 +index 1d5d440..bfde184 100644 --- a/drivers/soc/renesas/rcar-sysc.c +++ b/drivers/soc/renesas/rcar-sysc.c -@@ -327,6 +329,9 @@ static void __init rcar_sysc_pd_setup(struct rcar_sysc_pd *pd) +@@ -327,6 +327,9 @@ static void __init rcar_sysc_pd_setup(struct rcar_sysc_pd *pd) #ifdef CONFIG_ARCH_R8A7797 { .compatible = "renesas,r8a7797-sysc", .data = &r8a7797_sysc_info }, #endif @@ -5964,20 +6120,20 @@ index 1d5d440..87d5c21 100644 }; diff --git a/drivers/soc/renesas/rcar-sysc.h b/drivers/soc/renesas/rcar-sysc.h -index 1eb4e6d..c3b5bce 100644 +index 1eb4e6d..dc58a58 100644 --- a/drivers/soc/renesas/rcar-sysc.h +++ b/drivers/soc/renesas/rcar-sysc.h -@@ -62,4 +64,5 @@ struct rcar_sysc_info { +@@ -62,4 +62,5 @@ struct rcar_sysc_info { extern const struct rcar_sysc_info r8a7796_sysc_info; extern const struct rcar_sysc_info r8a77965_sysc_info; extern const struct rcar_sysc_info r8a7797_sysc_info; +extern const struct rcar_sysc_info r8a7798_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 388c570..007e203 100644 +index 388c570..516858d 100644 --- a/drivers/soc/renesas/rcar_ems_ctrl.c +++ b/drivers/soc/renesas/rcar_ems_ctrl.c -@@ -30,8 +31,9 @@ +@@ -30,8 +30,9 @@ #define EMS_THERMAL_ZONE_MAX 10 @@ -5988,7 +6144,7 @@ index 388c570..007e203 100644 { } }; -@@ -274,7 +276,7 @@ static int __init rcar_ems_cpu_shutdown_init(void) +@@ -274,7 +275,7 @@ static int __init rcar_ems_cpu_shutdown_init(void) for_each_online_cpu(cpu) { tmp_node = of_get_cpu_node(cpu, NULL); @@ -5998,10 +6154,10 @@ index 388c570..007e203 100644 continue; } diff --git a/drivers/soc/renesas/renesas-soc.c b/drivers/soc/renesas/renesas-soc.c -index 63f943d..c107f7c 100644 +index 63f943d..b1fcae1 100644 --- a/drivers/soc/renesas/renesas-soc.c +++ b/drivers/soc/renesas/renesas-soc.c -@@ -144,6 +146,11 @@ struct renesas_soc { +@@ -144,6 +144,11 @@ struct renesas_soc { .id = 0x54, }; @@ -6013,7 +6169,7 @@ index 63f943d..c107f7c 100644 static const struct renesas_soc soc_shmobile_ag5 __initconst __maybe_unused = { .family = &fam_shmobile, .id = 0x37, -@@ -199,6 +206,9 @@ struct renesas_soc { +@@ -199,6 +204,9 @@ struct renesas_soc { #ifdef CONFIG_ARCH_R8A7797 { .compatible = "renesas,r8a7797", .data = &soc_rcar_v3m }, #endif @@ -6024,10 +6180,10 @@ index 63f943d..c107f7c 100644 { .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 a2606fe..bbe2526 100644 +index a2606fe..13fd706 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c -@@ -217,7 +218,8 @@ static int msiof_rcar_is_gen3(struct device *dev) +@@ -217,7 +217,8 @@ static int msiof_rcar_is_gen3(struct device *dev) return of_device_is_compatible(node, "renesas,msiof-r8a7795") || of_device_is_compatible(node, "renesas,msiof-r8a7796") || of_device_is_compatible(node, "renesas,msiof-r8a77965") || @@ -6037,7 +6193,7 @@ index a2606fe..bbe2526 100644 } static u32 sh_msiof_read(struct sh_msiof_spi_priv *p, int reg_offs) -@@ -1192,6 +1194,7 @@ static int sh_msiof_transfer_one(struct spi_master *master, +@@ -1192,6 +1193,7 @@ static int sh_msiof_transfer_one(struct spi_master *master, { .compatible = "renesas,msiof-r8a7796", .data = &r8a779x_data }, { .compatible = "renesas,msiof-r8a77965", .data = &r8a779x_data }, { .compatible = "renesas,msiof-r8a7797", .data = &r8a779x_data }, @@ -6046,10 +6202,10 @@ index a2606fe..bbe2526 100644 }; MODULE_DEVICE_TABLE(of, sh_msiof_match); diff --git a/drivers/thermal/rcar_gen3_thermal.c b/drivers/thermal/rcar_gen3_thermal.c -index a23dd44..44bc4fd 100644 +index a23dd44..90978c2 100644 --- a/drivers/thermal/rcar_gen3_thermal.c +++ b/drivers/thermal/rcar_gen3_thermal.c -@@ -415,6 +416,11 @@ static int rcar_gen3_r8a7797_thermal_init(struct rcar_thermal_priv *priv) +@@ -415,6 +415,11 @@ static int rcar_gen3_r8a7797_thermal_init(struct rcar_thermal_priv *priv) return 0; } @@ -6061,7 +6217,7 @@ index a23dd44..44bc4fd 100644 /* * Interrupt */ -@@ -500,11 +506,16 @@ static int rcar_gen3_thermal_remove(struct platform_device *pdev) +@@ -500,11 +505,16 @@ static int rcar_gen3_thermal_remove(struct platform_device *pdev) .thermal_init = rcar_gen3_r8a7797_thermal_init, }; @@ -6080,7 +6236,7 @@ index a23dd44..44bc4fd 100644 MODULE_DEVICE_TABLE(of, rcar_thermal_dt_ids); diff --git a/include/dt-bindings/clock/r8a7798-cpg-mssr.h b/include/dt-bindings/clock/r8a7798-cpg-mssr.h new file mode 100644 -index 0000000..6c2d97a +index 0000000..3d85730 --- /dev/null +++ b/include/dt-bindings/clock/r8a7798-cpg-mssr.h @@ -0,0 +1,56 @@ @@ -6142,7 +6298,7 @@ index 0000000..6c2d97a +#endif /* __DT_BINDINGS_CLOCK_R8A7798_CPG_MSSR_H__ */ diff --git a/include/dt-bindings/power/r8a7798-sysc.h b/include/dt-bindings/power/r8a7798-sysc.h new file mode 100644 -index 0000000..2451b16 +index 0000000..c10d60e --- /dev/null +++ b/include/dt-bindings/power/r8a7798-sysc.h @@ -0,0 +1,46 @@ diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/condor.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/condor.cfg index 46f8879..c32c426 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/condor.cfg +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/condor.cfg @@ -27,3 +27,6 @@ CONFIG_TOUCHSCREEN_PROPERTIES=y CONFIG_HID_MULTITOUCH=y CONFIG_SERIAL_SH_SCI_DMA=y CONFIG_UIO=y +CONFIG_SH_ETH=y +CONFIG_BLK_DEV_NVME=m +CONFIG_SATA_ACARD_AHCI=y -- cgit 1.2.3-korg From c3071eefebc05eea24ee73250546084e8fd8d3c6 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Sun, 28 Jan 2018 02:54:39 +0300 Subject: Use POC-supply in VB, VB2 based board 1) replace gpio-hog power with POC-supply regulator on VideoBox and VideoBox2 boards 2) remove sensor-delay filed form dts if it is 0 and if it is replaced with POC-supply --- .../0040-arm64-dts-renesas-add-ADAS-boards.patch | 522 ++++++++++++--------- 1 file changed, 308 insertions(+), 214 deletions(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch index 30dbeb8..119042c 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch @@ -32,11 +32,11 @@ Signed-off-by: Vladimir Barinov --- arch/arm64/boot/dts/renesas/Makefile | 21 + arch/arm64/boot/dts/renesas/legacy/Makefile | 8 + - .../renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts | 1710 +++++++++++++++++++ + .../renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts | 1710 ++++++++++++++++++ .../renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts | 441 +++++ .../dts/renesas/legacy/r8a7795-h3ulcb-kf-v0.dts | 1724 +++++++++++++++++++ .../dts/renesas/legacy/r8a7795-h3ulcb-kf-v1.dts | 465 +++++ - .../dts/renesas/legacy/r8a7796-m3ulcb-kf-v0.dts | 1214 ++++++++++++++ + .../dts/renesas/legacy/r8a7796-m3ulcb-kf-v0.dts | 1214 +++++++++++++ .../dts/renesas/legacy/r8a7796-m3ulcb-kf-v1.dts | 465 +++++ .../dts/renesas/legacy/r8a7797-v3msk-kf-v0.dts | 82 + .../boot/dts/renesas/legacy/ulcb-kf-cmos.dtsi | 75 + @@ -48,8 +48,8 @@ Signed-off-by: Vladimir Barinov .../boot/dts/renesas/r8a7795-es1-h3ulcb-vb.dts | 69 + .../boot/dts/renesas/r8a7795-es1-h3ulcb-vb2.dts | 77 + .../boot/dts/renesas/r8a7795-es1-h3ulcb-vbm.dts | 26 + - .../boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts | 546 ++++++ - .../dts/renesas/r8a7795-es1-salvator-x-view.dts | 552 ++++++ + .../boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts | 544 ++++++ + .../dts/renesas/r8a7795-es1-salvator-x-view.dts | 550 ++++++ .../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 | 215 +++ @@ -57,27 +57,27 @@ Signed-off-by: Vladimir Barinov arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vb.dts | 68 + arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vb2.dts | 68 + arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vbm.dts | 26 + - .../arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts | 546 ++++++ - .../boot/dts/renesas/r8a7795-salvator-x-view.dts | 552 ++++++ + .../arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts | 544 ++++++ + .../boot/dts/renesas/r8a7795-salvator-x-view.dts | 550 ++++++ arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts | 40 + - .../arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts | 287 ++++ - .../boot/dts/renesas/r8a7796-salvator-x-view.dts | 318 ++++ + .../arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts | 286 +++ + .../boot/dts/renesas/r8a7796-salvator-x-view.dts | 317 ++++ .../boot/dts/renesas/r8a7797-eagle-function.dts | 62 + arch/arm64/boot/dts/renesas/r8a7797-eagle.dts | 575 +++++++ - arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts | 578 +++++++ - arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts | 550 ++++++ - arch/arm64/boot/dts/renesas/r8a7797-v3msk-view.dts | 298 ++++ + arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts | 575 +++++++ + arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts | 548 ++++++ + arch/arm64/boot/dts/renesas/r8a7797-v3msk-view.dts | 297 ++++ arch/arm64/boot/dts/renesas/r8a7797-v3msk.dts | 314 ++++ arch/arm64/boot/dts/renesas/r8a7798-condor.dts | 963 +++++++++++ arch/arm64/boot/dts/renesas/ulcb-kf-cn11.dtsi | 545 ++++++ arch/arm64/boot/dts/renesas/ulcb-kf-most.dtsi | 30 + arch/arm64/boot/dts/renesas/ulcb-kf-sd3.dtsi | 46 + - arch/arm64/boot/dts/renesas/ulcb-kf.dtsi | 1542 +++++++++++++++++ - arch/arm64/boot/dts/renesas/ulcb-vb-cn12.dtsi | 515 ++++++ - arch/arm64/boot/dts/renesas/ulcb-vb.dtsi | 1726 +++++++++++++++++++ - arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi | 1772 ++++++++++++++++++++ - arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi | 578 +++++++ - 47 files changed, 20155 insertions(+) + arch/arm64/boot/dts/renesas/ulcb-kf.dtsi | 1538 +++++++++++++++++ + arch/arm64/boot/dts/renesas/ulcb-vb-cn12.dtsi | 542 ++++++ + arch/arm64/boot/dts/renesas/ulcb-vb.dtsi | 1770 +++++++++++++++++++ + arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi | 1816 ++++++++++++++++++++ + arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi | 577 +++++++ + 47 files changed, 20249 insertions(+) create mode 100644 arch/arm64/boot/dts/renesas/legacy/Makefile create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts @@ -6998,10 +6998,10 @@ index 0000000..323722c +}; 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..6eb7cac +index 0000000..d91120e --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts -@@ -0,0 +1,546 @@ +@@ -0,0 +1,544 @@ +/* + * Device Tree Source for the H3ULCB.View board on r8a7795 ES1.x + * @@ -7168,7 +7168,6 @@ index 0000000..6eb7cac + compatible = "maxim,max9286"; + reg = <0x4c>; + gpios = <&gpio2 6 GPIO_ACTIVE_HIGH>; -+ maxim,sensor_delay = <0>; + maxim,links = <4>; + maxim,lanes = <4>; + maxim,resetb-gpio = <1>; @@ -7210,7 +7209,6 @@ index 0000000..6eb7cac + compatible = "maxim,max9286"; + reg = <0x6c>; + gpios = <&gpio5 25 GPIO_ACTIVE_HIGH>; -+ maxim,sensor_delay = <0>; + maxim,links = <4>; + maxim,lanes = <4>; + maxim,resetb-gpio = <1>; @@ -7550,10 +7548,10 @@ index 0000000..6eb7cac +}; 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..d4caf46 +index 0000000..a00147c --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x-view.dts -@@ -0,0 +1,552 @@ +@@ -0,0 +1,550 @@ +/* + * Device Tree Source for the Salvator-X.View board on r8a7795 ES1.x + * @@ -7735,7 +7733,6 @@ index 0000000..d4caf46 + compatible = "maxim,max9286"; + reg = <0x4c>; + gpios = <&gpio6 30 GPIO_ACTIVE_LOW>; -+ maxim,sensor_delay = <0>; + maxim,links = <4>; + maxim,lanes = <4>; + maxim,resetb-gpio = <1>; @@ -7776,7 +7773,6 @@ index 0000000..d4caf46 + max9286@1 { + compatible = "maxim,max9286"; + reg = <0x6c>; -+ maxim,sensor_delay = <0>; + maxim,links = <4>; + maxim,lanes = <4>; + maxim,resetb-gpio = <1>; @@ -8611,10 +8607,10 @@ index 0000000..87f1889 +}; 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..8541518 +index 0000000..d6adc07 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts -@@ -0,0 +1,546 @@ +@@ -0,0 +1,544 @@ +/* + * Device Tree Source for the H3ULCB.View board + * @@ -8781,7 +8777,6 @@ index 0000000..8541518 + compatible = "maxim,max9286"; + reg = <0x4c>; + gpios = <&gpio2 6 GPIO_ACTIVE_HIGH>; -+ maxim,sensor_delay = <0>; + maxim,links = <4>; + maxim,lanes = <4>; + maxim,resetb-gpio = <1>; @@ -8823,7 +8818,6 @@ index 0000000..8541518 + compatible = "maxim,max9286"; + reg = <0x6c>; + gpios = <&gpio5 25 GPIO_ACTIVE_HIGH>; -+ maxim,sensor_delay = <0>; + maxim,links = <4>; + maxim,lanes = <4>; + maxim,resetb-gpio = <1>; @@ -9163,10 +9157,10 @@ index 0000000..8541518 +}; 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..14539ea +index 0000000..54c585d --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x-view.dts -@@ -0,0 +1,552 @@ +@@ -0,0 +1,550 @@ +/* + * Device Tree Source for the Salvator-X.View board + * @@ -9348,7 +9342,6 @@ index 0000000..14539ea + compatible = "maxim,max9286"; + reg = <0x4c>; + gpios = <&gpio6 30 GPIO_ACTIVE_LOW>; -+ maxim,sensor_delay = <0>; + maxim,links = <4>; + maxim,lanes = <4>; + maxim,resetb-gpio = <1>; @@ -9389,7 +9382,6 @@ index 0000000..14539ea + max9286@1 { + compatible = "maxim,max9286"; + reg = <0x6c>; -+ maxim,sensor_delay = <0>; + maxim,links = <4>; + maxim,lanes = <4>; + maxim,resetb-gpio = <1>; @@ -9767,10 +9759,10 @@ index 0000000..a409402 +}; 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..ea7f378 +index 0000000..bfbd897 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts -@@ -0,0 +1,287 @@ +@@ -0,0 +1,286 @@ +/* + * Device Tree Source for the M3ULCB.View board on r8a7796 + * @@ -9865,7 +9857,6 @@ index 0000000..ea7f378 + compatible = "maxim,max9286"; + reg = <0x4c>; + gpios = <&gpio2 6 GPIO_ACTIVE_HIGH>; -+ maxim,sensor_delay = <0>; + maxim,links = <4>; + maxim,lanes = <4>; + maxim,resetb-gpio = <1>; @@ -10060,10 +10051,10 @@ index 0000000..ea7f378 +}; 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..319120f +index 0000000..c515046 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7796-salvator-x-view.dts -@@ -0,0 +1,318 @@ +@@ -0,0 +1,317 @@ +/* + * Device Tree Source for the Salvator-X.View board + * @@ -10173,7 +10164,6 @@ index 0000000..319120f + compatible = "maxim,max9286"; + reg = <0x4c>; + gpios = <&gpio6 30 GPIO_ACTIVE_LOW>; -+ maxim,sensor_delay = <0>; + maxim,links = <4>; + maxim,lanes = <4>; + maxim,resetb-gpio = <1>; @@ -11033,10 +11023,10 @@ index 0000000..ce7a88e +}; diff --git a/arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts new file mode 100644 -index 0000000..b92fe83 +index 0000000..9158c84 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts -@@ -0,0 +1,578 @@ +@@ -0,0 +1,575 @@ +/* + * Device Tree Source for the V3MSK Kingfisher board on r8a7797 + * @@ -11221,7 +11211,6 @@ index 0000000..b92fe83 + ti964-ti9x3@0 { + compatible = "ti,ti964-ti9x3"; + reg = <0x3a>; -+ ti,sensor_delay = <350>; + ti,links = <4>; + ti,lanes = <4>; + ti,forwarding-mode = "round-robin"; @@ -11262,7 +11251,6 @@ index 0000000..b92fe83 + 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"; @@ -11292,7 +11280,6 @@ index 0000000..b92fe83 + max9286@0 { + compatible = "maxim,max9286"; + reg = <0x2c>; -+ maxim,sensor_delay = <350>; + maxim,links = <4>; + maxim,lanes = <4>; + maxim,resetb-gpio = <1>; @@ -11617,10 +11604,10 @@ index 0000000..b92fe83 +}; diff --git a/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts new file mode 100644 -index 0000000..25970c9 +index 0000000..1cb8e95 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts -@@ -0,0 +1,550 @@ +@@ -0,0 +1,548 @@ +/* + * Device Tree Source for the V3MSK Videobox Mini board on r8a7797 + * @@ -11831,7 +11818,6 @@ index 0000000..25970c9 + max9286@0 { + compatible = "maxim,max9286"; + reg = <0x2c>; -+ maxim,sensor_delay = <350>; + maxim,links = <4>; + maxim,lanes = <4>; + maxim,resetb-gpio = <1>; @@ -11875,7 +11861,6 @@ index 0000000..25970c9 + ti964-ti9x3@0 { + compatible = "ti,ti964-ti9x3"; + reg = <0x3a>; -+ ti,sensor_delay = <350>; + ti,links = <4>; + ti,lanes = <4>; + ti,forwarding-mode = "round-robin"; @@ -12173,10 +12158,10 @@ index 0000000..25970c9 +}; diff --git a/arch/arm64/boot/dts/renesas/r8a7797-v3msk-view.dts b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-view.dts new file mode 100644 -index 0000000..6f82385 +index 0000000..58f82bf --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-view.dts -@@ -0,0 +1,298 @@ +@@ -0,0 +1,297 @@ +/* + * Device Tree Source for the V3MSK View board on r8a7797 + * @@ -12310,7 +12295,6 @@ index 0000000..6f82385 + compatible = "maxim,max9286"; + reg = <0x6c>; + gpios = <&gpio0 9 GPIO_ACTIVE_HIGH>; -+ maxim,sensor_delay = <0>; + maxim,links = <4>; + maxim,lanes = <4>; + maxim,resetb-gpio = <1>; @@ -14405,10 +14389,10 @@ index 0000000..b854216 +}; diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi new file mode 100644 -index 0000000..d7ffd79 +index 0000000..56194b4 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi -@@ -0,0 +1,1542 @@ +@@ -0,0 +1,1538 @@ +/* + * Device Tree Source for the ULCB Kingfisher board + * @@ -15303,7 +15287,6 @@ index 0000000..d7ffd79 + ti964-ti9x3@0 { + compatible = "ti,ti964-ti9x3"; + reg = <0x3a>; -+ ti,sensor_delay = <350>; + ti,links = <4>; + ti,lanes = <4>; + ti,forwarding-mode = "round-robin"; @@ -15348,7 +15331,6 @@ index 0000000..d7ffd79 + 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"; @@ -15382,12 +15364,10 @@ index 0000000..d7ffd79 + max9286@0 { + compatible = "maxim,max9286"; + reg = <0x2c>; -+ maxim,sensor_delay = <350>; + maxim,links = <4>; + maxim,lanes = <4>; + maxim,resetb-gpio = <1>; + maxim,fsync-mode = "automatic"; -+ + maxim,timeout = <100>; + POC0-supply = <&pwr1A>; + POC1-supply = <&pwr0A>; @@ -15953,10 +15933,10 @@ index 0000000..d7ffd79 + diff --git a/arch/arm64/boot/dts/renesas/ulcb-vb-cn12.dtsi b/arch/arm64/boot/dts/renesas/ulcb-vb-cn12.dtsi new file mode 100644 -index 0000000..d5c4f46 +index 0000000..df27324 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/ulcb-vb-cn12.dtsi -@@ -0,0 +1,515 @@ +@@ -0,0 +1,542 @@ +/* + * Device Tree Source for the H3ULCB Videobox board: + * this adding conflicting resource on VIN4/VIN5/VIN6/VIN7 for CN12 @@ -15969,6 +15949,44 @@ index 0000000..d5c4f46 + * kind, whether express or implied. + */ + ++/ { ++ pwr0C: regulator-pwr0C { ++ compatible = "regulator-fixed"; ++ regulator-name = "PWR0C"; ++ regulator-min-microvolt = <9000000>; ++ regulator-max-microvolt = <9000000>; ++ gpio = <&gpio_exp_c_5c 8 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ pwr1C: regulator-pwr1C { ++ compatible = "regulator-fixed"; ++ regulator-name = "PWR1C"; ++ regulator-min-microvolt = <9000000>; ++ regulator-max-microvolt = <9000000>; ++ gpio = <&gpio_exp_c_5c 9 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ pwr2C: regulator-pwr2C { ++ compatible = "regulator-fixed"; ++ regulator-name = "PWR2C"; ++ regulator-min-microvolt = <9000000>; ++ regulator-max-microvolt = <9000000>; ++ gpio = <&gpio_exp_c_5c 10 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ pwr3C: regulator-pwr3C { ++ compatible = "regulator-fixed"; ++ regulator-name = "PWR3C"; ++ regulator-min-microvolt = <9000000>; ++ regulator-max-microvolt = <9000000>; ++ gpio = <&gpio_exp_c_5c 11 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++}; ++ +&i2cswitch2 { + i2c@3 { + #address-cells = <1>; @@ -16075,6 +16093,10 @@ index 0000000..d5c4f46 + ti,lanes = <2>; + ti,forwarding-mode = "round-robin"; + ti,cable-mode = "coax"; ++ POC0-supply = <&pwr0C>; ++ POC1-supply = <&pwr1C>; ++ POC2-supply = <&pwr2C>; ++ POC3-supply = <&pwr3C>; + + port@0 { + ti964_des2ep0: endpoint@0 { @@ -16110,12 +16132,16 @@ index 0000000..d5c4f46 + ti954-ti9x3@2 { + compatible = "ti,ti954-ti9x3"; + reg = <0x38>; -+ /* gpios = <&video_c_ext1 10 GPIO_ACTIVE_HIGH>; */ ++ /* gpios = <&gpio_exp_c_5c 10 GPIO_ACTIVE_HIGH>; */ + ti,sensor_delay = <350>; + ti,links = <2>; + ti,lanes = <2>; + ti,forwarding-mode = "round-robin"; + ti,cable-mode = "coax"; ++ POC0-supply = <&pwr0C>; ++ POC1-supply = <&pwr1C>; ++ POC2-supply = <&pwr2C>; ++ POC3-supply = <&pwr3C>; + + port@0 { + ti954_des2ep0: endpoint@0 { @@ -16147,6 +16173,10 @@ index 0000000..d5c4f46 + maxim,resetb-gpio = <1>; + maxim,fsync-mode = "automatic"; + maxim,timeout = <100>; ++ POC0-supply = <&pwr1C>; ++ POC1-supply = <&pwr0C>; ++ POC2-supply = <&pwr3C>; ++ POC3-supply = <&pwr2C>; + + port@0 { + max9286_des2ep0: endpoint@0 { @@ -16185,7 +16215,8 @@ index 0000000..d5c4f46 + reg = <4>; + /* Slot C (CN12) */ + -+ video_c_ext0: pca9535@26 { ++ /* PCA9535 is a redundand/deprecated card */ ++ gpio_exp_c_27: gpio@27 { + compatible = "nxp,pca9535"; + reg = <0x26>; + gpio-controller; @@ -16247,7 +16278,7 @@ index 0000000..d5c4f46 + }; + }; + -+ video_c_ext1: max7325@5c { ++ gpio_exp_c_5c: gpio@5c { + compatible = "maxim,max7325"; + reg = <0x5c>; + gpio-controller; @@ -16277,30 +16308,6 @@ index 0000000..d5c4f46 + output-high; + line-name = "Video-C PWR_SHDN"; + }; -+ video_c_cam_pwr0 { -+ gpio-hog; -+ gpios = <8 GPIO_ACTIVE_HIGH>; -+ output-high; -+ line-name = "Video-C PWR0"; -+ }; -+ video_c_cam_pwr1 { -+ gpio-hog; -+ gpios = <9 GPIO_ACTIVE_HIGH>; -+ output-high; -+ line-name = "Video-C PWR1"; -+ }; -+ video_c_cam_pwr2 { -+ gpio-hog; -+ gpios = <10 GPIO_ACTIVE_HIGH>; -+ output-high; -+ line-name = "Video-C PWR2"; -+ }; -+ video_c_cam_pwr3 { -+ gpio-hog; -+ gpios = <11 GPIO_ACTIVE_HIGH>; -+ output-high; -+ line-name = "Video-C PWR3"; -+ }; + video_c_des_shdn { + gpio-hog; + gpios = <13 GPIO_ACTIVE_HIGH>; @@ -16474,10 +16481,10 @@ index 0000000..d5c4f46 +}; diff --git a/arch/arm64/boot/dts/renesas/ulcb-vb.dtsi b/arch/arm64/boot/dts/renesas/ulcb-vb.dtsi new file mode 100644 -index 0000000..4fcb320 +index 0000000..ab52fff --- /dev/null +++ b/arch/arm64/boot/dts/renesas/ulcb-vb.dtsi -@@ -0,0 +1,1726 @@ +@@ -0,0 +1,1770 @@ +/* + * Device Tree Source for the ULCB Videobox board + * @@ -16580,6 +16587,78 @@ index 0000000..4fcb320 + regulator-always-on; + }; + ++ pwr0A: regulator-pwr0A { ++ compatible = "regulator-fixed"; ++ regulator-name = "PWR0A"; ++ regulator-min-microvolt = <9000000>; ++ regulator-max-microvolt = <9000000>; ++ gpio = <&gpio_exp_a_5c 8 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ pwr1A: regulator-pwr1A { ++ compatible = "regulator-fixed"; ++ regulator-name = "PWR1A"; ++ regulator-min-microvolt = <9000000>; ++ regulator-max-microvolt = <9000000>; ++ gpio = <&gpio_exp_a_5c 9 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ pwr2A: regulator-pwr2A { ++ compatible = "regulator-fixed"; ++ regulator-name = "PWR2A"; ++ regulator-min-microvolt = <9000000>; ++ regulator-max-microvolt = <9000000>; ++ gpio = <&gpio_exp_a_5c 10 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ pwr3A: regulator-pwr3A { ++ compatible = "regulator-fixed"; ++ regulator-name = "PWR3A"; ++ regulator-min-microvolt = <9000000>; ++ regulator-max-microvolt = <9000000>; ++ gpio = <&gpio_exp_a_5c 11 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ pwr0B: regulator-pwr0B { ++ compatible = "regulator-fixed"; ++ regulator-name = "PWR0B"; ++ regulator-min-microvolt = <9000000>; ++ regulator-max-microvolt = <9000000>; ++ gpio = <&gpio_exp_b_5c 8 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ pwr1B: regulator-pwr1B { ++ compatible = "regulator-fixed"; ++ regulator-name = "PWR1B"; ++ regulator-min-microvolt = <9000000>; ++ regulator-max-microvolt = <9000000>; ++ gpio = <&gpio_exp_b_5c 9 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ pwr2B: regulator-pwr2B { ++ compatible = "regulator-fixed"; ++ regulator-name = "PWR2B"; ++ regulator-min-microvolt = <9000000>; ++ regulator-max-microvolt = <9000000>; ++ gpio = <&gpio_exp_b_5c 10 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ pwr3B: regulator-pwr3B { ++ compatible = "regulator-fixed"; ++ regulator-name = "PWR3B"; ++ regulator-min-microvolt = <9000000>; ++ regulator-max-microvolt = <9000000>; ++ gpio = <&gpio_exp_b_5c 11 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ + /delete-node/sound; + + rsnd_ak4613: sound@0 { @@ -17013,11 +17092,14 @@ index 0000000..4fcb320 + ti964-ti9x3@0 { + compatible = "ti,ti964-ti9x3"; + reg = <0x3a>; -+ ti,sensor_delay = <350>; + ti,links = <4>; + ti,lanes = <4>; + ti,forwarding-mode = "round-robin"; + ti,cable-mode = "stp"; ++ POC0-supply = <&pwr0A>; ++ POC1-supply = <&pwr1A>; ++ POC2-supply = <&pwr2A>; ++ POC3-supply = <&pwr3A>; + + port@0 { + ti964_des0ep0: endpoint@0 { @@ -17053,12 +17135,15 @@ index 0000000..4fcb320 + ti954-ti9x3@0 { + compatible = "ti,ti954-ti9x3"; + reg = <0x38>; -+ /* gpios = <&video_a_ext1 10 GPIO_ACTIVE_HIGH>; */ -+ ti,sensor_delay = <350>; ++ /* gpios = <&gpio_exp_a_5c 10 GPIO_ACTIVE_HIGH>; */ + ti,links = <2>; + ti,lanes = <4>; + ti,forwarding-mode = "round-robin"; + ti,cable-mode = "stp"; ++ POC0-supply = <&pwr0A>; ++ POC1-supply = <&pwr1A>; ++ POC2-supply = <&pwr2A>; ++ POC3-supply = <&pwr3A>; + + port@0 { + ti954_des0ep0: endpoint@0 { @@ -17084,12 +17169,15 @@ index 0000000..4fcb320 + max9286@0 { + compatible = "maxim,max9286"; + reg = <0x2c>; -+ maxim,sensor_delay = <350>; + maxim,links = <4>; + maxim,lanes = <4>; + maxim,resetb-gpio = <1>; + maxim,fsync-mode = "automatic"; + maxim,timeout = <100>; ++ POC0-supply = <&pwr1A>; ++ POC1-supply = <&pwr0A>; ++ POC2-supply = <&pwr3A>; ++ POC3-supply = <&pwr2A>; + + port@0 { + max9286_des0ep0: endpoint@0 { @@ -17222,11 +17310,14 @@ index 0000000..4fcb320 + ti964-ti9x3@1 { + compatible = "ti,ti964-ti9x3"; + reg = <0x3a>; -+ ti,sensor_delay = <350>; + ti,links = <4>; + ti,lanes = <4>; + ti,forwarding-mode = "round-robin"; + ti,cable-mode = "stp"; ++ POC0-supply = <&pwr0B>; ++ POC1-supply = <&pwr1B>; ++ POC2-supply = <&pwr2B>; ++ POC3-supply = <&pwr3B>; + + port@0 { + ti964_des1ep0: endpoint@0 { @@ -17262,12 +17353,15 @@ index 0000000..4fcb320 + ti954-ti9x3@1 { + compatible = "ti,ti954-ti9x3"; + reg = <0x38>; -+ /* gpios = <&video_b_ext1 10 GPIO_ACTIVE_HIGH>; */ -+ ti,sensor_delay = <350>; ++ /* gpios = <&gpio_exp_b_5c 10 GPIO_ACTIVE_HIGH>; */ + ti,links = <2>; + ti,lanes = <4>; + ti,forwarding-mode = "round-robin"; + ti,cable-mode = "stp"; ++ POC0-supply = <&pwr0B>; ++ POC1-supply = <&pwr1B>; ++ POC2-supply = <&pwr2B>; ++ POC3-supply = <&pwr3B>; + + port@0 { + ti954_des1ep0: endpoint@0 { @@ -17293,12 +17387,15 @@ index 0000000..4fcb320 + max9286@1 { + compatible = "maxim,max9286"; + reg = <0x2c>; -+ maxim,sensor_delay = <350>; + maxim,links = <4>; + maxim,lanes = <4>; + maxim,resetb-gpio = <1>; + maxim,fsync-mode = "automatic"; + maxim,timeout = <100>; ++ POC0-supply = <&pwr1B>; ++ POC1-supply = <&pwr0B>; ++ POC2-supply = <&pwr3B>; ++ POC3-supply = <&pwr2B>; + + port@0 { + max9286_des1ep0: endpoint@0 { @@ -17344,7 +17441,8 @@ index 0000000..4fcb320 + reg = <1>; + /* Slot A (CN10) */ + -+ video_a_ext0: pca9535@26 { ++ /* PCA9535 is a redundant/deprecated card */ ++ gpio_exp_a_26: gpio@26 { + compatible = "nxp,pca9535"; + reg = <0x26>; + gpio-controller; @@ -17406,7 +17504,7 @@ index 0000000..4fcb320 + }; + }; + -+ video_a_ext1: max7325@5c { ++ gpio_exp_a_5c: gpio@5c { + compatible = "maxim,max7325"; + reg = <0x5c>; + gpio-controller; @@ -17436,30 +17534,6 @@ index 0000000..4fcb320 + output-high; + line-name = "Video-A PWR_SHDN"; + }; -+ video_a_cam_pwr0 { -+ gpio-hog; -+ gpios = <8 GPIO_ACTIVE_HIGH>; -+ output-high; -+ line-name = "Video-A PWR0"; -+ }; -+ video_a_cam_pwr1 { -+ gpio-hog; -+ gpios = <9 GPIO_ACTIVE_HIGH>; -+ output-high; -+ line-name = "Video-A PWR1"; -+ }; -+ video_a_cam_pwr2 { -+ gpio-hog; -+ gpios = <10 GPIO_ACTIVE_HIGH>; -+ output-high; -+ line-name = "Video-A PWR2"; -+ }; -+ video_a_cam_pwr3 { -+ gpio-hog; -+ gpios = <11 GPIO_ACTIVE_HIGH>; -+ output-high; -+ line-name = "Video-A PWR3"; -+ }; + video_a_des_shdn { + gpio-hog; + gpios = <13 GPIO_ACTIVE_HIGH>; @@ -17481,7 +17555,8 @@ index 0000000..4fcb320 + reg = <5>; + /* Slot B (CN11) */ + -+ video_b_ext0: pca9535@26 { ++ /* PCA9535 is a redundant/deprecated card */ ++ gpio_exp_b_26: gpio@26 { + compatible = "nxp,pca9535"; + reg = <0x26>; + gpio-controller; @@ -17543,7 +17618,7 @@ index 0000000..4fcb320 + }; + }; + -+ video_b_ext1: max7325@5c { ++ gpio_exp_b_5c: gpio@5c { + compatible = "maxim,max7325"; + reg = <0x5c>; + gpio-controller; @@ -17573,30 +17648,6 @@ index 0000000..4fcb320 + output-high; + line-name = "Video-B PWR_SHDN"; + }; -+ video_b_cam_pwr0 { -+ gpio-hog; -+ gpios = <8 GPIO_ACTIVE_HIGH>; -+ output-high; -+ line-name = "Video-B PWR0"; -+ }; -+ video_b_cam_pwr1 { -+ gpio-hog; -+ gpios = <9 GPIO_ACTIVE_HIGH>; -+ output-high; -+ line-name = "Video-B PWR1"; -+ }; -+ video_b_cam_pwr2 { -+ gpio-hog; -+ gpios = <10 GPIO_ACTIVE_HIGH>; -+ output-high; -+ line-name = "Video-B PWR2"; -+ }; -+ video_b_cam_pwr3 { -+ gpio-hog; -+ gpios = <11 GPIO_ACTIVE_HIGH>; -+ output-high; -+ line-name = "Video-B PWR3"; -+ }; + video_b_des_shdn { + gpio-hog; + gpios = <13 GPIO_ACTIVE_HIGH>; @@ -18206,10 +18257,10 @@ index 0000000..4fcb320 +//#include "ulcb-vb-cn12.dtsi" diff --git a/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi b/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi new file mode 100644 -index 0000000..4b25a2f0 +index 0000000..1d9df5f --- /dev/null +++ b/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi -@@ -0,0 +1,1772 @@ +@@ -0,0 +1,1816 @@ +/* + * Device Tree Source for the ULCB Videobox V2 board + * @@ -18306,6 +18357,78 @@ index 0000000..4b25a2f0 + regulator-always-on; + }; + ++ pwr0A: regulator-pwr0A { ++ compatible = "regulator-fixed"; ++ regulator-name = "PWR0A"; ++ regulator-min-microvolt = <9000000>; ++ regulator-max-microvolt = <9000000>; ++ gpio = <&gpio_exp_a_5c 8 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ pwr1A: regulator-pwr1A { ++ compatible = "regulator-fixed"; ++ regulator-name = "PWR1A"; ++ regulator-min-microvolt = <9000000>; ++ regulator-max-microvolt = <9000000>; ++ gpio = <&gpio_exp_a_5c 9 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ pwr2A: regulator-pwr2A { ++ compatible = "regulator-fixed"; ++ regulator-name = "PWR2A"; ++ regulator-min-microvolt = <9000000>; ++ regulator-max-microvolt = <9000000>; ++ gpio = <&gpio_exp_a_5c 10 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ pwr3A: regulator-pwr3A { ++ compatible = "regulator-fixed"; ++ regulator-name = "PWR3A"; ++ regulator-min-microvolt = <9000000>; ++ regulator-max-microvolt = <9000000>; ++ gpio = <&gpio_exp_a_5c 11 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ pwr0B: regulator-pwr0B { ++ compatible = "regulator-fixed"; ++ regulator-name = "PWR0B"; ++ regulator-min-microvolt = <9000000>; ++ regulator-max-microvolt = <9000000>; ++ gpio = <&gpio_exp_b_5c 8 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ pwr1B: regulator-pwr1B { ++ compatible = "regulator-fixed"; ++ regulator-name = "PWR1B"; ++ regulator-min-microvolt = <9000000>; ++ regulator-max-microvolt = <9000000>; ++ gpio = <&gpio_exp_b_5c 9 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ pwr2B: regulator-pwr2B { ++ compatible = "regulator-fixed"; ++ regulator-name = "PWR2B"; ++ regulator-min-microvolt = <9000000>; ++ regulator-max-microvolt = <9000000>; ++ gpio = <&gpio_exp_b_5c 10 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ pwr3B: regulator-pwr3B { ++ compatible = "regulator-fixed"; ++ regulator-name = "PWR3B"; ++ regulator-min-microvolt = <9000000>; ++ regulator-max-microvolt = <9000000>; ++ gpio = <&gpio_exp_b_5c 11 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ + /delete-node/sound; + + rsnd_ak4613: sound@0 { @@ -18763,11 +18886,14 @@ index 0000000..4b25a2f0 + ti964-ti9x3@0 { + compatible = "ti,ti964-ti9x3"; + reg = <0x3a>; -+ ti,sensor_delay = <350>; + ti,links = <4>; + ti,lanes = <4>; + ti,forwarding-mode = "round-robin"; + ti,cable-mode = "stp"; ++ POC0-supply = <&pwr0A>; ++ POC1-supply = <&pwr1A>; ++ POC2-supply = <&pwr2A>; ++ POC3-supply = <&pwr3A>; + + port@0 { + ti964_des0ep0: endpoint@0 { @@ -18803,12 +18929,15 @@ index 0000000..4b25a2f0 + ti954-ti9x3@0 { + compatible = "ti,ti954-ti9x3"; + reg = <0x38>; -+ /* gpios = <&video_a_ext1 10 GPIO_ACTIVE_HIGH>; */ -+ ti,sensor_delay = <350>; ++ /* gpios = <&gpio_exp_a_5c 10 GPIO_ACTIVE_HIGH>; */ + ti,links = <2>; + ti,lanes = <4>; + ti,forwarding-mode = "round-robin"; + ti,cable-mode = "stp"; ++ POC0-supply = <&pwr0A>; ++ POC1-supply = <&pwr1A>; ++ POC2-supply = <&pwr2A>; ++ POC3-supply = <&pwr3A>; + + port@0 { + ti954_des0ep0: endpoint@0 { @@ -18834,12 +18963,15 @@ index 0000000..4b25a2f0 + max9286@0 { + compatible = "maxim,max9286"; + reg = <0x2c>; -+ maxim,sensor_delay = <350>; + maxim,links = <4>; + maxim,lanes = <4>; + maxim,resetb-gpio = <1>; + maxim,fsync-mode = "automatic"; + maxim,timeout = <100>; ++ POC0-supply = <&pwr1A>; ++ POC1-supply = <&pwr0A>; ++ POC2-supply = <&pwr3A>; ++ POC3-supply = <&pwr2A>; + + port@0 { + max9286_des0ep0: endpoint@0 { @@ -18972,11 +19104,14 @@ index 0000000..4b25a2f0 + ti964-ti9x3@1 { + compatible = "ti,ti964-ti9x3"; + reg = <0x3a>; -+ ti,sensor_delay = <350>; + ti,links = <4>; + ti,lanes = <4>; + ti,forwarding-mode = "round-robin"; + ti,cable-mode = "stp"; ++ POC0-supply = <&pwr0B>; ++ POC1-supply = <&pwr1B>; ++ POC2-supply = <&pwr2B>; ++ POC3-supply = <&pwr3B>; + + port@0 { + ti964_des1ep0: endpoint@0 { @@ -19012,12 +19147,15 @@ index 0000000..4b25a2f0 + ti954-ti9x3@1 { + compatible = "ti,ti954-ti9x3"; + reg = <0x38>; -+ /* gpios = <&video_b_ext1 10 GPIO_ACTIVE_HIGH>; */ -+ ti,sensor_delay = <350>; ++ /* gpios = <&gpio_exp_b_5c 10 GPIO_ACTIVE_HIGH>; */ + ti,links = <2>; + ti,lanes = <4>; + ti,forwarding-mode = "round-robin"; + ti,cable-mode = "stp"; ++ POC0-supply = <&pwr0B>; ++ POC1-supply = <&pwr1B>; ++ POC2-supply = <&pwr2B>; ++ POC3-supply = <&pwr3B>; + + port@0 { + ti954_des1ep0: endpoint@0 { @@ -19043,12 +19181,15 @@ index 0000000..4b25a2f0 + max9286@1 { + compatible = "maxim,max9286"; + reg = <0x2c>; -+ maxim,sensor_delay = <350>; + maxim,links = <4>; + maxim,lanes = <4>; + maxim,resetb-gpio = <1>; + maxim,fsync-mode = "automatic"; + maxim,timeout = <100>; ++ POC0-supply = <&pwr1B>; ++ POC1-supply = <&pwr0B>; ++ POC2-supply = <&pwr3B>; ++ POC3-supply = <&pwr2B>; + + port@0 { + max9286_des1ep0: endpoint@0 { @@ -19094,7 +19235,8 @@ index 0000000..4b25a2f0 + reg = <0>; + /* Slot A (CN10) */ + -+ video_a_ext0: pca9535@26 { ++ /* PCA9535 is a redundant/deprecated card */ ++ gpio_exp_a_26: gpio@26 { + compatible = "nxp,pca9535"; + reg = <0x26>; + gpio-controller; @@ -19144,7 +19286,7 @@ index 0000000..4b25a2f0 + }; + }; + -+ video_a_ext1: max7325@5c { ++ gpio_exp_a_5c: gpio@5c { + compatible = "maxim,max7325"; + reg = <0x5c>; + gpio-controller; @@ -19162,30 +19304,6 @@ index 0000000..4b25a2f0 + output-high; + line-name = "Video-A PWR_SHDN"; + }; -+ video_a_cam_pwr0 { -+ gpio-hog; -+ gpios = <8 GPIO_ACTIVE_HIGH>; -+ output-high; -+ line-name = "Video-A PWR0"; -+ }; -+ video_a_cam_pwr1 { -+ gpio-hog; -+ gpios = <9 GPIO_ACTIVE_HIGH>; -+ output-high; -+ line-name = "Video-A PWR1"; -+ }; -+ video_a_cam_pwr2 { -+ gpio-hog; -+ gpios = <10 GPIO_ACTIVE_HIGH>; -+ output-high; -+ line-name = "Video-A PWR2"; -+ }; -+ video_a_cam_pwr3 { -+ gpio-hog; -+ gpios = <11 GPIO_ACTIVE_HIGH>; -+ output-high; -+ line-name = "Video-A PWR3"; -+ }; + video_a_des_shdn { + gpio-hog; + gpios = <13 GPIO_ACTIVE_HIGH>; @@ -19207,7 +19325,8 @@ index 0000000..4b25a2f0 + reg = <2>; + /* Slot B (CN11) */ + -+ video_b_ext0: pca9535@26 { ++ /* PCA9535 is a redundant/deprecated card */ ++ gpio_exp_b_26: gpio@26 { + compatible = "nxp,pca9535"; + reg = <0x26>; + gpio-controller; @@ -19269,7 +19388,7 @@ index 0000000..4b25a2f0 + }; + }; + -+ video_b_ext1: max7325@5c { ++ gpio_exp_b_5c: gpio@5c { + compatible = "maxim,max7325"; + reg = <0x5c>; + gpio-controller; @@ -19299,30 +19418,6 @@ index 0000000..4b25a2f0 + output-high; + line-name = "Video-B PWR_SHDN"; + }; -+ video_b_cam_pwr0 { -+ gpio-hog; -+ gpios = <8 GPIO_ACTIVE_HIGH>; -+ output-high; -+ line-name = "Video-B PWR0"; -+ }; -+ video_b_cam_pwr1 { -+ gpio-hog; -+ gpios = <9 GPIO_ACTIVE_HIGH>; -+ output-high; -+ line-name = "Video-B PWR1"; -+ }; -+ video_b_cam_pwr2 { -+ gpio-hog; -+ gpios = <10 GPIO_ACTIVE_HIGH>; -+ output-high; -+ line-name = "Video-B PWR2"; -+ }; -+ video_b_cam_pwr3 { -+ gpio-hog; -+ gpios = <11 GPIO_ACTIVE_HIGH>; -+ output-high; -+ line-name = "Video-B PWR3"; -+ }; + video_b_des_shdn { + gpio-hog; + gpios = <13 GPIO_ACTIVE_HIGH>; @@ -19981,13 +20076,13 @@ index 0000000..4b25a2f0 +}; + +/* uncomment to enable CN12 on VIN4-7 */ -+//#include "ulcb-vb-cn12.dtsi" ++//#include "ulcb-vb2-cn12.dtsi" diff --git a/arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi b/arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi new file mode 100644 -index 0000000..7728bdd +index 0000000..2be4a7c --- /dev/null +++ b/arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi -@@ -0,0 +1,578 @@ +@@ -0,0 +1,577 @@ +/* + * Device Tree Source for the ULCB Videobox Mini board + * @@ -20254,7 +20349,6 @@ index 0000000..7728bdd + max9286@0 { + compatible = "maxim,max9286"; + reg = <0x2c>; -+ maxim,sensor_delay = <350>; + maxim,links = <4>; + maxim,lanes = <4>; + maxim,resetb-gpio = <1>; -- cgit 1.2.3-korg From 0f5e49cd832c4388bc2ddf03295f6f40a527ae1e Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Sun, 28 Jan 2018 02:57:28 +0300 Subject: LVDS: add poc-delay dts field 1) add poc-delay field that introduces extra delay after apply POC-supply power. Default value is 50ms 2) add stability fixes for AP0101-AR014x cameras: read OTP_ID runtime (do not use cached value at kernel boot time, since it may read unstable/incorrectly) --- .../linux-renesas/0030-Gen3-LVDS-cameras.patch | 108 ++++++++++++++------- 1 file changed, 71 insertions(+), 37 deletions(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') 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 index a2bfd20..67728ff 100644 --- 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 @@ -11,13 +11,13 @@ Signed-off-by: Vladimir Barinov --- drivers/media/i2c/soc_camera/Kconfig | 47 + drivers/media/i2c/soc_camera/Makefile | 7 + - drivers/media/i2c/soc_camera/ap0101_ar014x.c | 581 +++++++++++ + drivers/media/i2c/soc_camera/ap0101_ar014x.c | 588 +++++++++++ drivers/media/i2c/soc_camera/ap0101_ar014x.h | 28 + - drivers/media/i2c/soc_camera/ar0132.c | 581 +++++++++++ + drivers/media/i2c/soc_camera/ar0132.c | 582 +++++++++++ drivers/media/i2c/soc_camera/ar0132.h | 213 ++++ - drivers/media/i2c/soc_camera/max9286.c | 688 +++++++++++++ + drivers/media/i2c/soc_camera/max9286.c | 697 +++++++++++++ drivers/media/i2c/soc_camera/max9286.h | 244 +++++ - drivers/media/i2c/soc_camera/ov10635.c | 758 ++++++++++++++ + drivers/media/i2c/soc_camera/ov10635.c | 759 ++++++++++++++ drivers/media/i2c/soc_camera/ov10635.h | 1139 +++++++++++++++++++++ drivers/media/i2c/soc_camera/ov10635_debug.h | 54 + drivers/media/i2c/soc_camera/ov106xx.c | 117 +++ @@ -25,8 +25,8 @@ Signed-off-by: Vladimir Barinov drivers/media/i2c/soc_camera/ov490_ov10640.h | 102 ++ drivers/media/i2c/soc_camera/ov495_ov2775.c | 658 ++++++++++++ drivers/media/i2c/soc_camera/ov495_ov2775.h | 23 + - drivers/media/i2c/soc_camera/ti954_ti9x3.c | 431 ++++++++ - drivers/media/i2c/soc_camera/ti964_ti9x3.c | 400 ++++++++ + drivers/media/i2c/soc_camera/ti954_ti9x3.c | 439 ++++++++ + drivers/media/i2c/soc_camera/ti964_ti9x3.c | 408 ++++++++ drivers/media/i2c/soc_camera/ti9x4_ti9x3.h | 153 +++ drivers/media/platform/soc_camera/rcar_csi2.c | 297 ++++-- drivers/media/platform/soc_camera/rcar_vin.c | 211 +++- @@ -34,7 +34,7 @@ Signed-off-by: Vladimir Barinov drivers/media/platform/soc_camera/soc_mediabus.c | 16 + include/media/drv-intf/soc_mediabus.h | 3 + include/media/soc_camera.h | 1 + - 25 files changed, 7820 insertions(+), 109 deletions(-) + 25 files changed, 7854 insertions(+), 109 deletions(-) create mode 100644 drivers/media/i2c/soc_camera/ap0101_ar014x.c create mode 100644 drivers/media/i2c/soc_camera/ap0101_ar014x.h create mode 100644 drivers/media/i2c/soc_camera/ar0132.c @@ -133,10 +133,10 @@ index 6f994f9..e88f6a9 100644 obj-$(CONFIG_SOC_CAMERA_OV6650) += ov6650.o diff --git a/drivers/media/i2c/soc_camera/ap0101_ar014x.c b/drivers/media/i2c/soc_camera/ap0101_ar014x.c new file mode 100644 -index 0000000..3ba2a5a +index 0000000..2c6b034 --- /dev/null +++ b/drivers/media/i2c/soc_camera/ap0101_ar014x.c -@@ -0,0 +1,581 @@ +@@ -0,0 +1,588 @@ +/* + * ON Semiconductor AP0101-AR014X sensor camera driver + * @@ -168,6 +168,8 @@ index 0000000..3ba2a5a + +#define AP0101_MEDIA_BUS_FMT MEDIA_BUS_FMT_YUYV8_2X8 + ++static void ap0101_otp_id_read(struct i2c_client *client); ++ +struct ap0101_priv { + struct v4l2_subdev sd; + struct v4l2_ctrl_handler hdl; @@ -184,7 +186,6 @@ index 0000000..3ba2a5a + int port; + int gpio_resetb; + int gpio_fsin; -+ +}; + +static inline struct ap0101_priv *to_ap0101(const struct i2c_client *client) @@ -201,6 +202,7 @@ index 0000000..3ba2a5a + 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(5000, 5500); /* wait 5ms */ + client->addr = tmp_addr; + }; +} @@ -236,6 +238,7 @@ index 0000000..3ba2a5a + usleep_range(100, 150); /* wait 100 us */ + reg16_read16(client, 0xfc00, ®_val); + reg16_write16(client, 0x0040, 0x8d02); ++ usleep_range(100, 150); /* wait 100 us */ + + return reg_val; +} @@ -252,6 +255,7 @@ index 0000000..3ba2a5a + reg16_write16(client, 0x0040, 0x8d08); + usleep_range(100, 150); /* wait 100 us */ + reg16_write16(client, 0x0040, 0x8d02); ++ usleep_range(100, 150); /* wait 100 us */ +} + +static int ap0101_s_stream(struct v4l2_subdev *sd, int enable) @@ -312,6 +316,8 @@ index 0000000..3ba2a5a + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct ap0101_priv *priv = to_ap0101(client); + ++ ap0101_otp_id_read(client); ++ + memcpy(edid->edid, priv->id, 6); + + edid->edid[6] = 0xff; @@ -502,6 +508,8 @@ index 0000000..3ba2a5a + struct i2c_client *client = v4l2_get_subdevdata(sd); + struct ap0101_priv *priv = to_ap0101(client); + ++ ap0101_otp_id_read(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]); +} @@ -527,7 +535,6 @@ index 0000000..3ba2a5a + + /* Program wizard registers */ + ap0101_set_regs(client, ap0101_regs_wizard, ARRAY_SIZE(ap0101_regs_wizard)); -+ + /* Read OTP IDs */ + ap0101_otp_id_read(client); + @@ -754,10 +761,10 @@ index 0000000..16599a1 +}; diff --git a/drivers/media/i2c/soc_camera/ar0132.c b/drivers/media/i2c/soc_camera/ar0132.c new file mode 100644 -index 0000000..bbaeeaae +index 0000000..97d9878 --- /dev/null +++ b/drivers/media/i2c/soc_camera/ar0132.c -@@ -0,0 +1,581 @@ +@@ -0,0 +1,582 @@ +/* + * ON Semiconductor AR0132 sensor camera driver + * @@ -827,6 +834,7 @@ index 0000000..bbaeeaae + 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(5000, 5500); /* wait 5ms */ + client->addr = tmp_addr; + }; +} @@ -1560,10 +1568,10 @@ index 0000000..bcee0e5 +}; diff --git a/drivers/media/i2c/soc_camera/max9286.c b/drivers/media/i2c/soc_camera/max9286.c new file mode 100644 -index 0000000..8a62b91 +index 0000000..989c782 --- /dev/null +++ b/drivers/media/i2c/soc_camera/max9286.c -@@ -0,0 +1,688 @@ +@@ -0,0 +1,697 @@ +/* + * MAXIM max9286 GMSL driver + * @@ -1617,6 +1625,7 @@ index 0000000..8a62b91 + int hsync; + int vsync; + int timeout; ++ int poc_delay; + atomic_t use_count; + u32 csi2_outord; + struct i2c_client *client; @@ -1659,6 +1668,10 @@ index 0000000..8a62b91 +module_param(active_low_resetb, int, 0644); +MODULE_PARM_DESC(active_low_resetb, " Serializer GPIO reset level (default: 0 - active high) */"); + ++static int poc_delay; ++module_param(poc_delay, int, 0644); ++MODULE_PARM_DESC(poc_delay, " Delay in ms after POC enable (default: 0 ms) */"); ++ +static char* ser_name(int id) +{ + switch (id) { @@ -1786,6 +1799,7 @@ index 0000000..8a62b91 + mdelay(200); + if (regulator_enable(priv->poc_supply[idx])) + dev_err(&client->dev, "fail to enable POC%d regulator\n", idx); ++ mdelay(priv->poc_delay); + } + } + } @@ -1926,6 +1940,7 @@ index 0000000..8a62b91 + if (!IS_ERR(priv->poc_supply[idx])) { + if (regulator_enable(priv->poc_supply[idx])) + dev_err(&client->dev, "fail to enable POC%d regulator\n", idx); ++ mdelay(priv->poc_delay); + } + + ret = max9286_reverse_channel_setup(client, idx); @@ -2073,10 +2088,8 @@ index 0000000..8a62b91 + + 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; @@ -2092,6 +2105,8 @@ index 0000000..8a62b91 + priv->hsync = 0; + if (of_property_read_u32(np, "maxim,vsync", &priv->vsync)) + priv->vsync = 1; ++ if (of_property_read_u32(np, "maxim,poc-delay", &priv->poc_delay)) ++ priv->poc_delay = 50; + + /* module params override dts */ + if (him) @@ -2108,6 +2123,8 @@ index 0000000..8a62b91 + priv->gpio_resetb = gpio_resetb; + if (active_low_resetb) + priv->active_low_resetb = active_low_resetb; ++ if (poc_delay) ++ priv->poc_delay = poc_delay; + + for (i = 0; i < priv->links; i++) { + endpoint = of_graph_get_next_endpoint(np, endpoint); @@ -2504,10 +2521,10 @@ index 0000000..6c2a9e0 +#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..c8da1f4 +index 0000000..8c06e59 --- /dev/null +++ b/drivers/media/i2c/soc_camera/ov10635.c -@@ -0,0 +1,758 @@ +@@ -0,0 +1,759 @@ +/* + * OmniVision ov10635 sensor camera driver + * @@ -2580,6 +2597,7 @@ index 0000000..c8da1f4 + 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(5000, 5500); /* wait 5ms */ + client->addr = tmp_addr; + }; +} @@ -4596,7 +4614,7 @@ index 0000000..4c797f9 +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..690eac0 +index 0000000..f1e34a3 --- /dev/null +++ b/drivers/media/i2c/soc_camera/ov490_ov10640.c @@ -0,0 +1,1160 @@ @@ -4698,7 +4716,7 @@ index 0000000..690eac0 + 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 */ ++ usleep_range(5000, 5500); /* wait 5ms */ + client->addr = tmp_addr; + }; +} @@ -6563,10 +6581,10 @@ index 0000000..3f53689 +}; diff --git a/drivers/media/i2c/soc_camera/ti954_ti9x3.c b/drivers/media/i2c/soc_camera/ti954_ti9x3.c new file mode 100644 -index 0000000..1672173 +index 0000000..ff84128 --- /dev/null +++ b/drivers/media/i2c/soc_camera/ti954_ti9x3.c -@@ -0,0 +1,431 @@ +@@ -0,0 +1,439 @@ +/* + * TI ti954-(ti913/ti953) FPDLinkIII driver + * @@ -6602,6 +6620,7 @@ index 0000000..1672173 + int csi_rate; + const char *forwarding_mode; + const char *cable_mode; ++ int poc_delay; + atomic_t use_count; + struct i2c_client *client; + int ti9x3_addr_map[4]; @@ -6636,6 +6655,10 @@ index 0000000..1672173 +} +#endif + ++static int poc_delay; ++module_param(poc_delay, int, 0644); ++MODULE_PARM_DESC(poc_delay, " Delay in ms after POC enable (default: 0 ms) */"); ++ +static void ti954_ti9x3_read_chipid(struct i2c_client *client) +{ + struct ti954_ti9x3_priv *priv = i2c_get_clientdata(client); @@ -6743,6 +6766,7 @@ index 0000000..1672173 + if (!IS_ERR(priv->poc_supply[idx])) { + if (regulator_enable(priv->poc_supply[idx])) + dev_err(&client->dev, "fail to enable POC%d regulator\n", idx); ++ mdelay(priv->poc_delay); + } + + ti954_ti9x3_fpdlink3_setup(client, idx); @@ -6866,14 +6890,16 @@ index 0000000..1672173 + + 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) ++ if (of_property_read_string(np, "ti,forwarding-mode", &priv->forwarding_mode)) + priv->forwarding_mode = forwarding_mode_default; -+ -+ err = of_property_read_string(np, "ti,cable-mode", &priv->cable_mode); -+ if (err) ++ if (of_property_read_string(np, "ti,cable-mode", &priv->cable_mode)) + priv->cable_mode = cable_mode_default; ++ if (of_property_read_u32(np, "ti,poc-delay", &priv->poc_delay)) ++ priv->poc_delay = 50; ++ ++ /* module params override dts */ ++ if (poc_delay) ++ priv->poc_delay = poc_delay; + + for (i = 0; ; i++) { + endpoint = of_graph_get_next_endpoint(np, endpoint); @@ -7000,10 +7026,10 @@ index 0000000..1672173 +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..bffd7c2 +index 0000000..8393392 --- /dev/null +++ b/drivers/media/i2c/soc_camera/ti964_ti9x3.c -@@ -0,0 +1,400 @@ +@@ -0,0 +1,408 @@ +/* + * TI (ti964/ti960)-(ti913/ti953) FPDLinkIII driver + * @@ -7039,6 +7065,7 @@ index 0000000..bffd7c2 + int csi_rate; + const char *forwarding_mode; + const char *cable_mode; ++ int poc_delay; + atomic_t use_count; + struct i2c_client *client; + int ti9x3_addr_map[4]; @@ -7046,6 +7073,10 @@ index 0000000..bffd7c2 + struct regulator *poc_supply[4]; /* PoC power supply */ +}; + ++static int poc_delay; ++module_param(poc_delay, int, 0644); ++MODULE_PARM_DESC(poc_delay, " Delay in ms after POC enable (default: 0 ms) */"); ++ +static void ti964_ti9x3_read_chipid(struct i2c_client *client) +{ + struct ti964_ti9x3_priv *priv = i2c_get_clientdata(client); @@ -7154,6 +7185,7 @@ index 0000000..bffd7c2 + if (!IS_ERR(priv->poc_supply[idx])) { + if (regulator_enable(priv->poc_supply[idx])) + dev_err(&client->dev, "fail to enable POC%d regulator\n", idx); ++ mdelay(priv->poc_delay); + } + + ti964_ti9x3_fpdlink3_setup(client, idx); @@ -7272,14 +7304,16 @@ index 0000000..bffd7c2 + + 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) ++ if (of_property_read_string(np, "ti,forwarding-mode", &priv->forwarding_mode)) + priv->forwarding_mode = forwarding_mode_default; -+ -+ err = of_property_read_string(np, "ti,cable-mode", &priv->cable_mode); -+ if (err) ++ if (of_property_read_string(np, "ti,cable-mode", &priv->cable_mode)) + priv->cable_mode = cable_mode_default; ++ if (of_property_read_u32(np, "ti,poc-delay", &priv->poc_delay)) ++ priv->poc_delay = 50; ++ ++ /* module params override dts */ ++ if (poc_delay) ++ priv->poc_delay = poc_delay; + + for (i = 0; ; i++) { + endpoint = of_graph_get_next_endpoint(np, endpoint); -- cgit 1.2.3-korg From c615f6534e20af82961b94bf1d6c742017d4997b Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Wed, 31 Jan 2018 23:10:19 +0300 Subject: V3M/H: fix IMP resources Fix IMP sizes/names/sysc Add new IMP blocks --- ...0-arm64-dts-renesas-r8a779x-add-IMP-nodes.patch | 8 +-- ...as-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch | 66 ++++++++++++++++------ 2 files changed, 53 insertions(+), 21 deletions(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0050-arm64-dts-renesas-r8a779x-add-IMP-nodes.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0050-arm64-dts-renesas-r8a779x-add-IMP-nodes.patch index d52106e..e4d34a0 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0050-arm64-dts-renesas-r8a779x-add-IMP-nodes.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0050-arm64-dts-renesas-r8a779x-add-IMP-nodes.patch @@ -304,16 +304,16 @@ index f214f26..d3e91f1 100644 }; }; diff --git a/arch/arm64/boot/dts/renesas/r8a7797.dtsi b/arch/arm64/boot/dts/renesas/r8a7797.dtsi -index 118a473..05b50ca 100644 +index 5319b1a..a5552d6 100644 --- a/arch/arm64/boot/dts/renesas/r8a7797.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a7797.dtsi -@@ -967,6 +967,113 @@ +@@ -1121,6 +1121,113 @@ status = "okay"; }; + imp_distributer: impdes0 { + compatible = "renesas,impx5+-distributer"; -+ reg = <0 0xffa00000 0 0x4000>; ++ reg = <0 0xffa00000 0 0x10000>; + interrupts = ; + clocks = <&cpg CPG_MOD 830>; + power-domains = <&sysc R8A7797_PD_A3IR>; @@ -413,7 +413,7 @@ index 118a473..05b50ca 100644 + + impc0 { + compatible = "renesas,impx4-memory"; -+ reg = <0 0xed000000 0 0x100000>; ++ reg = <0 0xed000000 0 0xe0000>; + clocks = <&cpg CPG_MOD 830>; + power-domains = <&sysc R8A7797_PD_A3IR>; + }; diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch index 669f2e8..5a27c48 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch @@ -9,10 +9,10 @@ Signed-off-by: Vladimir Barinov Signed-off-by: Mikhail Ulyanov --- arch/arm64/Kconfig.platforms | 8 + - arch/arm64/boot/dts/renesas/r8a7798.dtsi | 1594 +++++++++++++ + arch/arm64/boot/dts/renesas/r8a7798.dtsi | 1628 +++++++++++++ drivers/clk/renesas/Kconfig | 1 + drivers/clk/renesas/Makefile | 1 + - drivers/clk/renesas/r8a7798-cpg-mssr.c | 284 +++ + drivers/clk/renesas/r8a7798-cpg-mssr.c | 282 +++ drivers/clk/renesas/rcar-gen3-cpg.c | 10 + drivers/clk/renesas/renesas-cpg-mssr.c | 6 + drivers/clk/renesas/renesas-cpg-mssr.h | 1 + @@ -47,7 +47,7 @@ Signed-off-by: Mikhail Ulyanov drivers/thermal/rcar_gen3_thermal.c | 10 + include/dt-bindings/clock/r8a7798-cpg-mssr.h | 56 + include/dt-bindings/power/r8a7798-sysc.h | 46 + - 39 files changed, 5493 insertions(+), 34 deletions(-) + 39 files changed, 5525 insertions(+), 34 deletions(-) create mode 100644 arch/arm64/boot/dts/renesas/r8a7798.dtsi create mode 100644 drivers/clk/renesas/r8a7798-cpg-mssr.c create mode 100644 drivers/pinctrl/sh-pfc/pfc-r8a7798.c @@ -76,10 +76,10 @@ index 9cebaad..3646b6e 100644 help diff --git a/arch/arm64/boot/dts/renesas/r8a7798.dtsi b/arch/arm64/boot/dts/renesas/r8a7798.dtsi new file mode 100644 -index 0000000..c0056b8 +index 0000000..e2b3404 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7798.dtsi -@@ -0,0 +1,1594 @@ +@@ -0,0 +1,1628 @@ +/* + * Device Tree Source for the r8a7798 SoC + * @@ -1482,7 +1482,7 @@ index 0000000..c0056b8 + + imp_distributer: impdes0 { + compatible = "renesas,impx5+-distributer"; -+ reg = <0 0xffa00000 0 0x4000>; ++ reg = <0 0xffa00000 0 0x10000>; + interrupts = ; + clocks = <&cpg CPG_MOD 830>; + power-domains = <&sysc R8A7798_PD_A3IR>; @@ -1535,13 +1535,13 @@ index 0000000..c0056b8 + power-domains = <&sysc R8A7798_PD_A2IR4>; + }; + -+ imp5 { -+ compatible = "renesas,impslc0"; -+ reg = <0 0xff9c0000 0 0x20000>; ++ impslc0 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff9c0000 0 0x10000>; + interrupt-parent = <&imp_distributer>; + interrupts = <5>; + clocks = <&cpg CPG_MOD 500>; -+ power-domains = <&sysc R8A7798_PD_A2IR4>; ++ power-domains = <&sysc R8A7798_PD_A2IR5>; + }; + + impsc0 { @@ -1600,6 +1600,15 @@ index 0000000..c0056b8 + + impdm1 { + compatible = "renesas,impx5-dmac"; ++ reg = <0 0xffa11000 0 0x1000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <12>; ++ clocks = <&cpg CPG_MOD 527>; ++ power-domains = <&sysc R8A7798_PD_A2PD0>; ++ }; ++ ++ impdm2 { ++ compatible = "renesas,impx5-dmac"; + reg = <0 0xffa14000 0 0x1000>; + interrupt-parent = <&imp_distributer>; + interrupts = <13>; @@ -1607,6 +1616,15 @@ index 0000000..c0056b8 + power-domains = <&sysc R8A7798_PD_A2PD1>; + }; + ++ impdm3 { ++ compatible = "renesas,impx5-dmac"; ++ reg = <0 0xffa15000 0 0x1000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <14>; ++ clocks = <&cpg CPG_MOD 526>; ++ power-domains = <&sysc R8A7798_PD_A2PD1>; ++ }; ++ + imppsc0 { + compatible = "renesas,impx5+-psc"; + reg = <0 0xffa20000 0 0x4000>; @@ -1636,7 +1654,7 @@ index 0000000..c0056b8 + + impc0 { + compatible = "renesas,impx4-memory"; -+ reg = <0 0xed000000 0 0x100000>; ++ reg = <0 0xed000000 0 0x200000>; + clocks = <&cpg CPG_MOD 830>; + power-domains = <&sysc R8A7798_PD_A3IR>; + }; @@ -1672,6 +1690,22 @@ index 0000000..c0056b8 + clocks = <&cpg CPG_MOD 820>; + power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; + }; ++ ++ imrlx4_ch4: imr-lx4@fe8a0000 { ++ compatible = "renesas,imr-lx4"; ++ reg = <0 0xfe8a0000 0 0x2000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 707>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ }; ++ ++ imrlx4_ch5: imr-lx4@fe8b0000 { ++ compatible = "renesas,imr-lx4"; ++ reg = <0 0xfe8b0000 0 0x2000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 706>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ }; + }; +}; diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig @@ -1700,10 +1734,10 @@ index c2ef11e..9f659d5 100644 obj-$(CONFIG_CLK_RENESAS_CPG_MSSR) += renesas-cpg-mssr.o clk-div6.o diff --git a/drivers/clk/renesas/r8a7798-cpg-mssr.c b/drivers/clk/renesas/r8a7798-cpg-mssr.c new file mode 100644 -index 0000000..3f82003 +index 0000000..e407916 --- /dev/null +++ b/drivers/clk/renesas/r8a7798-cpg-mssr.c -@@ -0,0 +1,284 @@ +@@ -0,0 +1,282 @@ +/* + * r8a7798 Clock Pulse Generator / Module Standby and Software Reset + * @@ -1863,10 +1897,8 @@ index 0000000..3f82003 + DEF_MOD("vin10", 625, R8A7798_CLK_S2D1), /* FIXME parent clk? */ + DEF_MOD("vin9", 627, R8A7798_CLK_S2D1), /* FIXME parent clk? */ + DEF_MOD("vin8", 628, R8A7798_CLK_S2D1), /* FIXME parent clk? */ -+#if 0 /* FIXME what is this? duplicated with 822,823 */ -+ DEF_MOD("imr1", 706, R8A7798_CLK_S2D1), /* FIXME parent clk? */ -+ DEF_MOD("imr0", 707, R8A7798_CLK_S2D1), /* FIXME parent clk? */ -+#endif ++ DEF_MOD("imr5", 706, R8A7798_CLK_S2D1), /* FIXME parent clk? */ ++ DEF_MOD("imr4", 707, R8A7798_CLK_S2D1), /* FIXME parent clk? */ + DEF_MOD("csi41", 715, R8A7798_CLK_CSI0), + DEF_MOD("csi40", 716, R8A7798_CLK_CSI0), + DEF_MOD("du0", 724, R8A7798_CLK_S2D1), -- cgit 1.2.3-korg From 68ed95db9c4b4ecde037e66603b43e8508936856 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Wed, 31 Jan 2018 23:11:53 +0300 Subject: H3 ws2.0: fix ssi349 name This is tested on KF + H3 ws2.0 --- ...nctrl-sh-pfc-r8a7795-fix-ssi349_ctrl-name.patch | 28 ++++++++++++++++++++++ .../linux/linux-renesas_4.9.bbappend | 1 + 2 files changed, 29 insertions(+) create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0090-pinctrl-sh-pfc-r8a7795-fix-ssi349_ctrl-name.patch (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0090-pinctrl-sh-pfc-r8a7795-fix-ssi349_ctrl-name.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0090-pinctrl-sh-pfc-r8a7795-fix-ssi349_ctrl-name.patch new file mode 100644 index 0000000..0b4cd6f --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0090-pinctrl-sh-pfc-r8a7795-fix-ssi349_ctrl-name.patch @@ -0,0 +1,28 @@ +From defb4800e4b12760ac0479a7bcd71b0a3cf0aaa3 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Tue, 30 Jan 2018 17:42:44 +0300 +Subject: [PATCH] pinctrl: sh-pfc: r8a7795: fix ssi349_ctrl name + +This fixes the ssi349_ctrl for r8a7795 SoC + +Signed-off-by: Vladimir Barinov +--- + drivers/pinctrl/sh-pfc/pfc-r8a7795.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7795.c b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c +index 3fc141a..f7dad4b 100644 +--- a/drivers/pinctrl/sh-pfc/pfc-r8a7795.c ++++ b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c +@@ -5066,7 +5066,7 @@ enum { + "ssi2_ctrl_a", + "ssi2_ctrl_b", + "ssi3_data", +- "ssi34_ctrl", ++ "ssi349_ctrl", + "ssi4_data", + "ssi4_ctrl", + "ssi5_data", +-- +1.9.1 + 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 index 1ab0ac5..ce41fa8 100644 --- 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 @@ -80,6 +80,7 @@ SRC_URI_append = " \ file://0087-spi-slave-Add-SPI-slave-handler-reporting-uptime-at-.patch \ file://0088-spi-slave-Add-SPI-slave-handler-controlling-system-s.patch \ file://0089-spi-Generalize-SPI-master-to-controller.patch \ + file://0090-pinctrl-sh-pfc-r8a7795-fix-ssi349_ctrl-name.patch \ file://0103-gpu-drm-rcar-du-Extend-VSP1-DRM-interface.patch \ file://0104-media-vsp1-extend-DRM-VSP1-interface.patch \ file://0105-media-rcar-imr-IMR-driver-updates-for-raw-DL.patch \ -- cgit 1.2.3-korg From 9d20b18f12b121c78ded5a25ea6dfb523f5ddfdd Mon Sep 17 00:00:00 2001 From: Andrey Gusakov Date: Thu, 1 Feb 2018 13:53:22 +0300 Subject: VB2: add rtc dts node --- .../0040-arm64-dts-renesas-add-ADAS-boards.patch | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch index 119042c..7755871 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch @@ -1,4 +1,4 @@ -From 51718d8f768ba719a8a295e013e3456e13b70a98 Mon Sep 17 00:00:00 2001 +From 9872a94a414d6d94423f52d59cb09cdb64cf2930 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Fri, 14 Jul 2017 15:05:42 +0300 Subject: [PATCH] arm64: dts: renesas: add ADAS boards @@ -34,7 +34,7 @@ Signed-off-by: Vladimir Barinov arch/arm64/boot/dts/renesas/legacy/Makefile | 8 + .../renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts | 1710 ++++++++++++++++++ .../renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts | 441 +++++ - .../dts/renesas/legacy/r8a7795-h3ulcb-kf-v0.dts | 1724 +++++++++++++++++++ + .../dts/renesas/legacy/r8a7795-h3ulcb-kf-v0.dts | 1724 ++++++++++++++++++ .../dts/renesas/legacy/r8a7795-h3ulcb-kf-v1.dts | 465 +++++ .../dts/renesas/legacy/r8a7796-m3ulcb-kf-v0.dts | 1214 +++++++++++++ .../dts/renesas/legacy/r8a7796-m3ulcb-kf-v1.dts | 465 +++++ @@ -75,9 +75,9 @@ Signed-off-by: Vladimir Barinov arch/arm64/boot/dts/renesas/ulcb-kf.dtsi | 1538 +++++++++++++++++ arch/arm64/boot/dts/renesas/ulcb-vb-cn12.dtsi | 542 ++++++ arch/arm64/boot/dts/renesas/ulcb-vb.dtsi | 1770 +++++++++++++++++++ - arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi | 1816 ++++++++++++++++++++ + arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi | 1820 ++++++++++++++++++++ arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi | 577 +++++++ - 47 files changed, 20249 insertions(+) + 47 files changed, 20253 insertions(+) create mode 100644 arch/arm64/boot/dts/renesas/legacy/Makefile create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts @@ -18257,10 +18257,10 @@ index 0000000..ab52fff +//#include "ulcb-vb-cn12.dtsi" diff --git a/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi b/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi new file mode 100644 -index 0000000..1d9df5f +index 0000000..72045a7 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi -@@ -0,0 +1,1816 @@ +@@ -0,0 +1,1820 @@ +/* + * Device Tree Source for the ULCB Videobox V2 board + * @@ -19633,6 +19633,10 @@ index 0000000..1d9df5f + + /* gpios 0..7 are used for indication LEDs, low-active */ + }; ++ rtc: mcp79411@6f { ++ compatible = "microchip,mcp7941x"; ++ reg = <0x6f>; ++ }; + }; + + /* port 7 is not used */ -- cgit 1.2.3-korg From 464f50d5ddaf533c29a4e82f8d48c48f31afe28f Mon Sep 17 00:00:00 2001 From: Andrey Gusakov Date: Thu, 1 Feb 2018 20:21:31 +0300 Subject: VB2: add MCP251X driver for can2 and can3 --- meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/ulcb.cfg | 1 + 1 file changed, 1 insertion(+) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/ulcb.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/ulcb.cfg index 8f36675..ed9fcb8 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/ulcb.cfg +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/ulcb.cfg @@ -6,6 +6,7 @@ CONFIG_CAN_DEV=y CONFIG_CAN_CALC_BITTIMING=y CONFIG_CAN_RCAR=y CONFIG_CAN_RCAR_CANFD=y +CONFIG_CAN_MCP251X=y CONFIG_DUMMY=y CONFIG_EXTRA_FIRMWARE="r8a779x_usb3_v2.dlmem r8a779x_usb3_v3.dlmem" CONFIG_EXTRA_FIRMWARE_DIR="firmware" -- cgit 1.2.3-korg From 8bf5313158312b395ee80594531b9cdfdb2833a5 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Fri, 2 Feb 2018 15:50:29 +0300 Subject: LVDS: unify TI9X4 deserilalizers family, add V3MZF board 1) unify TI9X4 deseializers (TI954, TI964) 2) add V3MZF board 3) shorten deserilziers name in Kconfig/Makefile 4) add camera sensor AR0220 --- .../linux-renesas/0030-Gen3-LVDS-cameras.patch | 8876 ++++++++++---------- .../0040-arm64-dts-renesas-add-ADAS-boards.patch | 1919 ++--- .../recipes-kernel/linux/linux-renesas/condor.cfg | 2 +- .../recipes-kernel/linux/linux-renesas/eagle.cfg | 2 +- .../linux/linux-renesas/salvator-x.cfg | 2 +- .../recipes-kernel/linux/linux-renesas/ulcb.cfg | 5 +- .../recipes-kernel/linux/linux-renesas/v3msk.cfg | 5 +- 7 files changed, 5421 insertions(+), 5390 deletions(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') 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 index 67728ff..3c80601 100644 --- 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 @@ -4,41 +4,45 @@ Date: Sun, 14 May 2017 15:20:01 +0300 Subject: [PATCH] Gen3: LVDS cameras This add Gen3 LVDS cameras support: -- deserializers: MAX9286, TI964, TI954, TI960 -- cameras: ov10635, ov490+ov10640, ov495+OV2775, ar0132, ap0101+ar014x +- deserializers: MAX9286, DS90UB954/960/964 +- cameras: ov10635, ov490+ov10640, ov495+OV2775, ar0132, ar0220, + ap0101+ar014x Signed-off-by: Vladimir Barinov --- - drivers/media/i2c/soc_camera/Kconfig | 47 + - drivers/media/i2c/soc_camera/Makefile | 7 + + drivers/media/i2c/soc_camera/Kconfig | 41 + + drivers/media/i2c/soc_camera/Makefile | 6 + drivers/media/i2c/soc_camera/ap0101_ar014x.c | 588 +++++++++++ drivers/media/i2c/soc_camera/ap0101_ar014x.h | 28 + - drivers/media/i2c/soc_camera/ar0132.c | 582 +++++++++++ + drivers/media/i2c/soc_camera/ar0132.c | 565 +++++++++++ drivers/media/i2c/soc_camera/ar0132.h | 213 ++++ + drivers/media/i2c/soc_camera/ar0220.c | 528 ++++++++++ + drivers/media/i2c/soc_camera/ar0220.h | 309 ++++++ drivers/media/i2c/soc_camera/max9286.c | 697 +++++++++++++ drivers/media/i2c/soc_camera/max9286.h | 244 +++++ drivers/media/i2c/soc_camera/ov10635.c | 759 ++++++++++++++ - drivers/media/i2c/soc_camera/ov10635.h | 1139 +++++++++++++++++++++ + drivers/media/i2c/soc_camera/ov10635.h | 1139 ++++++++++++++++++++++ drivers/media/i2c/soc_camera/ov10635_debug.h | 54 + - drivers/media/i2c/soc_camera/ov106xx.c | 117 +++ - drivers/media/i2c/soc_camera/ov490_ov10640.c | 1160 ++++++++++++++++++++++ + drivers/media/i2c/soc_camera/ov106xx.c | 128 +++ + drivers/media/i2c/soc_camera/ov490_ov10640.c | 1133 +++++++++++++++++++++ drivers/media/i2c/soc_camera/ov490_ov10640.h | 102 ++ - drivers/media/i2c/soc_camera/ov495_ov2775.c | 658 ++++++++++++ + drivers/media/i2c/soc_camera/ov495_ov2775.c | 639 ++++++++++++ drivers/media/i2c/soc_camera/ov495_ov2775.h | 23 + - drivers/media/i2c/soc_camera/ti954_ti9x3.c | 439 ++++++++ - drivers/media/i2c/soc_camera/ti964_ti9x3.c | 408 ++++++++ - drivers/media/i2c/soc_camera/ti9x4_ti9x3.h | 153 +++ + drivers/media/i2c/soc_camera/ti9x4.c | 520 ++++++++++ + drivers/media/i2c/soc_camera/ti9x4.h | 156 +++ drivers/media/platform/soc_camera/rcar_csi2.c | 297 ++++-- - drivers/media/platform/soc_camera/rcar_vin.c | 211 +++- + drivers/media/platform/soc_camera/rcar_vin.c | 194 +++- 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 + - 25 files changed, 7854 insertions(+), 109 deletions(-) + 26 files changed, 8291 insertions(+), 109 deletions(-) create mode 100644 drivers/media/i2c/soc_camera/ap0101_ar014x.c create mode 100644 drivers/media/i2c/soc_camera/ap0101_ar014x.h create mode 100644 drivers/media/i2c/soc_camera/ar0132.c create mode 100644 drivers/media/i2c/soc_camera/ar0132.h + create mode 100644 drivers/media/i2c/soc_camera/ar0220.c + create mode 100644 drivers/media/i2c/soc_camera/ar0220.h create mode 100644 drivers/media/i2c/soc_camera/max9286.c create mode 100644 drivers/media/i2c/soc_camera/max9286.h create mode 100644 drivers/media/i2c/soc_camera/ov10635.c @@ -49,42 +53,47 @@ Signed-off-by: Vladimir Barinov 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 + create mode 100644 drivers/media/i2c/soc_camera/ti9x4.c + create mode 100644 drivers/media/i2c/soc_camera/ti9x4.h diff --git a/drivers/media/i2c/soc_camera/Kconfig b/drivers/media/i2c/soc_camera/Kconfig -index 7704bcf..82da59f 100644 +index 7704bcf..d6377e9 100644 --- a/drivers/media/i2c/soc_camera/Kconfig +++ b/drivers/media/i2c/soc_camera/Kconfig -@@ -6,6 +6,53 @@ config SOC_CAMERA_IMX074 +@@ -6,6 +6,47 @@ config SOC_CAMERA_IMX074 help This driver supports IMX074 cameras from Sony -+config SOC_CAMERA_MAX9286_MAX9271 -+ tristate "max9286-max9271 GMSL support" ++config SOC_CAMERA_MAX9286 ++ tristate "max9286 GMSL support" + depends on SOC_CAMERA && I2C + help -+ This is a MAXIM max9286-max9271 GMSL driver ++ This is a MAXIM max9286 GMSL driver + +config SOC_CAMERA_OV106XX + tristate "ov106xx camera support" -+ depends on SOC_CAMERA && SOC_CAMERA_MAX9286_MAX9271 && I2C ++ depends on SOC_CAMERA && I2C + help + This is a runtime detected OmniVision ov10635 or ov490-ov10640 + or ov495-ov2775 sensors camera driver + ++config SOC_CAMERA_TI9X4 ++ tristate "ti9x4 FPDLinkIII support" ++ depends on SOC_CAMERA && I2C ++ help ++ This is an Texas Instruments ti9X4 FPDLinkIII driver ++ +if !SOC_CAMERA_OV106XX + +config SOC_CAMERA_OV10635 + tristate "ov10635 camera support" -+ depends on SOC_CAMERA && SOC_CAMERA_MAX9286_MAX9271 && I2C ++ depends on SOC_CAMERA && 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 ++ depends on SOC_CAMERA && I2C + help + This is an OmniVision ov490-ov10640 sensor camera driver + @@ -95,31 +104,18 @@ index 7704bcf..82da59f 100644 + 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..e88f6a9 100644 +index 6f994f9..58086d4 100644 --- a/drivers/media/i2c/soc_camera/Makefile +++ b/drivers/media/i2c/soc_camera/Makefile -@@ -1,8 +1,15 @@ +@@ -1,8 +1,14 @@ obj-$(CONFIG_SOC_CAMERA_IMX074) += imx074.o -+obj-$(CONFIG_SOC_CAMERA_MAX9286_MAX9271) += max9286.o -+obj-$(CONFIG_SOC_CAMERA_TI964_TI9X3) += ti964_ti9x3.o -+obj-$(CONFIG_SOC_CAMERA_TI954_TI9X3) += ti954_ti9x3.o ++obj-$(CONFIG_SOC_CAMERA_MAX9286) += max9286.o ++obj-$(CONFIG_SOC_CAMERA_TI9X4) += ti9x4.o obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o obj-$(CONFIG_SOC_CAMERA_MT9T031) += mt9t031.o obj-$(CONFIG_SOC_CAMERA_MT9T112) += mt9t112.o @@ -761,10 +757,10 @@ index 0000000..16599a1 +}; diff --git a/drivers/media/i2c/soc_camera/ar0132.c b/drivers/media/i2c/soc_camera/ar0132.c new file mode 100644 -index 0000000..97d9878 +index 0000000..e124e6a --- /dev/null +++ b/drivers/media/i2c/soc_camera/ar0132.c -@@ -0,0 +1,582 @@ +@@ -0,0 +1,565 @@ +/* + * ON Semiconductor AR0132 sensor camera driver + * @@ -811,8 +807,7 @@ index 0000000..97d9878 + /* serializers */ + int max9286_addr; + int max9271_addr; -+ int ti964_addr; -+ int ti954_addr; ++ int ti9x4_addr; + int ti9x3_addr; + int port; + int gpio_resetb; @@ -1160,19 +1155,13 @@ index 0000000..97d9878 + 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) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti9x4") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti9x4_addr) && + !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) + break; + } + -+ if (!priv->max9286_addr && !priv->ti964_addr && !priv->ti954_addr) { ++ if (!priv->max9286_addr && !priv->ti9x4_addr) { + dev_err(&client->dev, "deserializer does not present for AR0132\n"); + return -EINVAL; + } @@ -1188,18 +1177,8 @@ index 0000000..97d9878 + reg8_write(client, 0x0A, AR0132_I2C_ADDR << 1); /* Sensor native I2C address */ + usleep_range(2000, 2500); /* wait 2ms */ + }; -+ if (priv->ti964_addr) { -+ client->addr = priv->ti964_addr; /* Deserializer I2C address */ -+ -+ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ -+ usleep_range(2000, 2500); /* wait 2ms */ -+ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ -+ reg8_write(client, 0x5d, AR0132_I2C_ADDR << 1); /* Sensor native I2C address */ -+ -+ reg8_write(client, 0x6e, 0xa9); /* GPIO0 - reset, GPIO1 - fsin */ -+ } -+ if (priv->ti954_addr) { -+ client->addr = priv->ti954_addr; /* Deserializer I2C address */ ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x4_addr; /* Deserializer I2C address */ + + reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ + usleep_range(2000, 2500); /* wait 2ms */ @@ -1349,12 +1328,12 @@ index 0000000..97d9878 +#endif diff --git a/drivers/media/i2c/soc_camera/ar0132.h b/drivers/media/i2c/soc_camera/ar0132.h new file mode 100644 -index 0000000..bcee0e5 +index 0000000..bafa193 --- /dev/null +++ b/drivers/media/i2c/soc_camera/ar0132.h @@ -0,0 +1,213 @@ +/* -+ * ON Semiconductor ar0132 sensor camera wizard 1110x620@30/BGGR/BT601/12bit ++ * ON Semiconductor AR0132 sensor camera wizard 1110x620@30/BGGR/BT601/12bit + * + * Copyright (C) 2017 Cogent Embedded, Inc. + * @@ -1566,16 +1545,16 @@ index 0000000..bcee0e5 +{0x31D0, 0x0001}, +{0x30B0, 0x2002}, +}; -diff --git a/drivers/media/i2c/soc_camera/max9286.c b/drivers/media/i2c/soc_camera/max9286.c +diff --git a/drivers/media/i2c/soc_camera/ar0220.c b/drivers/media/i2c/soc_camera/ar0220.c new file mode 100644 -index 0000000..989c782 +index 0000000..ef2eb51 --- /dev/null -+++ b/drivers/media/i2c/soc_camera/max9286.c -@@ -0,0 +1,697 @@ ++++ b/drivers/media/i2c/soc_camera/ar0220.c +@@ -0,0 +1,528 @@ +/* -+ * MAXIM max9286 GMSL driver ++ * ON Semiconductor AR0220 sensor camera driver + * -+ * Copyright (C) 2015-2018 Cogent Embedded, Inc. ++ * Copyright (C) 2017-2018 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 @@ -1584,573 +1563,347 @@ index 0000000..989c782 + */ + +#include ++#include +#include +#include -+#include -+#include -+#include +#include + ++#include +#include -+#include ++#include +#include -+#include + -+#include "max9286.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_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 him; -+ int hsync; -+ int vsync; -+ int timeout; -+ int poc_delay; -+ atomic_t use_count; -+ u32 csi2_outord; -+ struct i2c_client *client; -+ int max9271_addr_map[4]; -+ int ser_id; -+ struct regulator *poc_supply[4]; /* PoC power supply */ -+}; ++#include "ar0220.h" + -+static char fsync_mode_default[20] = "manual"; /* manual, automatic, semi-automatic, external */ ++#define AR0220_I2C_ADDR 0x10 ++//#define AR0220_I2C_ADDR 0x54 // eeprom + -+static int conf_link; -+module_param(conf_link, int, 0644); -+MODULE_PARM_DESC(conf_link, " Force configuration link. Used only if robust firmware flashing required (f.e. recovery)"); ++#define AR0220_PID 0x3000 ++#define AR0220_VERSION_REG 0x0C54 + -+static int poc_trig; -+module_param(poc_trig, int, 0644); -+MODULE_PARM_DESC(poc_trig, " Use PoC triggering during reverse channel setup. Useful on systems with dedicated PoC and unstable ser-des lock */"); ++#define AR0220_MEDIA_BUS_FMT MEDIA_BUS_FMT_SBGGR8_1X8 + -+static int him; -+module_param(him, int, 0644); -+MODULE_PARM_DESC(him, " Use High-Immunity mode (default: leagacy mode) */"); ++struct ar0220_priv { ++ struct v4l2_subdev sd; ++ struct v4l2_ctrl_handler hdl; ++ struct media_pad pad; ++ struct v4l2_rect rect; ++ int init_complete; ++ u8 id[6]; ++ int exposure; ++ int gain; ++ int autogain; ++ /* serializers */ ++ int ti9x4_addr; ++ int ti9x3_addr; ++ int port; ++ int gpio_resetb; ++ int gpio_fsin; + -+static int fsync_period; -+module_param(fsync_period, int, 0644); -+MODULE_PARM_DESC(fsync_period, " Frame sync period (default: 3.2MHz) */"); ++}; + -+static int hsync; -+module_param(hsync, int, 0644); -+MODULE_PARM_DESC(hsync, " HSYNC invertion (default: 0 - not inverted) */"); ++static inline struct ar0220_priv *to_ar0220(const struct i2c_client *client) ++{ ++ return container_of(i2c_get_clientdata(client), struct ar0220_priv, sd); ++} + -+static int vsync = 1; -+module_param(vsync, int, 0644); -+MODULE_PARM_DESC(vsync, " VSYNC invertion (default: 1 - inverted) */"); ++static int ar0220_set_regs(struct i2c_client *client, ++ const struct ar0220_reg *regs, int nr_regs) ++{ ++ int i; + -+static int gpio_resetb; -+module_param(gpio_resetb, int, 0644); -+MODULE_PARM_DESC(gpio_resetb, " Serializer GPIO reset (default: 0 - not used) */"); ++ for (i = 0; i < nr_regs; i++) { ++ if (regs[i].reg == AR0220_DELAY) { ++ mdelay(regs[i].val); ++ continue; ++ } + -+static int active_low_resetb; -+module_param(active_low_resetb, int, 0644); -+MODULE_PARM_DESC(active_low_resetb, " Serializer GPIO reset level (default: 0 - active high) */"); ++ reg16_write16(client, regs[i].reg, regs[i].val); ++ } + -+static int poc_delay; -+module_param(poc_delay, int, 0644); -+MODULE_PARM_DESC(poc_delay, " Delay in ms after POC enable (default: 0 ms) */"); ++ return 0; ++} + -+static char* ser_name(int id) ++static int ar0220_s_stream(struct v4l2_subdev *sd, int enable) +{ -+ switch (id) { -+ case MAX9271_ID: -+ return "MAX9271"; -+ case MAX96705_ID: -+ return "MAX96705"; -+ default: -+ return "unknown"; -+ } ++ return 0; +} + -+static void max9286_preinit(struct i2c_client *client, int addr) ++static int ar0220_get_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) +{ -+ struct max9286_priv *priv = i2c_get_clientdata(client); ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0220_priv *priv = to_ar0220(client); + -+ 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 */ -+ reg8_write(client, 0x1c, priv->him ? 0xf4 : 0x04); /* high-immunity or legacy mode */ ++ if (format->pad) ++ return -EINVAL; ++ ++ mf->width = priv->rect.width; ++ mf->height = priv->rect.height; ++ mf->code = AR0220_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ return 0; +} + -+static void max9286_sensor_reset(struct i2c_client *client, int addr, int reset_on) ++static int ar0220_set_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) +{ -+ struct max9286_priv *priv = i2c_get_clientdata(client); ++ struct v4l2_mbus_framefmt *mf = &format->format; + -+ if (priv->gpio_resetb < 1 || priv->gpio_resetb > 5) -+ return; ++ mf->code = AR0220_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; + -+ /* sensor reset/unreset */ -+ client->addr = addr; /* MAX9271-CAMx I2C */ -+ reg8_write(client, 0x0f, (0xfe & ~BIT(priv->gpio_resetb)) | /* set GPIOn value to reset/unreset */ -+ ((priv->active_low_resetb ? BIT(priv->gpio_resetb) : 0) ^ reset_on)); -+ reg8_write(client, 0x0e, 0x42 | BIT(priv->gpio_resetb)); /* set GPIOn direction output */ ++ if (format->which == V4L2_SUBDEV_FORMAT_TRY) ++ cfg->try_fmt = *mf; ++ ++ return 0; +} + -+static void max9286_postinit(struct i2c_client *client, int addr) ++static int ar0220_enum_mbus_code(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_mbus_code_enum *code) +{ -+ struct max9286_priv *priv = i2c_get_clientdata(client); -+ int idx; ++ if (code->pad || code->index > 0) ++ return -EINVAL; + -+ for (idx = 0; idx < priv->links; idx++) { -+ client->addr = priv->des_addr; /* MAX9286 I2C */ -+ reg8_write(client, 0x0a, 0x11 << idx); /* enable reverse/forward control for CAMx */ ++ code->code = AR0220_MEDIA_BUS_FMT; + -+ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C */ -+ max9286_sensor_reset(client, client->addr, 0); /* sensor unreset */ -+ } ++ return 0; ++} + -+ client->addr = addr; /* MAX9286 I2C */ -+ reg8_write(client, 0x0a, 0x00); /* disable reverse control for all cams */ -+ reg8_write(client, 0x00, 0xe0 | priv->links_mask); /* enable GMSL link for CAMs */ -+ reg8_write(client, 0x0b, priv->csi2_outord); /* CSI2 output order */ -+ reg8_write(client, 0x15, 0x9b); /* enable CSI output, VC is set accordingly to Link number, BIT7 magic must be set */ -+ reg8_write(client, 0x1b, priv->links_mask); /* enable equalizer for CAMs */ -+ usleep_range(5000, 5500); /* wait 2ms after any change of reverse channel settings */ ++static int ar0220_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0220_priv *priv = to_ar0220(client); + -+ if (strcmp(priv->fsync_mode, "manual") == 0) { -+ 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 */ -+ } ++ memcpy(edid->edid, priv->id, 6); ++ ++ edid->edid[6] = 0xff; ++ edid->edid[7] = client->addr; ++ edid->edid[8] = AR0220_VERSION_REG >> 8; ++ edid->edid[9] = AR0220_VERSION_REG & 0xff; ++ ++ return 0; +} + -+static int max9286_reverse_channel_setup(struct i2c_client *client, int idx) ++static int ar0220_set_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) +{ -+ struct max9286_priv *priv = i2c_get_clientdata(client); -+ u8 val = 0; -+ int timeout = priv->timeout; -+ char timeout_str[10]; -+ int ret = 0; ++ struct v4l2_rect *rect = &sel->r; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0220_priv *priv = to_ar0220(client); + -+ /* 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 */ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || ++ sel->target != V4L2_SEL_TGT_CROP) ++ return -EINVAL; + -+ 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 */ ++ rect->left = ALIGN(rect->left, 2); ++ rect->top = ALIGN(rect->top, 2); ++ rect->width = ALIGN(rect->width, 2); ++ rect->height = ALIGN(rect->height, 2); + -+ client->addr = 0x40; /* MAX9271-CAMx I2C */ -+ reg8_write(client, 0x04, 0x43); /* wake-up, enable reverse_control/conf_link */ -+ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ -+ reg8_write(client, 0x08, 0x01); /* reverse channel receiver high threshold enable */ -+ reg8_write(client, 0x97, priv->him ? 0xaf : 0x5f); /* enable reverse control channel programming (MAX96705-MAX96711 only) */ -+ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ if ((rect->left + rect->width > AR0220_MAX_WIDTH) || ++ (rect->top + rect->height > AR0220_MAX_HEIGHT)) ++ *rect = priv->rect; + -+ client->addr = priv->des_addr; /* MAX9286-CAMx I2C */ -+ reg8_write(client, 0x3b, 0x19); /* reverse channel increase amplitude 170mV to compensate high threshold enabled */ -+ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ -+ -+ client->addr = 0x40; /* MAX9271-CAMx I2C */ -+ reg8_read(client, 0x1e, &val); /* read max9271 ID */ -+ if (val == MAX9271_ID || val == MAX96705_ID || --timeout == 0) { -+ priv->ser_id = val; -+ break; -+ } -+ -+ /* Check if already initialized (after reboot/reset ?) */ -+ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C */ -+ reg8_read(client, 0x1e, &val); /* read max9271 ID */ -+ if (val == MAX9271_ID || val == MAX96705_ID) { -+ priv->ser_id = val; -+ reg8_write(client, 0x04, 0x43); /* enable reverse_control/conf_link */ -+ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ -+ ret = -EADDRINUSE; -+ break; -+ } -+ -+ if (timeout == priv->timeout / 2 && poc_trig) { -+ if (!IS_ERR(priv->poc_supply[idx])) { -+ if (regulator_disable(priv->poc_supply[idx])) -+ dev_err(&client->dev, "fail to disable POC%d regulator\n", idx); -+ mdelay(200); -+ if (regulator_enable(priv->poc_supply[idx])) -+ dev_err(&client->dev, "fail to enable POC%d regulator\n", idx); -+ mdelay(priv->poc_delay); -+ } -+ } -+ } -+ -+ max9286_sensor_reset(client, client->addr, 1); /* sensor reset */ -+ -+ if (!timeout) { -+ ret = -ETIMEDOUT; -+ goto out; -+ } -+ -+ priv->links_mask |= BIT(idx); -+ priv->csi2_outord &= ~(0x3 << (idx * 2)); -+ priv->csi2_outord |= ((hweight8(priv->links_mask) - 1) << (idx * 2)); -+ -+out: -+ sprintf(timeout_str, "retries=%d", priv->timeout - timeout); -+ dev_info(&client->dev, "link%d %s %sat 0x%x %s %s\n", idx, ser_name(priv->ser_id), -+ ret == -EADDRINUSE ? "already " : "", priv->max9271_addr_map[idx], -+ ret == -ETIMEDOUT ? "not found: timeout GMSL link establish" : "", -+ priv->timeout - timeout? timeout_str : ""); -+ -+ return ret; -+} -+ -+static void max9286_initial_setup(struct i2c_client *client) -+{ -+ struct max9286_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); -+ } -+ -+ /* Start GMSL initialization with FSYNC disabled. This is required for some odd LVDS cameras */ -+ reg8_write(client, 0x01, 0xc0); /* ECU (aka MCU) based FrameSync using GPI-to-GPO */ -+ 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); ++ priv->rect.left = rect->left; ++ priv->rect.top = rect->top; ++ priv->rect.width = rect->width; ++ priv->rect.height = rect->height; + -+ reg8_write(client, 0x63, 0); /* disable overlap window */ -+ reg8_write(client, 0x64, 0); -+ reg8_write(client, 0x0c, 0x91 | (priv->vsync ? BIT(3) : 0) | (priv->hsync ? BIT(2) : 0)); /* enable HS/VS encoding, use D14/15 for HS/VS, invert HS/VS */ -+ reg8_write(client, 0x19, 0x0c); /* Drive HSTRAIL state for 120ns after the last payload bit */ ++ return 0; +} + -+static void max9286_gmsl_link_setup(struct i2c_client *client, int idx) ++static int ar0220_get_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) +{ -+ struct max9286_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 */ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0220_priv *priv = to_ar0220(client); + -+ if (priv->ser_id == MAX96705_ID) { -+ /* setup crossbar in DBL mode: reverse DVP bus */ -+ reg8_write(client, 0x20, 0x07); -+ reg8_write(client, 0x21, 0x06); -+ reg8_write(client, 0x22, 0x05); -+ reg8_write(client, 0x23, 0x04); -+ reg8_write(client, 0x24, 0x03); -+ reg8_write(client, 0x25, 0x02); -+ reg8_write(client, 0x26, 0x01); -+ reg8_write(client, 0x27, 0x00); ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) ++ return -EINVAL; + -+ reg8_write(client, 0x30, 0x17); -+ reg8_write(client, 0x31, 0x16); -+ reg8_write(client, 0x32, 0x15); -+ reg8_write(client, 0x33, 0x14); -+ reg8_write(client, 0x34, 0x13); -+ reg8_write(client, 0x35, 0x12); -+ reg8_write(client, 0x36, 0x11); -+ reg8_write(client, 0x37, 0x10); ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = AR0220_MAX_WIDTH; ++ sel->r.height = AR0220_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = AR0220_MAX_WIDTH; ++ sel->r.height = AR0220_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP: ++ sel->r = priv->rect; ++ return 0; ++ default: ++ return -EINVAL; + } -+ -+ client->addr = priv->des_addr; /* MAX9286-CAMx I2C */ -+ reg8_write(client, 0x34, 0x22 | MAXIM_I2C_I2C_SPEED); /* disable artificial ACK, I2C speed set */ -+ usleep_range(2000, 2500); /* wait 2ms */ -+ -+ /* I2C translator setup */ -+ client->addr = 0x40; /* MAX9271-CAMx I2C */ -+// reg8_write(client, 0x09, maxim_map[2][idx] << 1); /* SENSOR I2C translated - must be set by sensor driver */ -+// reg8_write(client, 0x0A, 0x30 << 1); /* SENSOR I2C native - must be set by sensor driver */ -+ reg8_write(client, 0x0B, BROADCAST << 1); /* broadcast I2C */ -+ reg8_write(client, 0x0C, priv->max9271_addr_map[idx] << 1); /* MAX9271-CAMx I2C new */ -+ /* I2C addresse change */ -+ reg8_write(client, 0x01, priv->des_addr << 1); /* MAX9286 I2C */ -+ reg8_write(client, 0x00, priv->max9271_addr_map[idx] << 1); /* MAX9271-CAM0 I2C new */ -+ usleep_range(2000, 2500); /* wait 2ms */ -+ /* put MAX9271 in configuration link state */ -+ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C new */ -+ reg8_write(client, 0x04, 0x43); /* enable reverse_control/conf_link */ -+ usleep_range(2000, 2500); /* wait 2ms */ -+#ifdef MAXIM_DUMP -+ client->addr = priv->des_addr; /* MAX9286-CAMx I2C */ -+ maxim_max927x_dump_regs(client); -+ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C new */ -+ maxim_max927x_dump_regs(client); -+#endif +} + -+static int max9286_initialize(struct i2c_client *client) ++static int ar0220_g_mbus_config(struct v4l2_subdev *sd, ++ struct v4l2_mbus_config *cfg) +{ -+ struct max9286_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_preinit(client, priv->des_quirk_addr); -+ -+ max9286_preinit(client, priv->des_addr); -+ max9286_initial_setup(client); -+ -+ for (idx = 0; idx < priv->links; idx++) { -+ if (!IS_ERR(priv->poc_supply[idx])) { -+ if (regulator_enable(priv->poc_supply[idx])) -+ dev_err(&client->dev, "fail to enable POC%d regulator\n", idx); -+ mdelay(priv->poc_delay); -+ } -+ -+ ret = max9286_reverse_channel_setup(client, idx); -+ if (ret) -+ continue; -+ max9286_gmsl_link_setup(client, idx); -+ } -+ -+ max9286_postinit(client, priv->des_addr); -+ -+ client->addr = priv->des_addr; ++ 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 max9286_g_register(struct v4l2_subdev *sd, -+ struct v4l2_dbg_register *reg) ++static int ar0220_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) +{ -+ struct max9286_priv *priv = v4l2_get_subdevdata(sd); -+ struct i2c_client *client = priv->client; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); + int ret; -+ u8 val = 0; ++ u16 val = 0; + -+ ret = reg8_read(client, (u8)reg->reg, &val); ++ ret = reg16_read16(client, (u16)reg->reg, &val); + if (ret < 0) + return ret; + + reg->val = val; -+ reg->size = sizeof(u8); ++ reg->size = sizeof(u16); + + return 0; +} + -+static int max9286_s_register(struct v4l2_subdev *sd, -+ const struct v4l2_dbg_register *reg) ++static int ar0220_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) +{ -+ struct max9286_priv *priv = v4l2_get_subdevdata(sd); -+ struct i2c_client *client = priv->client; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); + -+ return reg8_write(client, (u8)reg->reg, (u8)reg->val); ++ return reg16_write16(client, (u16)reg->reg, (u16)reg->val); +} +#endif + -+static int max9286_s_power(struct v4l2_subdev *sd, int on) ++static struct v4l2_subdev_core_ops ar0220_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = ar0220_g_register, ++ .s_register = ar0220_s_register, ++#endif ++}; ++ ++static int ar0220_s_ctrl(struct v4l2_ctrl *ctrl) +{ -+ struct max9286_priv *priv = v4l2_get_subdevdata(sd); -+ struct i2c_client *client = priv->client; ++ struct v4l2_subdev *sd = to_sd(ctrl); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ar0220_priv *priv = to_ar0220(client); ++ int ret = -EINVAL; + -+ 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 */ ++ if (!priv->init_complete) ++ return 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_BRIGHTNESS: ++ case V4L2_CID_CONTRAST: ++ case V4L2_CID_SATURATION: ++ case V4L2_CID_HUE: ++ case V4L2_CID_GAMMA: ++ case V4L2_CID_SHARPNESS: ++ case V4L2_CID_AUTOGAIN: ++ case V4L2_CID_GAIN: ++ case V4L2_CID_EXPOSURE: ++ case V4L2_CID_HFLIP: ++ case V4L2_CID_VFLIP: ++ break; + } + -+ return 0; ++ return ret; +} + -+static int max9286_registered_async(struct v4l2_subdev *sd) -+{ -+ struct max9286_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, conf_link ? 0x43 : 0x83); /* enable 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; ++static const struct v4l2_ctrl_ops ar0220_ctrl_ops = { ++ .s_ctrl = ar0220_s_ctrl, ++}; + -+ return 0; -+} ++static struct v4l2_subdev_video_ops ar0220_video_ops = { ++ .s_stream = ar0220_s_stream, ++ .g_mbus_config = ar0220_g_mbus_config, ++}; + -+static struct v4l2_subdev_core_ops max9286_subdev_core_ops = { -+#ifdef CONFIG_VIDEO_ADV_DEBUG -+ .g_register = max9286_g_register, -+ .s_register = max9286_s_register, -+#endif -+ .s_power = max9286_s_power, -+ .registered_async = max9286_registered_async, ++static const struct v4l2_subdev_pad_ops ar0220_subdev_pad_ops = { ++ .get_edid = ar0220_get_edid, ++ .enum_mbus_code = ar0220_enum_mbus_code, ++ .get_selection = ar0220_get_selection, ++ .set_selection = ar0220_set_selection, ++ .get_fmt = ar0220_get_fmt, ++ .set_fmt = ar0220_set_fmt, +}; + -+static struct v4l2_subdev_ops max9286_subdev_ops = { -+ .core = &max9286_subdev_core_ops, ++static struct v4l2_subdev_ops ar0220_subdev_ops = { ++ .core = &ar0220_core_ops, ++ .video = &ar0220_video_ops, ++ .pad = &ar0220_subdev_pad_ops, +}; + -+static int max9286_parse_dt(struct i2c_client *client) ++static void ar0220_otp_id_read(struct i2c_client *client) +{ -+ struct max9286_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; -+ -+ u8 val = 0; -+ -+ if (of_property_read_u32(np, "maxim,links", &priv->links)) -+ priv->links = 4; -+ -+ if (of_property_read_u32(np, "maxim,lanes", &priv->lanes)) -+ priv->lanes = 4; -+ -+ pwen = of_get_gpio(np, 0); -+ if (pwen > 0) { -+ err = gpio_request_one(pwen, GPIOF_OUT_INIT_HIGH, dev_name(&client->dev)); -+ if (err) -+ dev_err(&client->dev, "cannot request PWEN gpio %d: %d\n", pwen, err); -+ } ++} + -+ mdelay(250); ++static ssize_t ar0220_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 ar0220_priv *priv = to_ar0220(client); + -+ 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; -+ } ++ 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]); ++} + -+ 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); ++static DEVICE_ATTR(otp_id_ar0220, S_IRUGO, ar0220_otp_id_show, NULL); + -+ 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 = 0; -+ else -+ priv->active_low_resetb = 1; -+ } ++static int ar0220_initialize(struct i2c_client *client) ++{ ++ struct ar0220_priv *priv = to_ar0220(client); ++ u16 val = 0; ++ u16 pid = 0; ++ int ret = 0; + -+ 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; -+ if (of_property_read_u32(np, "maxim,him", &priv->him)) -+ priv->him = 0; -+ if (of_property_read_u32(np, "maxim,hsync", &priv->hsync)) -+ priv->hsync = 0; -+ if (of_property_read_u32(np, "maxim,vsync", &priv->vsync)) -+ priv->vsync = 1; -+ if (of_property_read_u32(np, "maxim,poc-delay", &priv->poc_delay)) -+ priv->poc_delay = 50; ++ /* check and show model ID */ ++ reg16_read16(client, AR0220_PID, &pid); + -+ /* module params override dts */ -+ if (him) -+ priv->him = him; -+ if (fsync_period) { -+ priv->fsync_period = fsync_period; -+ priv->fsync_mode = fsync_mode_default; ++ if (pid != AR0220_VERSION_REG) { ++ dev_dbg(&client->dev, "Product ID error %x\n", pid); ++ ret = -ENODEV; ++ goto err; + } -+ if (hsync) -+ priv->hsync = hsync; -+ if (!vsync) -+ priv->vsync = vsync; -+ if (gpio_resetb) -+ priv->gpio_resetb = gpio_resetb; -+ if (active_low_resetb) -+ priv->active_low_resetb = active_low_resetb; -+ if (poc_delay) -+ priv->poc_delay = poc_delay; -+ -+ for (i = 0; i < priv->links; i++) { -+ endpoint = of_graph_get_next_endpoint(np, endpoint); -+ if (!endpoint) -+ break; + -+ of_node_put(endpoint); ++ /* Program wizard registers */ ++ ar0220_set_regs(client, ar0220_regs_wizard, ARRAY_SIZE(ar0220_regs_wizard)); + -+ if (of_property_read_u32(endpoint, "max9271-addr", &priv->max9271_addr_map[i])) { -+ dev_err(&client->dev, "max9271-addr not set\n"); -+ return -EINVAL; -+ } ++ /* Enable stream */ ++ reg16_read16(client, 0x301a, &val); // read inital reset_register value ++ val |= (1 << 2); // Set streamOn bit ++ reg16_write16(client, 0x301a, val); // Start Streaming + -+ priv->sd_of_node[i] = endpoint; -+ } ++ /* Read OTP IDs */ ++ ar0220_otp_id_read(client); + -+ return 0; ++ dev_info(&client->dev, "ar0220 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, AR0220_MAX_WIDTH, AR0220_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++err: ++ return ret; +} + -+static void max9286_setup_remote_endpoint(struct i2c_client *client) ++static int ar0220_parse_dt(struct device_node *np, struct ar0220_priv *priv) +{ -+ struct max9286_priv *priv = i2c_get_clientdata(client); -+ struct device_node *np = client->dev.of_node; -+ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); + int i; -+ struct property *csi_rate_prop, *dvp_order_prop; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ int tmp_addr = 0; + + for (i = 0; ; i++) { + endpoint = of_graph_get_next_endpoint(np, endpoint); @@ -2163,122 +1916,179 @@ index 0000000..989c782 + 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); -+ } ++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti9x4") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti9x4_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ } + -+ dvp_order_prop = of_find_property(endpoint, "dvp-order", NULL); -+ if (dvp_order_prop) -+ of_update_property(rendpoint, dvp_order_prop); ++ if (!priv->ti9x4_addr) { ++ dev_err(&client->dev, "deserializer does not present\n"); ++ return -EINVAL; ++ } ++ ++ /* setup I2C translator address */ ++ tmp_addr = client->addr; ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x4_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, AR0220_I2C_ADDR << 1); /* Sensor native I2C address */ ++ ++// reg8_write(client, 0x6e, 0xa9); /* GPIO0 - reset, GPIO1 - fsin */ + } ++ client->addr = tmp_addr; ++ ++ mdelay(10); ++ ++ return 0; +} + -+static int max9286_probe(struct i2c_client *client, -+ const struct i2c_device_id *did) ++static int ar0220_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) +{ -+ struct max9286_priv *priv; -+ int err, i; -+ char supply_name[10]; ++ struct ar0220_priv *priv; ++ int ret; + + 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; ++ v4l2_i2c_subdev_init(&priv->sd, client, &ar0220_subdev_ops); ++ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; + -+ err = max9286_parse_dt(client); -+ if (err) -+ goto out; ++ priv->exposure = 0x100; ++ priv->gain = 0x100; ++ priv->autogain = 1; ++ v4l2_ctrl_handler_init(&priv->hdl, 4); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0220_ctrl_ops, ++ V4L2_CID_BRIGHTNESS, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0220_ctrl_ops, ++ V4L2_CID_CONTRAST, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0220_ctrl_ops, ++ V4L2_CID_SATURATION, 0, 7, 1, 2); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0220_ctrl_ops, ++ V4L2_CID_HUE, 0, 23, 1, 12); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0220_ctrl_ops, ++ V4L2_CID_GAMMA, -128, 128, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0220_ctrl_ops, ++ V4L2_CID_SHARPNESS, 0, 10, 1, 3); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0220_ctrl_ops, ++ V4L2_CID_AUTOGAIN, 0, 1, 1, priv->autogain); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0220_ctrl_ops, ++ V4L2_CID_GAIN, 0, 0xffff, 1, priv->gain); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0220_ctrl_ops, ++ V4L2_CID_EXPOSURE, 0, 0xffff, 1, priv->exposure); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0220_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 1); ++ v4l2_ctrl_new_std(&priv->hdl, &ar0220_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ priv->sd.ctrl_handler = &priv->hdl; + -+ for (i = 0; i < 4; i++) { -+ sprintf(supply_name, "POC%d", i); -+ priv->poc_supply[i] = devm_regulator_get_optional(&client->dev, supply_name); -+ } ++ ret = priv->hdl.error; ++ if (ret) ++ goto cleanup; + -+ err = max9286_initialize(client); -+ if (err < 0) -+ goto out; ++ v4l2_ctrl_handler_setup(&priv->hdl); + -+ max9286_setup_remote_endpoint(client); ++ 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; + -+ for (i = 0; i < 4; i++) { -+ v4l2_subdev_init(&priv->sd[i], &max9286_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]; ++ ret = ar0220_parse_dt(client->dev.of_node, priv); ++ if (ret) ++ goto cleanup; + -+ 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); ++ ret = ar0220_initialize(client); ++ if (ret < 0) ++ goto cleanup; + -+ err = v4l2_async_register_subdev(&priv->sd[i]); -+ if (err < 0) -+ goto out; -+ } -+out: -+ return err; -+} ++ priv->rect.left = 0; ++ priv->rect.top = 0; ++ priv->rect.width = AR0220_MAX_WIDTH; ++ priv->rect.height = AR0220_MAX_HEIGHT; + -+static int max9286_remove(struct i2c_client *client) -+{ -+ struct max9286_priv *priv = i2c_get_clientdata(client); -+ int i; ++ ret = v4l2_async_register_subdev(&priv->sd); ++ if (ret) ++ goto cleanup; + -+ for (i = 0; i < 4; i++) { -+ v4l2_async_unregister_subdev(&priv->sd[i]); -+ v4l2_device_unregister_subdev(&priv->sd[i]); ++ if (device_create_file(&client->dev, &dev_attr_otp_id_ar0220) != 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_AR0220 ++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", ++ client->addr, client->adapter->name); ++#endif ++ return ret; +} + -+static const struct of_device_id max9286_dt_ids[] = { -+ { .compatible = "maxim,max9286" }, -+ {}, ++static int ar0220_remove(struct i2c_client *client) ++{ ++ struct ar0220_priv *priv = i2c_get_clientdata(client); ++ ++ device_remove_file(&client->dev, &dev_attr_otp_id_ar0220); ++ 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_AR0220 ++static const struct i2c_device_id ar0220_id[] = { ++ { "ar0220", 0 }, ++ { } +}; -+MODULE_DEVICE_TABLE(of, max9286_dt_ids); ++MODULE_DEVICE_TABLE(i2c, ar0220_id); + -+static const struct i2c_device_id max9286_id[] = { -+ { "max9286", 0 }, ++static const struct of_device_id ar0220_of_ids[] = { ++ { .compatible = "aptina,ar0220", }, + { } +}; -+MODULE_DEVICE_TABLE(i2c, max9286_id); ++MODULE_DEVICE_TABLE(of, ar0220_of_ids); + -+static struct i2c_driver max9286_i2c_driver = { ++static struct i2c_driver ar0220_i2c_driver = { + .driver = { -+ .name = "max9286", -+ .of_match_table = of_match_ptr(max9286_dt_ids), ++ .name = "ar0220", ++ .of_match_table = ar0220_of_ids, + }, -+ .probe = max9286_probe, -+ .remove = max9286_remove, -+ .id_table = max9286_id, ++ .probe = ar0220_probe, ++ .remove = ar0220_remove, ++ .id_table = ar0220_id, +}; + -+module_i2c_driver(max9286_i2c_driver); ++module_i2c_driver(ar0220_i2c_driver); + -+MODULE_DESCRIPTION("GMSL driver for MAX9286"); ++MODULE_DESCRIPTION("SoC Camera driver for AR0220"); +MODULE_AUTHOR("Vladimir Barinov"); +MODULE_LICENSE("GPL"); -diff --git a/drivers/media/i2c/soc_camera/max9286.h b/drivers/media/i2c/soc_camera/max9286.h ++#endif +diff --git a/drivers/media/i2c/soc_camera/ar0220.h b/drivers/media/i2c/soc_camera/ar0220.h new file mode 100644 -index 0000000..6c2a9e0 +index 0000000..29987a6 --- /dev/null -+++ b/drivers/media/i2c/soc_camera/max9286.h -@@ -0,0 +1,244 @@ ++++ b/drivers/media/i2c/soc_camera/ar0220.h +@@ -0,0 +1,43 @@ +/* -+ * MAXIM max9286-max9271 GMSL driver include file ++ * ON Semiconductor AR0220 sensor camera wizard 1820x940@44/RCCB/BT656 + * -+ * Copyright (C) 2015-2017 Cogent Embedded, Inc. ++ * 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 @@ -2286,1012 +2096,999 @@ index 0000000..6c2a9e0 + * option) any later version. + */ + -+#ifndef _MAX9286_MAX9271_H -+#define _MAX9286_MAX9271_H ++//#define AR0220_DISPLAY_PATTERN_FIXED ++//#define AR0220_DISPLAY_PATTERN_COLOR_BAR + -+//#define DEBUG -+#ifdef DEBUG -+//#define WRITE_VERIFY -+#define MAXIM_DUMP -+#undef dev_dbg -+#define dev_dbg dev_info -+#endif ++#define AR0220_MAX_WIDTH 3648 // (1820*2=3640) <- must be multiple of 16 - requred by R-CAR VIN ++#define AR0220_MAX_HEIGHT 944 + -+#define REG8_NUM_RETRIES 1 /* number of read/write retries */ -+#define REG16_NUM_RETRIES 10 /* number of read/write retries */ -+#define MAX9271_ID 0x9 -+#define MAX96705_ID 0x41 -+#define MAX9286_ID 0x40 -+#define BROADCAST 0x6f ++#define AR0220_DELAY 0xffff + -+static inline int reg8_read(struct i2c_client *client, u8 reg, u8 *val) -+{ -+ int ret, retries; ++struct ar0220_reg { ++ u16 reg; ++ u16 val; ++}; + -+ for (retries = REG8_NUM_RETRIES; retries; retries--) { -+ ret = i2c_smbus_read_byte_data(client, reg); -+ if (!(ret < 0)) -+ break; -+ } ++static const struct ar0220_reg ar0220_regs_wizard[] = { ++{0x301A, 0x0018}, // RESET_REGISTER ++{AR0220_DELAY, 500}, // Wait 500ms ++{0x3070, 0x0000}, // 1: Solid color test pattern, ++ // 2: Full color bar test pattern, ++ // 3: Fade to grey color bar test pattern, ++ //256: Walking 1 test pattern (12 bit) ++{0x3072, 0x0123}, // R ++{0x3074, 0x0456}, // G(GR row) ++{0x3076, 0x0abc}, // B ++{0x3078, 0x0def}, // G(GB row) ++#ifdef AR0220_DISPLAY_PATTERN_FIXED ++{0x3070, 0x0001}, ++#endif ++#ifdef AR0220_DISPLAY_PATTERN_COLOR_BAR ++{0x3070, 0x0002}, ++#endif ++{AR0220_DELAY, 100}, // Wait 100ms ++}; +diff --git a/drivers/media/i2c/soc_camera/max9286.c b/drivers/media/i2c/soc_camera/max9286.c +new file mode 100644 +index 0000000..4dd80f5 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/max9286.c +@@ -0,0 +1,697 @@ ++/* ++ * MAXIM max9286 GMSL driver ++ * ++ * Copyright (C) 2015-2018 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. ++ */ + -+ if (ret < 0) { -+ dev_dbg(&client->dev, -+ "read fail: chip 0x%x register 0x%x: %d\n", -+ client->addr, reg, ret); -+ } else { -+ *val = ret; -+ } ++#include ++#include ++#include ++#include ++#include ++#include ++#include + -+ return ret < 0 ? ret : 0; -+} ++#include ++#include ++#include ++#include + -+static inline int reg8_write(struct i2c_client *client, u8 reg, u8 val) -+{ -+ int ret, retries; ++#include "max9286.h" + -+ for (retries = REG8_NUM_RETRIES; retries; retries--) { -+ ret = i2c_smbus_write_byte_data(client, reg, val); -+ if (!(ret < 0)) -+ break; -+ } ++#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 + -+ 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 -+ } ++struct max9286_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 him; ++ int hsync; ++ int vsync; ++ int timeout; ++ int poc_delay; ++ atomic_t use_count; ++ u32 csi2_outord; ++ struct i2c_client *client; ++ int max9271_addr_map[4]; ++ int ser_id; ++ struct regulator *poc_supply[4]; /* PoC power supply */ ++}; + -+ return ret < 0 ? ret : 0; -+} ++static char fsync_mode_default[20] = "manual"; /* manual, automatic, semi-automatic, external */ + -+static inline int reg16_read(struct i2c_client *client, u16 reg, u8 *val) -+{ -+ int ret, retries; -+ u8 buf[2] = {reg >> 8, reg & 0xff}; ++static int conf_link; ++module_param(conf_link, int, 0644); ++MODULE_PARM_DESC(conf_link, " Force configuration link. Used only if robust firmware flashing required (f.e. recovery)"); + -+ 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; -+ } -+ } ++static int poc_trig; ++module_param(poc_trig, int, 0644); ++MODULE_PARM_DESC(poc_trig, " Use PoC triggering during reverse channel setup. Useful on systems with dedicated PoC and unstable ser-des lock"); + -+ 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]; -+ } ++static int him; ++module_param(him, int, 0644); ++MODULE_PARM_DESC(him, " Use High-Immunity mode (default: leagacy mode)"); + -+ return ret < 0 ? ret : 0; -+} ++static int fsync_period; ++module_param(fsync_period, int, 0644); ++MODULE_PARM_DESC(fsync_period, " Frame sync period (default: 3.2MHz)"); + -+static inline int reg16_write(struct i2c_client *client, u16 reg, u8 val) -+{ -+ int ret, retries; -+ u8 buf[3] = {reg >> 8, reg & 0xff, val}; ++static int hsync; ++module_param(hsync, int, 0644); ++MODULE_PARM_DESC(hsync, " HSYNC invertion (default: 0 - not inverted)"); + -+ for (retries = REG16_NUM_RETRIES; retries; retries--) { -+ ret = i2c_master_send(client, buf, 3); -+ if (ret == 3) -+ break; -+ } ++static int vsync = 1; ++module_param(vsync, int, 0644); ++MODULE_PARM_DESC(vsync, " VSYNC invertion (default: 1 - inverted)"); + -+ 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 -+ } ++static int gpio_resetb; ++module_param(gpio_resetb, int, 0644); ++MODULE_PARM_DESC(gpio_resetb, " Serializer GPIO reset (default: 0 - not used)"); + -+ return ret < 0 ? ret : 0; -+} ++static int active_low_resetb; ++module_param(active_low_resetb, int, 0644); ++MODULE_PARM_DESC(active_low_resetb, " Serializer GPIO reset level (default: 0 - active high)"); + ++static int poc_delay; ++module_param(poc_delay, int, 0644); ++MODULE_PARM_DESC(poc_delay, " Delay in ms after POC enable (default: 0 ms)"); + -+static inline int reg16_read16(struct i2c_client *client, u16 reg, u16 *val) ++static char* ser_name(int id) +{ -+ int ret, retries; -+ u8 buf[2] = {reg >> 8, reg & 0xff}; -+ -+ for (retries = REG8_NUM_RETRIES; retries; retries--) { -+ ret = i2c_master_send(client, buf, 2); -+ if (ret == 2) { -+ ret = i2c_master_recv(client, buf, 2); -+ if (ret == 2) -+ break; -+ } -+ } -+ -+ if (ret < 0) { -+ dev_err(&client->dev, -+ "read fail: chip 0x%x register 0x%x: %d\n", -+ client->addr, reg, ret); -+ } else { -+ *val = ((u16)buf[0] << 8) | buf[1]; ++ switch (id) { ++ case MAX9271_ID: ++ return "MAX9271"; ++ case MAX96705_ID: ++ return "MAX96705"; ++ default: ++ return "unknown"; + } -+ -+ return ret < 0 ? ret : 0; +} + -+static inline int reg16_write16(struct i2c_client *client, u16 reg, u16 val) ++static void max9286_preinit(struct i2c_client *client, int addr) +{ -+ int ret, retries; -+ u8 buf[4] = {reg >> 8, reg & 0xff, val >> 8, val & 0xff}; -+ -+ for (retries = REG8_NUM_RETRIES; retries; retries--) { -+ ret = i2c_master_send(client, buf, 4); -+ if (ret == 4) -+ break; -+ } -+ -+ if (ret < 0) { -+ dev_err(&client->dev, -+ "write fail: chip 0x%x register 0x%x: %d\n", -+ client->addr, reg, ret); -+ } ++ struct max9286_priv *priv = i2c_get_clientdata(client); + -+ return ret < 0 ? ret : 0; ++ 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 */ ++ reg8_write(client, 0x1c, priv->him ? 0xf4 : 0x04); /* high-immunity or legacy mode */ +} + -+ -+#ifdef MAXIM_DUMP -+static void maxim_ovsensor_dump_regs(struct i2c_client *client) ++static void max9286_sensor_reset(struct i2c_client *client, int addr, int reset_on) +{ -+ int ret, i; -+ u8 val = 0; -+ u16 regs[] = {0x300a, 0x300b, 0x300c}; ++ struct max9286_priv *priv = i2c_get_clientdata(client); + -+ dev_dbg(&client->dev, "dump regs 0x%x\n", client->addr); ++ if (priv->gpio_resetb < 1 || priv->gpio_resetb > 5) ++ return; + -+ 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); -+ } ++ /* sensor reset/unreset */ ++ client->addr = addr; /* MAX9271-CAMx I2C */ ++ reg8_write(client, 0x0f, (0xfe & ~BIT(priv->gpio_resetb)) | /* set GPIOn value to reset/unreset */ ++ ((priv->active_low_resetb ? BIT(priv->gpio_resetb) : 0) ^ reset_on)); ++ reg8_write(client, 0x0e, 0x42 | BIT(priv->gpio_resetb)); /* set GPIOn direction output */ +} + -+static void maxim_ov10635_dump_format_regs(struct i2c_client *client) ++static void max9286_postinit(struct i2c_client *client, int addr) +{ -+ 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, -+ }; ++ struct max9286_priv *priv = i2c_get_clientdata(client); ++ int idx; + -+ dev_dbg(&client->dev, "dump regs 0x%x\n", client->addr); ++ for (idx = 0; idx < priv->links; idx++) { ++ client->addr = priv->des_addr; /* MAX9286 I2C */ ++ reg8_write(client, 0x0a, 0x11 << idx); /* enable reverse/forward control for CAMx */ + -+ 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); ++ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C */ ++ max9286_sensor_reset(client, client->addr, 0); /* sensor unreset */ + } -+} + -+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); ++ 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 */ + -+ 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"); ++ if (strcmp(priv->fsync_mode, "manual") == 0) { ++ 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 */ + } +} -+#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..8c06e59 ---- /dev/null -+++ b/drivers/media/i2c/soc_camera/ov10635.c -@@ -0,0 +1,759 @@ -+/* -+ * 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 -+#include -+#include -+#include -+#include ++static int max9286_reverse_channel_setup(struct i2c_client *client, int idx) ++{ ++ struct max9286_priv *priv = i2c_get_clientdata(client); ++ u8 val = 0; ++ int timeout = priv->timeout; ++ char timeout_str[10]; ++ int ret = 0; + -+#include -+#include -+#include -+#include ++ /* 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 */ + -+#include "max9286.h" -+#include "ov10635.h" ++ 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 */ + -+#define OV10635_I2C_ADDR 0x30 ++ client->addr = 0x40; /* MAX9271-CAMx I2C */ ++ reg8_write(client, 0x04, 0x43); /* wake-up, enable reverse_control/conf_link */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ reg8_write(client, 0x08, 0x01); /* reverse channel receiver high threshold enable */ ++ reg8_write(client, 0x97, priv->him ? 0xaf : 0x5f); /* enable reverse control channel programming (MAX96705-MAX96711 only) */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ + -+#define OV10635_PID 0x300a -+#define OV10635_VER 0x300b -+#define OV10635_VERSION_REG 0xa635 -+#define OV10635_VERSION(pid, ver) (((pid) << 8) | ((ver) & 0xff)) ++ 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 */ + -+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; -+}; ++ client->addr = 0x40; /* MAX9271-CAMx I2C */ ++ reg8_read(client, 0x1e, &val); /* read max9271 ID */ ++ if (val == MAX9271_ID || val == MAX96705_ID || --timeout == 0) { ++ priv->ser_id = val; ++ break; ++ } + -+static inline struct ov10635_priv *to_ov10635(const struct i2c_client *client) -+{ -+ return container_of(i2c_get_clientdata(client), struct ov10635_priv, sd); -+} ++ /* Check if already initialized (after reboot/reset ?) */ ++ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C */ ++ reg8_read(client, 0x1e, &val); /* read max9271 ID */ ++ if (val == MAX9271_ID || val == MAX96705_ID) { ++ priv->ser_id = val; ++ 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; ++ } + -+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) -+{ -+ return &container_of(ctrl->handler, struct ov10635_priv, hdl)->sd; -+} ++ if (timeout == priv->timeout / 2 && poc_trig) { ++ if (!IS_ERR(priv->poc_supply[idx])) { ++ if (regulator_disable(priv->poc_supply[idx])) ++ dev_err(&client->dev, "fail to disable POC%d regulator\n", idx); ++ mdelay(200); ++ if (regulator_enable(priv->poc_supply[idx])) ++ dev_err(&client->dev, "fail to enable POC%d regulator\n", idx); ++ mdelay(priv->poc_delay); ++ } ++ } ++ } + -+static void ov10635_s_port(struct i2c_client *client, int fwd_en) -+{ -+ struct ov10635_priv *priv = to_ov10635(client); -+ int tmp_addr; ++ max9286_sensor_reset(client, client->addr, 1); /* sensor reset */ + -+ 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(5000, 5500); /* wait 5ms */ -+ client->addr = tmp_addr; -+ }; ++ if (!timeout) { ++ ret = -ETIMEDOUT; ++ goto out; ++ } ++ ++ priv->links_mask |= BIT(idx); ++ priv->csi2_outord &= ~(0x3 << (idx * 2)); ++ priv->csi2_outord |= ((hweight8(priv->links_mask) - 1) << (idx * 2)); ++ ++out: ++ sprintf(timeout_str, "retries=%d", priv->timeout - timeout); ++ dev_info(&client->dev, "link%d %s %sat 0x%x %s %s\n", idx, ser_name(priv->ser_id), ++ ret == -EADDRINUSE ? "already " : "", priv->max9271_addr_map[idx], ++ ret == -ETIMEDOUT ? "not found: timeout GMSL link establish" : "", ++ priv->timeout - timeout? timeout_str : ""); ++ ++ return ret; +} + -+static int ov10635_set_regs(struct i2c_client *client, -+ const struct ov10635_reg *regs, int nr_regs) ++static void max9286_initial_setup(struct i2c_client *client) +{ -+ int i; ++ struct max9286_priv *priv = i2c_get_clientdata(client); + -+ 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); -+ } ++ /* 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); + } + -+ return 0; -+} ++ /* Start GMSL initialization with FSYNC disabled. This is required for some odd LVDS cameras */ ++ reg8_write(client, 0x01, 0xc0); /* ECU (aka MCU) based FrameSync using GPI-to-GPO */ ++ 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); + -+static int ov10635_s_stream(struct v4l2_subdev *sd, int enable) -+{ -+ return 0; ++ reg8_write(client, 0x63, 0); /* disable overlap window */ ++ reg8_write(client, 0x64, 0); ++ reg8_write(client, 0x0c, 0x91 | (priv->vsync ? BIT(3) : 0) | (priv->hsync ? BIT(2) : 0)); /* enable HS/VS encoding, use D14/15 for HS/VS, invert HS/VS */ ++ reg8_write(client, 0x19, 0x0c); /* Drive HSTRAIL state for 120ns after the last payload bit */ +} + -+static int ov10635_set_window(struct v4l2_subdev *sd, int subsampling) ++static void max9286_gmsl_link_setup(struct i2c_client *client, int idx) +{ -+ struct i2c_client *client = v4l2_get_subdevdata(sd); -+ struct ov10635_priv *priv = to_ov10635(client); ++ struct max9286_priv *priv = i2c_get_clientdata(client); + -+ /* disable clocks */ -+ reg16_write(client, 0x302e, 0x00); -+ reg16_write(client, 0x301b, 0xff); -+ reg16_write(client, 0x301c, 0xff); -+ reg16_write(client, 0x301a, 0xff); ++ /* 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 */ + -+ /* 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); ++ if (priv->ser_id == MAX96705_ID) { ++ /* setup crossbar in DBL mode: reverse DVP bus */ ++ reg8_write(client, 0x20, 0x07); ++ reg8_write(client, 0x21, 0x06); ++ reg8_write(client, 0x22, 0x05); ++ reg8_write(client, 0x23, 0x04); ++ reg8_write(client, 0x24, 0x03); ++ reg8_write(client, 0x25, 0x02); ++ reg8_write(client, 0x26, 0x01); ++ reg8_write(client, 0x27, 0x00); + -+ /* enable/disable subsampling */ -+ reg16_write(client, 0x5005, subsampling ? 0x89 : 0x08); -+ reg16_write(client, 0x3007, subsampling ? 0x02 : 0x01); -+ reg16_write(client, 0x4004, subsampling ? 0x02 : 0x04); ++ reg8_write(client, 0x30, 0x17); ++ reg8_write(client, 0x31, 0x16); ++ reg8_write(client, 0x32, 0x15); ++ reg8_write(client, 0x33, 0x14); ++ reg8_write(client, 0x34, 0x13); ++ reg8_write(client, 0x35, 0x12); ++ reg8_write(client, 0x36, 0x11); ++ reg8_write(client, 0x37, 0x10); ++ } + -+#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); ++ 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 */ + -+ return 0; -+}; ++ /* I2C translator setup */ ++ client->addr = 0x40; /* MAX9271-CAMx I2C */ ++// reg8_write(client, 0x09, maxim_map[2][idx] << 1); /* SENSOR I2C translated - must be set by sensor driver */ ++// reg8_write(client, 0x0A, 0x30 << 1); /* SENSOR I2C native - must be set by sensor driver */ ++ reg8_write(client, 0x0B, BROADCAST << 1); /* broadcast I2C */ ++ reg8_write(client, 0x0C, priv->max9271_addr_map[idx] << 1); /* MAX9271-CAMx I2C new */ ++ /* I2C addresse change */ ++ reg8_write(client, 0x01, priv->des_addr << 1); /* MAX9286 I2C */ ++ reg8_write(client, 0x00, priv->max9271_addr_map[idx] << 1); /* MAX9271-CAM0 I2C new */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ /* put MAX9271 in configuration link state */ ++ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C new */ ++ reg8_write(client, 0x04, 0x43); /* enable reverse_control/conf_link */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++#ifdef MAXIM_DUMP ++ client->addr = priv->des_addr; /* MAX9286-CAMx I2C */ ++ maxim_max927x_dump_regs(client); ++ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C new */ ++ maxim_max927x_dump_regs(client); ++#endif ++} + -+static int ov10635_get_fmt(struct v4l2_subdev *sd, -+ struct v4l2_subdev_pad_config *cfg, -+ struct v4l2_subdev_format *format) ++static int max9286_initialize(struct i2c_client *client) +{ -+ struct v4l2_mbus_framefmt *mf = &format->format; -+ struct i2c_client *client = v4l2_get_subdevdata(sd); -+ struct ov10635_priv *priv = to_ov10635(client); ++ struct max9286_priv *priv = i2c_get_clientdata(client); ++ int idx, ret; + -+ if (format->pad) -+ return -EINVAL; ++ 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"); + -+ 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; ++ if (priv->des_quirk_addr) ++ max9286_preinit(client, priv->des_quirk_addr); + -+ return 0; -+} ++ max9286_preinit(client, priv->des_addr); ++ max9286_initial_setup(client); + -+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; ++ for (idx = 0; idx < priv->links; idx++) { ++ if (!IS_ERR(priv->poc_supply[idx])) { ++ if (regulator_enable(priv->poc_supply[idx])) ++ dev_err(&client->dev, "fail to enable POC%d regulator\n", idx); ++ mdelay(priv->poc_delay); ++ } + -+ mf->code = MEDIA_BUS_FMT_YUYV8_2X8; -+ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; -+ mf->field = V4L2_FIELD_NONE; ++ ret = max9286_reverse_channel_setup(client, idx); ++ if (ret) ++ continue; ++ max9286_gmsl_link_setup(client, idx); ++ } + -+ if (format->which == V4L2_SUBDEV_FORMAT_TRY) -+ cfg->try_fmt = *mf; ++ max9286_postinit(client, priv->des_addr); ++ ++ client->addr = priv->des_addr; + + 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) ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int max9286_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) +{ -+ if (code->pad || code->index > 0) -+ return -EINVAL; ++ struct max9286_priv *priv = v4l2_get_subdevdata(sd); ++ struct i2c_client *client = priv->client; ++ int ret; ++ u8 val = 0; + -+ code->code = MEDIA_BUS_FMT_YUYV8_2X8; ++ ret = reg8_read(client, (u8)reg->reg, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u8); + + return 0; +} + -+static int ov10635_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++static int max9286_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) +{ -+ struct i2c_client *client = v4l2_get_subdevdata(sd); -+ struct ov10635_priv *priv = to_ov10635(client); ++ struct max9286_priv *priv = v4l2_get_subdevdata(sd); ++ struct i2c_client *client = priv->client; + -+ memcpy(edid->edid, priv->id, 6); ++ return reg8_write(client, (u8)reg->reg, (u8)reg->val); ++} ++#endif + -+ edid->edid[6] = 0xff; -+ edid->edid[7] = client->addr; -+ edid->edid[8] = OV10635_VERSION_REG >> 8; -+ edid->edid[9] = OV10635_VERSION_REG & 0xff; ++static int max9286_s_power(struct v4l2_subdev *sd, int on) ++{ ++ struct max9286_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 ov10635_set_selection(struct v4l2_subdev *sd, -+ struct v4l2_subdev_pad_config *cfg, -+ struct v4l2_subdev_selection *sel) ++static int max9286_registered_async(struct v4l2_subdev *sd) +{ -+ 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; ++ struct max9286_priv *priv = v4l2_get_subdevdata(sd); ++ struct i2c_client *client = priv->client; ++ int idx, tmp_addr; + -+ rect->left = ALIGN(rect->left, 2); -+ rect->top = ALIGN(rect->top, 2); -+ rect->width = ALIGN(rect->width, 2); -+ rect->height = ALIGN(rect->height, 2); ++ /* switch to GMSL serial_link for streaming video */ ++ tmp_addr = client->addr; ++ idx = sd->grp_id; + -+ if ((rect->left + rect->width > OV10635_MAX_WIDTH) || -+ (rect->top + rect->height > OV10635_MAX_HEIGHT)) -+ *rect = priv->rect; ++ client->addr = priv->des_addr; /* MAX9286 I2C */ ++ reg8_write(client, 0x0a, 0x11 << idx); /* enable reverse/forward control for CAMx */ + -+ if (rect->width == OV10635_MAX_WIDTH / 2 && -+ rect->height == OV10635_MAX_HEIGHT / 2) -+ subsampling = 1; ++ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx */ ++ reg8_write(client, 0x04, conf_link ? 0x43 : 0x83); /* enable serial_link */ ++ usleep_range(2000, 2500); /* wait 2ms after changing reverse_control */ + -+ priv->rect.left = rect->left; -+ priv->rect.top = rect->top; -+ priv->rect.width = rect->width; -+ priv->rect.height = rect->height; ++ 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 */ + -+ /* change window only for subsampling, crop is done by VIN */ -+ if (subsampling != priv->subsampling) { -+ ov10635_set_window(sd, subsampling); -+ priv->subsampling = subsampling; -+ } ++ client->addr = tmp_addr; + + 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; ++static struct v4l2_subdev_core_ops max9286_subdev_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = max9286_g_register, ++ .s_register = max9286_s_register, ++#endif ++ .s_power = max9286_s_power, ++ .registered_async = max9286_registered_async, ++}; + -+ 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 struct v4l2_subdev_ops max9286_subdev_ops = { ++ .core = &max9286_subdev_core_ops, ++}; + -+static int ov10635_g_mbus_config(struct v4l2_subdev *sd, -+ struct v4l2_mbus_config *cfg) ++static int max9286_parse_dt(struct i2c_client *client) +{ -+ cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | -+ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; -+ cfg->type = V4L2_MBUS_CSI2; ++ struct max9286_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; + -+ return 0; -+} ++ u8 val = 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 (of_property_read_u32(np, "maxim,links", &priv->links)) ++ priv->links = 4; + -+ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) -+ return -EINVAL; ++ if (of_property_read_u32(np, "maxim,lanes", &priv->lanes)) ++ priv->lanes = 4; + -+ memset(cp, 0, sizeof(struct v4l2_captureparm)); -+ cp->capability = V4L2_CAP_TIMEPERFRAME; -+ cp->timeperframe.numerator = 1; -+ cp->timeperframe.denominator = priv->fps_denominator; ++ 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); ++ } + -+ return 0; -+} ++ mdelay(250); + -+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; ++ 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 (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) -+ return -EINVAL; -+ if (cp->extendedmode != 0) -+ return -EINVAL; ++ 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 (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; -+ } ++ 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 = 0; ++ else ++ priv->active_low_resetb = 1; ++ } + -+ priv->fps_denominator = cp->timeperframe.denominator; ++ 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; ++ if (of_property_read_u32(np, "maxim,him", &priv->him)) ++ priv->him = 0; ++ if (of_property_read_u32(np, "maxim,hsync", &priv->hsync)) ++ priv->hsync = 0; ++ if (of_property_read_u32(np, "maxim,vsync", &priv->vsync)) ++ priv->vsync = 1; ++ if (of_property_read_u32(np, "maxim,poc-delay", &priv->poc_delay)) ++ priv->poc_delay = 50; ++ ++ /* module params override dts */ ++ if (him) ++ priv->him = him; ++ if (fsync_period) { ++ priv->fsync_period = fsync_period; ++ priv->fsync_mode = fsync_mode_default; + } ++ if (hsync) ++ priv->hsync = hsync; ++ if (!vsync) ++ priv->vsync = vsync; ++ if (gpio_resetb) ++ priv->gpio_resetb = gpio_resetb; ++ if (active_low_resetb) ++ priv->active_low_resetb = active_low_resetb; ++ if (poc_delay) ++ priv->poc_delay = poc_delay; + -+out: -+ return ret; -+} ++ for (i = 0; i < priv->links; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; + -+#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; ++ of_node_put(endpoint); + -+ ret = reg16_read(client, (u16)reg->reg, &val); -+ if (ret < 0) -+ return ret; ++ if (of_property_read_u32(endpoint, "max9271-addr", &priv->max9271_addr_map[i])) { ++ dev_err(&client->dev, "max9271-addr not set\n"); ++ return -EINVAL; ++ } + -+ reg->val = val; -+ reg->size = sizeof(u16); ++ priv->sd_of_node[i] = endpoint; ++ } + + return 0; +} + -+static int ov10635_s_register(struct v4l2_subdev *sd, -+ const struct v4l2_dbg_register *reg) ++static void max9286_setup_remote_endpoint(struct i2c_client *client) +{ -+ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct max9286_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; + -+ return reg16_write(client, (u16)reg->reg, (u8)reg->val); -+} -+#endif ++ for (i = 0; ; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; + -+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 -+}; ++ of_node_put(endpoint); + -+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; ++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); ++ if (!rendpoint) ++ continue; + -+ if (!priv->init_complete) -+ return 0; ++ 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); ++ } + -+ switch (ctrl->id) { -+ case V4L2_CID_BRIGHTNESS: -+ /* AEC/AGC target */ -+ ret = reg16_write(client, 0xc46a, ctrl->val); -+ break; -+ case V4L2_CID_CONTRAST: -+ udelay(100); -+ ret = ov10635_set_regs(client, &ov10635_regs_contrast[ctrl->val][0], 18); -+ break; -+ case V4L2_CID_SATURATION: -+ ret = reg16_write(client, 0xc316, ctrl->val); -+ break; -+ case V4L2_CID_HUE: -+ /* CMX ? */ -+ ret = 0; -+ break; -+ case V4L2_CID_GAMMA: -+ ret = reg16_write(client, 0xc4be, ctrl->val >> 8); -+ ret |= reg16_write(client, 0xc4bf, ctrl->val & 0xff); -+ break; -+ case V4L2_CID_AUTOGAIN: -+ /* automatic gain/exposure */ -+ ret = reg16_write(client, 0x56d0, !ctrl->val); -+ break; -+ case V4L2_CID_GAIN: -+ /* manual gain */ -+ ret = reg16_write(client, 0x3504, 0); -+ ret |= reg16_write(client, 0x56d1, ctrl->val >> 8); -+ ret |= reg16_write(client, 0x56d2, ctrl->val & 0xff); -+ ret |= reg16_write(client, 0x3504, 1); /* validate gain */ -+ break; -+ case V4L2_CID_EXPOSURE: -+ /* manual exposure */ -+ ret = reg16_write(client, 0x3504, 0); -+ ret |= reg16_write(client, 0x56d5, ctrl->val >> 8); -+ ret |= reg16_write(client, 0x56d6, ctrl->val & 0xff); -+ ret |= reg16_write(client, 0x3504, 1); /* validate exposure */ -+ break; -+ case V4L2_CID_HFLIP: -+ ret = reg16_read(client, 0x381d, &val); -+ if (ret < 0) -+ goto out; -+ if (ctrl->val) -+ val |= 0x3; -+ else -+ val &= ~0x3; -+ ret = reg16_write(client, 0x381d, val); -+ break; -+ case V4L2_CID_VFLIP: -+ ret = reg16_read(client, 0x381c, &val); -+ if (ctrl->val) -+ val |= 0xc0; -+ else -+ val &= ~0xc0; -+ ret = reg16_write(client, 0x381c, val); -+ break; -+ case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: -+ ret = 0; -+ break; ++ dvp_order_prop = of_find_property(endpoint, "dvp-order", NULL); ++ if (dvp_order_prop) ++ of_update_property(rendpoint, dvp_order_prop); + } -+ -+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) ++static int max9286_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) +{ -+ struct ov10635_priv *priv = to_ov10635(client); -+ int i; -+ -+ /* read camera id from OTP memory */ -+ reg16_write(client, 0x3d10, 1); ++ struct max9286_priv *priv; ++ int err, i; ++ char supply_name[10]; + -+ usleep_range(15000, 16000); /* wait 15ms */ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; + -+ for (i = 0; i < 6; i++) -+ reg16_read(client, 0x3d00 + i, &priv->id[i]); -+} ++ i2c_set_clientdata(client, priv); ++ priv->des_addr = client->addr; ++ priv->client = client; ++ atomic_set(&priv->use_count, 0); ++ priv->csi2_outord = 0xff; + -+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); ++ err = max9286_parse_dt(client); ++ if (err) ++ goto out; + -+ 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]); -+} ++ for (i = 0; i < 4; i++) { ++ sprintf(supply_name, "POC%d", i); ++ priv->poc_supply[i] = devm_regulator_get_optional(&client->dev, supply_name); ++ } + -+static DEVICE_ATTR(otp_id_ov10635, S_IRUGO, ov10635_otp_id_show, NULL); ++ err = max9286_initialize(client); ++ if (err < 0) ++ goto out; + -+static int ov10635_initialize(struct i2c_client *client) -+{ -+ struct ov10635_priv *priv = to_ov10635(client); -+ u8 pid = 0, ver = 0; -+ int ret = 0; ++ max9286_setup_remote_endpoint(client); + -+ ov10635_s_port(client, 1); ++ for (i = 0; i < 4; i++) { ++ v4l2_subdev_init(&priv->sd[i], &max9286_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]; + -+ /* check and show product ID and manufacturer ID */ -+ reg16_read(client, OV10635_PID, &pid); -+ reg16_read(client, OV10635_VER, &ver); ++ 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); + -+ if (OV10635_VERSION(pid, ver) != OV10635_VERSION_REG) { -+ dev_dbg(&client->dev, "Product ID error %x:%x\n", pid, ver); -+ ret = -ENODEV; -+ goto out; ++ err = v4l2_async_register_subdev(&priv->sd[i]); ++ if (err < 0) ++ 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; ++ return err; +} + -+static int ov10635_parse_dt(struct device_node *np, struct ov10635_priv *priv) ++static int max9286_remove(struct i2c_client *client) +{ -+ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); ++ struct max9286_priv *priv = i2c_get_clientdata(client); + 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); ++ for (i = 0; i < 4; i++) { ++ v4l2_async_unregister_subdev(&priv->sd[i]); ++ v4l2_device_unregister_subdev(&priv->sd[i]); ++ } + -+ of_property_read_u32(endpoint, "dvp-order", &priv->dvp_order); ++ return 0; ++} + -+ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); -+ if (!rendpoint) -+ continue; ++static const struct of_device_id max9286_dt_ids[] = { ++ { .compatible = "maxim,max9286" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, max9286_dt_ids); + -+ 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; ++static const struct i2c_device_id max9286_id[] = { ++ { "max9286", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, max9286_id); + -+ 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; ++static struct i2c_driver max9286_i2c_driver = { ++ .driver = { ++ .name = "max9286", ++ .of_match_table = of_match_ptr(max9286_dt_ids), ++ }, ++ .probe = max9286_probe, ++ .remove = max9286_remove, ++ .id_table = max9286_id, ++}; + -+ 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; -+ } ++module_i2c_driver(max9286_i2c_driver); + -+ if (!priv->max9286_addr && !priv->ti964_addr && !priv->ti954_addr) { -+ dev_err(&client->dev, "deserializer does not present for OV10635\n"); -+ return -EINVAL; -+ } ++MODULE_DESCRIPTION("GMSL driver for MAX9286"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/i2c/soc_camera/max9286.h b/drivers/media/i2c/soc_camera/max9286.h +new file mode 100644 +index 0000000..6c2a9e0 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/max9286.h +@@ -0,0 +1,244 @@ ++/* ++ * MAXIM max9286-max9271 GMSL driver include file ++ * ++ * Copyright (C) 2015-2017 Cogent Embedded, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ */ + -+ ov10635_s_port(client, 1); ++#ifndef _MAX9286_MAX9271_H ++#define _MAX9286_MAX9271_H + -+ /* setup I2C translator address */ -+ tmp_addr = client->addr; -+ if (priv->max9286_addr) { -+ client->addr = priv->max9271_addr; /* Serializer I2C address */ ++//#define DEBUG ++#ifdef DEBUG ++//#define WRITE_VERIFY ++#define MAXIM_DUMP ++#undef dev_dbg ++#define dev_dbg dev_info ++#endif + -+ 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 */ -+ }; ++#define REG8_NUM_RETRIES 1 /* number of read/write retries */ ++#define REG16_NUM_RETRIES 10 /* number of read/write retries */ ++#define MAX9271_ID 0x9 ++#define MAX96705_ID 0x41 ++#define MAX9286_ID 0x40 ++#define BROADCAST 0x6f + -+ if (priv->ti964_addr) { -+ client->addr = priv->ti964_addr; /* Deserializer I2C address */ ++static inline int reg8_read(struct i2c_client *client, u8 reg, u8 *val) ++{ ++ int ret, retries; + -+ 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 */ ++ for (retries = REG8_NUM_RETRIES; retries; retries--) { ++ ret = i2c_smbus_read_byte_data(client, reg); ++ if (!(ret < 0)) ++ break; ++ } + -+ reg8_write(client, 0x6e, 0xa9); /* GPIO0 - resetb, GPIO1 - fsin */ ++ if (ret < 0) { ++ dev_dbg(&client->dev, ++ "read fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } else { ++ *val = ret; + } + -+ if (priv->ti954_addr) { -+ client->addr = priv->ti954_addr; /* Deserializer I2C address */ ++ return ret < 0 ? ret : 0; ++} + -+ 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 */ ++static inline int reg8_write(struct i2c_client *client, u8 reg, u8 val) ++{ ++ int ret, retries; + -+ reg8_write(client, 0x6e, 0xa9); /* GPIO0 - resetb, GPIO1 - fsin */ ++ for (retries = REG8_NUM_RETRIES; retries; retries--) { ++ ret = i2c_smbus_write_byte_data(client, reg, val); ++ if (!(ret < 0)) ++ break; + } -+ client->addr = tmp_addr; + -+ udelay(100); ++ 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 0; ++ return ret < 0 ? ret : 0; +} + -+static int ov10635_probe(struct i2c_client *client, -+ const struct i2c_device_id *did) ++static inline int reg16_read(struct i2c_client *client, u16 reg, u8 *val) +{ -+ struct ov10635_priv *priv; -+ struct v4l2_ctrl *ctrl; -+ int ret; ++ int ret, retries; ++ u8 buf[2] = {reg >> 8, reg & 0xff}; + -+ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; ++ 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; ++ } ++ } + -+ 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; ++ 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]; ++ } + -+ v4l2_ctrl_handler_init(&priv->hdl, 4); -+ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, -+ V4L2_CID_BRIGHTNESS, 0, 0xff, 1, 0x30); -+ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, -+ V4L2_CID_CONTRAST, 0, 4, 1, 2); -+ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, -+ V4L2_CID_SATURATION, 0, 0xff, 1, 0xff); -+ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, -+ V4L2_CID_HUE, 0, 255, 1, 0); -+ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, -+ V4L2_CID_GAMMA, 0, 0xffff, 1, 0x233); -+ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, -+ V4L2_CID_AUTOGAIN, 0, 1, 1, 1); -+ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, -+ V4L2_CID_GAIN, 0, 0x3ff, 1, 0x10); -+ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, -+ V4L2_CID_EXPOSURE, 0, 0xffff, 1, 0x80); -+ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, -+ V4L2_CID_HFLIP, 0, 1, 1, 0); -+ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, -+ V4L2_CID_VFLIP, 0, 1, 1, 0); -+ ctrl = v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, -+ V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 9); -+ if (ctrl) -+ ctrl->flags &= ~V4L2_CTRL_FLAG_READ_ONLY; -+ priv->sd.ctrl_handler = &priv->hdl; ++ return ret < 0 ? ret : 0; ++} + -+ ret = priv->hdl.error; -+ if (ret) -+ goto cleanup; ++static inline int reg16_write(struct i2c_client *client, u16 reg, u8 val) ++{ ++ int ret, retries; ++ u8 buf[3] = {reg >> 8, reg & 0xff, val}; + -+ v4l2_ctrl_handler_setup(&priv->hdl); ++ for (retries = REG16_NUM_RETRIES; retries; retries--) { ++ ret = i2c_master_send(client, buf, 3); ++ if (ret == 3) ++ break; ++ } + -+ 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; ++ 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 ++ } + -+ ret = ov10635_parse_dt(client->dev.of_node, priv); -+ if (ret) -+ goto cleanup; ++ return ret < 0 ? ret : 0; ++} + -+ ret = ov10635_initialize(client); -+ if (ret < 0) -+ goto cleanup; + -+ ret = v4l2_async_register_subdev(&priv->sd); -+ if (ret) -+ goto cleanup; ++static inline int reg16_read16(struct i2c_client *client, u16 reg, u16 *val) ++{ ++ int ret, retries; ++ u8 buf[2] = {reg >> 8, reg & 0xff}; + -+ 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; ++ for (retries = REG8_NUM_RETRIES; retries; retries--) { ++ ret = i2c_master_send(client, buf, 2); ++ if (ret == 2) { ++ ret = i2c_master_recv(client, buf, 2); ++ if (ret == 2) ++ break; ++ } + } + -+ priv->init_complete = 1; -+ -+ return 0; ++ if (ret < 0) { ++ dev_err(&client->dev, ++ "read fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } else { ++ *val = ((u16)buf[0] << 8) | buf[1]; ++ } + -+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; ++ return ret < 0 ? ret : 0; +} + -+static int ov10635_remove(struct i2c_client *client) ++static inline int reg16_write16(struct i2c_client *client, u16 reg, u16 val) +{ -+ struct ov10635_priv *priv = i2c_get_clientdata(client); ++ int ret, retries; ++ u8 buf[4] = {reg >> 8, reg & 0xff, val >> 8, val & 0xff}; + -+ 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); ++ for (retries = REG8_NUM_RETRIES; retries; retries--) { ++ ret = i2c_master_send(client, buf, 4); ++ if (ret == 4) ++ break; ++ } + -+ return 0; ++ if (ret < 0) { ++ dev_err(&client->dev, ++ "write fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } ++ ++ return ret < 0 ? ret : 0; +} + -+#ifdef 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); ++#ifdef MAXIM_DUMP ++static void maxim_ovsensor_dump_regs(struct i2c_client *client) ++{ ++ int ret, i; ++ u8 val = 0; ++ u16 regs[] = {0x300a, 0x300b, 0x300c}; + -+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, -+}; ++ dev_dbg(&client->dev, "dump regs 0x%x\n", client->addr); + -+module_i2c_driver(ov10635_i2c_driver); ++ 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); ++ } ++} + -+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 ++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..a0e510d +index 0000000..8c06e59 --- /dev/null -+++ b/drivers/media/i2c/soc_camera/ov10635.h -@@ -0,0 +1,1139 @@ ++++ b/drivers/media/i2c/soc_camera/ov10635.c +@@ -0,0 +1,759 @@ +/* -+ * OmniVision ov10635 sensor camera wizard 1280x800@30/UYVY/BT601/8bit ++ * OmniVision ov10635 sensor camera driver + * + * Copyright (C) 2015-2017 Cogent Embedded, Inc. + * @@ -3301,1531 +3098,144 @@ index 0000000..a0e510d + * option) any later version. + */ + -+//#define OV10635_DISPLAY_PATTERN ++#include ++#include ++#include ++#include ++#include + -+#define OV10635_SENSOR_WIDTH 1312 -+#define OV10635_SENSOR_HEIGHT 814 ++#include ++#include ++#include ++#include + -+#define OV10635_MAX_WIDTH 1280 -+#define OV10635_MAX_HEIGHT 800 ++#include "max9286.h" ++#include "ov10635.h" + -+//#define OV10635_PCLK_96MHZ -+#define OV10635_PCLK_88MHZ ++#define OV10635_I2C_ADDR 0x30 + -+#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 ++#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 */ ++ usleep_range(5000, 5500); /* wait 5ms */ ++ 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); + -+struct ov10635_reg { -+ u16 reg; -+ u8 val; ++ return 0; +}; + -+static const struct ov10635_reg ov10635_regs_wizard[] = { -+//{0x0103, 0x01}, -+{0x300C, 0x61}, -+{0x300C, 0x61}, -+{0x300C, 0x61}, -+{0x300C, 0x61}, -+{0x300C, 0x61}, -+{0x300C, 0x61}, -+{0x300C, 0x61}, -+{0x300C, 0x61}, -+{0x300C, 0x61}, -+{0x300C, 0x61}, -+{0x300C, 0x61}, -+{0x300C, 0x61}, -+{0x300C, 0x61}, -+{0x300C, 0x61}, -+{0x300C, 0x61}, -+{0x300C, 0x61}, -+{0x300C, 0x61}, -+{0x300C, 0x61}, -+{0x300C, 0x61}, -+{0x300C, 0x61}, -+{0x300C, 0x61}, -+{0x300C, 0x61}, -+{0x300C, 0x61}, -+{0x301B, 0xFF}, -+{0x301C, 0xFF}, -+{0x301A, 0xFF}, -+{0x3011, 0x42}, -+{0x6900, 0x0C}, -+{0x6901, 0x19}, -+{0x3503, 0x10}, -+{0x3025, 0x03}, -+#if defined(OV10635_PCLK_96MHZ) -+{0x3003, 0x20}, -+{0x3004, 0x21}, -+#elif defined(OV10635_PCLK_88MHZ) -+{0x3003, 0x16}, -+{0x3004, 0x30}, -+#endif -+{0x3005, 0x40}, -+{0x3006, 0x91}, -+{0x3600, 0x74}, -+{0x3601, 0x2B}, -+{0x3612, 0x00}, -+{0x3611, 0x67}, -+{0x3633, 0xCA}, -+{0x3602, 0xAF}, -+{0x3603, 0x04}, -+{0x3630, 0x28}, -+{0x3631, 0x16}, -+{0x3714, 0x10}, -+{0x371D, 0x01}, -+{0x4300, 0x3A}, -+{0x3007, 0x01}, -+{0x3024, 0x03}, -+{0x3020, 0x0A}, -+{0x3702, 0x0D}, -+{0x3703, 0x20}, -+{0x3704, 0x15}, -+{0x3709, 0xA8}, -+{0x370C, 0xC7}, -+{0x370D, 0x80}, -+{0x3712, 0x00}, -+{0x3713, 0x20}, -+{0x3715, 0x04}, -+{0x381D, 0x40}, -+{0x381C, 0x00}, -+{0x3822, 0x50}, -+{0x3824, 0x10}, -+{0x3815, 0x8C}, -+{0x3804, 0x05}, -+{0x3805, 0x1F}, -+{0x3800, 0x00}, -+{0x3801, 0x00}, -+{0x3806, 0x03}, -+{0x3807, 0x28}, -+{0x3802, 0x00}, -+{0x3803, 0x07}, -+{0x3808, 0x05}, -+{0x3809, 0x00}, -+{0x380A, 0x03}, -+{0x380B, 0x20}, -+{0x380C, OV10635_HTS >> 8}, -+{0x380D, OV10635_HTS & 0xff}, -+{0x380E, OV10635_VTS >> 8}, -+{0x380F, OV10635_VTS & 0xff}, -+{0x3813, 0x02}, -+{0x3811, 0x08}, -+{0x381F, 0x0C}, -+{0x3819, 0x04}, -+{0x3804, 0x01}, -+{0x3805, 0x00}, -+{0x3828, 0x03}, -+{0x3829, 0x10}, -+{0x382A, 0x10}, -+{0x3621, 0x63}, -+{0x5005, 0x08}, -+{0x56D5, 0x00}, -+{0x56D6, 0x80}, -+{0x56D7, 0x00}, -+{0x56D8, 0x00}, -+{0x56D9, 0x00}, -+{0x56DA, 0x80}, -+{0x56DB, 0x00}, -+{0x56DC, 0x00}, -+{0x56E8, 0x00}, -+{0x56E9, 0x7F}, -+{0x56EA, 0x00}, -+{0x56EB, 0x7F}, -+{0x5100, 0x00}, -+{0x5101, 0x80}, -+{0x5102, 0x00}, -+{0x5103, 0x80}, -+{0x5104, 0x00}, -+{0x5105, 0x80}, -+{0x5106, 0x00}, -+{0x5107, 0x80}, -+{0x5108, 0x00}, -+{0x5109, 0x00}, -+{0x510A, 0x00}, -+{0x510B, 0x00}, -+{0x510C, 0x00}, -+{0x510D, 0x00}, -+{0x510E, 0x00}, -+{0x510F, 0x00}, -+{0x5110, 0x00}, -+{0x5111, 0x80}, -+{0x5112, 0x00}, -+{0x5113, 0x80}, -+{0x5114, 0x00}, -+{0x5115, 0x80}, -+{0x5116, 0x00}, -+{0x5117, 0x80}, -+{0x5118, 0x00}, -+{0x5119, 0x00}, -+{0x511A, 0x00}, -+{0x511B, 0x00}, -+{0x511C, 0x00}, -+{0x511D, 0x00}, -+{0x511E, 0x00}, -+{0x511F, 0x00}, -+{0x56D0, 0x00}, -+{0x5006, 0x04}, -+{0x5608, 0x05}, -+{0x52D7, 0x06}, -+{0x528D, 0x08}, -+{0x5293, 0x12}, -+{0x52D3, 0x12}, -+{0x5288, 0x06}, -+{0x5289, 0x20}, -+{0x52C8, 0x06}, -+{0x52C9, 0x20}, -+{0x52CD, 0x04}, -+{0x5381, 0x00}, -+{0x5382, 0xFF}, -+{0x5589, 0x76}, -+{0x558A, 0x47}, -+{0x558B, 0xEF}, -+{0x558C, 0xC9}, -+{0x558D, 0x49}, -+{0x558E, 0x30}, -+{0x558F, 0x67}, -+{0x5590, 0x3F}, -+{0x5591, 0xF0}, -+{0x5592, 0x10}, -+{0x55A2, 0x6D}, -+{0x55A3, 0x55}, -+{0x55A4, 0xC3}, -+{0x55A5, 0xB5}, -+{0x55A6, 0x43}, -+{0x55A7, 0x38}, -+{0x55A8, 0x5F}, -+{0x55A9, 0x4B}, -+{0x55AA, 0xF0}, -+{0x55AB, 0x10}, -+{0x5581, 0x52}, -+{0x5300, 0x01}, -+{0x5301, 0x00}, -+{0x5302, 0x00}, -+{0x5303, 0x0E}, -+{0x5304, 0x00}, -+{0x5305, 0x0E}, -+{0x5306, 0x00}, -+{0x5307, 0x36}, -+{0x5308, 0x00}, -+{0x5309, 0xD9}, -+{0x530A, 0x00}, -+{0x530B, 0x0F}, -+{0x530C, 0x00}, -+{0x530D, 0x2C}, -+{0x530E, 0x00}, -+{0x530F, 0x59}, -+{0x5310, 0x00}, -+{0x5311, 0x7B}, -+{0x5312, 0x00}, -+{0x5313, 0x22}, -+{0x5314, 0x00}, -+{0x5315, 0xD5}, -+{0x5316, 0x00}, -+{0x5317, 0x13}, -+{0x5318, 0x00}, -+{0x5319, 0x18}, -+{0x531A, 0x00}, -+{0x531B, 0x26}, -+{0x531C, 0x00}, -+{0x531D, 0xDC}, -+{0x531E, 0x00}, -+{0x531F, 0x02}, -+{0x5320, 0x00}, -+{0x5321, 0x24}, -+{0x5322, 0x00}, -+{0x5323, 0x56}, -+{0x5324, 0x00}, -+{0x5325, 0x85}, -+{0x5326, 0x00}, -+{0x5327, 0x20}, -+{0x5609, 0x01}, -+{0x560A, 0x40}, -+{0x560B, 0x01}, -+{0x560C, 0x40}, -+{0x560D, 0x00}, -+{0x560E, 0xFA}, -+{0x560F, 0x00}, -+{0x5610, 0xFA}, -+{0x5611, 0x02}, -+{0x5612, 0x80}, -+{0x5613, 0x02}, -+{0x5614, 0x80}, -+{0x5615, 0x01}, -+{0x5616, 0x2C}, -+{0x5617, 0x01}, -+{0x5618, 0x2C}, -+{0x563B, 0x01}, -+{0x563C, 0x01}, -+{0x563D, 0x01}, -+{0x563E, 0x01}, -+{0x563F, 0x03}, -+{0x5640, 0x03}, -+{0x5641, 0x03}, -+{0x5642, 0x05}, -+{0x5643, 0x09}, -+{0x5644, 0x05}, -+{0x5645, 0x05}, -+{0x5646, 0x05}, -+{0x5647, 0x05}, -+{0x5651, 0x00}, -+{0x5652, 0x80}, -+{0x521A, 0x01}, -+{0x521B, 0x03}, -+{0x521C, 0x06}, -+{0x521D, 0x0A}, -+{0x521E, 0x0E}, -+{0x521F, 0x12}, -+{0x5220, 0x16}, -+{0x5223, 0x02}, -+{0x5225, 0x04}, -+{0x5227, 0x08}, -+{0x5229, 0x0C}, -+{0x522B, 0x12}, -+{0x522D, 0x18}, -+{0x522F, 0x1E}, -+{0x5241, 0x04}, -+{0x5242, 0x01}, -+{0x5243, 0x03}, -+{0x5244, 0x06}, -+{0x5245, 0x0A}, -+{0x5246, 0x0E}, -+{0x5247, 0x12}, -+{0x5248, 0x16}, -+{0x524A, 0x03}, -+{0x524C, 0x04}, -+{0x524E, 0x08}, -+{0x5250, 0x0C}, -+{0x5252, 0x12}, -+{0x5254, 0x18}, -+{0x5256, 0x1E}, -+{0x4606, (2*OV10635_HTS) >> 8}, /* fifo_line_length = 2*hts */ -+{0x4607, (2*OV10635_HTS) & 0xff}, -+{0x460a, (2*(OV10635_HTS-OV10635_MAX_WIDTH)) >> 8}, /* fifo_hsync_start = 2*(hts - xres) */ -+{0x460b, (2*(OV10635_HTS-OV10635_MAX_WIDTH)) & 0xff }, -+{0x460C, 0x00}, -+{0x4620, 0x0E}, -+#if 0 -+{0x4700, 0x02}, // BT656: mode is acceptable but artefact lines on left/bottom due to BT656 SAV/EAV are parsed as image data -+#else -+{0x4700, 0x04}, // BT601: 0x08 is also accaptable as HS/VS mode -+#endif -+{0x4701, 0x00}, -+{0x4702, 0x01}, -+{0x4004, 0x04}, -+{0x4005, 0x18}, -+{0x4001, 0x06}, -+{0x4050, 0x22}, -+{0x4051, 0x24}, -+{0x4052, 0x02}, -+{0x4057, 0x9C}, -+{0x405A, 0x00}, -+{0x4202, 0x02}, -+{0x3023, 0x10}, -+{0x0100, 0x01}, -+{0x0100, 0x01}, -+{0x6F10, 0x07}, -+{0x6F11, 0x82}, -+{0x6F12, 0x04}, -+{0x6F13, 0x00}, -+{0xD000, 0x19}, -+{0xD001, 0xA0}, -+{0xD002, 0x00}, -+{0xD003, 0x01}, -+{0xD004, 0xA9}, -+{0xD005, 0xAD}, -+{0xD006, 0x10}, -+{0xD007, 0x40}, -+{0xD008, 0x44}, -+{0xD009, 0x00}, -+{0xD00A, 0x68}, -+{0xD00B, 0x00}, -+{0xD00C, 0x15}, -+{0xD00D, 0x00}, -+{0xD00E, 0x00}, -+{0xD00F, 0x00}, -+{0xD040, 0x9C}, -+{0xD041, 0x21}, -+{0xD042, 0xFF}, -+{0xD043, 0xF8}, -+{0xD044, 0xD4}, -+{0xD045, 0x01}, -+{0xD046, 0x48}, -+{0xD047, 0x00}, -+{0xD048, 0xD4}, -+{0xD049, 0x01}, -+{0xD04A, 0x50}, -+{0xD04B, 0x04}, -+{0xD04C, 0x18}, -+{0xD04D, 0x60}, -+{0xD04E, 0x00}, -+{0xD04F, 0x01}, -+{0xD050, 0xA8}, -+{0xD051, 0x63}, -+{0xD052, 0x02}, -+{0xD053, 0xA4}, -+{0xD054, 0x85}, -+{0xD055, 0x43}, -+{0xD056, 0x00}, -+{0xD057, 0x00}, -+{0xD058, 0x18}, -+{0xD059, 0x60}, -+{0xD05A, 0x00}, -+{0xD05B, 0x01}, -+{0xD05C, 0xA8}, -+{0xD05D, 0x63}, -+{0xD05E, 0x03}, -+{0xD05F, 0xF0}, -+{0xD060, 0x98}, -+{0xD061, 0xA3}, -+{0xD062, 0x00}, -+{0xD063, 0x00}, -+{0xD064, 0x8C}, -+{0xD065, 0x6A}, -+{0xD066, 0x00}, -+{0xD067, 0x6E}, -+{0xD068, 0xE5}, -+{0xD069, 0x85}, -+{0xD06A, 0x18}, -+{0xD06B, 0x00}, -+{0xD06C, 0x10}, -+{0xD06D, 0x00}, -+{0xD06E, 0x00}, -+{0xD06F, 0x10}, -+{0xD070, 0x9C}, -+{0xD071, 0x80}, -+{0xD072, 0x00}, -+{0xD073, 0x03}, -+{0xD074, 0x18}, -+{0xD075, 0x60}, -+{0xD076, 0x00}, -+{0xD077, 0x01}, -+{0xD078, 0xA8}, -+{0xD079, 0x63}, -+{0xD07A, 0x07}, -+{0xD07B, 0x80}, -+{0xD07C, 0x07}, -+{0xD07D, 0xFF}, -+{0xD07E, 0xF9}, -+{0xD07F, 0x03}, -+{0xD080, 0x8C}, -+{0xD081, 0x63}, -+{0xD082, 0x00}, -+{0xD083, 0x00}, -+{0xD084, 0xA5}, -+{0xD085, 0x6B}, -+{0xD086, 0x00}, -+{0xD087, 0xFF}, -+{0xD088, 0x18}, -+{0xD089, 0x80}, -+{0xD08A, 0x00}, -+{0xD08B, 0x01}, -+{0xD08C, 0xA8}, -+{0xD08D, 0x84}, -+{0xD08E, 0x01}, -+{0xD08F, 0x04}, -+{0xD090, 0xE1}, -+{0xD091, 0x6B}, -+{0xD092, 0x58}, -+{0xD093, 0x00}, -+{0xD094, 0x94}, -+{0xD095, 0x6A}, -+{0xD096, 0x00}, -+{0xD097, 0x70}, -+{0xD098, 0xE1}, -+{0xD099, 0x6B}, -+{0xD09A, 0x20}, -+{0xD09B, 0x00}, -+{0xD09C, 0x95}, -+{0xD09D, 0x6B}, -+{0xD09E, 0x00}, -+{0xD09F, 0x00}, -+{0xD0A0, 0xE4}, -+{0xD0A1, 0x8B}, -+{0xD0A2, 0x18}, -+{0xD0A3, 0x00}, -+{0xD0A4, 0x0C}, -+{0xD0A5, 0x00}, -+{0xD0A6, 0x00}, -+{0xD0A7, 0x23}, -+{0xD0A8, 0x15}, -+{0xD0A9, 0x00}, -+{0xD0AA, 0x00}, -+{0xD0AB, 0x00}, -+{0xD0AC, 0x18}, -+{0xD0AD, 0x60}, -+{0xD0AE, 0x80}, -+{0xD0AF, 0x06}, -+{0xD0B0, 0xA8}, -+{0xD0B1, 0x83}, -+{0xD0B2, 0x40}, -+{0xD0B3, 0x08}, -+{0xD0B4, 0xA8}, -+{0xD0B5, 0xE3}, -+{0xD0B6, 0x38}, -+{0xD0B7, 0x2A}, -+{0xD0B8, 0xA8}, -+{0xD0B9, 0xC3}, -+{0xD0BA, 0x40}, -+{0xD0BB, 0x09}, -+{0xD0BC, 0xA8}, -+{0xD0BD, 0xA3}, -+{0xD0BE, 0x38}, -+{0xD0BF, 0x29}, -+{0xD0C0, 0x8C}, -+{0xD0C1, 0x65}, -+{0xD0C2, 0x00}, -+{0xD0C3, 0x00}, -+{0xD0C4, 0xD8}, -+{0xD0C5, 0x04}, -+{0xD0C6, 0x18}, -+{0xD0C7, 0x00}, -+{0xD0C8, 0x8C}, -+{0xD0C9, 0x67}, -+{0xD0CA, 0x00}, -+{0xD0CB, 0x00}, -+{0xD0CC, 0xD8}, -+{0xD0CD, 0x06}, -+{0xD0CE, 0x18}, -+{0xD0CF, 0x00}, -+{0xD0D0, 0x18}, -+{0xD0D1, 0x60}, -+{0xD0D2, 0x80}, -+{0xD0D3, 0x06}, -+{0xD0D4, 0xA8}, -+{0xD0D5, 0xE3}, -+{0xD0D6, 0x67}, -+{0xD0D7, 0x02}, -+{0xD0D8, 0xA9}, -+{0xD0D9, 0x03}, -+{0xD0DA, 0x67}, -+{0xD0DB, 0x03}, -+{0xD0DC, 0xA8}, -+{0xD0DD, 0xC3}, -+{0xD0DE, 0x3D}, -+{0xD0DF, 0x05}, -+{0xD0E0, 0x8C}, -+{0xD0E1, 0x66}, -+{0xD0E2, 0x00}, -+{0xD0E3, 0x00}, -+{0xD0E4, 0xB8}, -+{0xD0E5, 0x63}, -+{0xD0E6, 0x00}, -+{0xD0E7, 0x18}, -+{0xD0E8, 0xB8}, -+{0xD0E9, 0x63}, -+{0xD0EA, 0x00}, -+{0xD0EB, 0x98}, -+{0xD0EC, 0xBC}, -+{0xD0ED, 0x03}, -+{0xD0EE, 0x00}, -+{0xD0EF, 0x00}, -+{0xD0F0, 0x10}, -+{0xD0F1, 0x00}, -+{0xD0F2, 0x00}, -+{0xD0F3, 0x16}, -+{0xD0F4, 0xB8}, -+{0xD0F5, 0x83}, -+{0xD0F6, 0x00}, -+{0xD0F7, 0x19}, -+{0xD0F8, 0x8C}, -+{0xD0F9, 0x67}, -+{0xD0FA, 0x00}, -+{0xD0FB, 0x00}, -+{0xD0FC, 0xB8}, -+{0xD0FD, 0xA4}, -+{0xD0FE, 0x00}, -+{0xD0FF, 0x98}, -+{0xD100, 0xB8}, -+{0xD101, 0x83}, -+{0xD102, 0x00}, -+{0xD103, 0x08}, -+{0xD104, 0x8C}, -+{0xD105, 0x68}, -+{0xD106, 0x00}, -+{0xD107, 0x00}, -+{0xD108, 0xE0}, -+{0xD109, 0x63}, -+{0xD10A, 0x20}, -+{0xD10B, 0x04}, -+{0xD10C, 0xE0}, -+{0xD10D, 0x65}, -+{0xD10E, 0x18}, -+{0xD10F, 0x00}, -+{0xD110, 0xA4}, -+{0xD111, 0x83}, -+{0xD112, 0xFF}, -+{0xD113, 0xFF}, -+{0xD114, 0xB8}, -+{0xD115, 0x64}, -+{0xD116, 0x00}, -+{0xD117, 0x48}, -+{0xD118, 0xD8}, -+{0xD119, 0x07}, -+{0xD11A, 0x18}, -+{0xD11B, 0x00}, -+{0xD11C, 0xD8}, -+{0xD11D, 0x08}, -+{0xD11E, 0x20}, -+{0xD11F, 0x00}, -+{0xD120, 0x9C}, -+{0xD121, 0x60}, -+{0xD122, 0x00}, -+{0xD123, 0x00}, -+{0xD124, 0xD8}, -+{0xD125, 0x06}, -+{0xD126, 0x18}, -+{0xD127, 0x00}, -+{0xD128, 0x00}, -+{0xD129, 0x00}, -+{0xD12A, 0x00}, -+{0xD12B, 0x08}, -+{0xD12C, 0x15}, -+{0xD12D, 0x00}, -+{0xD12E, 0x00}, -+{0xD12F, 0x00}, -+{0xD130, 0x8C}, -+{0xD131, 0x6A}, -+{0xD132, 0x00}, -+{0xD133, 0x76}, -+{0xD134, 0xBC}, -+{0xD135, 0x23}, -+{0xD136, 0x00}, -+{0xD137, 0x00}, -+{0xD138, 0x13}, -+{0xD139, 0xFF}, -+{0xD13A, 0xFF}, -+{0xD13B, 0xE6}, -+{0xD13C, 0x18}, -+{0xD13D, 0x60}, -+{0xD13E, 0x80}, -+{0xD13F, 0x06}, -+{0xD140, 0x03}, -+{0xD141, 0xFF}, -+{0xD142, 0xFF}, -+{0xD143, 0xDD}, -+{0xD144, 0xA8}, -+{0xD145, 0x83}, -+{0xD146, 0x40}, -+{0xD147, 0x08}, -+{0xD148, 0x85}, -+{0xD149, 0x21}, -+{0xD14A, 0x00}, -+{0xD14B, 0x00}, -+{0xD14C, 0x85}, -+{0xD14D, 0x41}, -+{0xD14E, 0x00}, -+{0xD14F, 0x04}, -+{0xD150, 0x44}, -+{0xD151, 0x00}, -+{0xD152, 0x48}, -+{0xD153, 0x00}, -+{0xD154, 0x9C}, -+{0xD155, 0x21}, -+{0xD156, 0x00}, -+{0xD157, 0x08}, -+{0x6F0E, 0x03}, -+{0x6F0F, 0x00}, -+{0x460E, 0x08}, -+{0x460F, 0x01}, -+{0x4610, 0x00}, -+{0x4611, 0x01}, -+{0x4612, 0x00}, -+{0x4613, 0x01}, -+{0x4605, 0x08}, // 8bit -+//{0x4709, 0x10}, // swap data bits order [9:0] -> [0:9] -+{0x4608, 0x00}, -+{0x4609, 0x08}, -+{0x6804, 0x00}, -+{0x6805, 0x06}, -+{0x6806, 0x00}, -+{0x5120, 0x00}, -+{0x3510, 0x00}, -+{0x3504, 0x00}, -+{0x6800, 0x00}, -+{0x6F0D, 0x01}, -+{0x4708, 0x01}, // PCLK rising edge -+{0x5000, 0xFF}, -+{0x5001, 0xBF}, -+{0x5002, 0x7E}, -+#ifdef OV10635_DISPLAY_PATTERN -+{0x503d, 0x80}, -+#else -+{0x503D, 0x00}, -+#endif -+{0xC450, 0x01}, /* AA mode */ -+{0xC452, 0x04}, -+{0xC453, 0x00}, -+{0xC454, 0x00}, -+{0xC455, 0x01}, -+{0xC456, 0x01}, -+{0xC457, 0x00}, -+{0xC458, 0x00}, -+{0xC459, 0x00}, -+{0xC45B, 0x00}, -+{0xC45C, 0x01}, -+{0xC45D, 0x00}, -+{0xC45E, 0x00}, -+{0xC45F, 0x00}, -+{0xC460, 0x00}, -+{0xC461, 0x01}, -+{0xC462, 0x01}, -+{0xC464, 0x03}, -+{0xC465, 0x00}, -+{0xC466, 0x8A}, -+{0xC467, 0x00}, -+{0xC468, 0x86}, -+{0xC469, 0x00}, -+{0xC46A, 0x30}, -+{0xC46B, 0x50}, -+{0xC46C, 0x30}, -+{0xC46D, 0x28}, -+{0xC46E, 0x60}, -+{0xC46F, 0x40}, -+{0xC47C, 0x01}, -+{0xC47D, 0x38}, -+{0xC47E, 0x00}, -+{0xC47F, 0x00}, -+{0xC480, 0x00}, -+{0xC481, 0xFF}, -+{0xC482, 0x00}, -+{0xC483, 0x40}, -+{0xC484, 0x00}, -+{0xC485, 0x18}, -+{0xC486, 0x00}, -+{0xC487, 0x18}, -+{0xC488, (OV10635_VTS-8)*16 >> 8}, -+{0xC489, (OV10635_VTS-8)*16 & 0xff}, -+{0xC48A, (OV10635_VTS-8)*16 >> 8}, -+{0xC48B, (OV10635_VTS-8)*16 & 0xff}, -+{0xC48C, 0x00}, -+{0xC48D, 0x04}, -+{0xC48E, 0x00}, -+{0xC48F, 0x04}, -+{0xC490, 0x03}, -+{0xC492, 0x20}, -+{0xC493, 0x08}, -+{0xC498, 0x02}, -+{0xC499, 0x00}, -+{0xC49A, 0x02}, -+{0xC49B, 0x00}, -+{0xC49C, 0x02}, -+{0xC49D, 0x00}, -+{0xC49E, 0x02}, -+{0xC49F, 0x60}, -+{0xC4A0, 0x03}, -+{0xC4A1, 0x00}, -+{0xC4A2, 0x04}, -+{0xC4A3, 0x00}, -+{0xC4A4, 0x00}, -+{0xC4A5, 0x10}, -+{0xC4A6, 0x00}, -+{0xC4A7, 0x40}, -+{0xC4A8, 0x00}, -+{0xC4A9, 0x80}, -+{0xC4AA, 0x0D}, -+{0xC4AB, 0x00}, -+{0xC4AC, 0x0F}, -+{0xC4AD, 0xC0}, -+{0xC4B4, 0x01}, -+{0xC4B5, 0x01}, -+{0xC4B6, 0x00}, -+{0xC4B7, 0x01}, -+{0xC4B8, 0x00}, -+{0xC4B9, 0x01}, -+{0xC4BA, 0x01}, -+{0xC4BB, 0x00}, -+{0xC4BC, 0x01}, -+{0xC4BD, 0x60}, -+{0xC4BE, 0x02}, -+{0xC4BF, 0x33}, -+{0xC4C8, 0x03}, -+{0xC4C9, 0xD0}, -+{0xC4CA, 0x0E}, -+{0xC4CB, 0x00}, -+{0xC4CC, 0x0E}, -+{0xC4CD, 0x51}, -+{0xC4CE, 0x0E}, -+{0xC4CF, 0x51}, -+{0xC4D0, 0x04}, -+{0xC4D1, 0x80}, -+{0xC4E0, 0x04}, -+{0xC4E1, 0x02}, -+{0xC4E2, 0x01}, -+{0xC4E4, 0x10}, -+{0xC4E5, 0x20}, -+{0xC4E6, 0x30}, -+{0xC4E7, 0x40}, -+{0xC4E8, 0x50}, -+{0xC4E9, 0x60}, -+{0xC4EA, 0x70}, -+{0xC4EB, 0x80}, -+{0xC4EC, 0x90}, -+{0xC4ED, 0xA0}, -+{0xC4EE, 0xB0}, -+{0xC4EF, 0xC0}, -+{0xC4F0, 0xD0}, -+{0xC4F1, 0xE0}, -+{0xC4F2, 0xF0}, -+{0xC4F3, 0x80}, -+{0xC4F4, 0x00}, -+{0xC4F5, 0x20}, -+{0xC4F6, 0x02}, -+{0xC4F7, 0x00}, -+{0xC4F8, 0x00}, -+{0xC4F9, 0x00}, -+{0xC4FA, 0x00}, -+{0xC4FB, 0x01}, -+{0xC4FC, 0x01}, -+{0xC4FD, 0x00}, -+{0xC4FE, 0x04}, -+{0xC4FF, 0x02}, -+{0xC500, 0x48}, -+{0xC501, 0x74}, -+{0xC502, 0x58}, -+{0xC503, 0x80}, -+{0xC504, 0x05}, -+{0xC505, 0x80}, -+{0xC506, 0x03}, -+{0xC507, 0x80}, -+{0xC508, 0x01}, -+{0xC509, 0xC0}, -+{0xC50A, 0x01}, -+{0xC50B, 0xA0}, -+{0xC50C, 0x01}, -+{0xC50D, 0x2C}, -+{0xC50E, 0x01}, -+{0xC50F, 0x0A}, -+{0xC510, 0x00}, -+{0xC511, 0x00}, -+{0xC512, 0xE5}, -+{0xC513, 0x14}, -+{0xC514, 0x04}, -+{0xC515, 0x00}, -+{0xC518, OV10635_VTS >> 8}, -+{0xC519, OV10635_VTS & 0xff}, -+{0xC51A, OV10635_HTS >> 8}, -+{0xC51B, OV10635_HTS & 0xff}, -+{0xC2E0, 0x00}, -+{0xC2E1, 0x51}, -+{0xC2E2, 0x00}, -+{0xC2E3, 0xD6}, -+{0xC2E4, 0x01}, -+{0xC2E5, 0x5E}, -+{0xC2E9, 0x01}, -+{0xC2EA, 0x7A}, -+{0xC2EB, 0x90}, -+{0xC2ED, 0x00}, -+{0xC2EE, 0x7A}, -+{0xC2EF, 0x64}, -+{0xC308, 0x00}, -+{0xC309, 0x00}, -+{0xC30A, 0x00}, -+{0xC30C, 0x00}, -+{0xC30D, 0x01}, -+{0xC30E, 0x00}, -+{0xC30F, 0x00}, -+{0xC310, 0x01}, -+{0xC311, 0x60}, -+{0xC312, 0xFF}, -+{0xC313, 0x08}, -+{0xC314, 0x01}, -+{0xC315, 0x00}, /* min saturation gain */ -+{0xC316, 0xFF}, /* max saturation gain */ -+{0xC317, 0x0B}, -+{0xC318, 0x00}, -+{0xC319, 0x0C}, -+{0xC31A, 0x00}, -+{0xC31B, 0xE0}, -+{0xC31C, 0x00}, -+{0xC31D, 0x14}, -+{0xC31E, 0x00}, -+{0xC31F, 0xC5}, -+{0xC320, 0xFF}, -+{0xC321, 0x4B}, -+{0xC322, 0xFF}, -+{0xC323, 0xF0}, -+{0xC324, 0xFF}, -+{0xC325, 0xE8}, -+{0xC326, 0x00}, -+{0xC327, 0x46}, -+{0xC328, 0xFF}, -+{0xC329, 0xD2}, -+{0xC32A, 0xFF}, -+{0xC32B, 0xE4}, -+{0xC32C, 0xFF}, -+{0xC32D, 0xBB}, -+{0xC32E, 0x00}, -+{0xC32F, 0x61}, -+{0xC330, 0xFF}, -+{0xC331, 0xF9}, -+{0xC332, 0x00}, -+{0xC333, 0xD9}, -+{0xC334, 0x00}, -+{0xC335, 0x2E}, -+{0xC336, 0x00}, -+{0xC337, 0xB1}, -+{0xC338, 0xFF}, -+{0xC339, 0x64}, -+{0xC33A, 0xFF}, -+{0xC33B, 0xEB}, -+{0xC33C, 0xFF}, -+{0xC33D, 0xE8}, -+{0xC33E, 0x00}, -+{0xC33F, 0x48}, -+{0xC340, 0xFF}, -+{0xC341, 0xD0}, -+{0xC342, 0xFF}, -+{0xC343, 0xED}, -+{0xC344, 0xFF}, -+{0xC345, 0xAD}, -+{0xC346, 0x00}, -+{0xC347, 0x66}, -+{0xC348, 0x01}, -+{0xC349, 0x00}, -+{0x6700, 0x04}, -+{0x6701, 0x7B}, -+{0x6702, 0xFD}, -+{0x6703, 0xF9}, -+{0x6704, 0x3D}, -+{0x6705, 0x71}, -+{0x6706, 0x78}, -+{0x6708, 0x05}, -+{0x6F06, 0x6F}, -+{0x6F07, 0x00}, -+{0x6F0A, 0x6F}, -+{0x6F0B, 0x00}, -+{0x6F00, 0x03}, -+{0xC34C, 0x01}, -+{0xC34D, 0x00}, -+{0xC34E, 0x46}, -+{0xC34F, 0x55}, -+{0xC350, 0x00}, -+{0xC351, 0x40}, -+{0xC352, 0x00}, -+{0xC353, 0xFF}, -+{0xC354, 0x04}, -+{0xC355, 0x08}, -+{0xC356, 0x01}, -+{0xC357, 0xEF}, -+{0xC358, 0x30}, -+{0xC359, 0x01}, -+{0xC35A, 0x64}, -+{0xC35B, 0x46}, -+{0xC35C, 0x00}, -+{0x3042, 0xF0}, -+{0x3042, 0xF0}, -+{0x3042, 0xF0}, -+{0x3042, 0xF0}, -+{0x3042, 0xF0}, -+{0x3042, 0xF0}, -+{0x3042, 0xF0}, -+{0x3042, 0xF0}, -+{0x3042, 0xF0}, -+{0x3042, 0xF0}, -+{0x3042, 0xF0}, -+{0x3042, 0xF0}, -+{0x3042, 0xF0}, -+{0x3042, 0xF0}, -+{0x3042, 0xF0}, -+{0x3042, 0xF0}, -+{0x3042, 0xF0}, -+{0x3042, 0xF0}, -+{0x3042, 0xF0}, -+{0x3042, 0xF0}, -+{0x3042, 0xF0}, -+{0x3042, 0xF0}, -+{0x3042, 0xF0}, -+{0x3042, 0xF0}, -+{0x3042, 0xF0}, -+{0x3042, 0xF0}, -+{0xC261, 0x01}, -+{0x301B, 0xF0}, -+{0x301C, 0xF0}, -+{0x301A, 0xF0}, -+{0x6F00, 0xC3}, -+{0xC46A, 0x30}, -+{0xC46D, 0x20}, -+{0xC464, 0x84}, -+{0xC465, 0x00}, -+{0x6F00, 0x03}, -+{0x6F00, 0x43}, -+{0x381C, 0x00}, -+{0x381D, 0x40}, -+{0xC454, 0x01}, -+{0x6F00, 0xC3}, -+{0xC454, 0x00}, -+{0xC4B1, 0x02}, -+{0xC4B2, 0x01}, -+{0xC4B3, 0x03}, -+{0x6F00, 0x03}, -+{0x6F00, 0x43}, -+/* enable FSIN (FRAMESYNC input) functionality */ -+{0x3832, (0x0d+2*0x20+0x15+38) >> 8}, -+{0x3833, (0x0d+2*0x20+0x15+38) & 0xff}, -+{0x3834, OV10635_VTS >> 8}, -+{0x3835, OV10635_VTS & 0xff}, -+{0x302E, 0x01}, -+}; -+ -+static const struct ov10635_reg ov10635_regs_30fps[] = { -+/* disable clocks */ -+{0x301b, 0xff}, -+{0x301c, 0xff}, -+{0x301a, 0xff}, -+/* clk = 24Mhz/2*32/2(1+1)=96Mhz, 30fps */ -+{0x3003, 0x20}, -+{0x3004, 0x21}, -+/* enable clocks */ -+{0x301b, 0xf0}, -+{0x301c, 0xf0}, -+{0x301a, 0xf0}, -+}; -+ -+static const struct ov10635_reg ov10635_regs_15fps[] = { -+/* disable clocks */ -+{0x301b, 0xff}, -+{0x301c, 0xff}, -+{0x301a, 0xff}, -+/* clk = 24Mhz/2*32/2(1+3)=48Mhz, 15fps */ -+{0x3003, 0x20}, -+{0x3004, 0x23}, -+/* enable clocks */ -+{0x301b, 0xf0}, -+{0x301c, 0xf0}, -+{0x301a, 0xf0}, -+}; -+ -+static const struct ov10635_reg ov10635_regs_10fps[] = { -+/* disable clocks */ -+{0x301b, 0xff}, -+{0x301c, 0xff}, -+{0x301a, 0xff}, -+/* clk = 24Mhz/2*32/2(1+5)=32Mhz, 10fps */ -+{0x3003, 0x20}, -+{0x3004, 0x25}, -+/* enable clocks */ -+{0x301b, 0xf0}, -+{0x301c, 0xf0}, -+{0x301a, 0xf0}, -+}; -+ -+static const struct ov10635_reg ov10635_regs_5fps[] = { -+/* disable clocks */ -+{0x301b, 0xff}, -+{0x301c, 0xff}, -+{0x301a, 0xff}, -+/* clk = 24Mhz/4*32/2(1+5)=96Mhz, 5fps */ -+{0x3003, 0x20}, -+{0x3004, 0x45}, -+/* enable clocks */ -+{0x301b, 0xf0}, -+{0x301c, 0xf0}, -+{0x301a, 0xf0}, -+}; -+ -+static const struct ov10635_reg ov10635_regs_contrast[5][18] = { -+{ -+ {0x6f00, 0xc3}, -+ {0xc4e4, 0x20}, -+ {0xc4e5, 0x40}, -+ {0xc4e6, 0x60}, -+ {0xc4e7, 0x80}, -+ {0xc4e8, 0xa0}, -+ {0xc4e9, 0xb4}, -+ {0xc4ea, 0xc0}, -+ {0xc4eb, 0xcb}, -+ {0xc4ec, 0xd5}, -+ {0xc4ed, 0xde}, -+ {0xc4ee, 0xe6}, -+ {0xc4ef, 0xed}, -+ {0xc4f0, 0xf3}, -+ {0xc4f1, 0xf8}, -+ {0xc4f2, 0xfc}, -+ {0x6f00, 0x03}, -+ {0x6f00, 0x43}, -+}, { -+ {0x6f00, 0xc3}, -+ {0xc4e4, 0x18}, -+ {0xc4e5, 0x30}, -+ {0xc4e6, 0x48}, -+ {0xc4e7, 0x60}, -+ {0xc4e8, 0x78}, -+ {0xc4e9, 0x90}, -+ {0xc4ea, 0xa4}, -+ {0xc4eb, 0xb4}, -+ {0xc4ec, 0xc2}, -+ {0xc4ed, 0xcf}, -+ {0xc4ee, 0xdb}, -+ {0xc4ef, 0xe5}, -+ {0xc4f0, 0xee}, -+ {0xc4f1, 0xf6}, -+ {0xc4f2, 0xfc}, -+ {0x6f00, 0x03}, -+ {0x6f00, 0x43}, -+}, { -+ {0x6f00, 0xc3}, -+ {0xc4e4, 0x10}, -+ {0xc4e5, 0x20}, -+ {0xc4e6, 0x30}, -+ {0xc4e7, 0x40}, -+ {0xc4e8, 0x50}, -+ {0xc4e9, 0x60}, -+ {0xc4ea, 0x70}, -+ {0xc4eb, 0x80}, -+ {0xc4ec, 0x90}, -+ {0xc4ed, 0xa0}, -+ {0xc4ee, 0xb0}, -+ {0xc4ef, 0xc0}, -+ {0xc4f0, 0xd0}, -+ {0xc4f1, 0xe0}, -+ {0xc4f2, 0xf0}, -+ {0x6f00, 0x03}, -+ {0x6f00, 0x43}, -+}, { -+ {0x6f00, 0xc3}, -+ {0xc4e4, 0x0c}, -+ {0xc4e5, 0x18}, -+ {0xc4e6, 0x24}, -+ {0xc4e7, 0x30}, -+ {0xc4e8, 0x3c}, -+ {0xc4e9, 0x48}, -+ {0xc4ea, 0x54}, -+ {0xc4eb, 0x62}, -+ {0xc4ec, 0x72}, -+ {0xc4ed, 0x84}, -+ {0xc4ee, 0x94}, -+ {0xc4ef, 0xa6}, -+ {0xc4f0, 0xb9}, -+ {0xc4f1, 0xcd}, -+ {0xc4f2, 0xe2}, -+ {0x6f00, 0x03}, -+ {0x6f00, 0x43}, -+}, { -+ {0x6f00, 0xc3}, -+ {0xc4e4, 0x06}, -+ {0xc4e5, 0x0d}, -+ {0xc4e6, 0x15}, -+ {0xc4e7, 0x1e}, -+ {0xc4e8, 0x28}, -+ {0xc4e9, 0x32}, -+ {0xc4ea, 0x3c}, -+ {0xc4eb, 0x48}, -+ {0xc4ec, 0x56}, -+ {0xc4ed, 0x66}, -+ {0xc4ee, 0x78}, -+ {0xc4ef, 0x8c}, -+ {0xc4f0, 0xa2}, -+ {0xc4f1, 0xba}, -+ {0xc4f2, 0xd4}, -+ {0x6f00, 0x03}, -+ {0x6f00, 0x43}, -+} -+}; -diff --git a/drivers/media/i2c/soc_camera/ov10635_debug.h b/drivers/media/i2c/soc_camera/ov10635_debug.h -new file mode 100644 -index 0000000..4c3515a ---- /dev/null -+++ b/drivers/media/i2c/soc_camera/ov10635_debug.h -@@ -0,0 +1,54 @@ -+ -+#if 0 -+{0x4700, 0x02}, // BT656 -+{0x381d, 0x40}, // mirror off -+{0x381c, 0x00}, // flip off -+{0x4300, 0x3a}, // YUV: UYVY -+{0x4708, 0x00}, // PCLK rising edge -+ -+// clk = 24Mhz/3*22/2= 88Mhz -+{0x3003, 0x16}, -+{0x3004, 0x30}, -+#endif -+ -+#define WIDTH 1280 -+#define HEIGHT 720 -+ -+// DVP frame size -+{0x3808, WIDTH >> 8}, -+{0x3809, WIDTH & 0xff}, -+{0x380a, HEIGHT >> 8}, -+{0x380b, HEIGHT & 0xff}, -+ -+{0x3802, ((814 - HEIGHT)/2) >> 8}, // vert crop start -+{0x3803, ((814 - HEIGHT)/2) & 0xff}, -+{0x3806, ((814 - HEIGHT)/2 + HEIGHT + 1) >> 8}, // vert crop end -+{0x3807, ((814 - HEIGHT)/2 + HEIGHT + 1) & 0xff}, -+ -+#if 0 -+#define HTS 0x6f6 // got from above table 1782 -+#define VTS (0x2ec+80) // got from above table 748 + 80 -+ -+{0x380c, HTS >> 8}, // hts -+{0x380d, HTS & 0xff}, -+{0x380e, VTS >> 8}, // vts -+{0x380f, VTS & 0xff}, -+ -+// fifo -+{0x4606, (2*HTS) >> 8}, // fifo_line_length = 2*hts -+{0x4607, (2*HTS) & 0xff}, -+{0x460a, (2*(HTS-1280)) >> 8}, // fifo_hsync_start = 2*(hts - xres) -+{0x460b, (2*(HTS-1280)) & 0xff }, -+ -+// exposure -+{0xC488, (VTS-8)*16 >> 8}, -+{0xC489, (VTS-8)*16 & 0xff}, -+{0xC48A, (VTS-8)*16 >> 8}, -+{0xC48B, (VTS-8)*16 & 0xff}, -+ -+// vts/hts -+{0xC518, VTS >> 8}, -+{0xC519, VTS & 0xff}, -+{0xC51A, HTS >> 8}, -+{0xC51B, HTS & 0xff}, -+#endif -diff --git a/drivers/media/i2c/soc_camera/ov106xx.c b/drivers/media/i2c/soc_camera/ov106xx.c -new file mode 100644 -index 0000000..4c797f9 ---- /dev/null -+++ b/drivers/media/i2c/soc_camera/ov106xx.c -@@ -0,0 +1,117 @@ -+/* -+ * OmniVision ov10635/ov490-ov10640/ov495-ov2775 sensor camera driver -+ * -+ * Copyright (C) 2016-2017 Cogent Embedded, Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ */ -+ -+#include "ov10635.c" -+#include "ov490_ov10640.c" -+#include "ov495_ov2775.c" -+#include "ar0132.c" -+#include "ap0101_ar014x.c" -+ -+static enum { -+ ID_OV10635, -+ ID_OV490_OV10640, -+ ID_OV495_OV2775, -+ ID_AR0132, -+ ID_AP0101_AR014X, -+} chip_id; -+ -+static int ov106xx_probe(struct i2c_client *client, -+ const struct i2c_device_id *did) -+{ -+ int ret; -+ chip_id = -EINVAL; -+ -+ ret = ov10635_probe(client, did); -+ if (!ret) { -+ chip_id = ID_OV10635; -+ goto out; -+ } -+ -+ ret = ov490_probe(client, did); -+ if (!ret) { -+ chip_id = ID_OV490_OV10640; -+ goto out; -+ } -+ -+ ret = ov495_probe(client, did); -+ if (!ret) { -+ chip_id = ID_OV495_OV2775; -+ goto out; -+ } -+ -+ ret = ar0132_probe(client, did); -+ if (!ret) { -+ chip_id = ID_AR0132; -+ goto out; -+ } -+ -+ ret = ap0101_probe(client, did); -+ if (!ret) { -+ chip_id = ID_AP0101_AR014X; -+ goto out; -+ } -+ -+ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", -+ client->addr, client->adapter->name); -+out: -+ return ret; -+} -+ -+static int ov106xx_remove(struct i2c_client *client) -+{ -+ switch (chip_id) { -+ case ID_OV10635: -+ ov10635_remove(client); -+ break; -+ case ID_OV490_OV10640: -+ ov490_remove(client); -+ break; -+ case ID_OV495_OV2775: -+ ov495_remove(client); -+ break; -+ case ID_AR0132: -+ ar0132_remove(client); -+ break; -+ case ID_AP0101_AR014X: -+ ap0101_remove(client); -+ break; -+ }; -+ -+ return 0; -+} -+ -+static const struct i2c_device_id ov106xx_id[] = { -+ { "ov106xx", 0 }, -+ { } -+}; -+MODULE_DEVICE_TABLE(i2c, ov106xx_id); -+ -+static const struct of_device_id ov106xx_of_ids[] = { -+ { .compatible = "ovti,ov106xx", }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, ov106xx_of_ids); -+ -+static struct i2c_driver ov106xx_i2c_driver = { -+ .driver = { -+ .name = "ov106xx", -+ .of_match_table = ov106xx_of_ids, -+ }, -+ .probe = ov106xx_probe, -+ .remove = ov106xx_remove, -+ .id_table = ov106xx_id, -+}; -+ -+module_i2c_driver(ov106xx_i2c_driver); -+ -+MODULE_DESCRIPTION("SoC Camera driver for OV10635 or OV490/OV10640 or OV495/OV2775 or AR0132 or AP0101/AR014X"); -+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..f1e34a3 ---- /dev/null -+++ b/drivers/media/i2c/soc_camera/ov490_ov10640.c -@@ -0,0 +1,1160 @@ -+/* -+ * 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 -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include "max9286.h" -+#include "ov490_ov10640.h" -+ -+#define OV490_I2C_ADDR 0x24 -+ -+#define OV490_PID 0x300a -+#define OV490_VER 0x300b -+#define OV490_VERSION_REG 0x0490 -+#define OV490_VERSION(pid, ver) (((pid) << 8) | ((ver) & 0xff)) -+ -+#define OV490_ISP_HSIZE_LOW 0x60 -+#define OV490_ISP_HSIZE_HIGH 0x61 -+#define OV490_ISP_VSIZE_LOW 0x62 -+#define OV490_ISP_VSIZE_HIGH 0x63 -+ -+struct ov490_priv { -+ struct v4l2_subdev sd; -+ struct v4l2_ctrl_handler hdl; -+ struct media_pad pad; -+ struct v4l2_rect rect; -+ int max_width; -+ int max_height; -+ char is_fixed_sensor; -+ int init_complete; -+ u8 id[6]; -+ int exposure; -+ int gain; -+ int autogain; -+ int red; -+ int green_r; -+ int green_b; -+ int blue; -+ int awb; -+ int dvp_order; -+ /* serializers */ -+ int max9286_addr; -+ int max9271_addr; -+ int ti964_addr; -+ int ti954_addr; -+ int ti9x3_addr; -+ int port; -+ int gpio_resetb; -+ int active_low_resetb; -+ int gpio_fsin; -+}; -+ -+static int conf_link; -+module_param(conf_link, int, 0644); -+MODULE_PARM_DESC(conf_link, " Force configuration link. Used only if robust firmware flashing required (f.e. recovery)"); -+ -+static int dvp_order; -+module_param(dvp_order, int, 0644); -+MODULE_PARM_DESC(dvp_order, " DVP bus bits order"); -+ -+static int max_width; -+module_param(max_width, int, 0644); -+MODULE_PARM_DESC(max_width, " Fixed sensor width"); -+ -+static int max_height; -+module_param(max_height, int, 0644); -+MODULE_PARM_DESC(max_height, " Fixed sensor height"); -+ -+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(5000, 5500); /* wait 5ms */ -+ client->addr = tmp_addr; -+ }; -+} -+ -+static void ov490_reset(struct i2c_client *client) -+{ -+ struct ov490_priv *priv = to_ov490(client); -+ int tmp_addr; -+ -+ if (priv->max9286_addr) { -+ if (priv->gpio_resetb < 1 || priv->gpio_resetb > 5) -+ return; -+ -+ tmp_addr = client->addr; -+ /* get out from sensor reset */ -+ client->addr = priv->max9271_addr; /* MAX9271 I2C address */ -+ reg8_write(client, 0x0f, (0xfe & ~BIT(priv->gpio_resetb)) | -+ (priv->active_low_resetb ? 0 : BIT(priv->gpio_resetb))); /* set GPIOn value to reset */ -+ usleep_range(2000, 2500); /* wait 2ms */ -+ reg8_write(client, 0x0f, (0xfe & ~BIT(priv->gpio_resetb)) | -+ (priv->active_low_resetb ? BIT(priv->gpio_resetb) : 0)); /* set GPIOn value to un-reset */ -+ usleep_range(2000, 2500); /* wait 2ms */ -+ client->addr = tmp_addr; -+ } -+ -+ if (priv->ti964_addr) { -+ client->addr = priv->ti964_addr; /* TI964 I2C address */ -+ -+ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ -+ usleep_range(2000, 2500); /* wait 2ms */ -+ reg8_write(client, 0x6e, 0x8a); /* set GPIO1 value to reset */ -+ usleep_range(2000, 2500); /* wait 2ms */ -+ reg8_write(client, 0x6e, 0x9a); /* set GPIO1 value to un-reset */ -+ } -+ -+ if (priv->ti954_addr) { -+ client->addr = priv->ti954_addr; /* TI964 I2C address */ -+ -+ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ -+ usleep_range(2000, 2500); /* wait 2ms */ -+ reg8_write(client, 0x6e, 0x8a); /* set GPIO1 value to reset */ -+ usleep_range(2000, 2500); /* wait 2ms */ -+ reg8_write(client, 0x6e, 0x9a); /* set GPIO1 value to un-reset */ -+ } -+} -+ -+static int ov490_set_regs(struct i2c_client *client, -+ const struct ov490_reg *regs, int nr_regs) -+{ -+ int i; -+ -+ for (i = 0; i < nr_regs; i++) { -+ if (reg16_write(client, regs[i].reg, regs[i].val)) { -+ usleep_range(100, 150); /* wait 100 us */ -+ reg16_write(client, regs[i].reg, regs[i].val); -+ } -+ } -+ -+ return 0; -+} -+ -+static u8 ov490_ov10640_read(struct i2c_client *client, u16 addr) -+{ -+ u8 reg_val = 0; -+ -+ reg16_write(client, 0xFFFD, 0x80); -+ usleep_range(100, 150); /* wait 100 us */ -+ reg16_write(client, 0xFFFE, 0x19); -+ usleep_range(100, 150); /* wait 100 us */ -+ reg16_write(client, 0x5000, 0x01); /* read operation */ -+ reg16_write(client, 0x5001, addr >> 8); -+ reg16_write(client, 0x5002, addr & 0xff); -+ reg16_write(client, 0xFFFE, 0x80); -+ usleep_range(100, 150); /* wait 100 us */ -+ reg16_write(client, 0x00C0, 0xc1); -+ reg16_write(client, 0xFFFE, 0x19); -+ usleep_range(1000, 1500); /* wait 1 ms */ -+ reg16_read(client, 0x5000, ®_val); -+ -+ return reg_val; -+} -+ -+static void ov490_ov10640_write(struct i2c_client *client, u16 addr, u8 val) -+{ -+ reg16_write(client, 0xFFFD, 0x80); -+ usleep_range(100, 150); /* wait 100 us */ -+ reg16_write(client, 0xFFFE, 0x19); -+ usleep_range(100, 150); /* wait 100 us */ -+ reg16_write(client, 0x5000, 0x00); /* write operation */ -+ reg16_write(client, 0x5001, addr >> 8); -+ reg16_write(client, 0x5002, addr & 0xff); -+ reg16_write(client, 0x5003, val); -+ reg16_write(client, 0xFFFE, 0x80); -+ usleep_range(100, 150); /* wait 100 us */ -+ reg16_write(client, 0x00C0, 0xc1); -+} -+ -+static int ov490_s_stream(struct v4l2_subdev *sd, int enable) -+{ -+ return 0; -+} -+ -+static int ov490_get_fmt(struct v4l2_subdev *sd, -+ struct v4l2_subdev_pad_config *cfg, -+ struct v4l2_subdev_format *format) ++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 ov490_priv *priv = to_ov490(client); ++ struct ov10635_priv *priv = to_ov10635(client); + + if (format->pad) + return -EINVAL; @@ -4839,9 +3249,9 @@ index 0000000..f1e34a3 + return 0; +} + -+static int ov490_set_fmt(struct v4l2_subdev *sd, -+ struct v4l2_subdev_pad_config *cfg, -+ struct v4l2_subdev_format *format) ++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; + @@ -4855,9 +3265,9 @@ index 0000000..f1e34a3 + 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) ++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; @@ -4867,28 +3277,29 @@ index 0000000..f1e34a3 + return 0; +} + -+static int ov490_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++static int ov10635_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); ++ 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] = OV490_VERSION_REG >> 8; -+ edid->edid[9] = OV490_VERSION_REG & 0xff; ++ edid->edid[8] = OV10635_VERSION_REG >> 8; ++ edid->edid[9] = OV10635_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) ++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 ov490_priv *priv = to_ov490(client); ++ struct ov10635_priv *priv = to_ov10635(client); ++ int subsampling = 0; + + if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || + sel->target != V4L2_SEL_TGT_CROP) @@ -4899,24 +3310,34 @@ index 0000000..f1e34a3 + 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)) ++ 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 ov490_get_selection(struct v4l2_subdev *sd, -+ struct v4l2_subdev_pad_config *cfg, -+ struct v4l2_subdev_selection *sel) ++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 ov490_priv *priv = to_ov490(client); ++ struct ov10635_priv *priv = to_ov10635(client); + + if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; @@ -4925,607 +3346,295 @@ index 0000000..f1e34a3 + 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; ++ 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 = priv->max_width; -+ sel->r.height = priv->max_height; ++ 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 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 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; + -+static int ov490_s_gamma(int a, int ref) ++ return 0; ++} ++ ++static int ov10635_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) +{ -+ if ((a + ref) > 0xff) -+ return 0xff; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10635_priv *priv = to_ov10635(client); ++ struct v4l2_captureparm *cp = &parms->parm.capture; + -+ if ((a + ref) < 0) -+ return 0; ++ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; + -+ return a + ref; ++ 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 ov490_s_ctrl(struct v4l2_ctrl *ctrl) ++static int ov10635_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) +{ -+ 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; ++ struct ov10635_priv *priv = to_ov10635(client); ++ struct v4l2_captureparm *cp = &parms->parm.capture; ++ int ret = 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; ++ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ if (cp->extendedmode != 0) ++ return -EINVAL; + -+ 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_AUTO_WHITE_BALANCE: -+ case V4L2_CID_RED_BALANCE: -+ case V4L2_CID_BLUE_BALANCE: -+ if (ctrl->id == V4L2_CID_AUTO_WHITE_BALANCE) -+ priv->awb = ctrl->val; -+ if (ctrl->id == V4L2_CID_RED_BALANCE) { -+ priv->red = ctrl->val; -+ priv->red <<= 8; -+ priv->green_r = priv->red / 2; -+ } -+ if (ctrl->id == V4L2_CID_BLUE_BALANCE) { -+ priv->blue = ctrl->val; -+ priv->blue <<= 8; -+ priv->green_b = priv->blue / 2; ++ 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; + } + -+ 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->awb); -+ ret |= reg16_write(client, 0x5001, priv->red >> 8); -+ ret |= reg16_write(client, 0x5002, priv->red & 0xff); -+ ret |= reg16_write(client, 0x5003, priv->green_r >> 8); -+ ret |= reg16_write(client, 0x5004, priv->green_r & 0xff); -+ ret |= reg16_write(client, 0x5005, priv->green_b >> 8); -+ ret |= reg16_write(client, 0x5006, priv->green_b & 0xff); -+ ret |= reg16_write(client, 0x5007, priv->blue >> 8); -+ ret |= reg16_write(client, 0x5008, priv->blue & 0xff); -+ ret |= reg16_write(client, 0x5009, priv->red >> 8); -+ ret |= reg16_write(client, 0x500a, priv->red & 0xff); -+ ret |= reg16_write(client, 0x500b, priv->green_r >> 8); -+ ret |= reg16_write(client, 0x500c, priv->green_r & 0xff); -+ ret |= reg16_write(client, 0x500d, priv->green_b >> 8); -+ ret |= reg16_write(client, 0x500e, priv->green_b & 0xff); -+ ret |= reg16_write(client, 0x500f, priv->blue >> 8); -+ ret |= reg16_write(client, 0x5010, priv->blue & 0xff); -+ ret |= reg16_write(client, 0x5011, priv->red >> 8); -+ ret |= reg16_write(client, 0x5012, priv->red & 0xff); -+ ret |= reg16_write(client, 0x5013, priv->green_r >> 8); -+ ret |= reg16_write(client, 0x5014, priv->green_r & 0xff); -+ ret |= reg16_write(client, 0x5015, priv->green_b >> 8); -+ ret |= reg16_write(client, 0x5016, priv->green_b & 0xff); -+ ret |= reg16_write(client, 0x5017, priv->blue >> 8); -+ ret |= reg16_write(client, 0x5018, priv->blue & 0xff); -+ ret |= reg16_write(client, 0xFFFE, 0x80); -+ usleep_range(100, 150); /* wait 100 us */ -+ ret |= reg16_write(client, 0x00C0, 0xeb); -+ 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); ++ priv->fps_denominator = cp->timeperframe.denominator; ++ } ++ ++out: ++ return ret; ++} + -+ 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); ++#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_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_read(client, (u16)reg->reg, &val); ++ if (ret < 0) ++ return ret; + -+ 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); ++ reg->val = val; ++ reg->size = sizeof(u16); + -+ 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); ++ return 0; ++} ++ ++static int ov10635_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ return reg16_write(client, (u16)reg->reg, (u8)reg->val); ++} ++#endif ++ ++static struct v4l2_subdev_core_ops ov10635_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = ov10635_g_register, ++ .s_register = ov10635_s_register, +#endif ++}; ++ ++static int ov10635_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct v4l2_subdev *sd = to_sd(ctrl); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10635_priv *priv = to_ov10635(client); ++ int ret = -EINVAL; ++ u8 val = 0; ++ ++ if (!priv->init_complete) ++ return 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_BRIGHTNESS: ++ /* AEC/AGC target */ ++ ret = reg16_write(client, 0xc46a, ctrl->val); ++ break; ++ case V4L2_CID_CONTRAST: ++ udelay(100); ++ ret = ov10635_set_regs(client, &ov10635_regs_contrast[ctrl->val][0], 18); ++ break; ++ case V4L2_CID_SATURATION: ++ ret = reg16_write(client, 0xc316, ctrl->val); ++ break; ++ case V4L2_CID_HUE: ++ /* CMX ? */ ++ ret = 0; ++ break; ++ case V4L2_CID_GAMMA: ++ ret = reg16_write(client, 0xc4be, ctrl->val >> 8); ++ ret |= reg16_write(client, 0xc4bf, ctrl->val & 0xff); ++ break; ++ case V4L2_CID_AUTOGAIN: ++ /* automatic gain/exposure */ ++ ret = reg16_write(client, 0x56d0, !ctrl->val); ++ break; ++ case V4L2_CID_GAIN: ++ /* manual gain */ ++ ret = reg16_write(client, 0x3504, 0); ++ ret |= reg16_write(client, 0x56d1, ctrl->val >> 8); ++ ret |= reg16_write(client, 0x56d2, ctrl->val & 0xff); ++ ret |= reg16_write(client, 0x3504, 1); /* validate gain */ ++ break; ++ case V4L2_CID_EXPOSURE: ++ /* manual exposure */ ++ ret = reg16_write(client, 0x3504, 0); ++ ret |= reg16_write(client, 0x56d5, ctrl->val >> 8); ++ ret |= reg16_write(client, 0x56d6, ctrl->val & 0xff); ++ ret |= reg16_write(client, 0x3504, 1); /* validate exposure */ ++ break; ++ case V4L2_CID_HFLIP: ++ ret = reg16_read(client, 0x381d, &val); ++ if (ret < 0) ++ goto out; ++ if (ctrl->val) ++ val |= 0x3; ++ else ++ val &= ~0x3; ++ ret = reg16_write(client, 0x381d, val); ++ break; ++ case V4L2_CID_VFLIP: ++ ret = reg16_read(client, 0x381c, &val); ++ if (ctrl->val) ++ val |= 0xc0; ++ else ++ val &= ~0xc0; ++ ret = reg16_write(client, 0x381c, val); + break; + case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: + ret = 0; + break; + } + ++out: + return ret; +} + -+static const struct v4l2_ctrl_ops ov490_ctrl_ops = { -+ .s_ctrl = ov490_s_ctrl, ++static const struct v4l2_ctrl_ops ov10635_ctrl_ops = { ++ .s_ctrl = ov10635_s_ctrl, +}; + -+static struct v4l2_subdev_video_ops ov490_video_ops = { -+ .s_stream = ov490_s_stream, -+ .g_mbus_config = ov490_g_mbus_config, ++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 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 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 ov490_subdev_ops = { -+ .core = &ov490_core_ops, -+ .video = &ov490_video_ops, -+ .pad = &ov490_subdev_pad_ops, ++static struct v4l2_subdev_ops ov10635_subdev_ops = { ++ .core = &ov10635_core_ops, ++ .video = &ov10635_video_ops, ++ .pad = &ov10635_subdev_pad_ops, +}; + -+static void ov490_otp_id_read(struct i2c_client *client) ++static void ov10635_otp_id_read(struct i2c_client *client) +{ -+ struct ov490_priv *priv = to_ov490(client); ++ struct ov10635_priv *priv = to_ov10635(client); + int i; -+ int otp_bank0_allzero = 1; + -+#if 0 -+ /* read camera id from ov490 OTP memory */ -+ reg16_write(client, 0xFFFD, 0x80); -+ reg16_write(client, 0xFFFE, 0x28); -+ usleep_range(100, 150); /* wait 100 us */ -+ reg16_write(client, 0xE084, 0x40); /* manual mode, bank#0 */ -+ reg16_write(client, 0xE081, 1); /* start OTP read */ ++ /* read camera id from OTP memory */ ++ reg16_write(client, 0x3d10, 1); + -+ usleep_range(25000, 26000); /* wait 25 ms */ ++ usleep_range(15000, 16000); /* wait 15ms */ + + for (i = 0; i < 6; i++) -+ reg16_read(client, 0xe000 + i + 4, &priv->id[i]); -+#else -+ /* read camera id from ov10640 OTP memory */ -+ ov490_ov10640_write(client, 0x349C, 1); -+ usleep_range(25000, 25500); /* wait 25 ms */ -+ -+ for (i = 0; i < 6; i++) { -+ /* first 6 bytes are equal on all ov10640 */ -+ priv->id[i] = ov490_ov10640_read(client, 0x349e + i + 6); -+ if (priv->id[i]) -+ otp_bank0_allzero = 0; -+ } -+ -+ if (otp_bank0_allzero) { -+ ov490_ov10640_write(client, 0x3495, 0x41); /* bank#1 */ -+ ov490_ov10640_write(client, 0x349C, 1); -+ usleep_range(25000, 25500); /* wait 25 ms */ -+ -+ for (i = 0; i < 6; i++) -+ priv->id[i] = ov490_ov10640_read(client, 0x34ae + i); -+ } -+#endif ++ reg16_read(client, 0x3d00 + i, &priv->id[i]); +} + -+static ssize_t ov490_otp_id_show(struct device *dev, -+ struct device_attribute *attr, char *buf) ++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 ov490_priv *priv = to_ov490(client); ++ 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_ov490, S_IRUGO, ov490_otp_id_show, NULL); ++static DEVICE_ATTR(otp_id_ov10635, S_IRUGO, ov10635_otp_id_show, NULL); + -+static int ov490_initialize(struct i2c_client *client) ++static int ov10635_initialize(struct i2c_client *client) +{ -+ struct ov490_priv *priv = to_ov490(client); -+ u8 val = 0; ++ struct ov10635_priv *priv = to_ov10635(client); + u8 pid = 0, ver = 0; -+ int ret = 0, timeout, retry_timeout = 3; -+ -+ if (priv->is_fixed_sensor) { -+ dev_info(&client->dev, "ov490/ov10640 fixed-sensor res %dx%d\n", priv->max_width, priv->max_height); -+ return 0; -+ } ++ int ret = 0; + -+ ov490_s_port(client, 1); ++ ov10635_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, OV10635_PID, &pid); ++ reg16_read(client, OV10635_VER, &ver); + -+ if (OV490_VERSION(pid, ver) != OV490_VERSION_REG) { ++ if (OV10635_VERSION(pid, ver) != OV10635_VERSION_REG) { + dev_dbg(&client->dev, "Product ID error %x:%x\n", pid, ver); + ret = -ENODEV; -+ goto err; -+ } -+ -+ if (unlikely(conf_link)) + goto out; -+ -+again: -+ /* Check if firmware booted by reading stream-on status */ -+ reg16_write(client, 0xFFFD, 0x80); -+ reg16_write(client, 0xFFFE, 0x29); -+ usleep_range(100, 150); /* wait 100 us */ -+ for (timeout = 300; timeout > 0; timeout--) { -+ reg16_read(client, 0xd000, &val); -+ if (val == 0x0c) -+ break; -+ mdelay(1); -+ } -+ -+ /* wait firmware apps started by reading OV10640 ID */ -+ for (;timeout > 0; timeout--) { -+ reg16_write(client, 0xFFFD, 0x80); -+ reg16_write(client, 0xFFFE, 0x19); -+ usleep_range(100, 150); /* wait 100 us */ -+ reg16_write(client, 0x5000, 0x01); -+ reg16_write(client, 0x5001, 0x30); -+ reg16_write(client, 0x5002, 0x0a); -+ reg16_write(client, 0xFFFE, 0x80); -+ usleep_range(100, 150); /* wait 100 us */ -+ reg16_write(client, 0xC0, 0xc1); -+ reg16_write(client, 0xFFFE, 0x19); -+ usleep_range(1000, 1500); /* wait 1 ms */ -+ reg16_read(client, 0x5000, &val); -+ if (val == 0xa6) -+ break; -+ mdelay(1); -+ } -+ -+ if (!timeout) { -+ dev_err(&client->dev, "Timeout firmware boot wait, retrying\n"); -+ /* reset OV10640 using RESETB pin controlled by OV490 GPIO0 */ -+ reg16_write(client, 0xFFFD, 0x80); -+ reg16_write(client, 0xFFFE, 0x80); -+ usleep_range(100, 150); /* wait 100 us */ -+ reg16_write(client, 0x0050, 0x01); -+ reg16_write(client, 0x0054, 0x01); -+ reg16_write(client, 0x0058, 0x00); -+ mdelay(10); -+ reg16_write(client, 0x0058, 0x01); -+ /* reset OV490 using RESETB pin controlled by serializer */ -+ ov490_reset(client); -+ if (retry_timeout--) -+ goto again; + } + -+ /* read resolution used by current firmware */ -+ reg16_write(client, 0xFFFD, 0x80); -+ reg16_write(client, 0xFFFE, 0x82); -+ usleep_range(100, 150); /* wait 100 us */ -+ reg16_read(client, OV490_ISP_HSIZE_HIGH, &val); -+ priv->max_width = val; -+ reg16_read(client, OV490_ISP_HSIZE_LOW, &val); -+ priv->max_width = (priv->max_width << 8) | val; -+ reg16_read(client, OV490_ISP_VSIZE_HIGH, &val); -+ priv->max_height = val; -+ reg16_read(client, OV490_ISP_VSIZE_LOW, &val); -+ priv->max_height = (priv->max_height << 8) | val; ++ /* s/w reset sensor */ ++ reg16_write(client, 0x103, 0x1); ++ udelay(100); + /* Program wizard registers */ -+ ov490_set_regs(client, ov490_regs_wizard, ARRAY_SIZE(ov490_regs_wizard)); ++ ov10635_set_regs(client, ov10635_regs_wizard, ARRAY_SIZE(ov10635_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); ++ reg16_write(client, 0x4709, priv->dvp_order << 4); + /* Read OTP IDs */ -+ ov490_otp_id_read(client); ++ 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: -+ dev_info(&client->dev, "ov490/ov10640 PID %x%x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", -+ pid, ver, priv->max_width, priv->max_height, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); -+err: -+ ov490_s_port(client, 0); ++ ov10635_s_port(client, 0); + + return ret; +} + -+static int ov490_parse_dt(struct device_node *np, struct ov490_priv *priv) ++static int ov10635_parse_dt(struct device_node *np, struct ov10635_priv *priv) +{ + struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); + int i; -+ const char *fixed_sensor; + struct device_node *endpoint = NULL, *rendpoint = NULL; + int tmp_addr = 0; + @@ -5544,17 +3653,8 @@ index 0000000..f1e34a3 + + if (!of_property_read_u32(rendpoint, "max9271-addr", &priv->max9271_addr) && + !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->max9286_addr) && -+ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) { -+ if (of_property_read_u32(rendpoint->parent->parent, "maxim,resetb-gpio", &priv->gpio_resetb)) { -+ priv->gpio_resetb = -1; -+ } else { -+ if (of_property_read_bool(rendpoint->parent->parent, "maxim,resetb-active-high")) -+ priv->active_low_resetb = false; -+ else -+ priv->active_low_resetb = true; -+ } ++ !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") && @@ -5570,11 +3670,11 @@ index 0000000..f1e34a3 + } + + if (!priv->max9286_addr && !priv->ti964_addr && !priv->ti954_addr) { -+ dev_err(&client->dev, "deserializer does not present for OV490\n"); ++ dev_err(&client->dev, "deserializer does not present for OV10635\n"); + return -EINVAL; + } + -+ ov490_s_port(client, 1); ++ ov10635_s_port(client, 1); + + /* setup I2C translator address */ + tmp_addr = client->addr; @@ -5582,106 +3682,79 @@ index 0000000..f1e34a3 + 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 */ ++ 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, OV490_I2C_ADDR << 1); /* Sensor native I2C address */ ++ reg8_write(client, 0x5d, OV10635_I2C_ADDR << 1); /* Sensor native I2C address */ + -+ reg8_write(client, 0x6e, 0x9a); /* GPIO0 - fsin, GPIO1 - resetb */ ++ reg8_write(client, 0x6e, 0xa9); /* GPIO0 - resetb, GPIO1 - fsin */ + } ++ + if (priv->ti954_addr) { + client->addr = priv->ti954_addr; /* Deserializer I2C address */ + + reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ + usleep_range(2000, 2500); /* wait 2ms */ + reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ -+ reg8_write(client, 0x5d, OV490_I2C_ADDR << 1); /* Sensor native I2C address */ ++ reg8_write(client, 0x5d, OV10635_I2C_ADDR << 1); /* Sensor native I2C address */ + -+ reg8_write(client, 0x6e, 0x9a); /* GPIO0 - fsin, GPIO1 - resetb */ ++ reg8_write(client, 0x6e, 0xa9); /* GPIO0 - resetb, GPIO1 - fsin */ + } + client->addr = tmp_addr; -+ -+ if (!of_property_read_string(np, "maxim,fixed-sensor", &fixed_sensor) && -+ strcmp(fixed_sensor, "ov490") == 0) { -+ if (of_property_read_u32(np, "maxim,width", &priv->max_width)) -+ priv->max_width = 1280; -+ -+ if (of_property_read_u32(np, "maxim,height", &priv->max_height)) -+ priv->max_height = 966; -+ -+ priv->is_fixed_sensor = true; -+ } -+ -+ /* module params override dts */ -+ if (dvp_order) -+ priv->dvp_order = dvp_order; -+ if (max_width && max_height) { -+ priv->max_width = max_width; -+ priv->max_height = max_height; -+ priv->is_fixed_sensor = true; -+ } -+ -+ return 0; -+} -+ -+static int ov490_probe(struct i2c_client *client, -+ const struct i2c_device_id *did) -+{ -+ struct ov490_priv *priv; -+ struct v4l2_ctrl *ctrl; -+ int ret; -+ -+ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ v4l2_i2c_subdev_init(&priv->sd, client, &ov490_subdev_ops); -+ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; -+ -+ priv->exposure = 0x100; -+ priv->gain = 0x100; -+ priv->autogain = 1; -+ priv->red = 0x400; -+ priv->blue = 0x400; -+ priv->green_r = priv->red / 2; -+ priv->green_b = priv->blue / 2; -+ priv->awb = 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_AUTO_WHITE_BALANCE, 0, 1, 1, priv->autogain); -+ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, -+ V4L2_CID_RED_BALANCE, 2, 0xf, 1, priv->red >> 8); -+ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, -+ V4L2_CID_BLUE_BALANCE, 2, 0xf, 1, priv->blue >> 8); -+ 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, ++ ++ udelay(100); ++ ++ return 0; ++} ++ ++static int ov10635_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct ov10635_priv *priv; ++ struct v4l2_ctrl *ctrl; ++ int ret; ++ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ v4l2_i2c_subdev_init(&priv->sd, client, &ov10635_subdev_ops); ++ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; ++ priv->rect.left = 0; ++ priv->rect.top = 0; ++ priv->rect.width = OV10635_MAX_WIDTH; ++ priv->rect.height = OV10635_MAX_HEIGHT; ++ priv->fps_denominator = 30; ++ ++ v4l2_ctrl_handler_init(&priv->hdl, 4); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_BRIGHTNESS, 0, 0xff, 1, 0x30); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_CONTRAST, 0, 4, 1, 2); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_SATURATION, 0, 0xff, 1, 0xff); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_HUE, 0, 255, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_GAMMA, 0, 0xffff, 1, 0x233); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_AUTOGAIN, 0, 1, 1, 1); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_GAIN, 0, 0x3ff, 1, 0x10); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_EXPOSURE, 0, 0xffff, 1, 0x80); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, + V4L2_CID_VFLIP, 0, 1, 1, 0); -+ ctrl = v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ ctrl = v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, + V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 9); + if (ctrl) + ctrl->flags &= ~V4L2_CTRL_FLAG_READ_ONLY; @@ -5699,93 +3772,1293 @@ index 0000000..f1e34a3 + if (ret < 0) + goto cleanup; + -+ ret = ov490_parse_dt(client->dev.of_node, priv); ++ 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; + -+ ret = ov490_initialize(client); -+ if (ret < 0) -+ goto cleanup; ++ if (device_create_file(&client->dev, &dev_attr_otp_id_ov10635) != 0) { ++ dev_err(&client->dev, "sysfs otp_id entry creation failed\n"); ++ goto cleanup; ++ } ++ ++ priv->init_complete = 1; ++ ++ return 0; ++ ++cleanup: ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++#ifdef CONFIG_SOC_CAMERA_OV10635 ++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", ++ client->addr, client->adapter->name); ++#endif ++ return ret; ++} ++ ++static int ov10635_remove(struct i2c_client *client) ++{ ++ struct ov10635_priv *priv = i2c_get_clientdata(client); ++ ++ device_remove_file(&client->dev, &dev_attr_otp_id_ov10635); ++ v4l2_async_unregister_subdev(&priv->sd); ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_SOC_CAMERA_OV10635 ++static const struct i2c_device_id ov10635_id[] = { ++ { "ov10635", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, ov10635_id); ++ ++static const struct of_device_id ov10635_of_ids[] = { ++ { .compatible = "ovti,ov10635", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ov10635_of_ids); ++ ++static struct i2c_driver ov10635_i2c_driver = { ++ .driver = { ++ .name = "ov10635", ++ .of_match_table = ov10635_of_ids, ++ }, ++ .probe = ov10635_probe, ++ .remove = ov10635_remove, ++ .id_table = ov10635_id, ++}; ++ ++module_i2c_driver(ov10635_i2c_driver); ++ ++MODULE_DESCRIPTION("SoC Camera driver for OV10635"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); ++#endif +diff --git a/drivers/media/i2c/soc_camera/ov10635.h b/drivers/media/i2c/soc_camera/ov10635.h +new file mode 100644 +index 0000000..a0e510d +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov10635.h +@@ -0,0 +1,1139 @@ ++/* ++ * OmniVision ov10635 sensor camera wizard 1280x800@30/UYVY/BT601/8bit ++ * ++ * Copyright (C) 2015-2017 Cogent Embedded, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ */ ++ ++//#define OV10635_DISPLAY_PATTERN ++ ++#define OV10635_SENSOR_WIDTH 1312 ++#define OV10635_SENSOR_HEIGHT 814 ++ ++#define OV10635_MAX_WIDTH 1280 ++#define OV10635_MAX_HEIGHT 800 ++ ++//#define OV10635_PCLK_96MHZ ++#define OV10635_PCLK_88MHZ ++ ++#if defined(OV10635_PCLK_96MHZ) ++/* VTS=PCLK/FPS/HTS/2 (=96MHz/30/1600/2) */ ++ #define OV10635_HTS 1600 ++ #define OV10635_VTS 1000 /* fps=30 */ ++#elif defined(OV10635_PCLK_88MHZ) ++/* VTS=PCLK/FPS/HTS/2 (=88MHz/1572/30/2) */ ++ #define OV10635_HTS 1572 ++ #define OV10635_VTS 933 /* fps=29.9998 */ ++#else ++ #error PCLK not defined ++#endif ++ ++struct ov10635_reg { ++ u16 reg; ++ u8 val; ++}; ++ ++static const struct ov10635_reg ov10635_regs_wizard[] = { ++//{0x0103, 0x01}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x300C, 0x61}, ++{0x301B, 0xFF}, ++{0x301C, 0xFF}, ++{0x301A, 0xFF}, ++{0x3011, 0x42}, ++{0x6900, 0x0C}, ++{0x6901, 0x19}, ++{0x3503, 0x10}, ++{0x3025, 0x03}, ++#if defined(OV10635_PCLK_96MHZ) ++{0x3003, 0x20}, ++{0x3004, 0x21}, ++#elif defined(OV10635_PCLK_88MHZ) ++{0x3003, 0x16}, ++{0x3004, 0x30}, ++#endif ++{0x3005, 0x40}, ++{0x3006, 0x91}, ++{0x3600, 0x74}, ++{0x3601, 0x2B}, ++{0x3612, 0x00}, ++{0x3611, 0x67}, ++{0x3633, 0xCA}, ++{0x3602, 0xAF}, ++{0x3603, 0x04}, ++{0x3630, 0x28}, ++{0x3631, 0x16}, ++{0x3714, 0x10}, ++{0x371D, 0x01}, ++{0x4300, 0x3A}, ++{0x3007, 0x01}, ++{0x3024, 0x03}, ++{0x3020, 0x0A}, ++{0x3702, 0x0D}, ++{0x3703, 0x20}, ++{0x3704, 0x15}, ++{0x3709, 0xA8}, ++{0x370C, 0xC7}, ++{0x370D, 0x80}, ++{0x3712, 0x00}, ++{0x3713, 0x20}, ++{0x3715, 0x04}, ++{0x381D, 0x40}, ++{0x381C, 0x00}, ++{0x3822, 0x50}, ++{0x3824, 0x10}, ++{0x3815, 0x8C}, ++{0x3804, 0x05}, ++{0x3805, 0x1F}, ++{0x3800, 0x00}, ++{0x3801, 0x00}, ++{0x3806, 0x03}, ++{0x3807, 0x28}, ++{0x3802, 0x00}, ++{0x3803, 0x07}, ++{0x3808, 0x05}, ++{0x3809, 0x00}, ++{0x380A, 0x03}, ++{0x380B, 0x20}, ++{0x380C, OV10635_HTS >> 8}, ++{0x380D, OV10635_HTS & 0xff}, ++{0x380E, OV10635_VTS >> 8}, ++{0x380F, OV10635_VTS & 0xff}, ++{0x3813, 0x02}, ++{0x3811, 0x08}, ++{0x381F, 0x0C}, ++{0x3819, 0x04}, ++{0x3804, 0x01}, ++{0x3805, 0x00}, ++{0x3828, 0x03}, ++{0x3829, 0x10}, ++{0x382A, 0x10}, ++{0x3621, 0x63}, ++{0x5005, 0x08}, ++{0x56D5, 0x00}, ++{0x56D6, 0x80}, ++{0x56D7, 0x00}, ++{0x56D8, 0x00}, ++{0x56D9, 0x00}, ++{0x56DA, 0x80}, ++{0x56DB, 0x00}, ++{0x56DC, 0x00}, ++{0x56E8, 0x00}, ++{0x56E9, 0x7F}, ++{0x56EA, 0x00}, ++{0x56EB, 0x7F}, ++{0x5100, 0x00}, ++{0x5101, 0x80}, ++{0x5102, 0x00}, ++{0x5103, 0x80}, ++{0x5104, 0x00}, ++{0x5105, 0x80}, ++{0x5106, 0x00}, ++{0x5107, 0x80}, ++{0x5108, 0x00}, ++{0x5109, 0x00}, ++{0x510A, 0x00}, ++{0x510B, 0x00}, ++{0x510C, 0x00}, ++{0x510D, 0x00}, ++{0x510E, 0x00}, ++{0x510F, 0x00}, ++{0x5110, 0x00}, ++{0x5111, 0x80}, ++{0x5112, 0x00}, ++{0x5113, 0x80}, ++{0x5114, 0x00}, ++{0x5115, 0x80}, ++{0x5116, 0x00}, ++{0x5117, 0x80}, ++{0x5118, 0x00}, ++{0x5119, 0x00}, ++{0x511A, 0x00}, ++{0x511B, 0x00}, ++{0x511C, 0x00}, ++{0x511D, 0x00}, ++{0x511E, 0x00}, ++{0x511F, 0x00}, ++{0x56D0, 0x00}, ++{0x5006, 0x04}, ++{0x5608, 0x05}, ++{0x52D7, 0x06}, ++{0x528D, 0x08}, ++{0x5293, 0x12}, ++{0x52D3, 0x12}, ++{0x5288, 0x06}, ++{0x5289, 0x20}, ++{0x52C8, 0x06}, ++{0x52C9, 0x20}, ++{0x52CD, 0x04}, ++{0x5381, 0x00}, ++{0x5382, 0xFF}, ++{0x5589, 0x76}, ++{0x558A, 0x47}, ++{0x558B, 0xEF}, ++{0x558C, 0xC9}, ++{0x558D, 0x49}, ++{0x558E, 0x30}, ++{0x558F, 0x67}, ++{0x5590, 0x3F}, ++{0x5591, 0xF0}, ++{0x5592, 0x10}, ++{0x55A2, 0x6D}, ++{0x55A3, 0x55}, ++{0x55A4, 0xC3}, ++{0x55A5, 0xB5}, ++{0x55A6, 0x43}, ++{0x55A7, 0x38}, ++{0x55A8, 0x5F}, ++{0x55A9, 0x4B}, ++{0x55AA, 0xF0}, ++{0x55AB, 0x10}, ++{0x5581, 0x52}, ++{0x5300, 0x01}, ++{0x5301, 0x00}, ++{0x5302, 0x00}, ++{0x5303, 0x0E}, ++{0x5304, 0x00}, ++{0x5305, 0x0E}, ++{0x5306, 0x00}, ++{0x5307, 0x36}, ++{0x5308, 0x00}, ++{0x5309, 0xD9}, ++{0x530A, 0x00}, ++{0x530B, 0x0F}, ++{0x530C, 0x00}, ++{0x530D, 0x2C}, ++{0x530E, 0x00}, ++{0x530F, 0x59}, ++{0x5310, 0x00}, ++{0x5311, 0x7B}, ++{0x5312, 0x00}, ++{0x5313, 0x22}, ++{0x5314, 0x00}, ++{0x5315, 0xD5}, ++{0x5316, 0x00}, ++{0x5317, 0x13}, ++{0x5318, 0x00}, ++{0x5319, 0x18}, ++{0x531A, 0x00}, ++{0x531B, 0x26}, ++{0x531C, 0x00}, ++{0x531D, 0xDC}, ++{0x531E, 0x00}, ++{0x531F, 0x02}, ++{0x5320, 0x00}, ++{0x5321, 0x24}, ++{0x5322, 0x00}, ++{0x5323, 0x56}, ++{0x5324, 0x00}, ++{0x5325, 0x85}, ++{0x5326, 0x00}, ++{0x5327, 0x20}, ++{0x5609, 0x01}, ++{0x560A, 0x40}, ++{0x560B, 0x01}, ++{0x560C, 0x40}, ++{0x560D, 0x00}, ++{0x560E, 0xFA}, ++{0x560F, 0x00}, ++{0x5610, 0xFA}, ++{0x5611, 0x02}, ++{0x5612, 0x80}, ++{0x5613, 0x02}, ++{0x5614, 0x80}, ++{0x5615, 0x01}, ++{0x5616, 0x2C}, ++{0x5617, 0x01}, ++{0x5618, 0x2C}, ++{0x563B, 0x01}, ++{0x563C, 0x01}, ++{0x563D, 0x01}, ++{0x563E, 0x01}, ++{0x563F, 0x03}, ++{0x5640, 0x03}, ++{0x5641, 0x03}, ++{0x5642, 0x05}, ++{0x5643, 0x09}, ++{0x5644, 0x05}, ++{0x5645, 0x05}, ++{0x5646, 0x05}, ++{0x5647, 0x05}, ++{0x5651, 0x00}, ++{0x5652, 0x80}, ++{0x521A, 0x01}, ++{0x521B, 0x03}, ++{0x521C, 0x06}, ++{0x521D, 0x0A}, ++{0x521E, 0x0E}, ++{0x521F, 0x12}, ++{0x5220, 0x16}, ++{0x5223, 0x02}, ++{0x5225, 0x04}, ++{0x5227, 0x08}, ++{0x5229, 0x0C}, ++{0x522B, 0x12}, ++{0x522D, 0x18}, ++{0x522F, 0x1E}, ++{0x5241, 0x04}, ++{0x5242, 0x01}, ++{0x5243, 0x03}, ++{0x5244, 0x06}, ++{0x5245, 0x0A}, ++{0x5246, 0x0E}, ++{0x5247, 0x12}, ++{0x5248, 0x16}, ++{0x524A, 0x03}, ++{0x524C, 0x04}, ++{0x524E, 0x08}, ++{0x5250, 0x0C}, ++{0x5252, 0x12}, ++{0x5254, 0x18}, ++{0x5256, 0x1E}, ++{0x4606, (2*OV10635_HTS) >> 8}, /* fifo_line_length = 2*hts */ ++{0x4607, (2*OV10635_HTS) & 0xff}, ++{0x460a, (2*(OV10635_HTS-OV10635_MAX_WIDTH)) >> 8}, /* fifo_hsync_start = 2*(hts - xres) */ ++{0x460b, (2*(OV10635_HTS-OV10635_MAX_WIDTH)) & 0xff }, ++{0x460C, 0x00}, ++{0x4620, 0x0E}, ++#if 0 ++{0x4700, 0x02}, // BT656: mode is acceptable but artefact lines on left/bottom due to BT656 SAV/EAV are parsed as image data ++#else ++{0x4700, 0x04}, // BT601: 0x08 is also accaptable as HS/VS mode ++#endif ++{0x4701, 0x00}, ++{0x4702, 0x01}, ++{0x4004, 0x04}, ++{0x4005, 0x18}, ++{0x4001, 0x06}, ++{0x4050, 0x22}, ++{0x4051, 0x24}, ++{0x4052, 0x02}, ++{0x4057, 0x9C}, ++{0x405A, 0x00}, ++{0x4202, 0x02}, ++{0x3023, 0x10}, ++{0x0100, 0x01}, ++{0x0100, 0x01}, ++{0x6F10, 0x07}, ++{0x6F11, 0x82}, ++{0x6F12, 0x04}, ++{0x6F13, 0x00}, ++{0xD000, 0x19}, ++{0xD001, 0xA0}, ++{0xD002, 0x00}, ++{0xD003, 0x01}, ++{0xD004, 0xA9}, ++{0xD005, 0xAD}, ++{0xD006, 0x10}, ++{0xD007, 0x40}, ++{0xD008, 0x44}, ++{0xD009, 0x00}, ++{0xD00A, 0x68}, ++{0xD00B, 0x00}, ++{0xD00C, 0x15}, ++{0xD00D, 0x00}, ++{0xD00E, 0x00}, ++{0xD00F, 0x00}, ++{0xD040, 0x9C}, ++{0xD041, 0x21}, ++{0xD042, 0xFF}, ++{0xD043, 0xF8}, ++{0xD044, 0xD4}, ++{0xD045, 0x01}, ++{0xD046, 0x48}, ++{0xD047, 0x00}, ++{0xD048, 0xD4}, ++{0xD049, 0x01}, ++{0xD04A, 0x50}, ++{0xD04B, 0x04}, ++{0xD04C, 0x18}, ++{0xD04D, 0x60}, ++{0xD04E, 0x00}, ++{0xD04F, 0x01}, ++{0xD050, 0xA8}, ++{0xD051, 0x63}, ++{0xD052, 0x02}, ++{0xD053, 0xA4}, ++{0xD054, 0x85}, ++{0xD055, 0x43}, ++{0xD056, 0x00}, ++{0xD057, 0x00}, ++{0xD058, 0x18}, ++{0xD059, 0x60}, ++{0xD05A, 0x00}, ++{0xD05B, 0x01}, ++{0xD05C, 0xA8}, ++{0xD05D, 0x63}, ++{0xD05E, 0x03}, ++{0xD05F, 0xF0}, ++{0xD060, 0x98}, ++{0xD061, 0xA3}, ++{0xD062, 0x00}, ++{0xD063, 0x00}, ++{0xD064, 0x8C}, ++{0xD065, 0x6A}, ++{0xD066, 0x00}, ++{0xD067, 0x6E}, ++{0xD068, 0xE5}, ++{0xD069, 0x85}, ++{0xD06A, 0x18}, ++{0xD06B, 0x00}, ++{0xD06C, 0x10}, ++{0xD06D, 0x00}, ++{0xD06E, 0x00}, ++{0xD06F, 0x10}, ++{0xD070, 0x9C}, ++{0xD071, 0x80}, ++{0xD072, 0x00}, ++{0xD073, 0x03}, ++{0xD074, 0x18}, ++{0xD075, 0x60}, ++{0xD076, 0x00}, ++{0xD077, 0x01}, ++{0xD078, 0xA8}, ++{0xD079, 0x63}, ++{0xD07A, 0x07}, ++{0xD07B, 0x80}, ++{0xD07C, 0x07}, ++{0xD07D, 0xFF}, ++{0xD07E, 0xF9}, ++{0xD07F, 0x03}, ++{0xD080, 0x8C}, ++{0xD081, 0x63}, ++{0xD082, 0x00}, ++{0xD083, 0x00}, ++{0xD084, 0xA5}, ++{0xD085, 0x6B}, ++{0xD086, 0x00}, ++{0xD087, 0xFF}, ++{0xD088, 0x18}, ++{0xD089, 0x80}, ++{0xD08A, 0x00}, ++{0xD08B, 0x01}, ++{0xD08C, 0xA8}, ++{0xD08D, 0x84}, ++{0xD08E, 0x01}, ++{0xD08F, 0x04}, ++{0xD090, 0xE1}, ++{0xD091, 0x6B}, ++{0xD092, 0x58}, ++{0xD093, 0x00}, ++{0xD094, 0x94}, ++{0xD095, 0x6A}, ++{0xD096, 0x00}, ++{0xD097, 0x70}, ++{0xD098, 0xE1}, ++{0xD099, 0x6B}, ++{0xD09A, 0x20}, ++{0xD09B, 0x00}, ++{0xD09C, 0x95}, ++{0xD09D, 0x6B}, ++{0xD09E, 0x00}, ++{0xD09F, 0x00}, ++{0xD0A0, 0xE4}, ++{0xD0A1, 0x8B}, ++{0xD0A2, 0x18}, ++{0xD0A3, 0x00}, ++{0xD0A4, 0x0C}, ++{0xD0A5, 0x00}, ++{0xD0A6, 0x00}, ++{0xD0A7, 0x23}, ++{0xD0A8, 0x15}, ++{0xD0A9, 0x00}, ++{0xD0AA, 0x00}, ++{0xD0AB, 0x00}, ++{0xD0AC, 0x18}, ++{0xD0AD, 0x60}, ++{0xD0AE, 0x80}, ++{0xD0AF, 0x06}, ++{0xD0B0, 0xA8}, ++{0xD0B1, 0x83}, ++{0xD0B2, 0x40}, ++{0xD0B3, 0x08}, ++{0xD0B4, 0xA8}, ++{0xD0B5, 0xE3}, ++{0xD0B6, 0x38}, ++{0xD0B7, 0x2A}, ++{0xD0B8, 0xA8}, ++{0xD0B9, 0xC3}, ++{0xD0BA, 0x40}, ++{0xD0BB, 0x09}, ++{0xD0BC, 0xA8}, ++{0xD0BD, 0xA3}, ++{0xD0BE, 0x38}, ++{0xD0BF, 0x29}, ++{0xD0C0, 0x8C}, ++{0xD0C1, 0x65}, ++{0xD0C2, 0x00}, ++{0xD0C3, 0x00}, ++{0xD0C4, 0xD8}, ++{0xD0C5, 0x04}, ++{0xD0C6, 0x18}, ++{0xD0C7, 0x00}, ++{0xD0C8, 0x8C}, ++{0xD0C9, 0x67}, ++{0xD0CA, 0x00}, ++{0xD0CB, 0x00}, ++{0xD0CC, 0xD8}, ++{0xD0CD, 0x06}, ++{0xD0CE, 0x18}, ++{0xD0CF, 0x00}, ++{0xD0D0, 0x18}, ++{0xD0D1, 0x60}, ++{0xD0D2, 0x80}, ++{0xD0D3, 0x06}, ++{0xD0D4, 0xA8}, ++{0xD0D5, 0xE3}, ++{0xD0D6, 0x67}, ++{0xD0D7, 0x02}, ++{0xD0D8, 0xA9}, ++{0xD0D9, 0x03}, ++{0xD0DA, 0x67}, ++{0xD0DB, 0x03}, ++{0xD0DC, 0xA8}, ++{0xD0DD, 0xC3}, ++{0xD0DE, 0x3D}, ++{0xD0DF, 0x05}, ++{0xD0E0, 0x8C}, ++{0xD0E1, 0x66}, ++{0xD0E2, 0x00}, ++{0xD0E3, 0x00}, ++{0xD0E4, 0xB8}, ++{0xD0E5, 0x63}, ++{0xD0E6, 0x00}, ++{0xD0E7, 0x18}, ++{0xD0E8, 0xB8}, ++{0xD0E9, 0x63}, ++{0xD0EA, 0x00}, ++{0xD0EB, 0x98}, ++{0xD0EC, 0xBC}, ++{0xD0ED, 0x03}, ++{0xD0EE, 0x00}, ++{0xD0EF, 0x00}, ++{0xD0F0, 0x10}, ++{0xD0F1, 0x00}, ++{0xD0F2, 0x00}, ++{0xD0F3, 0x16}, ++{0xD0F4, 0xB8}, ++{0xD0F5, 0x83}, ++{0xD0F6, 0x00}, ++{0xD0F7, 0x19}, ++{0xD0F8, 0x8C}, ++{0xD0F9, 0x67}, ++{0xD0FA, 0x00}, ++{0xD0FB, 0x00}, ++{0xD0FC, 0xB8}, ++{0xD0FD, 0xA4}, ++{0xD0FE, 0x00}, ++{0xD0FF, 0x98}, ++{0xD100, 0xB8}, ++{0xD101, 0x83}, ++{0xD102, 0x00}, ++{0xD103, 0x08}, ++{0xD104, 0x8C}, ++{0xD105, 0x68}, ++{0xD106, 0x00}, ++{0xD107, 0x00}, ++{0xD108, 0xE0}, ++{0xD109, 0x63}, ++{0xD10A, 0x20}, ++{0xD10B, 0x04}, ++{0xD10C, 0xE0}, ++{0xD10D, 0x65}, ++{0xD10E, 0x18}, ++{0xD10F, 0x00}, ++{0xD110, 0xA4}, ++{0xD111, 0x83}, ++{0xD112, 0xFF}, ++{0xD113, 0xFF}, ++{0xD114, 0xB8}, ++{0xD115, 0x64}, ++{0xD116, 0x00}, ++{0xD117, 0x48}, ++{0xD118, 0xD8}, ++{0xD119, 0x07}, ++{0xD11A, 0x18}, ++{0xD11B, 0x00}, ++{0xD11C, 0xD8}, ++{0xD11D, 0x08}, ++{0xD11E, 0x20}, ++{0xD11F, 0x00}, ++{0xD120, 0x9C}, ++{0xD121, 0x60}, ++{0xD122, 0x00}, ++{0xD123, 0x00}, ++{0xD124, 0xD8}, ++{0xD125, 0x06}, ++{0xD126, 0x18}, ++{0xD127, 0x00}, ++{0xD128, 0x00}, ++{0xD129, 0x00}, ++{0xD12A, 0x00}, ++{0xD12B, 0x08}, ++{0xD12C, 0x15}, ++{0xD12D, 0x00}, ++{0xD12E, 0x00}, ++{0xD12F, 0x00}, ++{0xD130, 0x8C}, ++{0xD131, 0x6A}, ++{0xD132, 0x00}, ++{0xD133, 0x76}, ++{0xD134, 0xBC}, ++{0xD135, 0x23}, ++{0xD136, 0x00}, ++{0xD137, 0x00}, ++{0xD138, 0x13}, ++{0xD139, 0xFF}, ++{0xD13A, 0xFF}, ++{0xD13B, 0xE6}, ++{0xD13C, 0x18}, ++{0xD13D, 0x60}, ++{0xD13E, 0x80}, ++{0xD13F, 0x06}, ++{0xD140, 0x03}, ++{0xD141, 0xFF}, ++{0xD142, 0xFF}, ++{0xD143, 0xDD}, ++{0xD144, 0xA8}, ++{0xD145, 0x83}, ++{0xD146, 0x40}, ++{0xD147, 0x08}, ++{0xD148, 0x85}, ++{0xD149, 0x21}, ++{0xD14A, 0x00}, ++{0xD14B, 0x00}, ++{0xD14C, 0x85}, ++{0xD14D, 0x41}, ++{0xD14E, 0x00}, ++{0xD14F, 0x04}, ++{0xD150, 0x44}, ++{0xD151, 0x00}, ++{0xD152, 0x48}, ++{0xD153, 0x00}, ++{0xD154, 0x9C}, ++{0xD155, 0x21}, ++{0xD156, 0x00}, ++{0xD157, 0x08}, ++{0x6F0E, 0x03}, ++{0x6F0F, 0x00}, ++{0x460E, 0x08}, ++{0x460F, 0x01}, ++{0x4610, 0x00}, ++{0x4611, 0x01}, ++{0x4612, 0x00}, ++{0x4613, 0x01}, ++{0x4605, 0x08}, // 8bit ++//{0x4709, 0x10}, // swap data bits order [9:0] -> [0:9] ++{0x4608, 0x00}, ++{0x4609, 0x08}, ++{0x6804, 0x00}, ++{0x6805, 0x06}, ++{0x6806, 0x00}, ++{0x5120, 0x00}, ++{0x3510, 0x00}, ++{0x3504, 0x00}, ++{0x6800, 0x00}, ++{0x6F0D, 0x01}, ++{0x4708, 0x01}, // PCLK rising edge ++{0x5000, 0xFF}, ++{0x5001, 0xBF}, ++{0x5002, 0x7E}, ++#ifdef OV10635_DISPLAY_PATTERN ++{0x503d, 0x80}, ++#else ++{0x503D, 0x00}, ++#endif ++{0xC450, 0x01}, /* AA mode */ ++{0xC452, 0x04}, ++{0xC453, 0x00}, ++{0xC454, 0x00}, ++{0xC455, 0x01}, ++{0xC456, 0x01}, ++{0xC457, 0x00}, ++{0xC458, 0x00}, ++{0xC459, 0x00}, ++{0xC45B, 0x00}, ++{0xC45C, 0x01}, ++{0xC45D, 0x00}, ++{0xC45E, 0x00}, ++{0xC45F, 0x00}, ++{0xC460, 0x00}, ++{0xC461, 0x01}, ++{0xC462, 0x01}, ++{0xC464, 0x03}, ++{0xC465, 0x00}, ++{0xC466, 0x8A}, ++{0xC467, 0x00}, ++{0xC468, 0x86}, ++{0xC469, 0x00}, ++{0xC46A, 0x30}, ++{0xC46B, 0x50}, ++{0xC46C, 0x30}, ++{0xC46D, 0x28}, ++{0xC46E, 0x60}, ++{0xC46F, 0x40}, ++{0xC47C, 0x01}, ++{0xC47D, 0x38}, ++{0xC47E, 0x00}, ++{0xC47F, 0x00}, ++{0xC480, 0x00}, ++{0xC481, 0xFF}, ++{0xC482, 0x00}, ++{0xC483, 0x40}, ++{0xC484, 0x00}, ++{0xC485, 0x18}, ++{0xC486, 0x00}, ++{0xC487, 0x18}, ++{0xC488, (OV10635_VTS-8)*16 >> 8}, ++{0xC489, (OV10635_VTS-8)*16 & 0xff}, ++{0xC48A, (OV10635_VTS-8)*16 >> 8}, ++{0xC48B, (OV10635_VTS-8)*16 & 0xff}, ++{0xC48C, 0x00}, ++{0xC48D, 0x04}, ++{0xC48E, 0x00}, ++{0xC48F, 0x04}, ++{0xC490, 0x03}, ++{0xC492, 0x20}, ++{0xC493, 0x08}, ++{0xC498, 0x02}, ++{0xC499, 0x00}, ++{0xC49A, 0x02}, ++{0xC49B, 0x00}, ++{0xC49C, 0x02}, ++{0xC49D, 0x00}, ++{0xC49E, 0x02}, ++{0xC49F, 0x60}, ++{0xC4A0, 0x03}, ++{0xC4A1, 0x00}, ++{0xC4A2, 0x04}, ++{0xC4A3, 0x00}, ++{0xC4A4, 0x00}, ++{0xC4A5, 0x10}, ++{0xC4A6, 0x00}, ++{0xC4A7, 0x40}, ++{0xC4A8, 0x00}, ++{0xC4A9, 0x80}, ++{0xC4AA, 0x0D}, ++{0xC4AB, 0x00}, ++{0xC4AC, 0x0F}, ++{0xC4AD, 0xC0}, ++{0xC4B4, 0x01}, ++{0xC4B5, 0x01}, ++{0xC4B6, 0x00}, ++{0xC4B7, 0x01}, ++{0xC4B8, 0x00}, ++{0xC4B9, 0x01}, ++{0xC4BA, 0x01}, ++{0xC4BB, 0x00}, ++{0xC4BC, 0x01}, ++{0xC4BD, 0x60}, ++{0xC4BE, 0x02}, ++{0xC4BF, 0x33}, ++{0xC4C8, 0x03}, ++{0xC4C9, 0xD0}, ++{0xC4CA, 0x0E}, ++{0xC4CB, 0x00}, ++{0xC4CC, 0x0E}, ++{0xC4CD, 0x51}, ++{0xC4CE, 0x0E}, ++{0xC4CF, 0x51}, ++{0xC4D0, 0x04}, ++{0xC4D1, 0x80}, ++{0xC4E0, 0x04}, ++{0xC4E1, 0x02}, ++{0xC4E2, 0x01}, ++{0xC4E4, 0x10}, ++{0xC4E5, 0x20}, ++{0xC4E6, 0x30}, ++{0xC4E7, 0x40}, ++{0xC4E8, 0x50}, ++{0xC4E9, 0x60}, ++{0xC4EA, 0x70}, ++{0xC4EB, 0x80}, ++{0xC4EC, 0x90}, ++{0xC4ED, 0xA0}, ++{0xC4EE, 0xB0}, ++{0xC4EF, 0xC0}, ++{0xC4F0, 0xD0}, ++{0xC4F1, 0xE0}, ++{0xC4F2, 0xF0}, ++{0xC4F3, 0x80}, ++{0xC4F4, 0x00}, ++{0xC4F5, 0x20}, ++{0xC4F6, 0x02}, ++{0xC4F7, 0x00}, ++{0xC4F8, 0x00}, ++{0xC4F9, 0x00}, ++{0xC4FA, 0x00}, ++{0xC4FB, 0x01}, ++{0xC4FC, 0x01}, ++{0xC4FD, 0x00}, ++{0xC4FE, 0x04}, ++{0xC4FF, 0x02}, ++{0xC500, 0x48}, ++{0xC501, 0x74}, ++{0xC502, 0x58}, ++{0xC503, 0x80}, ++{0xC504, 0x05}, ++{0xC505, 0x80}, ++{0xC506, 0x03}, ++{0xC507, 0x80}, ++{0xC508, 0x01}, ++{0xC509, 0xC0}, ++{0xC50A, 0x01}, ++{0xC50B, 0xA0}, ++{0xC50C, 0x01}, ++{0xC50D, 0x2C}, ++{0xC50E, 0x01}, ++{0xC50F, 0x0A}, ++{0xC510, 0x00}, ++{0xC511, 0x00}, ++{0xC512, 0xE5}, ++{0xC513, 0x14}, ++{0xC514, 0x04}, ++{0xC515, 0x00}, ++{0xC518, OV10635_VTS >> 8}, ++{0xC519, OV10635_VTS & 0xff}, ++{0xC51A, OV10635_HTS >> 8}, ++{0xC51B, OV10635_HTS & 0xff}, ++{0xC2E0, 0x00}, ++{0xC2E1, 0x51}, ++{0xC2E2, 0x00}, ++{0xC2E3, 0xD6}, ++{0xC2E4, 0x01}, ++{0xC2E5, 0x5E}, ++{0xC2E9, 0x01}, ++{0xC2EA, 0x7A}, ++{0xC2EB, 0x90}, ++{0xC2ED, 0x00}, ++{0xC2EE, 0x7A}, ++{0xC2EF, 0x64}, ++{0xC308, 0x00}, ++{0xC309, 0x00}, ++{0xC30A, 0x00}, ++{0xC30C, 0x00}, ++{0xC30D, 0x01}, ++{0xC30E, 0x00}, ++{0xC30F, 0x00}, ++{0xC310, 0x01}, ++{0xC311, 0x60}, ++{0xC312, 0xFF}, ++{0xC313, 0x08}, ++{0xC314, 0x01}, ++{0xC315, 0x00}, /* min saturation gain */ ++{0xC316, 0xFF}, /* max saturation gain */ ++{0xC317, 0x0B}, ++{0xC318, 0x00}, ++{0xC319, 0x0C}, ++{0xC31A, 0x00}, ++{0xC31B, 0xE0}, ++{0xC31C, 0x00}, ++{0xC31D, 0x14}, ++{0xC31E, 0x00}, ++{0xC31F, 0xC5}, ++{0xC320, 0xFF}, ++{0xC321, 0x4B}, ++{0xC322, 0xFF}, ++{0xC323, 0xF0}, ++{0xC324, 0xFF}, ++{0xC325, 0xE8}, ++{0xC326, 0x00}, ++{0xC327, 0x46}, ++{0xC328, 0xFF}, ++{0xC329, 0xD2}, ++{0xC32A, 0xFF}, ++{0xC32B, 0xE4}, ++{0xC32C, 0xFF}, ++{0xC32D, 0xBB}, ++{0xC32E, 0x00}, ++{0xC32F, 0x61}, ++{0xC330, 0xFF}, ++{0xC331, 0xF9}, ++{0xC332, 0x00}, ++{0xC333, 0xD9}, ++{0xC334, 0x00}, ++{0xC335, 0x2E}, ++{0xC336, 0x00}, ++{0xC337, 0xB1}, ++{0xC338, 0xFF}, ++{0xC339, 0x64}, ++{0xC33A, 0xFF}, ++{0xC33B, 0xEB}, ++{0xC33C, 0xFF}, ++{0xC33D, 0xE8}, ++{0xC33E, 0x00}, ++{0xC33F, 0x48}, ++{0xC340, 0xFF}, ++{0xC341, 0xD0}, ++{0xC342, 0xFF}, ++{0xC343, 0xED}, ++{0xC344, 0xFF}, ++{0xC345, 0xAD}, ++{0xC346, 0x00}, ++{0xC347, 0x66}, ++{0xC348, 0x01}, ++{0xC349, 0x00}, ++{0x6700, 0x04}, ++{0x6701, 0x7B}, ++{0x6702, 0xFD}, ++{0x6703, 0xF9}, ++{0x6704, 0x3D}, ++{0x6705, 0x71}, ++{0x6706, 0x78}, ++{0x6708, 0x05}, ++{0x6F06, 0x6F}, ++{0x6F07, 0x00}, ++{0x6F0A, 0x6F}, ++{0x6F0B, 0x00}, ++{0x6F00, 0x03}, ++{0xC34C, 0x01}, ++{0xC34D, 0x00}, ++{0xC34E, 0x46}, ++{0xC34F, 0x55}, ++{0xC350, 0x00}, ++{0xC351, 0x40}, ++{0xC352, 0x00}, ++{0xC353, 0xFF}, ++{0xC354, 0x04}, ++{0xC355, 0x08}, ++{0xC356, 0x01}, ++{0xC357, 0xEF}, ++{0xC358, 0x30}, ++{0xC359, 0x01}, ++{0xC35A, 0x64}, ++{0xC35B, 0x46}, ++{0xC35C, 0x00}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0x3042, 0xF0}, ++{0xC261, 0x01}, ++{0x301B, 0xF0}, ++{0x301C, 0xF0}, ++{0x301A, 0xF0}, ++{0x6F00, 0xC3}, ++{0xC46A, 0x30}, ++{0xC46D, 0x20}, ++{0xC464, 0x84}, ++{0xC465, 0x00}, ++{0x6F00, 0x03}, ++{0x6F00, 0x43}, ++{0x381C, 0x00}, ++{0x381D, 0x40}, ++{0xC454, 0x01}, ++{0x6F00, 0xC3}, ++{0xC454, 0x00}, ++{0xC4B1, 0x02}, ++{0xC4B2, 0x01}, ++{0xC4B3, 0x03}, ++{0x6F00, 0x03}, ++{0x6F00, 0x43}, ++/* enable FSIN (FRAMESYNC input) functionality */ ++{0x3832, (0x0d+2*0x20+0x15+38) >> 8}, ++{0x3833, (0x0d+2*0x20+0x15+38) & 0xff}, ++{0x3834, OV10635_VTS >> 8}, ++{0x3835, OV10635_VTS & 0xff}, ++{0x302E, 0x01}, ++}; ++ ++static const struct ov10635_reg ov10635_regs_30fps[] = { ++/* disable clocks */ ++{0x301b, 0xff}, ++{0x301c, 0xff}, ++{0x301a, 0xff}, ++/* clk = 24Mhz/2*32/2(1+1)=96Mhz, 30fps */ ++{0x3003, 0x20}, ++{0x3004, 0x21}, ++/* enable clocks */ ++{0x301b, 0xf0}, ++{0x301c, 0xf0}, ++{0x301a, 0xf0}, ++}; + -+ priv->rect.left = 0; -+ priv->rect.top = 0; -+ priv->rect.width = priv->max_width; -+ priv->rect.height = priv->max_height; ++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}, ++}; + -+ ret = v4l2_async_register_subdev(&priv->sd); -+ if (ret) -+ goto cleanup; ++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}, ++}; + -+ 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; -+ } ++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}, ++}; + -+ priv->init_complete = 1; ++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 @@ + -+ return 0; ++#if 0 ++{0x4700, 0x02}, // BT656 ++{0x381d, 0x40}, // mirror off ++{0x381c, 0x00}, // flip off ++{0x4300, 0x3a}, // YUV: UYVY ++{0x4708, 0x00}, // PCLK rising edge + -+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); ++// clk = 24Mhz/3*22/2= 88Mhz ++{0x3003, 0x16}, ++{0x3004, 0x30}, +#endif -+ return ret; -+} + -+static int ov490_remove(struct i2c_client *client) -+{ -+ struct ov490_priv *priv = i2c_get_clientdata(client); ++#define WIDTH 1280 ++#define HEIGHT 720 + -+ 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); ++// DVP frame size ++{0x3808, WIDTH >> 8}, ++{0x3809, WIDTH & 0xff}, ++{0x380a, HEIGHT >> 8}, ++{0x380b, HEIGHT & 0xff}, + -+ return 0; -+} ++{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}, + -+#ifdef CONFIG_SOC_CAMERA_OV490_OV10640 -+static const struct i2c_device_id ov490_id[] = { -+ { "ov490-ov10640", 0 }, -+ { } -+}; -+MODULE_DEVICE_TABLE(i2c, ov490_id); ++#if 0 ++#define HTS 0x6f6 // got from above table 1782 ++#define VTS (0x2ec+80) // got from above table 748 + 80 + -+static const struct of_device_id ov490_of_ids[] = { -+ { .compatible = "ovti,ov490-ov10640", }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, ov490_of_ids); ++{0x380c, HTS >> 8}, // hts ++{0x380d, HTS & 0xff}, ++{0x380e, VTS >> 8}, // vts ++{0x380f, VTS & 0xff}, + -+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, -+}; ++// 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 }, + -+module_i2c_driver(ov490_i2c_driver); ++// exposure ++{0xC488, (VTS-8)*16 >> 8}, ++{0xC489, (VTS-8)*16 & 0xff}, ++{0xC48A, (VTS-8)*16 >> 8}, ++{0xC48B, (VTS-8)*16 & 0xff}, + -+MODULE_DESCRIPTION("SoC Camera driver for OV490-OV10640"); -+MODULE_AUTHOR("Vladimir Barinov"); -+MODULE_LICENSE("GPL"); ++// vts/hts ++{0xC518, VTS >> 8}, ++{0xC519, VTS & 0xff}, ++{0xC51A, HTS >> 8}, ++{0xC51B, HTS & 0xff}, +#endif -diff --git a/drivers/media/i2c/soc_camera/ov490_ov10640.h b/drivers/media/i2c/soc_camera/ov490_ov10640.h +diff --git a/drivers/media/i2c/soc_camera/ov106xx.c b/drivers/media/i2c/soc_camera/ov106xx.c new file mode 100644 -index 0000000..b22e93e +index 0000000..1dca809 --- /dev/null -+++ b/drivers/media/i2c/soc_camera/ov490_ov10640.h -@@ -0,0 +1,102 @@ ++++ b/drivers/media/i2c/soc_camera/ov106xx.c +@@ -0,0 +1,128 @@ +/* -+ * OmniVision ov490-ov10640 sensor camera wizard 1280x1080@30/UYVY/BT601/8bit ++ * OmniVision ov10635/ov490-ov10640/ov495-ov2775 sensor camera driver + * + * Copyright (C) 2016-2017 Cogent Embedded, Inc. + * @@ -5795,107 +5068,133 @@ index 0000000..b22e93e + * option) any later version. + */ + -+//#define OV490_DISPLAY_PATTERN ++#include "ov10635.c" ++#include "ov490_ov10640.c" ++#include "ov495_ov2775.c" ++#include "ar0132.c" ++#include "ar0220.c" ++#include "ap0101_ar014x.c" + -+struct ov490_reg { -+ u16 reg; -+ u8 val; -+}; ++static enum { ++ ID_OV10635, ++ ID_OV490_OV10640, ++ ID_OV495_OV2775, ++ ID_AR0132, ++ ID_AR0220, ++ ID_AP0101_AR014X, ++} chip_id; + -+static const struct ov490_reg ov490_regs_wizard[] = { -+/* The following registers should match firmware */ -+{0xfffd, 0x80}, -+{0xfffe, 0x82}, -+{0x0071, 0x11}, -+{0x0075, 0x11}, -+{0xfffe, 0x29}, -+{0x6010, 0x01}, -+/* ov490 EMB line disable in YUV and RAW data, NOTE: EMB line is still used in ISP and sensor */ -+{0xe000, 0x14}, -+#if 0 /* do not disable EMB line in ISP! */ -+{0x4017, 0x00}, -+#endif -+{0xfffe, 0x28}, -+{0x6000, 0x04}, -+{0x6004, 0x00}, -+{0x6008, 0x00}, // PCLK polarity - useless due to silicon bug -> use 0x808000bb register -+{0xfffe, 0x80}, -+{0x0091, 0x00}, -+{0x00bb, 0x1d}, // bit[3]=0 - PCLK polarity workaround -+/* ov10640 EMB line disable */ -+#if 0 /* do not disable EMB line in sensor! */ -+{0xfffe, 0x19}, -+{0x5000, 0x00}, -+{0x5001, 0x30}, -+{0x5002, 0x91}, -+{0x5003, 0x08}, -+{0xfffe, 0x80}, -+{0x00c0, 0xc1}, -+#endif -+/* Ov490 FSIN: app_fsin_from_fsync */ -+{0xfffe, 0x85}, -+{0x0008, 0x00}, -+{0x0009, 0x01}, -+{0x000A, 0x05}, // fsin0 src -+{0x000B, 0x00}, -+{0x0030, 0x02}, // fsin0_delay -+{0x0031, 0x00}, -+{0x0032, 0x00}, -+{0x0033, 0x00}, -+{0x0038, 0x02}, // fsin1_delay -+{0x0039, 0x00}, -+{0x003A, 0x00}, -+{0x003B, 0x00}, -+{0x0070, 0x2C}, // fsin0_length -+{0x0071, 0x01}, -+{0x0072, 0x00}, -+{0x0073, 0x00}, -+{0x0074, 0x64}, // fsin1_length -+{0x0075, 0x00}, -+{0x0076, 0x00}, -+{0x0077, 0x00}, -+{0x0000, 0x14}, -+{0x0001, 0x00}, -+{0x0002, 0x00}, -+{0x0003, 0x00}, -+{0x0004, 0x32}, // load fsin0,load fsin1,load other, it will be cleared automatically. -+{0x0005, 0x00}, -+{0x0006, 0x00}, -+{0x0007, 0x00}, -+{0xfffe, 0x80}, -+{0x0081, 0x00}, // 03;SENSOR FSIN -+/* ov10640 FSIN */ -+{0xfffe, 0x19}, -+{0x5000, 0x00}, -+{0x5001, 0x30}, -+{0x5002, 0x8c}, -+{0x5003, 0xb2}, -+{0xfffe, 0x80}, -+{0x00c0, 0xc1}, -+/* ov10640 HFLIP=1 by default */ -+{0xfffe, 0x19}, -+{0x5000, 0x01}, -+{0x5001, 0x00}, -+{0xfffe, 0x80}, -+{0x00c0, 0xdc}, -+#ifdef OV490_DISPLAY_PATTERN -+{0xfffd, 0x80}, -+{0xfffe, 0x19}, -+{0x5000, 0x02}, -+{0xfffe, 0x80}, -+{0x00c0, 0xd6}, -+#endif ++static int ov106xx_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ int ret; ++ chip_id = -EINVAL; ++ ++ ret = ov10635_probe(client, did); ++ if (!ret) { ++ chip_id = ID_OV10635; ++ goto out; ++ } ++ ++ ret = ov490_probe(client, did); ++ if (!ret) { ++ chip_id = ID_OV490_OV10640; ++ goto out; ++ } ++ ++ ret = ov495_probe(client, did); ++ if (!ret) { ++ chip_id = ID_OV495_OV2775; ++ goto out; ++ } ++ ++ ret = ar0132_probe(client, did); ++ if (!ret) { ++ chip_id = ID_AR0132; ++ goto out; ++ } ++ ++ ret = ar0220_probe(client, did); ++ if (!ret) { ++ chip_id = ID_AR0220; ++ goto out; ++ } ++ ++ ret = ap0101_probe(client, did); ++ if (!ret) { ++ chip_id = ID_AP0101_AR014X; ++ goto out; ++ } ++ ++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", ++ client->addr, client->adapter->name); ++out: ++ return ret; ++} ++ ++static int ov106xx_remove(struct i2c_client *client) ++{ ++ switch (chip_id) { ++ case ID_OV10635: ++ ov10635_remove(client); ++ break; ++ case ID_OV490_OV10640: ++ ov490_remove(client); ++ break; ++ case ID_OV495_OV2775: ++ ov495_remove(client); ++ break; ++ case ID_AR0132: ++ ar0132_remove(client); ++ break; ++ case ID_AR0220: ++ ar0220_remove(client); ++ break; ++ case ID_AP0101_AR014X: ++ ap0101_remove(client); ++ break; ++ }; ++ ++ return 0; ++} ++ ++static const struct i2c_device_id ov106xx_id[] = { ++ { "ov106xx", 0 }, ++ { } +}; -diff --git a/drivers/media/i2c/soc_camera/ov495_ov2775.c b/drivers/media/i2c/soc_camera/ov495_ov2775.c ++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, OV490/OV10640, OV495/OV2775, AR0132, AR0220, AP0101/AR014X"); ++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..6dc0675 +index 0000000..812f367 --- /dev/null -+++ b/drivers/media/i2c/soc_camera/ov495_ov2775.c -@@ -0,0 +1,658 @@ ++++ b/drivers/media/i2c/soc_camera/ov490_ov10640.c +@@ -0,0 +1,1133 @@ +/* -+ * OmniVision ov495-ov2775 sensor camera driver ++ * OmniVision ov490-ov10640 sensor camera driver + * -+ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * Copyright (C) 2016-2018 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 @@ -5914,62 +5213,120 @@ index 0000000..6dc0675 +#include +#include + -+#include "ov495_ov2775.h" ++#include "max9286.h" ++#include "ov490_ov10640.h" + -+#define OV495_I2C_ADDR 0x24 ++#define OV490_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 OV490_PID 0x300a ++#define OV490_VER 0x300b ++#define OV490_VERSION_REG 0x0490 ++#define OV490_VERSION(pid, ver) (((pid) << 8) | ((ver) & 0xff)) + -+#define OV495_ISP_HSIZE_LOW 0x60 -+#define OV495_ISP_HSIZE_HIGH 0x61 -+#define OV495_ISP_VSIZE_LOW 0x62 -+#define OV495_ISP_VSIZE_HIGH 0x63 ++#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 ov495_priv { ++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 red; ++ int green_r; ++ int green_b; ++ int blue; ++ int awb; ++ int dvp_order; + /* serializers */ + int max9286_addr; + int max9271_addr; -+ int ti960_addr; -+ int ti954_addr; ++ int ti9x4_addr; + int ti9x3_addr; + int port; + int gpio_resetb; ++ int active_low_resetb; + int gpio_fsin; -+ +}; + -+static int force_conf_link; ++static int conf_link; ++module_param(conf_link, int, 0644); ++MODULE_PARM_DESC(conf_link, " Force configuration link. Used only if robust firmware flashing required (f.e. recovery)"); + -+static __init int ov495_force_conf_link(char *str) ++static int dvp_order; ++module_param(dvp_order, int, 0644); ++MODULE_PARM_DESC(dvp_order, " DVP bus bits order"); ++ ++static int max_width; ++module_param(max_width, int, 0644); ++MODULE_PARM_DESC(max_width, " Fixed sensor width"); ++ ++static int max_height; ++module_param(max_height, int, 0644); ++MODULE_PARM_DESC(max_height, " Fixed sensor height"); ++ ++static inline struct ov490_priv *to_ov490(const struct i2c_client *client) +{ -+ /* force configuration link */ -+ /* used only if robust firmware flashing required (f.e. recovery) */ -+ force_conf_link = 1; -+ return 0; ++ return container_of(i2c_get_clientdata(client), struct ov490_priv, sd); +} -+early_param("force_conf_link", ov495_force_conf_link); + -+static inline struct ov495_priv *to_ov495(const struct i2c_client *client) ++static void ov490_s_port(struct i2c_client *client, int fwd_en) +{ -+ return container_of(i2c_get_clientdata(client), struct ov495_priv, sd); ++ 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(5000, 5500); /* wait 5ms */ ++ client->addr = tmp_addr; ++ }; +} + -+static int ov495_set_regs(struct i2c_client *client, -+ const struct ov495_reg *regs, int nr_regs) ++static void ov490_reset(struct i2c_client *client) ++{ ++ struct ov490_priv *priv = to_ov490(client); ++ int tmp_addr; ++ ++ if (priv->max9286_addr) { ++ if (priv->gpio_resetb < 1 || priv->gpio_resetb > 5) ++ return; ++ ++ tmp_addr = client->addr; ++ /* get out from sensor reset */ ++ client->addr = priv->max9271_addr; /* MAX9271 I2C address */ ++ reg8_write(client, 0x0f, (0xfe & ~BIT(priv->gpio_resetb)) | ++ (priv->active_low_resetb ? 0 : BIT(priv->gpio_resetb))); /* set GPIOn value to reset */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x0f, (0xfe & ~BIT(priv->gpio_resetb)) | ++ (priv->active_low_resetb ? BIT(priv->gpio_resetb) : 0)); /* set GPIOn value to un-reset */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ client->addr = tmp_addr; ++ } ++ ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x4_addr; /* TI9x4 I2C address */ ++ ++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x6e, 0x8a); /* set GPIO1 value to reset */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x6e, 0x9a); /* set GPIO1 value to un-reset */ ++ } ++} ++ ++static int ov490_set_regs(struct i2c_client *client, ++ const struct ov490_reg *regs, int nr_regs) +{ + int i; + @@ -5983,18 +5340,54 @@ index 0000000..6dc0675 + return 0; +} + -+static int ov495_s_stream(struct v4l2_subdev *sd, int enable) ++static u8 ov490_ov10640_read(struct i2c_client *client, u16 addr) ++{ ++ u8 reg_val = 0; ++ ++ reg16_write(client, 0xFFFD, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x5000, 0x01); /* read operation */ ++ reg16_write(client, 0x5001, addr >> 8); ++ reg16_write(client, 0x5002, addr & 0xff); ++ reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x00C0, 0xc1); ++ reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(1000, 1500); /* wait 1 ms */ ++ reg16_read(client, 0x5000, ®_val); ++ ++ return reg_val; ++} ++ ++static void ov490_ov10640_write(struct i2c_client *client, u16 addr, u8 val) ++{ ++ reg16_write(client, 0xFFFD, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x5000, 0x00); /* write operation */ ++ reg16_write(client, 0x5001, addr >> 8); ++ reg16_write(client, 0x5002, addr & 0xff); ++ reg16_write(client, 0x5003, val); ++ reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x00C0, 0xc1); ++} ++ ++static int ov490_s_stream(struct v4l2_subdev *sd, int enable) +{ + return 0; +} + -+static int ov495_get_fmt(struct v4l2_subdev *sd, ++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 ov495_priv *priv = to_ov495(client); ++ struct ov490_priv *priv = to_ov490(client); + + if (format->pad) + return -EINVAL; @@ -6008,7 +5401,7 @@ index 0000000..6dc0675 + return 0; +} + -+static int ov495_set_fmt(struct v4l2_subdev *sd, ++static int ov490_set_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *format) +{ @@ -6024,7 +5417,7 @@ index 0000000..6dc0675 + return 0; +} + -+static int ov495_enum_mbus_code(struct v4l2_subdev *sd, ++static int ov490_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_mbus_code_enum *code) +{ @@ -6036,28 +5429,28 @@ index 0000000..6dc0675 + return 0; +} + -+static int ov495_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++static int ov490_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); ++ 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] = OV495_VERSION_REG >> 8; -+ edid->edid[9] = OV495_VERSION_REG & 0xff; ++ edid->edid[8] = OV490_VERSION_REG >> 8; ++ edid->edid[9] = OV490_VERSION_REG & 0xff; + + return 0; +} + -+static int ov495_set_selection(struct v4l2_subdev *sd, ++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 ov495_priv *priv = to_ov495(client); ++ struct ov490_priv *priv = to_ov490(client); + + if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || + sel->target != V4L2_SEL_TGT_CROP) @@ -6080,12 +5473,12 @@ index 0000000..6dc0675 + return 0; +} + -+static int ov495_get_selection(struct v4l2_subdev *sd, ++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 ov495_priv *priv = to_ov495(client); ++ struct ov490_priv *priv = to_ov490(client); + + if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; @@ -6111,7 +5504,7 @@ index 0000000..6dc0675 + } +} + -+static int ov495_g_mbus_config(struct v4l2_subdev *sd, ++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 | @@ -6122,7 +5515,7 @@ index 0000000..6dc0675 +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG -+static int ov495_g_register(struct v4l2_subdev *sd, ++static int ov490_g_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); @@ -6139,7 +5532,7 @@ index 0000000..6dc0675 + return 0; +} + -+static int ov495_s_register(struct v4l2_subdev *sd, ++static int ov490_s_register(struct v4l2_subdev *sd, + const struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); @@ -6154,18 +5547,29 @@ index 0000000..6dc0675 +} +#endif + -+static struct v4l2_subdev_core_ops ov495_core_ops = { ++static struct v4l2_subdev_core_ops ov490_core_ops = { +#ifdef CONFIG_VIDEO_ADV_DEBUG -+ .g_register = ov495_g_register, -+ .s_register = ov495_s_register, ++ .g_register = ov490_g_register, ++ .s_register = ov490_s_register, +#endif +}; + -+static int ov495_s_ctrl(struct v4l2_ctrl *ctrl) ++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 ov495_priv *priv = to_ov495(client); ++ struct ov490_priv *priv = to_ov490(client); + int ret = -EINVAL; + + if (!priv->init_complete) @@ -6173,38 +5577,316 @@ index 0000000..6dc0675 + + 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_AUTO_WHITE_BALANCE: ++ case V4L2_CID_RED_BALANCE: ++ case V4L2_CID_BLUE_BALANCE: ++ if (ctrl->id == V4L2_CID_AUTO_WHITE_BALANCE) ++ priv->awb = ctrl->val; ++ if (ctrl->id == V4L2_CID_RED_BALANCE) { ++ priv->red = ctrl->val; ++ priv->red <<= 8; ++ priv->green_r = priv->red / 2; ++ } ++ if (ctrl->id == V4L2_CID_BLUE_BALANCE) { ++ priv->blue = ctrl->val; ++ priv->blue <<= 8; ++ priv->green_b = priv->blue / 2; ++ } ++ ++ 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->awb); ++ ret |= reg16_write(client, 0x5001, priv->red >> 8); ++ ret |= reg16_write(client, 0x5002, priv->red & 0xff); ++ ret |= reg16_write(client, 0x5003, priv->green_r >> 8); ++ ret |= reg16_write(client, 0x5004, priv->green_r & 0xff); ++ ret |= reg16_write(client, 0x5005, priv->green_b >> 8); ++ ret |= reg16_write(client, 0x5006, priv->green_b & 0xff); ++ ret |= reg16_write(client, 0x5007, priv->blue >> 8); ++ ret |= reg16_write(client, 0x5008, priv->blue & 0xff); ++ ret |= reg16_write(client, 0x5009, priv->red >> 8); ++ ret |= reg16_write(client, 0x500a, priv->red & 0xff); ++ ret |= reg16_write(client, 0x500b, priv->green_r >> 8); ++ ret |= reg16_write(client, 0x500c, priv->green_r & 0xff); ++ ret |= reg16_write(client, 0x500d, priv->green_b >> 8); ++ ret |= reg16_write(client, 0x500e, priv->green_b & 0xff); ++ ret |= reg16_write(client, 0x500f, priv->blue >> 8); ++ ret |= reg16_write(client, 0x5010, priv->blue & 0xff); ++ ret |= reg16_write(client, 0x5011, priv->red >> 8); ++ ret |= reg16_write(client, 0x5012, priv->red & 0xff); ++ ret |= reg16_write(client, 0x5013, priv->green_r >> 8); ++ ret |= reg16_write(client, 0x5014, priv->green_r & 0xff); ++ ret |= reg16_write(client, 0x5015, priv->green_b >> 8); ++ ret |= reg16_write(client, 0x5016, priv->green_b & 0xff); ++ ret |= reg16_write(client, 0x5017, priv->blue >> 8); ++ ret |= reg16_write(client, 0x5018, priv->blue & 0xff); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xeb); + 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); ++#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, 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); ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ret |= reg16_write(client, 0xFFFE, 0x19); + usleep_range(100, 150); /* wait 100 us */ -+ ret |= reg16_write(client, 0x30C0, 0xdc); -+ ret |= reg16_write(client, 0x3516, 0x01); ++ ret |= reg16_read(client, 0x5000, &val); ++ val &= ~(0x1 << 3); ++ val |= (ctrl->val << 3); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x00); // write 0x3090 ++ ret |= reg16_write(client, 0x5001, 0x30); ++ ret |= reg16_write(client, 0x5002, 0x90); ++ ret |= reg16_write(client, 0x5003, val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++#endif + break; + case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: + ret = 0; @@ -6214,142 +5896,198 @@ index 0000000..6dc0675 + return ret; +} + -+static const struct v4l2_ctrl_ops ov495_ctrl_ops = { -+ .s_ctrl = ov495_s_ctrl, ++static const struct v4l2_ctrl_ops ov490_ctrl_ops = { ++ .s_ctrl = ov490_s_ctrl, +}; + -+static struct v4l2_subdev_video_ops ov495_video_ops = { -+ .s_stream = ov495_s_stream, -+ .g_mbus_config = ov495_g_mbus_config, ++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 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 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 ov495_subdev_ops = { -+ .core = &ov495_core_ops, -+ .video = &ov495_video_ops, -+ .pad = &ov495_subdev_pad_ops, ++static struct v4l2_subdev_ops ov490_subdev_ops = { ++ .core = &ov490_core_ops, ++ .video = &ov490_video_ops, ++ .pad = &ov490_subdev_pad_ops, +}; + -+static void ov495_otp_id_read(struct i2c_client *client) ++static void ov490_otp_id_read(struct i2c_client *client) +{ -+ struct ov495_priv *priv = to_ov495(client); ++ struct ov490_priv *priv = to_ov490(client); + int i; ++ int otp_bank0_allzero = 1; + +#if 0 -+ /* read camera id from ov495 OTP memory */ ++ /* read camera id from ov490 OTP memory */ + reg16_write(client, 0xFFFD, 0x80); -+ reg16_write(client, 0xFFFE, 0x20); ++ reg16_write(client, 0xFFFE, 0x28); + usleep_range(100, 150); /* wait 100 us */ -+ reg16_write(client, 0x7384, 0x40); /* manual mode, bank#0 */ -+ reg16_write(client, 0x7381, 1); /* start OTP read */ ++ 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, 0x7300 + i + 4, &priv->id[i]); ++ reg16_read(client, 0xe000 + i + 4, &priv->id[i]); +#else -+ /* read camera id from ov2775 OTP memory */ -+ reg16_write(client, 0x3516, 0x00); /* unlock write */ -+ reg16_write(client, 0x0FFC, 0); -+ reg16_write(client, 0x0500, 0x00); /* write 0x34a1 -> 1 */ -+ reg16_write(client, 0x0501, 0x34); -+ reg16_write(client, 0x0502, 0xa1); -+ reg16_write(client, 0x0503, 1); -+ reg16_write(client, 0x30C0, 0xc1); -+ ++ /* read camera id from ov10640 OTP memory */ ++ ov490_ov10640_write(client, 0x349C, 1); + usleep_range(25000, 25500); /* wait 25 ms */ + + for (i = 0; i < 6; i++) { -+ reg16_write(client, 0x3516, 0x00); /* unlock write */ -+ reg16_write(client, 0x0500, 0x01); /* read (0x7a00 + i) */ -+ reg16_write(client, 0x0501, 0x7a); -+ reg16_write(client, 0x0502, 0x00 + i + (i < 3 ? 11 : 3)); /* take bytes 11,12,13,6,7,8 */ -+ reg16_write(client, 0x30C0, 0xc1); -+ usleep_range(1000, 1500); /* wait 1 ms */ -+ reg16_read(client, 0x0500, &priv->id[i]); ++ /* first 6 bytes are equal on all ov10640 */ ++ priv->id[i] = ov490_ov10640_read(client, 0x349e + i + 6); ++ if (priv->id[i]) ++ otp_bank0_allzero = 0; ++ } ++ ++ if (otp_bank0_allzero) { ++ ov490_ov10640_write(client, 0x3495, 0x41); /* bank#1 */ ++ ov490_ov10640_write(client, 0x349C, 1); ++ usleep_range(25000, 25500); /* wait 25 ms */ ++ ++ for (i = 0; i < 6; i++) ++ priv->id[i] = ov490_ov10640_read(client, 0x34ae + i); + } +#endif +} + -+static ssize_t ov495_otp_id_show(struct device *dev, ++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 ov495_priv *priv = to_ov495(client); ++ 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_ov495, S_IRUGO, ov495_otp_id_show, NULL); ++static DEVICE_ATTR(otp_id_ov490, S_IRUGO, ov490_otp_id_show, NULL); + -+static int ov495_initialize(struct i2c_client *client) ++static int ov490_initialize(struct i2c_client *client) +{ -+ struct ov495_priv *priv = to_ov495(client); ++ struct ov490_priv *priv = to_ov490(client); ++ u8 val = 0; + u8 pid = 0, ver = 0; -+ int ret = 0; ++ int ret = 0, timeout, retry_timeout = 3; ++ ++ if (priv->is_fixed_sensor) { ++ dev_info(&client->dev, "ov490/ov10640 fixed-sensor res %dx%d\n", priv->max_width, priv->max_height); ++ return 0; ++ } ++ ++ ov490_s_port(client, 1); + + /* check and show product ID and manufacturer ID */ + reg16_write(client, 0xFFFD, 0x80); + reg16_write(client, 0xFFFE, 0x80); + usleep_range(100, 150); /* wait 100 us */ -+ reg16_read(client, OV495_PID, &pid); -+ reg16_read(client, OV495_VER, &ver); ++ reg16_read(client, OV490_PID, &pid); ++ reg16_read(client, OV490_VER, &ver); + -+ if (OV495_VERSION(pid, ver) != OV495_VERSION_REG) { -+ dev_err(&client->dev, "Product ID error %x:%x\n", pid, ver); ++ if (OV490_VERSION(pid, ver) != OV490_VERSION_REG) { ++ dev_dbg(&client->dev, "Product ID error %x:%x\n", pid, ver); + ret = -ENODEV; + goto err; + } + -+ if (unlikely(force_conf_link)) ++ if (unlikely(conf_link)) + goto out; + -+#if 0 ++again: ++ /* Check if firmware booted by reading stream-on status */ ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x29); ++ usleep_range(100, 150); /* wait 100 us */ ++ for (timeout = 300; timeout > 0; timeout--) { ++ reg16_read(client, 0xd000, &val); ++ if (val == 0x0c) ++ break; ++ mdelay(1); ++ } ++ ++ /* wait firmware apps started by reading OV10640 ID */ ++ for (;timeout > 0; timeout--) { ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x5000, 0x01); ++ reg16_write(client, 0x5001, 0x30); ++ reg16_write(client, 0x5002, 0x0a); ++ reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0xC0, 0xc1); ++ reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(1000, 1500); /* wait 1 ms */ ++ reg16_read(client, 0x5000, &val); ++ if (val == 0xa6) ++ break; ++ mdelay(1); ++ } ++ ++ if (!timeout) { ++ dev_err(&client->dev, "Timeout firmware boot wait, retrying\n"); ++ /* reset OV10640 using RESETB pin controlled by OV490 GPIO0 */ ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x0050, 0x01); ++ reg16_write(client, 0x0054, 0x01); ++ reg16_write(client, 0x0058, 0x00); ++ mdelay(10); ++ reg16_write(client, 0x0058, 0x01); ++ /* reset OV490 using RESETB pin controlled by serializer */ ++ ov490_reset(client); ++ if (retry_timeout--) ++ goto again; ++ } ++ + /* read resolution used by current firmware */ + reg16_write(client, 0xFFFD, 0x80); + reg16_write(client, 0xFFFE, 0x82); + usleep_range(100, 150); /* wait 100 us */ -+ reg16_read(client, OV495_ISP_HSIZE_HIGH, &val); ++ reg16_read(client, OV490_ISP_HSIZE_HIGH, &val); + priv->max_width = val; -+ reg16_read(client, OV495_ISP_HSIZE_LOW, &val); ++ reg16_read(client, OV490_ISP_HSIZE_LOW, &val); + priv->max_width = (priv->max_width << 8) | val; -+ reg16_read(client, OV495_ISP_VSIZE_HIGH, &val); ++ reg16_read(client, OV490_ISP_VSIZE_HIGH, &val); + priv->max_height = val; -+ reg16_read(client, OV495_ISP_VSIZE_LOW, &val); ++ reg16_read(client, OV490_ISP_VSIZE_LOW, &val); + priv->max_height = (priv->max_height << 8) | val; -+#else -+ priv->max_width = 1920; -+ priv->max_height = 1080; -+#endif -+ -+ /* set virtual channel */ -+ ov495_regs_wizard[3].val = 0x1e | (priv->port << 6); + /* Program wizard registers */ -+ ov495_set_regs(client, ov495_regs_wizard, ARRAY_SIZE(ov495_regs_wizard)); ++ 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 */ -+ ov495_otp_id_read(client); ++ ov490_otp_id_read(client); + +out: -+ dev_info(&client->dev, "ov495/ov2775 PID %x%x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ dev_info(&client->dev, "ov490/ov10640 PID %x%x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", + pid, ver, priv->max_width, priv->max_height, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); +err: ++ ov490_s_port(client, 0); ++ + return ret; +} + -+static int ov495_parse_dt(struct device_node *np, struct ov495_priv *priv) ++static int ov490_parse_dt(struct device_node *np, struct ov490_priv *priv) +{ + struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); + int i; ++ const char *fixed_sensor; + struct device_node *endpoint = NULL, *rendpoint = NULL; + int tmp_addr = 0; + @@ -6360,63 +6098,88 @@ index 0000000..6dc0675 + + 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)) ++ if (!of_property_read_u32(rendpoint, "max9271-addr", &priv->max9271_addr) && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->max9286_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) { ++ if (of_property_read_u32(rendpoint->parent->parent, "maxim,resetb-gpio", &priv->gpio_resetb)) { ++ priv->gpio_resetb = -1; ++ } else { ++ if (of_property_read_bool(rendpoint->parent->parent, "maxim,resetb-active-high")) ++ priv->active_low_resetb = false; ++ else ++ priv->active_low_resetb = true; ++ } + break; ++ } + + if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && -+ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti954-ti9x3") && -+ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti954_addr) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti9x4") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti9x4_addr) && + !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) + break; + } + -+ if (!priv->ti960_addr && !priv->ti954_addr) { -+ dev_err(&client->dev, "deserializer does not present for OV495\n"); ++ if (!priv->max9286_addr && !priv->ti9x4_addr) { ++ dev_err(&client->dev, "deserializer does not present for OV490\n"); + return -EINVAL; + } + ++ ov490_s_port(client, 1); ++ + /* setup I2C translator address */ + tmp_addr = client->addr; -+ if (priv->ti960_addr) { -+ client->addr = priv->ti960_addr; /* Deserializer I2C address */ ++ if (priv->max9286_addr) { ++ client->addr = priv->max9271_addr; /* Serializer I2C address */ + -+ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ ++ 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 */ -+ 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 */ ++ }; ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x4_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, 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; + ++ if (!of_property_read_string(np, "maxim,fixed-sensor", &fixed_sensor) && ++ strcmp(fixed_sensor, "ov490") == 0) { ++ if (of_property_read_u32(np, "maxim,width", &priv->max_width)) ++ priv->max_width = 1280; ++ ++ if (of_property_read_u32(np, "maxim,height", &priv->max_height)) ++ priv->max_height = 966; ++ ++ priv->is_fixed_sensor = true; ++ } ++ ++ /* module params override dts */ ++ if (dvp_order) ++ priv->dvp_order = dvp_order; ++ if (max_width && max_height) { ++ priv->max_width = max_width; ++ priv->max_height = max_height; ++ priv->is_fixed_sensor = true; ++ } ++ + return 0; +} + -+static int ov495_probe(struct i2c_client *client, ++static int ov490_probe(struct i2c_client *client, + const struct i2c_device_id *did) +{ -+ struct ov495_priv *priv; ++ struct ov490_priv *priv; + struct v4l2_ctrl *ctrl; + int ret; + @@ -6424,36 +6187,47 @@ index 0000000..6dc0675 + if (!priv) + return -ENOMEM; + -+ v4l2_i2c_subdev_init(&priv->sd, client, &ov495_subdev_ops); ++ 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; ++ priv->red = 0x400; ++ priv->blue = 0x400; ++ priv->green_r = priv->red / 2; ++ priv->green_b = priv->blue / 2; ++ priv->awb = 1; + v4l2_ctrl_handler_init(&priv->hdl, 4); -+ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, + V4L2_CID_BRIGHTNESS, 0, 16, 1, 7); -+ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, + V4L2_CID_CONTRAST, 0, 16, 1, 7); -+ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, + V4L2_CID_SATURATION, 0, 7, 1, 2); -+ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, + V4L2_CID_HUE, 0, 23, 1, 12); -+ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, + V4L2_CID_GAMMA, -128, 128, 1, 0); -+ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, + V4L2_CID_SHARPNESS, 0, 10, 1, 3); -+ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, + V4L2_CID_AUTOGAIN, 0, 1, 1, priv->autogain); -+ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, + V4L2_CID_GAIN, 0, 0xffff, 1, priv->gain); -+ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_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_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, priv->autogain); ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_RED_BALANCE, 2, 0xf, 1, priv->red >> 8); ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_BLUE_BALANCE, 2, 0xf, 1, priv->blue >> 8); ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 1); ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, + V4L2_CID_VFLIP, 0, 1, 1, 0); -+ ctrl = v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ ctrl = v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, + V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 9); + if (ctrl) + ctrl->flags &= ~V4L2_CTRL_FLAG_READ_ONLY; @@ -6471,11 +6245,11 @@ index 0000000..6dc0675 + if (ret < 0) + goto cleanup; + -+ ret = ov495_parse_dt(client->dev.of_node, priv); ++ ret = ov490_parse_dt(client->dev.of_node, priv); + if (ret) + goto cleanup; + -+ ret = ov495_initialize(client); ++ ret = ov490_initialize(client); + if (ret < 0) + goto cleanup; + @@ -6488,7 +6262,7 @@ index 0000000..6dc0675 + if (ret) + goto cleanup; + -+ if (device_create_file(&client->dev, &dev_attr_otp_id_ov495) != 0) { ++ 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; + } @@ -6501,18 +6275,18 @@ index 0000000..6dc0675 + media_entity_cleanup(&priv->sd.entity); + v4l2_ctrl_handler_free(&priv->hdl); + v4l2_device_unregister_subdev(&priv->sd); -+#ifdef CONFIG_SOC_CAMERA_OV495_OV2775 ++#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 ov495_remove(struct i2c_client *client) ++static int ov490_remove(struct i2c_client *client) +{ -+ struct ov495_priv *priv = i2c_get_clientdata(client); ++ struct ov490_priv *priv = i2c_get_clientdata(client); + -+ device_remove_file(&client->dev, &dev_attr_otp_id_ov495); ++ 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); @@ -6521,45 +6295,45 @@ index 0000000..6dc0675 + return 0; +} + -+#ifdef CONFIG_SOC_CAMERA_OV495_OV2775 -+static const struct i2c_device_id ov495_id[] = { -+ { "ov495-ov2775", 0 }, ++#ifdef CONFIG_SOC_CAMERA_OV490_OV10640 ++static const struct i2c_device_id ov490_id[] = { ++ { "ov490-ov10640", 0 }, + { } +}; -+MODULE_DEVICE_TABLE(i2c, ov495_id); ++MODULE_DEVICE_TABLE(i2c, ov490_id); + -+static const struct of_device_id ov495_of_ids[] = { -+ { .compatible = "ovti,ov495-ov2775", }, ++static const struct of_device_id ov490_of_ids[] = { ++ { .compatible = "ovti,ov490-ov10640", }, + { } +}; -+MODULE_DEVICE_TABLE(of, ov495_of_ids); ++MODULE_DEVICE_TABLE(of, ov490_of_ids); + -+static struct i2c_driver ov495_i2c_driver = { ++static struct i2c_driver ov490_i2c_driver = { + .driver = { -+ .name = "ov495-ov2775", -+ .of_match_table = ov495_of_ids, ++ .name = "ov490-ov10640", ++ .of_match_table = ov490_of_ids, + }, -+ .probe = ov495_probe, -+ .remove = ov495_remove, -+ .id_table = ov495_id, ++ .probe = ov490_probe, ++ .remove = ov490_remove, ++ .id_table = ov490_id, +}; + -+module_i2c_driver(ov495_i2c_driver); ++module_i2c_driver(ov490_i2c_driver); + -+MODULE_DESCRIPTION("SoC Camera driver for OV495-OV2775"); ++MODULE_DESCRIPTION("SoC Camera driver for OV490-OV10640"); +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 +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..3f53689 +index 0000000..b22e93e --- /dev/null -+++ b/drivers/media/i2c/soc_camera/ov495_ov2775.h -@@ -0,0 +1,23 @@ ++++ b/drivers/media/i2c/soc_camera/ov490_ov10640.h +@@ -0,0 +1,102 @@ +/* -+ * OmniVision ov495-ov2775 sensor camera wizard 1280x1080@30/UYVY/BT601/8bit ++ * OmniVision ov490-ov10640 sensor camera wizard 1280x1080@30/UYVY/BT601/8bit + * -+ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * 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 @@ -6567,26 +6341,105 @@ index 0000000..3f53689 + * option) any later version. + */ + -+struct ov495_reg { ++//#define OV490_DISPLAY_PATTERN ++ ++struct ov490_reg { + u16 reg; + u8 val; +}; + -+static struct ov495_reg ov495_regs_wizard[] = { -+{0x3516, 0x00}, /* unlock write */ -+{0xFFFD, 0x80}, -+{0xFFFE, 0x20}, -+{0x8017, 0x1e | (0 << 6)}, -+{0x7c10, 0x01}, /* UYVY */ ++static const struct ov490_reg ov490_regs_wizard[] = { ++/* The following registers should match firmware */ ++{0xfffd, 0x80}, ++{0xfffe, 0x82}, ++{0x0071, 0x11}, ++{0x0075, 0x11}, ++{0xfffe, 0x29}, ++{0x6010, 0x01}, ++/* ov490 EMB line disable in YUV and RAW data, NOTE: EMB line is still used in ISP and sensor */ ++{0xe000, 0x14}, ++#if 0 /* do not disable EMB line in ISP! */ ++{0x4017, 0x00}, ++#endif ++{0xfffe, 0x28}, ++{0x6000, 0x04}, ++{0x6004, 0x00}, ++{0x6008, 0x00}, // PCLK polarity - useless due to silicon bug -> use 0x808000bb register ++{0xfffe, 0x80}, ++{0x0091, 0x00}, ++{0x00bb, 0x1d}, // bit[3]=0 - PCLK polarity workaround ++/* ov10640 EMB line disable */ ++#if 0 /* do not disable EMB line in sensor! */ ++{0xfffe, 0x19}, ++{0x5000, 0x00}, ++{0x5001, 0x30}, ++{0x5002, 0x91}, ++{0x5003, 0x08}, ++{0xfffe, 0x80}, ++{0x00c0, 0xc1}, ++#endif ++/* Ov490 FSIN: app_fsin_from_fsync */ ++{0xfffe, 0x85}, ++{0x0008, 0x00}, ++{0x0009, 0x01}, ++{0x000A, 0x05}, // fsin0 src ++{0x000B, 0x00}, ++{0x0030, 0x02}, // fsin0_delay ++{0x0031, 0x00}, ++{0x0032, 0x00}, ++{0x0033, 0x00}, ++{0x0038, 0x02}, // fsin1_delay ++{0x0039, 0x00}, ++{0x003A, 0x00}, ++{0x003B, 0x00}, ++{0x0070, 0x2C}, // fsin0_length ++{0x0071, 0x01}, ++{0x0072, 0x00}, ++{0x0073, 0x00}, ++{0x0074, 0x64}, // fsin1_length ++{0x0075, 0x00}, ++{0x0076, 0x00}, ++{0x0077, 0x00}, ++{0x0000, 0x14}, ++{0x0001, 0x00}, ++{0x0002, 0x00}, ++{0x0003, 0x00}, ++{0x0004, 0x32}, // load fsin0,load fsin1,load other, it will be cleared automatically. ++{0x0005, 0x00}, ++{0x0006, 0x00}, ++{0x0007, 0x00}, ++{0xfffe, 0x80}, ++{0x0081, 0x00}, // 03;SENSOR FSIN ++/* ov10640 FSIN */ ++{0xfffe, 0x19}, ++{0x5000, 0x00}, ++{0x5001, 0x30}, ++{0x5002, 0x8c}, ++{0x5003, 0xb2}, ++{0xfffe, 0x80}, ++{0x00c0, 0xc1}, ++/* ov10640 HFLIP=1 by default */ ++{0xfffe, 0x19}, ++{0x5000, 0x01}, ++{0x5001, 0x00}, ++{0xfffe, 0x80}, ++{0x00c0, 0xdc}, ++#ifdef OV490_DISPLAY_PATTERN ++{0xfffd, 0x80}, ++{0xfffe, 0x19}, ++{0x5000, 0x02}, ++{0xfffe, 0x80}, ++{0x00c0, 0xd6}, ++#endif +}; -diff --git a/drivers/media/i2c/soc_camera/ti954_ti9x3.c b/drivers/media/i2c/soc_camera/ti954_ti9x3.c +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..ff84128 +index 0000000..e53c482 --- /dev/null -+++ b/drivers/media/i2c/soc_camera/ti954_ti9x3.c -@@ -0,0 +1,439 @@ ++++ b/drivers/media/i2c/soc_camera/ov495_ov2775.c +@@ -0,0 +1,639 @@ +/* -+ * TI ti954-(ti913/ti953) FPDLinkIII driver ++ * OmniVision ov495-ov2775 sensor camera driver + * + * Copyright (C) 2017 Cogent Embedded, Inc. + * @@ -6596,310 +6449,454 @@ index 0000000..ff84128 + * option) any later version. + */ + -+#include -+#include -+#include -+#include -+#include -+#include -+#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "ov495_ov2775.h" ++ ++#define OV495_I2C_ADDR 0x24 ++ ++#define OV495_PID 0x300a ++#define OV495_VER 0x300b ++#define OV495_VERSION_REG 0x0495 ++#define OV495_VERSION(pid, ver) (((pid) << 8) | ((ver) & 0xff)) ++ ++#define OV495_ISP_HSIZE_LOW 0x60 ++#define OV495_ISP_HSIZE_HIGH 0x61 ++#define OV495_ISP_VSIZE_LOW 0x62 ++#define OV495_ISP_VSIZE_HIGH 0x63 ++ ++struct ov495_priv { ++ struct v4l2_subdev sd; ++ struct v4l2_ctrl_handler hdl; ++ struct media_pad pad; ++ struct v4l2_rect rect; ++ int max_width; ++ int max_height; ++ int init_complete; ++ u8 id[6]; ++ int exposure; ++ int gain; ++ int autogain; ++ /* serializers */ ++ int max9286_addr; ++ int max9271_addr; ++ int ti9x4_addr; ++ int ti9x3_addr; ++ int port; ++ int gpio_resetb; ++ int gpio_fsin; ++ ++}; + -+#include -+#include -+#include -+#include ++static int force_conf_link; + -+#include "ti9x4_ti9x3.h" ++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); + -+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; -+ int poc_delay; -+ atomic_t use_count; -+ struct i2c_client *client; -+ int ti9x3_addr_map[4]; -+ char chip_id[6]; -+ struct regulator *poc_supply[4]; /* PoC power supply */ -+ int xtal_gpio; -+}; ++static inline struct ov495_priv *to_ov495(const struct i2c_client *client) ++{ ++ return container_of(i2c_get_clientdata(client), struct ov495_priv, sd); ++} + -+static int indirect_write(struct i2c_client *client, unsigned int page, u8 reg, u8 val) ++static int ov495_set_regs(struct i2c_client *client, ++ const struct ov495_reg *regs, int nr_regs) +{ -+ if (page > 7) -+ return -EINVAL; ++ int i; + -+ reg8_write(client, 0xb0, page << 2); -+ reg8_write(client, 0xb1, reg); -+ reg8_write(client, 0xb2, val); ++ 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; +} + -+#if 0 -+static int indirect_read(struct i2c_client *client, unsigned int page, u8 reg, u8 *val) ++static int ov495_s_stream(struct v4l2_subdev *sd, int enable) +{ -+ if (page > 7) ++ 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; + -+ reg8_write(client, 0xb0, page << 2); -+ reg8_write(client, 0xb1, reg); -+ reg8_read(client, 0xb2, val); ++ 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; +} -+#endif -+ -+static int poc_delay; -+module_param(poc_delay, int, 0644); -+MODULE_PARM_DESC(poc_delay, " Delay in ms after POC enable (default: 0 ms) */"); + -+static void ti954_ti9x3_read_chipid(struct i2c_client *client) ++static int ov495_set_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) +{ -+ struct ti954_ti9x3_priv *priv = i2c_get_clientdata(client); ++ struct v4l2_mbus_framefmt *mf = &format->format; + -+ /* 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'; ++ 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 void ti954_ti9x3_initial_setup(struct i2c_client *client) ++static int ov495_enum_mbus_code(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_mbus_code_enum *code) +{ -+ 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 (code->pad || code->index > 0) ++ return -EINVAL; + -+ 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!!) */ -+ } ++ code->code = MEDIA_BUS_FMT_YUYV8_2X8; + -+ reg8_write(client, 0x32, 0x01); /* Select TX (CSI) port 0 */ -+ reg8_write(client, 0x33, ((priv->lanes - 1) ^ 0x3) << 4); /* disable CSI output, set CSI lane count, non-continuous CSI mode */ -+ reg8_write(client, 0x20, 0xf0); /* disable port forwarding */ -+#if 0 -+ /* FrameSync setup for REFCLK=25MHz, FPS=30: period_counts=1/2/FPS*25MHz =1/2/30*25Mhz =416666 -> FS_TIME=416666 */ -+ /* FrameSync setup for REFCLK=22.5MHz, FPS=30: period_counts=1/2/FPS*22.5Mhz=1/2/30*22.5Mhz=375000 -> FS_TIME=375000 */ -+// #define FS_TIME (priv->csi_rate == 1450 ? 376000 : 417666) -+ #define FS_TIME (priv->csi_rate == 1450 ? 385000 : 428000) // FPS=29.2 (new vendor's firmware AWB restriction?) -+ reg8_write(client, 0x1a, FS_TIME >> 16); /* FrameSync time 24bit */ -+ reg8_write(client, 0x1b, (FS_TIME >> 8) & 0xff); -+ reg8_write(client, 0x1c, FS_TIME & 0xff); -+ reg8_write(client, 0x18, 0x43); /* Enable FrameSync, 50/50 mode, Frame clock from 25MHz */ -+#else -+ /* FrameSync setup for REFCLK=25MHz, FPS=30: period_counts=1/FPS/12mks=1/30/12e-6=2777 -> HI=2, LO=2775 */ -+ /* FrameSync setup for REFCLK=22.5MHz, FPS=30: period_counts=1/FPS/13.333mks=1/30/13.333e-6=2500 -> HI=2, LO=2498 */ -+ #define FS_TIME (priv->csi_rate == 1450 ? (2498+15) : (2775+15)) -+ reg8_write(client, 0x19, 2 >> 8); /* FrameSync high time MSB */ -+ reg8_write(client, 0x1a, 2 & 0xff); /* FrameSync high time LSB */ -+ reg8_write(client, 0x1b, FS_TIME >> 8); /* FrameSync low time MSB */ -+ reg8_write(client, 0x1c, FS_TIME & 0xff); /* FrameSync low time LSB */ -+ reg8_write(client, 0x18, 0x01); /* Enable FrameSync, HI/LO mode, Frame clock from port0 */ -+#endif ++ return 0; +} + -+//#define SENSOR_ID 0x30 // ov10635 -+//#define SENSOR_ID 0x24 // ov490 -+ -+static void ti954_ti9x3_fpdlink3_setup(struct i2c_client *client, int idx) ++static int ov495_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) +{ -+ struct ti954_ti9x3_priv *priv = i2c_get_clientdata(client); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov495_priv *priv = to_ov495(client); + -+ /* FPDLinkIII setup */ -+ client->addr = priv->des_addr; /* TI954 I2C */ -+ reg8_write(client, 0x4c, (idx << 4) | (1 << idx)); /* Select RX port number */ -+ usleep_range(2000, 2500); /* wait 2ms */ -+ reg8_write(client, 0x58, 0x58); /* Back channel: pass-through/backchannel/CRC enable, Freq=2.5Mbps */ -+ reg8_write(client, 0x5c, priv->ti9x3_addr_map[idx] << 1); /* TI9X3 I2C addr */ -+// reg8_write(client, 0x5d, SENSOR_ID << 1); /* SENSOR I2C native - must be set by sensor driver */ -+// reg8_write(client, 0x65, (0x60 + idx) << 1); /* SENSOR I2C translated - must be set by sensor driver */ -+ if (strcmp(priv->cable_mode, "coax") == 0) { -+ reg8_write(client, 0x6d, 0x7f); /* Coax, RAW10 */ -+ } else if (strcmp(priv->cable_mode, "stp") == 0) { -+ reg8_write(client, 0x6d, 0x78); /* STP, CSI */ -+ } -+ reg8_write(client, 0x70, (idx << 6) | 0x1e); /* CSI data type: yuv422 8-bit, assign VC */ -+ reg8_write(client, 0x7c, 0x81); /* BIT(7) - magic to Use RAW10 as 8-bit mode */ -+ reg8_write(client, 0x6e, 0x88); /* Sensor reset: backchannel GPIO0/GPIO1 set low */ ++ 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 ti954_ti9x3_initialize(struct i2c_client *client) ++static int ov495_set_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) +{ -+ struct ti954_ti9x3_priv *priv = i2c_get_clientdata(client); -+ int idx; ++ struct v4l2_rect *rect = &sel->r; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov495_priv *priv = to_ov495(client); + -+ 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); ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || ++ sel->target != V4L2_SEL_TGT_CROP) ++ return -EINVAL; + -+ ti954_ti9x3_initial_setup(client); ++ rect->left = ALIGN(rect->left, 2); ++ rect->top = ALIGN(rect->top, 2); ++ rect->width = ALIGN(rect->width, 2); ++ rect->height = ALIGN(rect->height, 2); + -+ for (idx = 0; idx < priv->links; idx++) { -+ if (!IS_ERR(priv->poc_supply[idx])) { -+ if (regulator_enable(priv->poc_supply[idx])) -+ dev_err(&client->dev, "fail to enable POC%d regulator\n", idx); -+ mdelay(priv->poc_delay); -+ } ++ 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; + -+ ti954_ti9x3_fpdlink3_setup(client, idx); ++ 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; + } ++} + -+ client->addr = priv->des_addr; ++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 ti954_ti9x3_g_register(struct v4l2_subdev *sd, -+ struct v4l2_dbg_register *reg) ++static int ov495_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; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); + int ret; + u8 val = 0; + -+ ret = reg8_read(client, (u8)reg->reg, &val); ++ ret = reg16_read(client, (u16)reg->reg, &val); + if (ret < 0) + return ret; + + reg->val = val; -+ reg->size = sizeof(u8); ++ reg->size = sizeof(u16); + + return 0; +} + -+static int ti954_ti9x3_s_register(struct v4l2_subdev *sd, -+ const struct v4l2_dbg_register *reg) ++static int ov495_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; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ int ret; + -+ return reg8_write(client, (u8)reg->reg, (u8)reg->val); ++ 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 int ti954_ti9x3_s_power(struct v4l2_subdev *sd, int on) ++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 ti954_ti9x3_priv *priv = v4l2_get_subdevdata(sd); -+ struct i2c_client *client = priv->client; ++ 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 (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 */ ++ if (!priv->init_complete) ++ return 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_BRIGHTNESS: ++ break; ++ case V4L2_CID_CONTRAST: ++ break; ++ case V4L2_CID_SATURATION: ++ break; ++ case V4L2_CID_HUE: ++ break; ++ case V4L2_CID_GAMMA: ++ break; ++ case V4L2_CID_SHARPNESS: ++ break; ++ case V4L2_CID_AUTOGAIN: ++ case V4L2_CID_GAIN: ++ case V4L2_CID_EXPOSURE: ++ break; ++ case V4L2_CID_HFLIP: ++ ret = reg16_write(client, 0x3516, 0x00); ++ ret |= reg16_write(client, 0x0ffc, 0x00); ++ ret |= reg16_write(client, 0x0500, ctrl->val); ++ ret |= reg16_write(client, 0x0501, 0x00); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x30C0, 0xdc); ++ ret |= reg16_write(client, 0x3516, 0x01); ++ break; ++ case V4L2_CID_VFLIP: ++ ret = reg16_write(client, 0x3516, 0x00); ++ ret |= reg16_write(client, 0x0ffc, 0x00); ++ ret |= reg16_write(client, 0x0500, ctrl->val); ++ ret |= reg16_write(client, 0x0501, 0x01); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x30C0, 0xdc); ++ ret |= reg16_write(client, 0x3516, 0x01); ++ break; ++ case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: ++ ret = 0; ++ break; + } + -+ return 0; ++ return ret; +} + -+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 */ ++static const struct v4l2_ctrl_ops ov495_ctrl_ops = { ++ .s_ctrl = ov495_s_ctrl, ++}; + -+ return 0; -+} ++static struct v4l2_subdev_video_ops ov495_video_ops = { ++ .s_stream = ov495_s_stream, ++ .g_mbus_config = ov495_g_mbus_config, ++}; + -+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 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 ti954_ti9x3_subdev_ops = { -+ .core = &ti954_ti9x3_subdev_core_ops, ++static struct v4l2_subdev_ops ov495_subdev_ops = { ++ .core = &ov495_core_ops, ++ .video = &ov495_video_ops, ++ .pad = &ov495_subdev_pad_ops, +}; + -+static int ti954_ti9x3_parse_dt(struct i2c_client *client) ++static void ov495_otp_id_read(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; ++ struct ov495_priv *priv = to_ov495(client); ++ int i; + -+ if (of_property_read_u32(np, "ti,links", &priv->links)) -+ priv->links = 2; ++#if 0 ++ /* read camera id from ov495 OTP memory */ ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x20); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x7384, 0x40); /* manual mode, bank#0 */ ++ reg16_write(client, 0x7381, 1); /* start OTP read */ + -+ if (of_property_read_u32(np, "ti,lanes", &priv->lanes)) -+ priv->lanes = 4; ++ usleep_range(25000, 26000); /* wait 25 ms */ + -+ priv->xtal_gpio = of_get_gpio(np, 0); -+ if (priv->xtal_gpio > 0) { -+ err = devm_gpio_request_one(&client->dev, priv->xtal_gpio, GPIOF_OUT_INIT_LOW, dev_name(&client->dev)); -+ if (err) -+ dev_err(&client->dev, "cannot request XTAL gpio %d: %d\n", priv->xtal_gpio, err); -+ else -+ mdelay(250); ++ for (i = 0; i < 6; i++) ++ reg16_read(client, 0x7300 + i + 4, &priv->id[i]); ++#else ++ /* read camera id from ov2775 OTP memory */ ++ reg16_write(client, 0x3516, 0x00); /* unlock write */ ++ reg16_write(client, 0x0FFC, 0); ++ reg16_write(client, 0x0500, 0x00); /* write 0x34a1 -> 1 */ ++ reg16_write(client, 0x0501, 0x34); ++ reg16_write(client, 0x0502, 0xa1); ++ reg16_write(client, 0x0503, 1); ++ reg16_write(client, 0x30C0, 0xc1); ++ ++ usleep_range(25000, 25500); /* wait 25 ms */ ++ ++ for (i = 0; i < 6; i++) { ++ reg16_write(client, 0x3516, 0x00); /* unlock write */ ++ reg16_write(client, 0x0500, 0x01); /* read (0x7a00 + i) */ ++ reg16_write(client, 0x0501, 0x7a); ++ reg16_write(client, 0x0502, 0x00 + i + (i < 3 ? 11 : 3)); /* take bytes 11,12,13,6,7,8 */ ++ reg16_write(client, 0x30C0, 0xc1); ++ usleep_range(1000, 1500); /* wait 1 ms */ ++ reg16_read(client, 0x0500, &priv->id[i]); + } ++#endif ++} + -+ 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; ++static ssize_t ov495_otp_id_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(to_i2c_client(dev)); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov495_priv *priv = to_ov495(client); ++ ++ return snprintf(buf, 32, "%02x:%02x:%02x:%02x:%02x:%02x\n", ++ priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++} ++ ++static DEVICE_ATTR(otp_id_ov495, S_IRUGO, ov495_otp_id_show, NULL); ++ ++static int ov495_initialize(struct i2c_client *client) ++{ ++ struct ov495_priv *priv = to_ov495(client); ++ u8 pid = 0, ver = 0; ++ int ret = 0; ++ ++ /* check and show product ID and manufacturer ID */ ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_read(client, OV495_PID, &pid); ++ reg16_read(client, OV495_VER, &ver); ++ ++ if (OV495_VERSION(pid, ver) != OV495_VERSION_REG) { ++ dev_err(&client->dev, "Product ID error %x:%x\n", pid, ver); ++ ret = -ENODEV; ++ goto err; + } + -+ ti954_ti9x3_read_chipid(client); ++ if (unlikely(force_conf_link)) ++ goto out; + -+ 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 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 + -+ if (!of_property_read_u32(np, "ti,sensor_delay", &sensor_delay)) -+ mdelay(sensor_delay); -+ if (of_property_read_string(np, "ti,forwarding-mode", &priv->forwarding_mode)) -+ priv->forwarding_mode = forwarding_mode_default; -+ if (of_property_read_string(np, "ti,cable-mode", &priv->cable_mode)) -+ priv->cable_mode = cable_mode_default; -+ if (of_property_read_u32(np, "ti,poc-delay", &priv->poc_delay)) -+ priv->poc_delay = 50; ++ /* set virtual channel */ ++ ov495_regs_wizard[3].val = 0x1e | (priv->port << 6); ++ /* Program wizard registers */ ++ ov495_set_regs(client, ov495_regs_wizard, ARRAY_SIZE(ov495_regs_wizard)); ++ /* Read OTP IDs */ ++ ov495_otp_id_read(client); + -+ /* module params override dts */ -+ if (poc_delay) -+ priv->poc_delay = poc_delay; ++out: ++ dev_info(&client->dev, "ov495/ov2775 PID %x%x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, ver, priv->max_width, priv->max_height, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++err: ++ return ret; ++} ++ ++static int ov495_parse_dt(struct device_node *np, struct ov495_priv *priv) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); ++ int i; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ int tmp_addr = 0; + + for (i = 0; ; i++) { + endpoint = of_graph_get_next_endpoint(np, endpoint); @@ -6908,130 +6905,186 @@ index 0000000..ff84128 + + 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; ++ ++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti9x4") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti9x4_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ } ++ ++ if (!priv->ti9x4_addr) { ++ dev_err(&client->dev, "deserializer does not present for OV495\n"); ++ return -EINVAL; ++ } + -+ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); -+ if (!rendpoint) -+ continue; ++ /* setup I2C translator address */ ++ tmp_addr = client->addr; ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x4_addr; /* Deserializer I2C address */ + -+ 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); -+ } ++ 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 */ + -+ dvp_order_prop = of_find_property(endpoint, "dvp-order", NULL); -+ if (dvp_order_prop) -+ of_update_property(rendpoint, dvp_order_prop); ++ 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 ti954_ti9x3_probe(struct i2c_client *client, -+ const struct i2c_device_id *did) ++static int ov495_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) +{ -+ struct ti954_ti9x3_priv *priv; -+ int err, i; -+ char supply_name[10]; ++ struct ov495_priv *priv; ++ struct v4l2_ctrl *ctrl; ++ int ret; + + 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); ++ v4l2_i2c_subdev_init(&priv->sd, client, &ov495_subdev_ops); ++ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; + -+ err = ti954_ti9x3_parse_dt(client); -+ if (err) -+ goto out; ++ priv->exposure = 0x100; ++ priv->gain = 0x100; ++ priv->autogain = 1; ++ v4l2_ctrl_handler_init(&priv->hdl, 4); ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ V4L2_CID_BRIGHTNESS, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ V4L2_CID_CONTRAST, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ V4L2_CID_SATURATION, 0, 7, 1, 2); ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ V4L2_CID_HUE, 0, 23, 1, 12); ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ V4L2_CID_GAMMA, -128, 128, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ V4L2_CID_SHARPNESS, 0, 10, 1, 3); ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ V4L2_CID_AUTOGAIN, 0, 1, 1, priv->autogain); ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ V4L2_CID_GAIN, 0, 0xffff, 1, priv->gain); ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ V4L2_CID_EXPOSURE, 0, 0xffff, 1, priv->exposure); ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ ctrl = v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 9); ++ if (ctrl) ++ ctrl->flags &= ~V4L2_CTRL_FLAG_READ_ONLY; ++ priv->sd.ctrl_handler = &priv->hdl; + -+ for (i = 0; i < 4; i++) { -+ sprintf(supply_name, "POC%d", i); -+ priv->poc_supply[i] = devm_regulator_get_optional(&client->dev, supply_name); -+ } ++ ret = priv->hdl.error; ++ if (ret) ++ goto cleanup; + -+ err = ti954_ti9x3_initialize(client); -+ if (err < 0) -+ goto out; ++ v4l2_ctrl_handler_setup(&priv->hdl); + -+ 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]; ++ 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; + -+ snprintf(priv->sd[i].name, V4L2_SUBDEV_NAME_SIZE, "%s %d-%04x", -+ client->dev.driver->name, i2c_adapter_id(client->adapter), -+ client->addr); ++ ret = ov495_parse_dt(client->dev.of_node, priv); ++ if (ret) ++ goto cleanup; + -+ err = v4l2_async_register_subdev(&priv->sd[i]); -+ if (err < 0) -+ goto out; ++ 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; + } + -+out: -+ return err; ++ 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 ti954_ti9x3_remove(struct i2c_client *client) ++static int ov495_remove(struct i2c_client *client) +{ -+ struct ti954_ti9x3_priv *priv = i2c_get_clientdata(client); -+ int i; ++ struct ov495_priv *priv = i2c_get_clientdata(client); + -+ for (i = 0; i < priv->links; i++) { -+ v4l2_async_unregister_subdev(&priv->sd[i]); -+ v4l2_device_unregister_subdev(&priv->sd[i]); -+ } ++ 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; +} + -+static const struct of_device_id ti954_ti9x3_dt_ids[] = { -+ { .compatible = "ti,ti954-ti9x3" }, -+ {}, ++#ifdef CONFIG_SOC_CAMERA_OV495_OV2775 ++static const struct i2c_device_id ov495_id[] = { ++ { "ov495-ov2775", 0 }, ++ { } +}; -+MODULE_DEVICE_TABLE(of, ti954_ti9x3_dt_ids); ++MODULE_DEVICE_TABLE(i2c, ov495_id); + -+static const struct i2c_device_id ti954_ti9x3_id[] = { -+ { "ti954_ti9x3", 0 }, ++static const struct of_device_id ov495_of_ids[] = { ++ { .compatible = "ovti,ov495-ov2775", }, + { } +}; -+MODULE_DEVICE_TABLE(i2c, ti954_ti9x3_id); ++MODULE_DEVICE_TABLE(of, ov495_of_ids); + -+static struct i2c_driver ti954_ti9x3_i2c_driver = { ++static struct i2c_driver ov495_i2c_driver = { + .driver = { -+ .name = "ti954_ti9x3", -+ .of_match_table = of_match_ptr(ti954_ti9x3_dt_ids), ++ .name = "ov495-ov2775", ++ .of_match_table = ov495_of_ids, + }, -+ .probe = ti954_ti9x3_probe, -+ .remove = ti954_ti9x3_remove, -+ .id_table = ti954_ti9x3_id, ++ .probe = ov495_probe, ++ .remove = ov495_remove, ++ .id_table = ov495_id, +}; + -+module_i2c_driver(ti954_ti9x3_i2c_driver); ++module_i2c_driver(ov495_i2c_driver); + -+MODULE_DESCRIPTION("FPDLinkIII driver for TI954-TI9X3"); ++MODULE_DESCRIPTION("SoC Camera driver for OV495-OV2775"); +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 ++#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..8393392 +index 0000000..3f53689 --- /dev/null -+++ b/drivers/media/i2c/soc_camera/ti964_ti9x3.c -@@ -0,0 +1,408 @@ ++++ b/drivers/media/i2c/soc_camera/ov495_ov2775.h +@@ -0,0 +1,23 @@ +/* -+ * TI (ti964/ti960)-(ti913/ti953) FPDLinkIII driver ++ * OmniVision ov495-ov2775 sensor camera wizard 1280x1080@30/UYVY/BT601/8bit + * + * Copyright (C) 2017 Cogent Embedded, Inc. + * @@ -7041,6 +7094,35 @@ index 0000000..8393392 + * option) any later version. + */ + ++struct ov495_reg { ++ u16 reg; ++ u8 val; ++}; ++ ++static struct ov495_reg ov495_regs_wizard[] = { ++{0x3516, 0x00}, /* unlock write */ ++{0xFFFD, 0x80}, ++{0xFFFE, 0x20}, ++{0x8017, 0x1e | (0 << 6)}, ++{0x7c10, 0x01}, /* UYVY */ ++}; +diff --git a/drivers/media/i2c/soc_camera/ti9x4.c b/drivers/media/i2c/soc_camera/ti9x4.c +new file mode 100644 +index 0000000..aac892b +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ti9x4.c +@@ -0,0 +1,520 @@ ++/* ++ * TI DS90UB954/960/964 FPDLinkIII driver ++ * ++ * Copyright (C) 2017-2018 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 +#include +#include @@ -7054,9 +7136,9 @@ index 0000000..8393392 +#include +#include + -+#include "ti9x4_ti9x3.h" ++#include "ti9x4.h" + -+struct ti964_ti9x3_priv { ++struct ti9x4_priv { + struct v4l2_subdev sd[4]; + struct device_node *sd_of_node[4]; + int des_addr; @@ -7064,22 +7146,72 @@ index 0000000..8393392 + int lanes; + int csi_rate; + const char *forwarding_mode; -+ const char *cable_mode; ++ int is_coax; ++ int dvp_bus; ++ int hsync; ++ int vsync; + int poc_delay; + atomic_t use_count; + struct i2c_client *client; + int ti9x3_addr_map[4]; + char chip_id[6]; ++ int ser_id; + struct regulator *poc_supply[4]; /* PoC power supply */ +}; + ++static int ser_id; ++module_param(ser_id, int, 0644); ++MODULE_PARM_DESC(ser_id, " Serializer ID (default: TI913)"); ++ ++static int is_stp; ++module_param(is_stp, int, 0644); ++MODULE_PARM_DESC(is_stp, " STP cable (default: Coax cable)"); ++ ++static int dvp_bus = 8; ++module_param(dvp_bus, int, 0644); ++MODULE_PARM_DESC(dvp_bus, " DVP/CSI over FPDLink (default: DVP 8-bit)"); ++ ++static int hsync; ++module_param(hsync, int, 0644); ++MODULE_PARM_DESC(hsync, " HSYNC invertion (default: 0 - not inverted)"); ++ ++static int vsync = 1; ++module_param(vsync, int, 0644); ++MODULE_PARM_DESC(vsync, " VSYNC invertion (default: 1 - inverted)"); ++ +static int poc_delay; +module_param(poc_delay, int, 0644); -+MODULE_PARM_DESC(poc_delay, " Delay in ms after POC enable (default: 0 ms) */"); ++MODULE_PARM_DESC(poc_delay, " Delay in ms after POC enable (default: 0 ms)"); ++ ++#ifdef TI954_SILICON_ERRATA ++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; ++} ++ ++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 ti964_ti9x3_read_chipid(struct i2c_client *client) ++static void ti9x4_read_chipid(struct i2c_client *client) +{ -+ struct ti964_ti9x3_priv *priv = i2c_get_clientdata(client); ++ struct ti9x4_priv *priv = i2c_get_clientdata(client); + + /* Chip ID */ + reg8_read(client, 0xf1, &priv->chip_id[0]); @@ -7090,12 +7222,12 @@ index 0000000..8393392 + priv->chip_id[5] = '\0'; +} + -+static void ti964_ti9x3_initial_setup(struct i2c_client *client) ++static void ti9x4_initial_setup(struct i2c_client *client) +{ -+ struct ti964_ti9x3_priv *priv = i2c_get_clientdata(client); ++ struct ti9x4_priv *priv = i2c_get_clientdata(client); + + /* Initial setup */ -+ client->addr = priv->des_addr; /* TI964 I2C */ ++ client->addr = priv->des_addr; /* TI9x4 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 */ @@ -7141,7 +7273,7 @@ index 0000000..8393392 + reg8_write(client, 0x19, 2 >> 8); /* FrameSync high time MSB */ + reg8_write(client, 0x1a, 2 & 0xff); /* FrameSync high time LSB */ + reg8_write(client, 0x1b, FS_TIME >> 8); /* FrameSync low time MSB */ -+ reg8_write(client, 0x1c, FS_TIME & 0xff); /* FrameSync low time LSB */ ++ reg8_write(client, 0x1c, FS_TIME & 0xff); /* FrameSync low time LSB */ + reg8_write(client, 0x18, 0x01); /* Enable FrameSync, HI/LO mode, Frame clock from port0 */ +#endif +} @@ -7149,37 +7281,73 @@ index 0000000..8393392 +//#define SENSOR_ID 0x30 // ov10635 +//#define SENSOR_ID 0x24 // ov490 + -+static void ti964_ti9x3_fpdlink3_setup(struct i2c_client *client, int idx) ++static void ti9x4_fpdlink3_setup(struct i2c_client *client, int idx) +{ -+ struct ti964_ti9x3_priv *priv = i2c_get_clientdata(client); ++ struct ti9x4_priv *priv = i2c_get_clientdata(client); ++ u8 port_config = 0x78; ++ u8 port_config2 = 0; + + /* FPDLinkIII setup */ -+ client->addr = priv->des_addr; /* TI964 I2C */ ++ client->addr = priv->des_addr; /* TI9x4 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 */ ++ ++ switch (priv->ser_id) { ++ case TI913_ID: ++ reg8_write(client, 0x58, 0x58); /* Back channel: Freq=2.5Mbps */ ++ break; ++ case TI953_ID: ++ reg8_write(client, 0x58, 0x5e); /* Back channel: Freq=50Mbps */ ++ break; ++ default: ++ break; ++ } ++ + 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 */ ++ ++ if (priv->is_coax) ++ port_config |= 0x04; /* Coax */ ++ else ++ port_config |= 0x00; /* STP */ ++ ++ switch (priv->dvp_bus) { ++ case 8: ++ port_config2 |= 0x80; /* RAW10 as 8-bit prosessing using upper bits */ ++ /* fall through */ ++ case 10: ++ port_config |= 0x03; /* DVP over FPDLink (TI913 compatible) RAW10/RAW8 */ ++ break; ++ case 12: ++ port_config |= 0x02; /* DVP over FPDLink (TI913 compatible) RAW12 */ ++ break; ++ default: ++ port_config |= 0x00; /* CSI over FPDLink (TI953 compatible) */ + } ++ ++ if (priv->vsync) ++ port_config2 |= 0x01; /* VSYNC acive low */ ++ if (priv->hsync) ++ port_config2 |= 0x02; /* HSYNC acive low */ ++ ++ reg8_write(client, 0x6d, port_config); ++ reg8_write(client, 0x7c, port_config2); + reg8_write(client, 0x70, (idx << 6) | 0x1e); /* CSI data type: yuv422 8-bit, assign VC */ -+ reg8_write(client, 0x7c, 0x81); /* BIT(7) - magic to Use RAW10 as 8-bit mode */ ++ reg8_write(client, 0x71, (idx << 6) | 0x2a); /* CSI data type: RAW8, assign VC */ ++ reg8_write(client, 0xbc, 0x00); /* Setup minimal time between FV and LV to 3 PCLKs */ + reg8_write(client, 0x6e, 0x88); /* Sensor reset: backchannel GPIO0/GPIO1 set low */ +} + -+static int ti964_ti9x3_initialize(struct i2c_client *client) ++static int ti9x4_initialize(struct i2c_client *client) +{ -+ struct ti964_ti9x3_priv *priv = i2c_get_clientdata(client); ++ struct ti9x4_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); ++ priv->links, priv->lanes, priv->forwarding_mode, priv->is_coax ? "coax" : "stp", priv->chip_id); + -+ ti964_ti9x3_initial_setup(client); ++ ti9x4_initial_setup(client); + + for (idx = 0; idx < priv->links; idx++) { + if (!IS_ERR(priv->poc_supply[idx])) { @@ -7188,7 +7356,7 @@ index 0000000..8393392 + mdelay(priv->poc_delay); + } + -+ ti964_ti9x3_fpdlink3_setup(client, idx); ++ ti9x4_fpdlink3_setup(client, idx); + } + + client->addr = priv->des_addr; @@ -7197,10 +7365,10 @@ index 0000000..8393392 +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG -+static int ti964_ti9x3_g_register(struct v4l2_subdev *sd, ++static int ti9x4_g_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +{ -+ struct ti964_ti9x3_priv *priv = v4l2_get_subdevdata(sd); ++ struct ti9x4_priv *priv = v4l2_get_subdevdata(sd); + struct i2c_client *client = priv->client; + int ret; + u8 val = 0; @@ -7215,19 +7383,19 @@ index 0000000..8393392 + return 0; +} + -+static int ti964_ti9x3_s_register(struct v4l2_subdev *sd, ++static int ti9x4_s_register(struct v4l2_subdev *sd, + const struct v4l2_dbg_register *reg) +{ -+ struct ti964_ti9x3_priv *priv = v4l2_get_subdevdata(sd); ++ struct ti9x4_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) ++static int ti9x4_s_power(struct v4l2_subdev *sd, int on) +{ -+ struct ti964_ti9x3_priv *priv = v4l2_get_subdevdata(sd); ++ struct ti9x4_priv *priv = v4l2_get_subdevdata(sd); + struct i2c_client *client = priv->client; + + if (on) { @@ -7241,9 +7409,9 @@ index 0000000..8393392 + return 0; +} + -+static int ti964_ti9x3_registered_async(struct v4l2_subdev *sd) ++static int ti9x4_registered_async(struct v4l2_subdev *sd) +{ -+ struct ti964_ti9x3_priv *priv = v4l2_get_subdevdata(sd); ++ struct ti9x4_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 */ @@ -7251,29 +7419,28 @@ index 0000000..8393392 + return 0; +} + -+static struct v4l2_subdev_core_ops ti964_ti9x3_subdev_core_ops = { ++static struct v4l2_subdev_core_ops ti9x4_subdev_core_ops = { +#ifdef CONFIG_VIDEO_ADV_DEBUG -+ .g_register = ti964_ti9x3_g_register, -+ .s_register = ti964_ti9x3_s_register, ++ .g_register = ti9x4_g_register, ++ .s_register = ti9x4_s_register, +#endif -+ .s_power = ti964_ti9x3_s_power, -+ .registered_async = ti964_ti9x3_registered_async, ++ .s_power = ti9x4_s_power, ++ .registered_async = ti9x4_registered_async, +}; + -+static struct v4l2_subdev_ops ti964_ti9x3_subdev_ops = { -+ .core = &ti964_ti9x3_subdev_core_ops, ++static struct v4l2_subdev_ops ti9x4_subdev_ops = { ++ .core = &ti9x4_subdev_core_ops, +}; + -+static int ti964_ti9x3_parse_dt(struct i2c_client *client) ++static int ti9x4_parse_dt(struct i2c_client *client) +{ -+ struct ti964_ti9x3_priv *priv = i2c_get_clientdata(client); ++ struct ti9x4_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; + @@ -7285,14 +7452,14 @@ index 0000000..8393392 + + pwen = of_get_gpio(np, 0); + if (pwen > 0) { -+ err = devm_gpio_request_one(&client->dev, pwen, GPIOF_OUT_INIT_HIGH, dev_name(&client->dev)); ++ err = devm_gpio_request_one(&client->dev, pwen, GPIOF_OUT_INIT_LOW, 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 */ ++ reg8_read(client, 0x00, &val); /* read TI9x4 I2C address */ + if (val != (priv->des_addr << 1)) { + prop = of_find_property(np, "reg", NULL); + if (prop) @@ -7300,18 +7467,45 @@ index 0000000..8393392 + return -ENODEV; + } + -+ ti964_ti9x3_read_chipid(client); ++ ti9x4_read_chipid(client); + ++#ifdef TI954_SILICON_ERRATA ++ indirect_write(client, 7, 0x15, 0x30); ++ if (pwen > 0) ++ gpio_set_value(pwen, 1); ++ usleep_range(5000, 5500); /* wait 5ms */ ++ indirect_write(client, 7, 0x15, 0); ++#endif + if (!of_property_read_u32(np, "ti,sensor_delay", &sensor_delay)) + mdelay(sensor_delay); + if (of_property_read_string(np, "ti,forwarding-mode", &priv->forwarding_mode)) + priv->forwarding_mode = forwarding_mode_default; -+ if (of_property_read_string(np, "ti,cable-mode", &priv->cable_mode)) -+ priv->cable_mode = cable_mode_default; ++ if (of_property_read_bool(np, "ti,stp")) ++ priv->is_coax = 0; ++ else ++ priv->is_coax = 1; ++ if (of_property_read_u32(np, "ti,dvp_bus", &priv->dvp_bus)) ++ priv->dvp_bus = 8; ++ if (of_property_read_u32(np, "ti,hsync", &priv->hsync)) ++ priv->vsync = 0; ++ if (of_property_read_u32(np, "ti,vsync", &priv->vsync)) ++ priv->vsync = 1; ++ if (of_property_read_u32(np, "ti,ser_id", &priv->ser_id)) ++ priv->ser_id = TI913_ID; + if (of_property_read_u32(np, "ti,poc-delay", &priv->poc_delay)) + priv->poc_delay = 50; + + /* module params override dts */ ++ if (is_stp) ++ priv->is_coax = 0; ++ if (dvp_bus != 8) ++ priv->dvp_bus = dvp_bus; ++ if (hsync) ++ priv->hsync = hsync; ++ if (!vsync) ++ priv->vsync = vsync; ++ if (ser_id) ++ priv->ser_id = ser_id; + if (poc_delay) + priv->poc_delay = poc_delay; + @@ -7348,10 +7542,10 @@ index 0000000..8393392 + return 0; +} + -+static int ti964_ti9x3_probe(struct i2c_client *client, ++static int ti9x4_probe(struct i2c_client *client, + const struct i2c_device_id *did) +{ -+ struct ti964_ti9x3_priv *priv; ++ struct ti9x4_priv *priv; + int err, i; + char supply_name[10]; + @@ -7364,7 +7558,7 @@ index 0000000..8393392 + priv->client = client; + atomic_set(&priv->use_count, 0); + -+ err = ti964_ti9x3_parse_dt(client); ++ err = ti9x4_parse_dt(client); + if (err) + goto out; + @@ -7373,12 +7567,12 @@ index 0000000..8393392 + priv->poc_supply[i] = devm_regulator_get_optional(&client->dev, supply_name); + } + -+ err = ti964_ti9x3_initialize(client); ++ err = ti9x4_initialize(client); + if (err < 0) + goto out; + + for (i = 0; i < priv->links; i++) { -+ v4l2_subdev_init(&priv->sd[i], &ti964_ti9x3_subdev_ops); ++ v4l2_subdev_init(&priv->sd[i], &ti9x4_subdev_ops); + priv->sd[i].owner = client->dev.driver->owner; + priv->sd[i].dev = &client->dev; + priv->sd[i].grp_id = i; @@ -7398,9 +7592,9 @@ index 0000000..8393392 + return err; +} + -+static int ti964_ti9x3_remove(struct i2c_client *client) ++static int ti9x4_remove(struct i2c_client *client) +{ -+ struct ti964_ti9x3_priv *priv = i2c_get_clientdata(client); ++ struct ti9x4_priv *priv = i2c_get_clientdata(client); + int i; + + for (i = 0; i < priv->links; i++) { @@ -7411,39 +7605,39 @@ index 0000000..8393392 + return 0; +} + -+static const struct of_device_id ti964_ti9x3_dt_ids[] = { -+ { .compatible = "ti,ti964-ti9x3" }, ++static const struct of_device_id ti9x4_dt_ids[] = { ++ { .compatible = "ti,ti9x4" }, + {}, +}; -+MODULE_DEVICE_TABLE(of, ti964_ti9x3_dt_ids); ++MODULE_DEVICE_TABLE(of, ti9x4_dt_ids); + -+static const struct i2c_device_id ti964_ti9x3_id[] = { -+ { "ti964_ti9x3", 0 }, ++static const struct i2c_device_id ti9x4_id[] = { ++ { "ti9x4", 0 }, + { } +}; -+MODULE_DEVICE_TABLE(i2c, ti964_ti9x3_id); ++MODULE_DEVICE_TABLE(i2c, ti9x4_id); + -+static struct i2c_driver ti964_ti9x3_i2c_driver = { ++static struct i2c_driver ti9x4_i2c_driver = { + .driver = { -+ .name = "ti964_ti9x3", -+ .of_match_table = of_match_ptr(ti964_ti9x3_dt_ids), ++ .name = "ti9x4", ++ .of_match_table = of_match_ptr(ti9x4_dt_ids), + }, -+ .probe = ti964_ti9x3_probe, -+ .remove = ti964_ti9x3_remove, -+ .id_table = ti964_ti9x3_id, ++ .probe = ti9x4_probe, ++ .remove = ti9x4_remove, ++ .id_table = ti9x4_id, +}; + -+module_i2c_driver(ti964_ti9x3_i2c_driver); ++module_i2c_driver(ti9x4_i2c_driver); + -+MODULE_DESCRIPTION("FPDLinkIII driver for TI964-TI9X3"); ++MODULE_DESCRIPTION("FPDLinkIII driver for DS90UB9x4"); +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 +diff --git a/drivers/media/i2c/soc_camera/ti9x4.h b/drivers/media/i2c/soc_camera/ti9x4.h new file mode 100644 -index 0000000..69d3728 +index 0000000..b53b4c6 --- /dev/null -+++ b/drivers/media/i2c/soc_camera/ti9x4_ti9x3.h -@@ -0,0 +1,153 @@ ++++ b/drivers/media/i2c/soc_camera/ti9x4.h +@@ -0,0 +1,156 @@ +/* + * TI FPDLinkIII driver include file + * @@ -7465,6 +7659,9 @@ index 0000000..69d3728 +#endif + +#define MAXIM_NUM_RETRIES 1 /* number of read/write retries */ ++#define TI913_ID 0x58 ++#define TI953_ID 0x30 /* or starapped to 0x32 */ ++#define TI9X4_ID 0x00 /* strapped */ +#define BROADCAST 0x6f + +static inline int reg8_read(struct i2c_client *client, u8 reg, u8 *val) @@ -8084,7 +8281,7 @@ index 4d95da6..2ef27e8 100644 return 0; diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c -index 74fb005..ac75af6 100644 +index 74fb005..f6119e5 100644 --- a/drivers/media/platform/soc_camera/rcar_vin.c +++ b/drivers/media/platform/soc_camera/rcar_vin.c @@ -95,17 +95,21 @@ @@ -8249,7 +8446,7 @@ index 74fb005..ac75af6 100644 while (priv->state != STOPPED) { /* issue stop if running */ if (priv->state == RUNNING) -@@ -1361,6 +1422,31 @@ static struct v4l2_subdev *find_csi2(struct rcar_vin_priv *pcdev) +@@ -1361,6 +1422,26 @@ static struct v4l2_subdev *find_csi2(struct rcar_vin_priv *pcdev) return NULL; } @@ -8257,8 +8454,7 @@ index 74fb005..ac75af6 100644 +{ + struct v4l2_subdev *sd; + char name[] = "max9286"; -+ char name2[] = "ti964_ti9x3"; -+ char name3[] = "ti954_ti9x3"; ++ char name2[] = "ti9x4"; + + v4l2_device_for_each_subdev(sd, &pcdev->ici.v4l2_dev) { + if (!strncmp(name, sd->name, sizeof(name) - 1)) { @@ -8269,10 +8465,6 @@ index 74fb005..ac75af6 100644 + pcdev->deser_sd = sd; + return sd; + } -+ if (!strncmp(name3, sd->name, sizeof(name3) - 1)) { -+ pcdev->deser_sd = sd; -+ return sd; -+ } + } + + return NULL; @@ -8281,7 +8473,7 @@ index 74fb005..ac75af6 100644 static int rcar_vin_add_device(struct soc_camera_device *icd) { struct soc_camera_host *ici = to_soc_camera_host(icd->parent); -@@ -1375,7 +1461,8 @@ static int rcar_vin_add_device(struct soc_camera_device *icd) +@@ -1375,7 +1456,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); @@ -8291,7 +8483,7 @@ index 74fb005..ac75af6 100644 if (csi2_sd) { csi2_sd->grp_id = soc_camera_grp_id(icd); -@@ -1390,6 +1477,18 @@ static int rcar_vin_add_device(struct soc_camera_device *icd) +@@ -1390,6 +1472,18 @@ static int rcar_vin_add_device(struct soc_camera_device *icd) if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) return ret; } @@ -8310,7 +8502,7 @@ index 74fb005..ac75af6 100644 /* * -ENODEV is special: * either csi2_sd == NULL or the CSI-2 driver -@@ -1417,6 +1516,7 @@ static void rcar_vin_remove_device(struct soc_camera_device *icd) +@@ -1417,6 +1511,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); @@ -8318,7 +8510,7 @@ index 74fb005..ac75af6 100644 int i; /* disable capture, disable interrupts */ -@@ -1443,6 +1543,8 @@ static void rcar_vin_remove_device(struct soc_camera_device *icd) +@@ -1443,6 +1538,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); @@ -8327,7 +8519,7 @@ index 74fb005..ac75af6 100644 dev_dbg(icd->parent, "R-Car VIN driver detached from camera %d\n", icd->devnum); -@@ -1621,13 +1723,19 @@ static int rcar_vin_set_rect(struct soc_camera_device *icd) +@@ -1621,13 +1718,19 @@ static int rcar_vin_set_rect(struct soc_camera_device *icd) if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || priv->chip == RCAR_V3M) { @@ -8349,7 +8541,7 @@ index 74fb005..ac75af6 100644 (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 +1976,14 @@ static bool rcar_vin_packing_supported(const struct soc_mbus_pixelfmt *fmt) +@@ -1868,6 +1971,14 @@ static bool rcar_vin_packing_supported(const struct soc_mbus_pixelfmt *fmt) .layout = SOC_MBUS_LAYOUT_PACKED, }, { @@ -8364,7 +8556,7 @@ index 74fb005..ac75af6 100644 .fourcc = V4L2_PIX_FMT_RGB565, .name = "RGB565", .bits_per_sample = 16, -@@ -1899,6 +2015,22 @@ static bool rcar_vin_packing_supported(const struct soc_mbus_pixelfmt *fmt) +@@ -1899,6 +2010,22 @@ static bool rcar_vin_packing_supported(const struct soc_mbus_pixelfmt *fmt) .order = SOC_MBUS_ORDER_LE, .layout = SOC_MBUS_LAYOUT_PACKED, }, @@ -8387,7 +8579,7 @@ index 74fb005..ac75af6 100644 }; static int rcar_vin_get_formats(struct soc_camera_device *icd, unsigned int idx, -@@ -2012,6 +2144,8 @@ static int rcar_vin_get_formats(struct soc_camera_device *icd, unsigned int idx, +@@ -2012,6 +2139,8 @@ static int rcar_vin_get_formats(struct soc_camera_device *icd, unsigned int idx, case MEDIA_BUS_FMT_YUYV8_2X8: case MEDIA_BUS_FMT_YUYV10_2X10: case MEDIA_BUS_FMT_RGB888_1X24: @@ -8396,7 +8588,7 @@ index 74fb005..ac75af6 100644 if (cam->extra_fmt) break; -@@ -2218,12 +2352,15 @@ static int rcar_vin_set_fmt(struct soc_camera_device *icd, +@@ -2218,12 +2347,15 @@ static int rcar_vin_set_fmt(struct soc_camera_device *icd, case V4L2_PIX_FMT_ABGR32: case V4L2_PIX_FMT_UYVY: case V4L2_PIX_FMT_YUYV: @@ -8412,7 +8604,7 @@ index 74fb005..ac75af6 100644 default: can_scale = false; break; -@@ -2316,7 +2453,8 @@ static int rcar_vin_try_fmt(struct soc_camera_device *icd, +@@ -2316,7 +2448,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) || @@ -8422,7 +8614,7 @@ index 74fb005..ac75af6 100644 v4l_bound_align_image(&pix->width, 5, priv->max_width, 1, &pix->height, 2, priv->max_height, 0, 0); else -@@ -2486,6 +2624,19 @@ static int rcar_vin_cropcap(struct soc_camera_device *icd, +@@ -2486,6 +2619,19 @@ static int rcar_vin_cropcap(struct soc_camera_device *icd, } #endif @@ -8442,7 +8634,7 @@ index 74fb005..ac75af6 100644 static struct soc_camera_host_ops rcar_vin_host_ops = { .owner = THIS_MODULE, .add = rcar_vin_add_device, -@@ -2504,6 +2655,7 @@ static int rcar_vin_cropcap(struct soc_camera_device *icd, +@@ -2504,6 +2650,7 @@ static int rcar_vin_cropcap(struct soc_camera_device *icd, .get_selection = rcar_vin_get_selection, .cropcap = rcar_vin_cropcap, #endif @@ -8450,7 +8642,7 @@ index 74fb005..ac75af6 100644 }; #ifdef CONFIG_OF -@@ -2524,7 +2676,7 @@ static int rcar_vin_cropcap(struct soc_camera_device *icd, +@@ -2524,7 +2671,7 @@ static int rcar_vin_cropcap(struct soc_camera_device *icd, MODULE_DEVICE_TABLE(of, rcar_vin_of_table); #endif @@ -8459,19 +8651,18 @@ index 74fb005..ac75af6 100644 static DECLARE_BITMAP(device_map, MAP_MAX_NUM); static DEFINE_MUTEX(list_lock); -@@ -2714,7 +2866,11 @@ static int rcar_vin_probe(struct platform_device *pdev) +@@ -2714,7 +2861,10 @@ 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; ++ struct device_node *csi2_ren = NULL, *max9286_ren = NULL, *ti9x4_ren = NULL; bool csi_use = false; + bool max9286_use = false; -+ bool ti964_use = false; -+ bool ti954_use = false; ++ bool ti9x4_use = false; match = of_match_device(of_match_ptr(rcar_vin_of_table), &pdev->dev); -@@ -2741,13 +2897,27 @@ static int rcar_vin_probe(struct platform_device *pdev) +@@ -2741,13 +2891,22 @@ static int rcar_vin_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "node name:%s\n", of_node_full_name(ren->parent)); @@ -8489,21 +8680,16 @@ index 74fb005..ac75af6 100644 - 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; ++ if (strcmp(ren->parent->name, "ti9x4") == 0) { ++ ti9x4_ren = of_parse_phandle(epn, "remote-endpoint", 0); ++ ti9x4_use = true; + } + + of_node_put(ren); } ret = v4l2_of_parse_endpoint(np, &ep); -@@ -2799,6 +2969,7 @@ static int rcar_vin_probe(struct platform_device *pdev) +@@ -2799,6 +2958,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; @@ -8511,7 +8697,7 @@ index 74fb005..ac75af6 100644 priv->pdata_flags = pdata_flags; if (!match) { -@@ -2983,7 +3154,25 @@ static int rcar_vin_probe(struct platform_device *pdev) +@@ -2983,7 +3143,19 @@ static int rcar_vin_probe(struct platform_device *pdev) goto cleanup; if (csi_use) { @@ -8527,14 +8713,8 @@ index 74fb005..ac75af6 100644 + 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 (ti9x4_use) { ++ ret = rcar_vin_soc_of_bind(priv, &priv->ici, epn, ti9x4_ren); if (ret) goto cleanup; } diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch index 7755871..b351089 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch @@ -21,6 +21,7 @@ Eagle board on R8A7797 SoC Eagle Function board on R8A7797 SoC V3MSK board on R8A7797 SoC V3MSK.View board on R8A7797 SoC +V3MZF board on R8A7797 SoC Videobox Mini board on R8A7795 ES1.x SoC Videobox Mini board on R8A7795 SoC Videobox Mini board on R8A7797 SoC @@ -30,14 +31,14 @@ Condor board on R8A7798 SoC Signed-off-by: Vladimir Barinov --- - arch/arm64/boot/dts/renesas/Makefile | 21 + + arch/arm64/boot/dts/renesas/Makefile | 22 + arch/arm64/boot/dts/renesas/legacy/Makefile | 8 + - .../renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts | 1710 ++++++++++++++++++ + .../renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts | 1624 ++++++++++++++++++ .../renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts | 441 +++++ - .../dts/renesas/legacy/r8a7795-h3ulcb-kf-v0.dts | 1724 ++++++++++++++++++ - .../dts/renesas/legacy/r8a7795-h3ulcb-kf-v1.dts | 465 +++++ - .../dts/renesas/legacy/r8a7796-m3ulcb-kf-v0.dts | 1214 +++++++++++++ - .../dts/renesas/legacy/r8a7796-m3ulcb-kf-v1.dts | 465 +++++ + .../dts/renesas/legacy/r8a7795-h3ulcb-kf-v0.dts | 1638 +++++++++++++++++++ + .../dts/renesas/legacy/r8a7795-h3ulcb-kf-v1.dts | 465 ++++++ + .../dts/renesas/legacy/r8a7796-m3ulcb-kf-v0.dts | 1171 +++++++++++++ + .../dts/renesas/legacy/r8a7796-m3ulcb-kf-v1.dts | 465 ++++++ .../dts/renesas/legacy/r8a7797-v3msk-kf-v0.dts | 82 + .../boot/dts/renesas/legacy/ulcb-kf-cmos.dtsi | 75 + .../arm64/boot/dts/renesas/legacy/ulcb-kf-rpi.dtsi | 77 + @@ -49,7 +50,7 @@ Signed-off-by: Vladimir Barinov .../boot/dts/renesas/r8a7795-es1-h3ulcb-vb2.dts | 77 + .../boot/dts/renesas/r8a7795-es1-h3ulcb-vbm.dts | 26 + .../boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts | 544 ++++++ - .../dts/renesas/r8a7795-es1-salvator-x-view.dts | 550 ++++++ + .../dts/renesas/r8a7795-es1-salvator-x-view.dts | 550 +++++++ .../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 | 215 +++ @@ -58,26 +59,27 @@ Signed-off-by: Vladimir Barinov arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vb2.dts | 68 + arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vbm.dts | 26 + .../arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts | 544 ++++++ - .../boot/dts/renesas/r8a7795-salvator-x-view.dts | 550 ++++++ + .../boot/dts/renesas/r8a7795-salvator-x-view.dts | 550 +++++++ arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts | 40 + - .../arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts | 286 +++ + .../arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts | 286 ++++ .../boot/dts/renesas/r8a7796-salvator-x-view.dts | 317 ++++ .../boot/dts/renesas/r8a7797-eagle-function.dts | 62 + arch/arm64/boot/dts/renesas/r8a7797-eagle.dts | 575 +++++++ - arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts | 575 +++++++ - arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts | 548 ++++++ + arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts | 533 ++++++ + arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts | 548 +++++++ arch/arm64/boot/dts/renesas/r8a7797-v3msk-view.dts | 297 ++++ arch/arm64/boot/dts/renesas/r8a7797-v3msk.dts | 314 ++++ + arch/arm64/boot/dts/renesas/r8a7797-v3mzf.dts | 424 +++++ arch/arm64/boot/dts/renesas/r8a7798-condor.dts | 963 +++++++++++ - arch/arm64/boot/dts/renesas/ulcb-kf-cn11.dtsi | 545 ++++++ + arch/arm64/boot/dts/renesas/ulcb-kf-cn11.dtsi | 498 ++++++ arch/arm64/boot/dts/renesas/ulcb-kf-most.dtsi | 30 + arch/arm64/boot/dts/renesas/ulcb-kf-sd3.dtsi | 46 + - arch/arm64/boot/dts/renesas/ulcb-kf.dtsi | 1538 +++++++++++++++++ - arch/arm64/boot/dts/renesas/ulcb-vb-cn12.dtsi | 542 ++++++ - arch/arm64/boot/dts/renesas/ulcb-vb.dtsi | 1770 +++++++++++++++++++ - arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi | 1820 ++++++++++++++++++++ + arch/arm64/boot/dts/renesas/ulcb-kf.dtsi | 1492 +++++++++++++++++ + arch/arm64/boot/dts/renesas/ulcb-vb-cn12.dtsi | 495 ++++++ + arch/arm64/boot/dts/renesas/ulcb-vb.dtsi | 1678 +++++++++++++++++++ + arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi | 1724 ++++++++++++++++++++ arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi | 577 +++++++ - 47 files changed, 20253 insertions(+) + 48 files changed, 20093 insertions(+) create mode 100644 arch/arm64/boot/dts/renesas/legacy/Makefile create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts @@ -115,6 +117,7 @@ Signed-off-by: Vladimir Barinov create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-v3msk-view.dts create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-v3msk.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-v3mzf.dts create mode 100644 arch/arm64/boot/dts/renesas/r8a7798-condor.dts create mode 100644 arch/arm64/boot/dts/renesas/ulcb-kf-cn11.dtsi create mode 100644 arch/arm64/boot/dts/renesas/ulcb-kf-most.dtsi @@ -126,10 +129,10 @@ Signed-off-by: Vladimir Barinov create mode 100644 arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile -index f9c71df..3b5cff6 100644 +index f9c71df..6ca2c60 100644 --- a/arch/arm64/boot/dts/renesas/Makefile +++ b/arch/arm64/boot/dts/renesas/Makefile -@@ -6,5 +6,26 @@ dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-xs.dtb +@@ -6,5 +6,27 @@ dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-xs.dtb dtb-$(CONFIG_ARCH_R8A77965) += r8a77965-salvator-x.dtb dtb-$(CONFIG_ARCH_R8A77965) += r8a77965-salvator-xs.dtb @@ -149,6 +152,7 @@ index f9c71df..3b5cff6 100644 +dtb-$(CONFIG_ARCH_R8A7797) += r8a7797-v3msk-view.dtb +dtb-$(CONFIG_ARCH_R8A7797) += r8a7797-v3msk-kf.dtb +dtb-$(CONFIG_ARCH_R8A7797) += r8a7797-v3msk-vbm.dtb ++dtb-$(CONFIG_ARCH_R8A7797) += r8a7797-v3mzf.dtb +dtb-$(CONFIG_ARCH_R8A7798) += r8a7798-condor.dtb + +# ADAS legacy boards @@ -172,10 +176,10 @@ index 0000000..7f25079 +clean-files := *.dtb diff --git a/arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts b/arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts new file mode 100644 -index 0000000..fe07e22 +index 0000000..01aef82 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts -@@ -0,0 +1,1710 @@ +@@ -0,0 +1,1624 @@ +/* + * Device Tree Source for the H3ULCB Kingfisher V0 board on r8a7795 ES1.x + * @@ -764,11 +768,8 @@ index 0000000..fe07e22 + 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_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; + }; + }; + }; @@ -788,11 +789,8 @@ index 0000000..fe07e22 + 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_ti9x4_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep1>; + }; + }; + }; @@ -812,8 +810,8 @@ index 0000000..fe07e22 + ov106xx_max9286_des0ep2: endpoint@0 { + remote-endpoint = <&max9286_des0ep2>; + }; -+ ov106xx_ti964_des0ep2: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep2>; ++ ov106xx_ti9x4_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep2>; + }; + }; + }; @@ -833,15 +831,15 @@ index 0000000..fe07e22 + ov106xx_max9286_des0ep3: endpoint@0 { + remote-endpoint = <&max9286_des0ep3>; + }; -+ ov106xx_ti964_des0ep3: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep3>; ++ ov106xx_ti9x4_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep3>; + }; + }; + }; + -+ /* DS90UB964 @ 0x3a */ -+ ti964-ti9x3@0 { -+ compatible = "ti,ti964-ti9x3"; ++ /* DS90UB9x4 @ 0x3a */ ++ ti9x4@0 { ++ compatible = "ti,ti9x4"; + reg = <0x3a>; + ti,sensor_delay = <350>; + ti,links = <4>; @@ -850,60 +848,29 @@ index 0000000..fe07e22 + ti,cable-mode = "coax"; + + port@0 { -+ ti964_des0ep0: endpoint@0 { ++ ti9x4_des0ep0: endpoint@0 { + ti9x3-addr = <0x0c>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in0>; + }; -+ ti964_des0ep1: endpoint@1 { ++ ti9x4_des0ep1: endpoint@1 { + ti9x3-addr = <0x0d>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in1>; + }; -+ ti964_des0ep2: endpoint@2 { ++ ti9x4_des0ep2: endpoint@2 { + ti9x3-addr = <0x0e>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in2>; + }; -+ ti964_des0ep3: endpoint@3 { ++ ti9x4_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 { ++ ti9x4_csi0ep0: endpoint { + csi-rate = <1450>; + remote-endpoint = <&csi2_40_ep>; + }; @@ -973,11 +940,8 @@ index 0000000..fe07e22 + 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_ti9x4_des1ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep0>; + }; + }; + }; @@ -997,11 +961,8 @@ index 0000000..fe07e22 + 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_ti9x4_des1ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep1>; + }; + }; + }; @@ -1021,8 +982,8 @@ index 0000000..fe07e22 + ov106xx_max9286_des1ep2: endpoint@0 { + remote-endpoint = <&max9286_des1ep2>; + }; -+ ov106xx_ti964_des1ep2: endpoint@1 { -+ remote-endpoint = <&ti964_des1ep2>; ++ ov106xx_ti9x4_des1ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep2>; + }; + }; + }; @@ -1042,15 +1003,15 @@ index 0000000..fe07e22 + ov106xx_max9286_des1ep3: endpoint@0 { + remote-endpoint = <&max9286_des1ep3>; + }; -+ ov106xx_ti964_des1ep3: endpoint@1 { -+ remote-endpoint = <&ti964_des1ep3>; ++ ov106xx_ti9x4_des1ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep3>; + }; + }; + }; + -+ /* DS90UB964 @ 0x3a */ -+ ti964-ti9x3@1 { -+ compatible = "ti,ti964-ti9x3"; ++ /* DS90UB9x4 @ 0x3a */ ++ ti9x4@1 { ++ compatible = "ti,ti9x4"; + reg = <0x3a>; + ti,sensor_delay = <350>; + ti,links = <4>; @@ -1059,60 +1020,29 @@ index 0000000..fe07e22 + ti,cable-mode = "coax"; + + port@0 { -+ ti964_des1ep0: endpoint@0 { ++ ti9x4_des1ep0: endpoint@0 { + ti9x3-addr = <0x0c>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in4>; + }; -+ ti964_des1ep1: endpoint@1 { ++ ti9x4_des1ep1: endpoint@1 { + ti9x3-addr = <0x0d>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in5>; + }; -+ ti964_des1ep2: endpoint@2 { ++ ti9x4_des1ep2: endpoint@2 { + ti9x3-addr = <0x0e>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in6>; + }; -+ ti964_des1ep3: endpoint@3 { ++ ti9x4_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 { ++ ti9x4_csi2ep0: endpoint { + csi-rate = <1450>; + remote-endpoint = <&csi2_41_ep>; + }; @@ -1474,11 +1404,8 @@ index 0000000..fe07e22 + 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>; ++ vin0_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; + }; + }; + }; @@ -1508,11 +1435,8 @@ index 0000000..fe07e22 + 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>; ++ vin1_ti9x4_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep1>; + }; + }; + }; @@ -1542,8 +1466,8 @@ index 0000000..fe07e22 + vin2_max9286_des0ep2: endpoint@0 { + remote-endpoint = <&max9286_des0ep2>; + }; -+ vin2_ti964_des0ep2: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep2>; ++ vin2_ti9x4_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep2>; + }; + }; + }; @@ -1573,8 +1497,8 @@ index 0000000..fe07e22 + vin3_max9286_des0ep3: endpoint@0 { + remote-endpoint = <&max9286_des0ep3>; + }; -+ vin3_ti964_des0ep3: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep3>; ++ vin3_ti9x4_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep3>; + }; + }; + }; @@ -1604,11 +1528,8 @@ index 0000000..fe07e22 + 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>; ++ vin4_ti9x4_des1ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep0>; + }; + }; + }; @@ -1638,11 +1559,8 @@ index 0000000..fe07e22 + 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>; ++ vin5_ti9x4_des1ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep1>; + }; + }; + }; @@ -1672,8 +1590,8 @@ index 0000000..fe07e22 + vin6_max9286_des1ep2: endpoint@0 { + remote-endpoint = <&max9286_des1ep2>; + }; -+ vin6_ti964_des1ep2: endpoint@1 { -+ remote-endpoint = <&ti964_des1ep2>; ++ vin6_ti9x4_des1ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep2>; + }; + }; + }; @@ -1703,8 +1621,8 @@ index 0000000..fe07e22 + vin7_max9286_des1ep3: endpoint@0 { + remote-endpoint = <&max9286_des1ep3>; + }; -+ vin7_ti964_des1ep3: endpoint@1 { -+ remote-endpoint = <&ti964_des1ep3>; ++ vin7_ti9x4_des1ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep3>; + }; + }; + }; @@ -2335,10 +2253,10 @@ index 0000000..ac6a12b +}; diff --git a/arch/arm64/boot/dts/renesas/legacy/r8a7795-h3ulcb-kf-v0.dts b/arch/arm64/boot/dts/renesas/legacy/r8a7795-h3ulcb-kf-v0.dts new file mode 100644 -index 0000000..c19bc58 +index 0000000..dd1aadc --- /dev/null +++ b/arch/arm64/boot/dts/renesas/legacy/r8a7795-h3ulcb-kf-v0.dts -@@ -0,0 +1,1724 @@ +@@ -0,0 +1,1638 @@ +/* + * Device Tree Source for the H3ULCB Kingfisher V0 board on r8a7795 + * @@ -2927,11 +2845,8 @@ index 0000000..c19bc58 + 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_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; + }; + }; + }; @@ -2951,11 +2866,8 @@ index 0000000..c19bc58 + 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_ti9x4_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep1>; + }; + }; + }; @@ -2975,8 +2887,8 @@ index 0000000..c19bc58 + ov106xx_max9286_des0ep2: endpoint@0 { + remote-endpoint = <&max9286_des0ep2>; + }; -+ ov106xx_ti964_des0ep2: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep2>; ++ ov106xx_ti9x4_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep2>; + }; + }; + }; @@ -2996,15 +2908,15 @@ index 0000000..c19bc58 + ov106xx_max9286_des0ep3: endpoint@0 { + remote-endpoint = <&max9286_des0ep3>; + }; -+ ov106xx_ti964_des0ep3: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep3>; ++ ov106xx_ti9x4_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep3>; + }; + }; + }; + -+ /* DS90UB964 @ 0x3a */ -+ ti964-ti9x3@0 { -+ compatible = "ti,ti964-ti9x3"; ++ /* DS90UB9x4 @ 0x3a */ ++ ti9x4@0 { ++ compatible = "ti,ti9x4"; + reg = <0x3a>; + ti,sensor_delay = <350>; + ti,links = <4>; @@ -3013,60 +2925,29 @@ index 0000000..c19bc58 + ti,cable-mode = "coax"; + + port@0 { -+ ti964_des0ep0: endpoint@0 { ++ ti9x4_des0ep0: endpoint@0 { + ti9x3-addr = <0x0c>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in0>; + }; -+ ti964_des0ep1: endpoint@1 { ++ ti9x4_des0ep1: endpoint@1 { + ti9x3-addr = <0x0d>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in1>; + }; -+ ti964_des0ep2: endpoint@2 { ++ ti9x4_des0ep2: endpoint@2 { + ti9x3-addr = <0x0e>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in2>; + }; -+ ti964_des0ep3: endpoint@3 { ++ ti9x4_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 { ++ ti9x4_csi0ep0: endpoint { + csi-rate = <1450>; + remote-endpoint = <&csi2_40_ep>; + }; @@ -3136,11 +3017,8 @@ index 0000000..c19bc58 + 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_ti9x4_des1ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep0>; + }; + }; + }; @@ -3160,11 +3038,8 @@ index 0000000..c19bc58 + 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_ti9x4_des1ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep1>; + }; + }; + }; @@ -3184,8 +3059,8 @@ index 0000000..c19bc58 + ov106xx_max9286_des1ep2: endpoint@0 { + remote-endpoint = <&max9286_des1ep2>; + }; -+ ov106xx_ti964_des1ep2: endpoint@1 { -+ remote-endpoint = <&ti964_des1ep2>; ++ ov106xx_ti9x4_des1ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep2>; + }; + }; + }; @@ -3205,15 +3080,15 @@ index 0000000..c19bc58 + ov106xx_max9286_des1ep3: endpoint@0 { + remote-endpoint = <&max9286_des1ep3>; + }; -+ ov106xx_ti964_des1ep3: endpoint@1 { -+ remote-endpoint = <&ti964_des1ep3>; ++ ov106xx_ti9x4_des1ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep3>; + }; + }; + }; + -+ /* DS90UB964 @ 0x3a */ -+ ti964-ti9x3@1 { -+ compatible = "ti,ti964-ti9x3"; ++ /* DS90UB9x4 @ 0x3a */ ++ ti9x4@1 { ++ compatible = "ti,ti9x4"; + reg = <0x3a>; + ti,sensor_delay = <350>; + ti,links = <4>; @@ -3222,60 +3097,29 @@ index 0000000..c19bc58 + ti,cable-mode = "coax"; + + port@0 { -+ ti964_des1ep0: endpoint@0 { ++ ti9x4_des1ep0: endpoint@0 { + ti9x3-addr = <0x0c>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in4>; + }; -+ ti964_des1ep1: endpoint@1 { ++ ti9x4_des1ep1: endpoint@1 { + ti9x3-addr = <0x0d>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in5>; + }; -+ ti964_des1ep2: endpoint@2 { ++ ti9x4_des1ep2: endpoint@2 { + ti9x3-addr = <0x0e>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in6>; + }; -+ ti964_des1ep3: endpoint@3 { ++ ti9x4_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 { ++ ti9x4_csi2ep0: endpoint { + csi-rate = <1450>; + remote-endpoint = <&csi2_41_ep>; + }; @@ -3644,11 +3488,8 @@ index 0000000..c19bc58 + 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>; ++ vin0_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; + }; + }; + }; @@ -3678,11 +3519,8 @@ index 0000000..c19bc58 + 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>; ++ vin1_ti9x4_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep1>; + }; + }; + }; @@ -3712,8 +3550,8 @@ index 0000000..c19bc58 + vin2_max9286_des0ep2: endpoint@0 { + remote-endpoint = <&max9286_des0ep2>; + }; -+ vin2_ti964_des0ep2: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep2>; ++ vin2_ti9x4_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep2>; + }; + }; + }; @@ -3743,8 +3581,8 @@ index 0000000..c19bc58 + vin3_max9286_des0ep3: endpoint@0 { + remote-endpoint = <&max9286_des0ep3>; + }; -+ vin3_ti964_des0ep3: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep3>; ++ vin3_ti9x4_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep3>; + }; + }; + }; @@ -3774,11 +3612,8 @@ index 0000000..c19bc58 + 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>; ++ vin4_ti9x4_des1ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep0>; + }; + }; + }; @@ -3808,11 +3643,8 @@ index 0000000..c19bc58 + 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>; ++ vin5_ti9x4_des1ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep1>; + }; + }; + }; @@ -3842,8 +3674,8 @@ index 0000000..c19bc58 + vin6_max9286_des1ep2: endpoint@0 { + remote-endpoint = <&max9286_des1ep2>; + }; -+ vin6_ti964_des1ep2: endpoint@1 { -+ remote-endpoint = <&ti964_des1ep2>; ++ vin6_ti9x4_des1ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep2>; + }; + }; + }; @@ -3873,8 +3705,8 @@ index 0000000..c19bc58 + vin7_max9286_des1ep3: endpoint@0 { + remote-endpoint = <&max9286_des1ep3>; + }; -+ vin7_ti964_des1ep3: endpoint@1 { -+ remote-endpoint = <&ti964_des1ep3>; ++ vin7_ti9x4_des1ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep3>; + }; + }; + }; @@ -4536,10 +4368,10 @@ index 0000000..14b6f52 +}; diff --git a/arch/arm64/boot/dts/renesas/legacy/r8a7796-m3ulcb-kf-v0.dts b/arch/arm64/boot/dts/renesas/legacy/r8a7796-m3ulcb-kf-v0.dts new file mode 100644 -index 0000000..8e7de0f +index 0000000..b17a42e --- /dev/null +++ b/arch/arm64/boot/dts/renesas/legacy/r8a7796-m3ulcb-kf-v0.dts -@@ -0,0 +1,1214 @@ +@@ -0,0 +1,1171 @@ +/* + * Device Tree Source for the M3ULCB Kingfisher V0 board on r8a7796 + * @@ -5128,11 +4960,8 @@ index 0000000..8e7de0f + 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_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; + }; + }; + }; @@ -5152,11 +4981,8 @@ index 0000000..8e7de0f + 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_ti9x4_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep1>; + }; + }; + }; @@ -5176,8 +5002,8 @@ index 0000000..8e7de0f + ov106xx_max9286_des0ep2: endpoint@0 { + remote-endpoint = <&max9286_des0ep2>; + }; -+ ov106xx_ti964_des0ep2: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep2>; ++ ov106xx_ti9x4_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep2>; + }; + }; + }; @@ -5197,15 +5023,15 @@ index 0000000..8e7de0f + ov106xx_max9286_des0ep3: endpoint@0 { + remote-endpoint = <&max9286_des0ep3>; + }; -+ ov106xx_ti964_des0ep3: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep3>; ++ ov106xx_ti9x4_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep3>; + }; + }; + }; + -+ /* DS90UB964 @ 0x3a */ -+ ti964-ti9x3@0 { -+ compatible = "ti,ti964-ti9x3"; ++ /* DS90UB9x4 @ 0x3a */ ++ ti9x4@0 { ++ compatible = "ti,ti9x4"; + reg = <0x3a>; + ti,sensor_delay = <350>; + ti,links = <4>; @@ -5214,60 +5040,29 @@ index 0000000..8e7de0f + ti,cable-mode = "coax"; + + port@0 { -+ ti964_des0ep0: endpoint@0 { ++ ti9x4_des0ep0: endpoint@0 { + ti9x3-addr = <0x0c>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in0>; + }; -+ ti964_des0ep1: endpoint@1 { ++ ti9x4_des0ep1: endpoint@1 { + ti9x3-addr = <0x0d>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in1>; + }; -+ ti964_des0ep2: endpoint@2 { ++ ti9x4_des0ep2: endpoint@2 { + ti9x3-addr = <0x0e>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in2>; + }; -+ ti964_des0ep3: endpoint@3 { ++ ti9x4_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 { ++ ti9x4_csi0ep0: endpoint { + csi-rate = <1450>; + remote-endpoint = <&csi2_40_ep>; + }; @@ -5499,11 +5294,8 @@ index 0000000..8e7de0f + 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>; ++ vin0_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; + }; + }; + }; @@ -5533,11 +5325,8 @@ index 0000000..8e7de0f + 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>; ++ vin1_ti9x4_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep1>; + }; + }; + }; @@ -5567,8 +5356,8 @@ index 0000000..8e7de0f + vin2_max9286_des0ep2: endpoint@0 { + remote-endpoint = <&max9286_des0ep2>; + }; -+ vin2_ti964_des0ep2: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep2>; ++ vin2_ti9x4_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep2>; + }; + }; + }; @@ -5598,8 +5387,8 @@ index 0000000..8e7de0f + vin3_max9286_des0ep3: endpoint@0 { + remote-endpoint = <&max9286_des0ep3>; + }; -+ vin3_ti964_des0ep3: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep3>; ++ vin3_ti9x4_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep3>; + }; + }; + }; @@ -11023,10 +10812,10 @@ index 0000000..ce7a88e +}; diff --git a/arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts new file mode 100644 -index 0000000..9158c84 +index 0000000..c61b613 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts -@@ -0,0 +1,575 @@ +@@ -0,0 +1,533 @@ +/* + * Device Tree Source for the V3MSK Kingfisher board on r8a7797 + * @@ -11132,11 +10921,8 @@ index 0000000..9158c84 + 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_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; + }; + }; + }; @@ -11156,11 +10942,8 @@ index 0000000..9158c84 + 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_ti9x4_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep1>; + }; + }; + }; @@ -11180,8 +10963,8 @@ index 0000000..9158c84 + ov106xx_max9286_des0ep2: endpoint@0 { + remote-endpoint = <&max9286_des0ep2>; + }; -+ ov106xx_ti964_des0ep2: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep2>; ++ ov106xx_ti9x4_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep2>; + }; + }; + }; @@ -11201,15 +10984,15 @@ index 0000000..9158c84 + ov106xx_max9286_des0ep3: endpoint@0 { + remote-endpoint = <&max9286_des0ep3>; + }; -+ ov106xx_ti964_des0ep3: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep3>; ++ ov106xx_ti9x4_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep3>; + }; + }; + }; + -+ /* DS90UB964 @ 0x3a */ -+ ti964-ti9x3@0 { -+ compatible = "ti,ti964-ti9x3"; ++ /* DS90UB9x4 @ 0x3a */ ++ ti9x4@0 { ++ compatible = "ti,ti9x4"; + reg = <0x3a>; + ti,links = <4>; + ti,lanes = <4>; @@ -11217,59 +11000,29 @@ index 0000000..9158c84 + ti,cable-mode = "coax"; + + port@0 { -+ ti964_des0ep0: endpoint@0 { ++ ti9x4_des0ep0: endpoint@0 { + ti9x3-addr = <0x0c>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in0>; + }; -+ ti964_des0ep1: endpoint@1 { ++ ti9x4_des0ep1: endpoint@1 { + ti9x3-addr = <0x0d>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in1>; + }; -+ ti964_des0ep2: endpoint@2 { ++ ti9x4_des0ep2: endpoint@2 { + ti9x3-addr = <0x0e>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in2>; + }; -+ ti964_des0ep3: endpoint@3 { ++ ti9x4_des0ep3: endpoint@3 { + ti9x3-addr = <0x0f>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in3>; + }; + }; + port@1 { -+ ti964_csi0ep0: endpoint { -+ csi-rate = <800>; -+ remote-endpoint = <&csi2_40_ep>; -+ }; -+ }; -+ }; -+ -+ /* DS90UB954 @ 0x38 */ -+ ti954-ti9x3@0 { -+ compatible = "ti,ti954-ti9x3"; -+ reg = <0x38>; -+ /* gpios = <&video_a_ext1 10 GPIO_ACTIVE_HIGH>; */ -+ ti,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 { ++ ti9x4_csi0ep0: endpoint { + csi-rate = <800>; + remote-endpoint = <&csi2_40_ep>; + }; @@ -11497,11 +11250,8 @@ index 0000000..9158c84 + 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>; ++ vin0_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; + }; + }; + }; @@ -11531,11 +11281,8 @@ index 0000000..9158c84 + 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>; ++ vin1_ti9x4_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep1>; + }; + }; + }; @@ -11565,8 +11312,8 @@ index 0000000..9158c84 + vin2_max9286_des0ep2: endpoint@0 { + remote-endpoint = <&max9286_des0ep2>; + }; -+ vin2_ti964_des0ep2: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep2>; ++ vin2_ti9x4_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep2>; + }; + }; + }; @@ -11596,15 +11343,15 @@ index 0000000..9158c84 + vin3_max9286_des0ep3: endpoint@0 { + remote-endpoint = <&max9286_des0ep3>; + }; -+ vin3_ti964_des0ep3: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep3>; ++ vin3_ti9x4_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep3>; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts new file mode 100644 -index 0000000..1cb8e95 +index 0000000..d355adb --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts @@ -0,0 +1,548 @@ @@ -11746,8 +11493,8 @@ index 0000000..1cb8e95 + ov106xx_max9286_des0ep0: endpoint@0 { + remote-endpoint = <&max9286_des0ep0>; + }; -+ ov106xx_ti964_des0ep0: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep0>; ++ ov106xx_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; + }; + }; + }; @@ -11767,8 +11514,8 @@ index 0000000..1cb8e95 + ov106xx_max9286_des0ep1: endpoint@0 { + remote-endpoint = <&max9286_des0ep1>; + }; -+ ov106xx_ti964_des0ep1: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep1>; ++ ov106xx_ti9x4_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep1>; + }; + }; + }; @@ -11788,8 +11535,8 @@ index 0000000..1cb8e95 + ov106xx_max9286_des0ep2: endpoint@0 { + remote-endpoint = <&max9286_des0ep2>; + }; -+ ov106xx_ti964_des0ep2: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep2>; ++ ov106xx_ti9x4_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep2>; + }; + }; + }; @@ -11809,8 +11556,8 @@ index 0000000..1cb8e95 + ov106xx_max9286_des0ep3: endpoint@0 { + remote-endpoint = <&max9286_des0ep3>; + }; -+ ov106xx_ti964_des0ep3: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep3>; ++ ov106xx_ti9x4_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep3>; + }; + }; + }; @@ -11858,8 +11605,8 @@ index 0000000..1cb8e95 + }; + }; + -+ ti964-ti9x3@0 { -+ compatible = "ti,ti964-ti9x3"; ++ ti9x4@0 { ++ compatible = "ti,ti9x4"; + reg = <0x3a>; + ti,links = <4>; + ti,lanes = <4>; @@ -11871,29 +11618,29 @@ index 0000000..1cb8e95 + POC3-supply = <&pwr3>; + + port@0 { -+ ti964_des0ep0: endpoint@0 { ++ ti9x4_des0ep0: endpoint@0 { + ti9x3-addr = <0x0c>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in0>; + }; -+ ti964_des0ep1: endpoint@1 { ++ ti9x4_des0ep1: endpoint@1 { + ti9x3-addr = <0x0d>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in1>; + }; -+ ti964_des0ep2: endpoint@2 { ++ ti9x4_des0ep2: endpoint@2 { + ti9x3-addr = <0x0e>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in2>; + }; -+ ti964_des0ep3: endpoint@3 { ++ ti9x4_des0ep3: endpoint@3 { + ti9x3-addr = <0x0f>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in3>; + }; + }; + port@1 { -+ ti964_csi0ep0: endpoint { ++ ti9x4_csi0ep0: endpoint { + csi-rate = <700>; + remote-endpoint = <&csi2_40_ep>; + }; @@ -12057,8 +11804,8 @@ index 0000000..1cb8e95 + vin0_max9286_des0ep0: endpoint@0 { + remote-endpoint = <&max9286_des0ep0>; + }; -+ vin0_ti964_des0ep0: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep0>; ++ vin0_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; + }; + }; + }; @@ -12088,8 +11835,8 @@ index 0000000..1cb8e95 + vin1_max9286_des0ep1: endpoint@0 { + remote-endpoint = <&max9286_des0ep1>; + }; -+ vin1_ti964_des0ep1: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep1>; ++ vin1_ti9x4_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep1>; + }; + }; + }; @@ -12119,8 +11866,8 @@ index 0000000..1cb8e95 + vin2_max9286_des0ep2: endpoint@0 { + remote-endpoint = <&max9286_des0ep2>; + }; -+ vin2_ti964_des0ep2: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep2>; ++ vin2_ti9x4_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep2>; + }; + }; + }; @@ -12150,8 +11897,8 @@ index 0000000..1cb8e95 + vin3_max9286_des0ep3: endpoint@0 { + remote-endpoint = <&max9286_des0ep3>; + }; -+ vin3_ti964_des0ep3: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep3>; ++ vin3_ti9x4_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep3>; + }; + }; + }; @@ -12779,16 +12526,15 @@ index 0000000..91d10c5 + non-removable; + status = "okay"; +}; -diff --git a/arch/arm64/boot/dts/renesas/r8a7798-condor.dts b/arch/arm64/boot/dts/renesas/r8a7798-condor.dts +diff --git a/arch/arm64/boot/dts/renesas/r8a7797-v3mzf.dts b/arch/arm64/boot/dts/renesas/r8a7797-v3mzf.dts new file mode 100644 -index 0000000..cdd9844 +index 0000000..7926d2e --- /dev/null -+++ b/arch/arm64/boot/dts/renesas/r8a7798-condor.dts -@@ -0,0 +1,963 @@ ++++ b/arch/arm64/boot/dts/renesas/r8a7797-v3mzf.dts +@@ -0,0 +1,424 @@ +/* -+ * Device Tree Source for the Condor board ++ * Device Tree Source for the V3MZF board + * -+ * Copyright (C) 2018 Renesas Electronics Corp. + * Copyright (C) 2018 Cogent Embedded, Inc. + * + * This file is licensed under the terms of the GNU General Public License @@ -12797,17 +12543,16 @@ index 0000000..cdd9844 + */ + +/dts-v1/; -+#include "r8a7798.dtsi" ++#include "r8a7797.dtsi" +#include + +/ { -+ model = "Renesas Condor board based on r8a7798"; -+ compatible = "renesas,condor", "renesas,r8a7798"; ++ model = "Renesas V3MZF board based on r8a7797"; ++ compatible = "renesas,v3mzf", "renesas,r8a7797"; + + aliases { + serial0 = &scif0; + ethernet0 = &avb; -+ ethernet1 = &gether; + }; + + chosen { @@ -12815,7 +12560,6 @@ index 0000000..cdd9844 + stdout-path = "serial0:115200n8"; + }; + -+ + memory@48000000 { + device_type = "memory"; + /* first 128MB is reserved for secure area. */ @@ -12837,16 +12581,9 @@ index 0000000..cdd9844 + linux,cma { + compatible = "shared-dma-pool"; + reusable; -+ reg = <0x00000000 0x6f000000 0x0 0x10000000>; ++ reg = <0x00000000 0x6f000000 0x0 0x11000000>; + linux,cma-default; + }; -+ -+ /* device specific region for contiguous allocations */ -+ linux,multimedia { -+ compatible = "shared-dma-pool"; -+ reusable; -+ reg = <0x00000000 0x7f000000 0x0 0x01000000>; -+ }; + }; + + mmngr { @@ -12891,15 +12628,15 @@ index 0000000..cdd9844 + height-mm = <158>; + + panel-timing { -+ clock-frequency = <138000000>; -+ hactive = <1920>; -+ vactive = <1080>; -+ hsync-len = <32>; -+ hfront-porch = <20>; -+ hback-porch = <160>; -+ vfront-porch = <3>; -+ vback-porch = <31>; -+ vsync-len = <5>; ++ 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 { @@ -12909,17 +12646,6 @@ index 0000000..cdd9844 + }; + }; + -+ hdmi-out { -+ compatible = "hdmi-connector"; -+ type = "a"; -+ -+ port { -+ hdmi_con: endpoint { -+ remote-endpoint = <&adv7511_out>; -+ }; -+ }; -+ }; -+ + dclkin_p0: clock-out0 { + compatible = "fixed-clock"; + #clock-cells = <0>; @@ -12931,27 +12657,478 @@ index 0000000..cdd9844 + #clock-cells = <0>; + clock-frequency = <66666666>; + }; ++}; + -+ vcc_3v3: regulator0 { -+ compatible = "regulator-fixed"; -+ regulator-name = "fixed-VCC3V3"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; ++&avb { ++ pinctrl-0 = <&avb_pins>; ++ pinctrl-names = "default"; ++ renesas,no-ether-link; ++ phy-handle = <&phy0>; ++ status = "okay"; ++ phy-int-gpio = <&gpio1 17 GPIO_ACTIVE_LOW>; + -+ vcc_vddq_vin0: regulator1 { -+ compatible = "regulator-fixed"; -+ regulator-name = "VCC-VDDQ-VIN0"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-boot-on; -+ regulator-always-on; ++ phy0: ethernet-phy@0 { ++ rxc-skew-ps = <1500>; ++ rxdv-skew-ps = <420>; /* default */ ++ rxd0-skew-ps = <420>; /* default */ ++ rxd1-skew-ps = <420>; /* default */ ++ rxd2-skew-ps = <420>; /* default */ ++ rxd3-skew-ps = <420>; /* default */ ++ txc-skew-ps = <900>; /* default */ ++ txen-skew-ps = <420>; /* default */ ++ txd0-skew-ps = <420>; /* default */ ++ txd1-skew-ps = <420>; /* default */ ++ txd2-skew-ps = <420>; /* default */ ++ txd3-skew-ps = <420>; /* default */ ++ reg = <0>; ++ interrupt-parent = <&gpio1>; ++ interrupts = <17 IRQ_TYPE_LEVEL_LOW>; ++ max-speed = <1000>; + }; +}; + -+&du { ++&canfd { ++ pinctrl-0 = <&canfd0_pins &canfd1_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ channel0 { ++ status = "okay"; ++ }; ++ ++ channel1 { ++ status = "okay"; ++ }; ++}; ++ ++&csi2_40 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "raw8"; ++ receive,vc = <0>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi2_40_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; ++ ++&du { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ endpoint { ++ remote-endpoint = <&lvds_in>; ++ }; ++ }; ++ }; ++}; ++ ++&extal_clk { ++ clock-frequency = <16666666>; ++}; ++ ++&extalr_clk { ++ clock-frequency = <32768>; ++}; ++ ++&gpio1 { ++ pdb_ser_enable { ++ gpio-hog; ++ gpios = <26 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "PDB_SER_Enable"; ++ }; ++ ++ lvds_sw_sel { ++ gpio-hog; ++ gpios = <27 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "LVDS_SW_SEL"; ++ }; ++}; ++ ++&gpio2 { ++ can0_inh_v3m { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "CAN0_INH_V3M"; ++ }; ++ ++ can1_inh_v3m { ++ gpio-hog; ++ gpios = <15 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "CAN1_INH_V3M"; ++ }; ++}; ++ ++&gpio3 { ++ pdb_des_enable { ++ gpio-hog; ++ gpios = <0 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "PDB_DES_Enable"; ++ }; ++}; ++ ++&i2c0 { ++ pinctrl-0 = <&i2c0_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++ clock-frequency = <400000>; ++}; ++ ++&i2c3 { ++ pinctrl-0 = <&i2c3_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++ clock-frequency = <400000>; ++ ++ ov106xx@0 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x60>; ++ ++ port@0 { ++ ov106xx_in0: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin0ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_ti9x4_des0ep0: endpoint@0 { ++ remote-endpoint = <&ti9x4_des0ep0>; ++ }; ++ }; ++ }; ++ ++ ti9x4@30 { ++ compatible = "ti,ti9x4"; ++ reg = <0x30>; ++ ti,links = <1>; ++ ti,lanes = <4>; ++ ti,forwarding-mode = "round-robin"; ++ ti,dvp_bus = <0>; ++ ti,ser_id = <0x30>; ++ ++ port@0 { ++ ti9x4_des0ep0: endpoint@0 { ++ ti9x3-addr = <0x0c>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ }; ++ port@1 { ++ ti9x4_csi0ep0: endpoint { ++ csi-rate = <800>; ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ }; ++}; ++ ++&msiof2 { ++ pinctrl-0 = <&msiof2_pins>; ++ pinctrl-names = "default"; ++ cs-gpios = <&gpio2 4 0>; ++ ++ status = "okay"; ++ spidev@0 { ++ compatible = "renesas,sh-msiof"; ++ reg = <0>; ++ spi-max-frequency = <66666666>; ++ }; ++}; ++ ++&msiof3 { ++ pinctrl-0 = <&msiof3_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++ slave; ++}; ++ ++&pfc { ++ pinctrl-0 = <&scif_clk_pins>; ++ pinctrl-names = "default"; ++ ++ avb_pins: avb { ++ groups = "avb0_mdc"; ++ function = "avb0"; ++ }; ++ ++ canfd0_pins: canfd0 { ++ groups = "canfd0_data_a"; ++ function = "canfd0"; ++ }; ++ ++ canfd1_pins: canfd1 { ++ groups = "canfd1_data"; ++ function = "canfd1"; ++ }; ++ ++ i2c0_pins: i2c0 { ++ groups = "i2c0"; ++ function = "i2c0"; ++ }; ++ ++ i2c3_pins: i2c3 { ++ groups = "i2c3"; ++ function = "i2c3"; ++ }; ++ ++ msiof2_pins: msiof2 { ++ groups = "msiof2_clk", "msiof2_txd", "msiof2_rxd"; ++ function = "msiof2"; ++ }; ++ ++ msiof3_pins: msiof3 { ++ groups = "msiof3_clk", "msiof3_txd", "msiof3_rxd", "msiof3_sync"; ++ function = "msiof3"; ++ }; ++ ++ scif0_pins: scif0 { ++ groups = "scif0_data"; ++ function = "scif0"; ++ }; ++ ++ scif_clk_pins: scif_clk { ++ groups = "scif_clk_b"; ++ function = "scif_clk"; ++ }; ++}; ++ ++&scif0 { ++ pinctrl-0 = <&scif0_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&scif_clk { ++ clock-frequency = <14745600>; ++ 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_ti9x4_des0ep0: endpoint@0 { ++ remote-endpoint = <&ti9x4_des0ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&wdt0 { ++ status = "okay"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7798-condor.dts b/arch/arm64/boot/dts/renesas/r8a7798-condor.dts +new file mode 100644 +index 0000000..cdd9844 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7798-condor.dts +@@ -0,0 +1,963 @@ ++/* ++ * Device Tree Source for the Condor board ++ * ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++/dts-v1/; ++#include "r8a7798.dtsi" ++#include ++ ++/ { ++ model = "Renesas Condor board based on r8a7798"; ++ compatible = "renesas,condor", "renesas,r8a7798"; ++ ++ aliases { ++ serial0 = &scif0; ++ ethernet0 = &avb; ++ ethernet1 = &gether; ++ }; ++ ++ chosen { ++ bootargs = "ignore_loglevel rw root=/dev/nfs ip=dhcp"; ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ ++ memory@48000000 { ++ device_type = "memory"; ++ /* first 128MB is reserved for secure area. */ ++ reg = <0x0 0x48000000 0x0 0x38000000>; ++ }; ++ ++ reserved-memory { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ /* device specific region for Lossy Decompression */ ++ lossy_decompress: linux,lossy_decompress { ++ no-map; ++ reg = <0x00000000 0x6c000000 0x0 0x03000000>; ++ }; ++ ++ /* global autoconfigured region for contiguous allocations */ ++ linux,cma { ++ compatible = "shared-dma-pool"; ++ reusable; ++ reg = <0x00000000 0x6f000000 0x0 0x10000000>; ++ linux,cma-default; ++ }; ++ ++ /* device specific region for contiguous allocations */ ++ linux,multimedia { ++ compatible = "shared-dma-pool"; ++ reusable; ++ reg = <0x00000000 0x7f000000 0x0 0x01000000>; ++ }; ++ }; ++ ++ mmngr { ++ compatible = "renesas,mmngr"; ++ memory-region = <&lossy_decompress>; ++ }; ++ ++ mmngrbuf { ++ compatible = "renesas,mmngrbuf"; ++ }; ++ ++ vspm_if { ++ compatible = "renesas,vspm_if"; ++ }; ++ ++ lvds-encoder { ++ compatible = "thine,thc63lvdm83d"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ lvds_enc_in: endpoint { ++ remote-endpoint = <&du_out_lvds0>; ++ }; ++ }; ++ port@1 { ++ reg = <1>; ++ lvds_enc_out: endpoint { ++ remote-endpoint = <&lvds_in>; ++ }; ++ }; ++ }; ++ }; ++ ++ lvds { ++ compatible = "lvds-connector"; ++ ++ width-mm = <210>; ++ height-mm = <158>; ++ ++ panel-timing { ++ clock-frequency = <138000000>; ++ hactive = <1920>; ++ vactive = <1080>; ++ hsync-len = <32>; ++ hfront-porch = <20>; ++ hback-porch = <160>; ++ vfront-porch = <3>; ++ vback-porch = <31>; ++ vsync-len = <5>; ++ }; ++ ++ port { ++ lvds_in: endpoint { ++ remote-endpoint = <&lvds_enc_out>; ++ }; ++ }; ++ }; ++ ++ hdmi-out { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi_con: endpoint { ++ remote-endpoint = <&adv7511_out>; ++ }; ++ }; ++ }; ++ ++ dclkin_p0: clock-out0 { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <148500000>; ++ }; ++ ++ msiof_ref_clk: msiof-ref-clock { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <66666666>; ++ }; ++ ++ vcc_3v3: regulator0 { ++ compatible = "regulator-fixed"; ++ regulator-name = "fixed-VCC3V3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ vcc_vddq_vin0: regulator1 { ++ compatible = "regulator-fixed"; ++ regulator-name = "VCC-VDDQ-VIN0"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++}; ++ ++&du { + status = "okay"; + + ports { @@ -13750,10 +13927,10 @@ index 0000000..cdd9844 +}; diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf-cn11.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf-cn11.dtsi new file mode 100644 -index 0000000..b469ca6 +index 0000000..095a503 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/ulcb-kf-cn11.dtsi -@@ -0,0 +1,545 @@ +@@ -0,0 +1,498 @@ +/* + * Device Tree Source for the H3ULCB Kingfisher board: + * this adding conflicting resource on VIN4/VIN5/VIN6/VIN7 for CN11 @@ -13827,11 +14004,8 @@ index 0000000..b469ca6 + 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_ti9x4_des1ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep0>; + }; + }; + }; @@ -13851,11 +14025,8 @@ index 0000000..b469ca6 + 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_ti9x4_des1ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep1>; + }; + }; + }; @@ -13874,8 +14045,8 @@ index 0000000..b469ca6 + ov106xx_max9286_des1ep2: endpoint@0 { + remote-endpoint = <&max9286_des1ep2>; + }; -+ ov106xx_ti964_des1ep2: endpoint@1 { -+ remote-endpoint = <&ti964_des1ep2>; ++ ov106xx_ti9x4_des1ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep2>; + }; + }; + }; @@ -13894,15 +14065,15 @@ index 0000000..b469ca6 + ov106xx_max9286_des1ep3: endpoint@0 { + remote-endpoint = <&max9286_des1ep3>; + }; -+ ov106xx_ti964_des1ep3: endpoint@1 { -+ remote-endpoint = <&ti964_des1ep3>; ++ ov106xx_ti9x4_des1ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep3>; + }; + }; + }; + -+ /* DS90UB964 @ 0x3a */ -+ ti964-ti9x3@1 { -+ compatible = "ti,ti964-ti9x3"; ++ /* DS90UB9x4 @ 0x3a */ ++ ti9x4@1 { ++ compatible = "ti,ti9x4"; + reg = <0x3a>; + ti,sensor_delay = <350>; + ti,links = <4>; @@ -13915,64 +14086,29 @@ index 0000000..b469ca6 + POC3-supply = <&pwr3B>; + + port@0 { -+ ti964_des1ep0: endpoint@0 { ++ ti9x4_des1ep0: endpoint@0 { + ti9x3-addr = <0x0c>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in4>; + }; -+ ti964_des1ep1: endpoint@1 { ++ ti9x4_des1ep1: endpoint@1 { + ti9x3-addr = <0x0d>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in5>; + }; -+ ti964_des1ep2: endpoint@2 { ++ ti9x4_des1ep2: endpoint@2 { + ti9x3-addr = <0x0e>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in6>; + }; -+ ti964_des1ep3: endpoint@3 { ++ ti9x4_des1ep3: endpoint@3 { + ti9x3-addr = <0x0f>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in7>; + }; + }; + port@1 { -+ ti964_csi2ep0: endpoint { -+ csi-rate = <1450>; -+ remote-endpoint = <&csi2_41_ep>; -+ }; -+ }; -+ }; -+ -+ /* DS90UB954 @ 0x38 */ -+ ti954-ti9x3@1 { -+ compatible = "ti,ti954-ti9x3"; -+ reg = <0x38>; -+ /* gpios = <&video_b_ext1 10 GPIO_ACTIVE_HIGH>; */ -+ ti,sensor_delay = <350>; -+ ti,links = <2>; -+ ti,lanes = <4>; -+ ti,forwarding-mode = "round-robin"; -+ ti,cable-mode = "coax"; -+ POC0-supply = <&pwr0B>; -+ POC1-supply = <&pwr1B>; -+ POC2-supply = <&pwr2B>; -+ POC3-supply = <&pwr3B>; -+ -+ port@0 { -+ ti954_des1ep0: endpoint@0 { -+ ti9x3-addr = <0x0c>; -+ dvp-order = <0>; -+ remote-endpoint = <&ov106xx_in4>; -+ }; -+ ti954_des1ep1: endpoint@1 { -+ ti9x3-addr = <0x0d>; -+ dvp-order = <0>; -+ remote-endpoint = <&ov106xx_in5>; -+ }; -+ }; -+ port@1 { -+ ti954_csi2ep0: endpoint { ++ ti9x4_csi2ep0: endpoint { + csi-rate = <1450>; + remote-endpoint = <&csi2_41_ep>; + }; @@ -14162,11 +14298,8 @@ index 0000000..b469ca6 + 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>; ++ vin4_ti9x4_des1ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep0>; + }; + }; + }; @@ -14194,11 +14327,8 @@ index 0000000..b469ca6 + 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>; ++ vin5_ti9x4_des1ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep1>; + }; + }; + }; @@ -14228,8 +14358,8 @@ index 0000000..b469ca6 + vin6_max9286_des1ep2: endpoint@0 { + remote-endpoint = <&max9286_des1ep2>; + }; -+ vin6_ti964_des1ep2: endpoint@1 { -+ remote-endpoint = <&ti964_des1ep2>; ++ vin6_ti9x4_des1ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep2>; + }; + }; + }; @@ -14259,8 +14389,8 @@ index 0000000..b469ca6 + vin7_max9286_des1ep3: endpoint@0 { + remote-endpoint = <&max9286_des1ep3>; + }; -+ vin7_ti964_des1ep3: endpoint@1 { -+ remote-endpoint = <&ti964_des1ep3>; ++ vin7_ti9x4_des1ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep3>; + }; + }; + }; @@ -14389,10 +14519,10 @@ index 0000000..b854216 +}; diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi new file mode 100644 -index 0000000..56194b4 +index 0000000..a33a2a0 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi -@@ -0,0 +1,1538 @@ +@@ -0,0 +1,1492 @@ +/* + * Device Tree Source for the ULCB Kingfisher board + * @@ -15208,11 +15338,8 @@ index 0000000..56194b4 + 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_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; + }; + }; + }; @@ -15232,11 +15359,8 @@ index 0000000..56194b4 + 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_ti9x4_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep1>; + }; + }; + }; @@ -15256,8 +15380,8 @@ index 0000000..56194b4 + ov106xx_max9286_des0ep2: endpoint@0 { + remote-endpoint = <&max9286_des0ep2>; + }; -+ ov106xx_ti964_des0ep2: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep2>; ++ ov106xx_ti9x4_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep2>; + }; + }; + }; @@ -15277,15 +15401,15 @@ index 0000000..56194b4 + ov106xx_max9286_des0ep3: endpoint@0 { + remote-endpoint = <&max9286_des0ep3>; + }; -+ ov106xx_ti964_des0ep3: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep3>; ++ ov106xx_ti9x4_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep3>; + }; + }; + }; + -+ /* DS90UB964 @ 0x3a */ -+ ti964-ti9x3@0 { -+ compatible = "ti,ti964-ti9x3"; ++ /* DS90UB9x4 @ 0x3a */ ++ ti9x4@0 { ++ compatible = "ti,ti9x4"; + reg = <0x3a>; + ti,links = <4>; + ti,lanes = <4>; @@ -15297,63 +15421,29 @@ index 0000000..56194b4 + POC3-supply = <&pwr3A>; + + port@0 { -+ ti964_des0ep0: endpoint@0 { ++ ti9x4_des0ep0: endpoint@0 { + ti9x3-addr = <0x0c>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in0>; + }; -+ ti964_des0ep1: endpoint@1 { ++ ti9x4_des0ep1: endpoint@1 { + ti9x3-addr = <0x0d>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in1>; + }; -+ ti964_des0ep2: endpoint@2 { ++ ti9x4_des0ep2: endpoint@2 { + ti9x3-addr = <0x0e>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in2>; + }; -+ ti964_des0ep3: endpoint@3 { ++ ti9x4_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,links = <2>; -+ ti,lanes = <4>; -+ ti,forwarding-mode = "round-robin"; -+ ti,cable-mode = "coax"; -+ POC0-supply = <&pwr0A>; -+ POC1-supply = <&pwr1A>; -+ POC2-supply = <&pwr2A>; -+ POC3-supply = <&pwr3A>; -+ -+ port@0 { -+ ti954_des0ep0: endpoint@0 { -+ ti9x3-addr = <0x0c>; -+ dvp-order = <0>; -+ remote-endpoint = <&ov106xx_in0>; -+ }; -+ ti954_des0ep1: endpoint@1 { -+ ti9x3-addr = <0x0d>; -+ dvp-order = <0>; -+ remote-endpoint = <&ov106xx_in1>; -+ }; -+ }; -+ port@1 { -+ ti954_csi0ep0: endpoint { ++ ti9x4_csi0ep0: endpoint { + csi-rate = <1450>; + remote-endpoint = <&csi2_40_ep>; + }; @@ -15603,11 +15693,8 @@ index 0000000..56194b4 + 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>; ++ vin0_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; + }; + }; + }; @@ -15637,11 +15724,8 @@ index 0000000..56194b4 + 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>; ++ vin1_ti9x4_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep1>; + }; + }; + }; @@ -15671,8 +15755,8 @@ index 0000000..56194b4 + vin2_max9286_des0ep2: endpoint@0 { + remote-endpoint = <&max9286_des0ep2>; + }; -+ vin2_ti964_des0ep2: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep2>; ++ vin2_ti9x4_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep2>; + }; + }; + }; @@ -15702,8 +15786,8 @@ index 0000000..56194b4 + vin3_max9286_des0ep3: endpoint@0 { + remote-endpoint = <&max9286_des0ep3>; + }; -+ vin3_ti964_des0ep3: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep3>; ++ vin3_ti9x4_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep3>; + }; + }; + }; @@ -15933,10 +16017,10 @@ index 0000000..56194b4 + diff --git a/arch/arm64/boot/dts/renesas/ulcb-vb-cn12.dtsi b/arch/arm64/boot/dts/renesas/ulcb-vb-cn12.dtsi new file mode 100644 -index 0000000..df27324 +index 0000000..778a477 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/ulcb-vb-cn12.dtsi -@@ -0,0 +1,542 @@ +@@ -0,0 +1,495 @@ +/* + * Device Tree Source for the H3ULCB Videobox board: + * this adding conflicting resource on VIN4/VIN5/VIN6/VIN7 for CN12 @@ -16009,11 +16093,8 @@ index 0000000..df27324 + ov106xx_max9286_des2ep0: endpoint@0 { + remote-endpoint = <&max9286_des2ep0>; + }; -+ ov106xx_ti964_des2ep0: endpoint@1 { -+ remote-endpoint = <&ti964_des2ep0>; -+ }; -+ ov106xx_ti954_des2ep0: endpoint@2 { -+ remote-endpoint = <&ti954_des2ep0>; ++ ov106xx_ti9x4_des2ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des2ep0>; + }; + }; + }; @@ -16033,11 +16114,8 @@ index 0000000..df27324 + ov106xx_max9286_des2ep1: endpoint@0 { + remote-endpoint = <&max9286_des2ep1>; + }; -+ ov106xx_ti964_des2ep1: endpoint@1 { -+ remote-endpoint = <&ti964_des2ep1>; -+ }; -+ ov106xx_ti954_des2ep1: endpoint@2 { -+ remote-endpoint = <&ti954_des2ep1>; ++ ov106xx_ti9x4_des2ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des2ep1>; + }; + }; + }; @@ -16057,8 +16135,8 @@ index 0000000..df27324 + ov106xx_max9286_des2ep2: endpoint@0 { + remote-endpoint = <&max9286_des2ep2>; + }; -+ ov106xx_ti964_des2ep2: endpoint@1 { -+ remote-endpoint = <&ti964_des2ep2>; ++ ov106xx_ti9x4_des2ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des2ep2>; + }; + }; + }; @@ -16078,15 +16156,15 @@ index 0000000..df27324 + ov106xx_max9286_des2ep3: endpoint@0 { + remote-endpoint = <&max9286_des2ep3>; + }; -+ ov106xx_ti964_des2ep3: endpoint@1 { -+ remote-endpoint = <&ti964_des2ep3>; ++ ov106xx_ti9x4_des2ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des2ep3>; + }; + }; + }; + -+ /* DS90UB964 @ 0x3a */ -+ ti964-ti9x3@2 { -+ compatible = "ti,ti964-ti9x3"; ++ /* DS90UB9x4 @ 0x3a */ ++ ti9x4@2 { ++ compatible = "ti,ti9x4"; + reg = <0x3a>; + ti,sensor_delay = <350>; + ti,links = <4>; @@ -16099,64 +16177,29 @@ index 0000000..df27324 + POC3-supply = <&pwr3C>; + + port@0 { -+ ti964_des2ep0: endpoint@0 { ++ ti9x4_des2ep0: endpoint@0 { + ti9x3-addr = <0x0c>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in8>; + }; -+ ti964_des2ep1: endpoint@1 { ++ ti9x4_des2ep1: endpoint@1 { + ti9x3-addr = <0x0d>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in9>; + }; -+ ti964_des2ep2: endpoint@2 { ++ ti9x4_des2ep2: endpoint@2 { + ti9x3-addr = <0x0e>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in10>; + }; -+ ti964_des2ep3: endpoint@3 { ++ ti9x4_des2ep3: endpoint@3 { + ti9x3-addr = <0x0f>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in11>; + }; + }; + port@1 { -+ ti964_csi1ep0: endpoint { -+ csi-rate = <1450>; -+ remote-endpoint = <&csi2_20_ep>; -+ }; -+ }; -+ }; -+ -+ /* DS90UB954 @ 0x38 */ -+ ti954-ti9x3@2 { -+ compatible = "ti,ti954-ti9x3"; -+ reg = <0x38>; -+ /* gpios = <&gpio_exp_c_5c 10 GPIO_ACTIVE_HIGH>; */ -+ ti,sensor_delay = <350>; -+ ti,links = <2>; -+ ti,lanes = <2>; -+ ti,forwarding-mode = "round-robin"; -+ ti,cable-mode = "coax"; -+ POC0-supply = <&pwr0C>; -+ POC1-supply = <&pwr1C>; -+ POC2-supply = <&pwr2C>; -+ POC3-supply = <&pwr3C>; -+ -+ port@0 { -+ ti954_des2ep0: endpoint@0 { -+ ti9x3-addr = <0x0c>; -+ dvp-order = <0>; -+ remote-endpoint = <&ov106xx_in8>; -+ }; -+ ti954_des2ep1: endpoint@1 { -+ ti9x3-addr = <0x0d>; -+ dvp-order = <0>; -+ remote-endpoint = <&ov106xx_in9>; -+ }; -+ }; -+ port@1 { -+ ti954_csi1ep0: endpoint { ++ ti9x4_csi1ep0: endpoint { + csi-rate = <1450>; + remote-endpoint = <&csi2_20_ep>; + }; @@ -16346,11 +16389,8 @@ index 0000000..df27324 + vin4_max9286_des2ep0: endpoint@0 { + remote-endpoint = <&max9286_des2ep0>; + }; -+ vin4_ti964_des2ep0: endpoint@1 { -+ remote-endpoint = <&ti964_des2ep0>; -+ }; -+ vin4_ti954_des2ep0: endpoint@2 { -+ remote-endpoint = <&ti954_des2ep0>; ++ vin4_ti9x4_des2ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des2ep0>; + }; + }; + }; @@ -16378,11 +16418,8 @@ index 0000000..df27324 + vin5_max9286_des2ep1: endpoint@0 { + remote-endpoint = <&max9286_des2ep1>; + }; -+ vin5_ti964_des2ep1: endpoint@1 { -+ remote-endpoint = <&ti964_des2ep1>; -+ }; -+ vin5_ti954_des2ep1: endpoint@2 { -+ remote-endpoint = <&ti954_des2ep1>; ++ vin5_ti9x4_des2ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des2ep1>; + }; + }; + }; @@ -16410,8 +16447,8 @@ index 0000000..df27324 + vin6_max9286_des2ep2: endpoint@0 { + remote-endpoint = <&max9286_des2ep2>; + }; -+ vin6_ti964_des2ep2: endpoint@1 { -+ remote-endpoint = <&ti964_des2ep2>; ++ vin6_ti9x4_des2ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des2ep2>; + }; + }; + }; @@ -16439,8 +16476,8 @@ index 0000000..df27324 + vin7_max9286_des2ep3: endpoint@0 { + remote-endpoint = <&max9286_des2ep3>; + }; -+ vin7_ti964_des2ep3: endpoint@1 { -+ remote-endpoint = <&ti964_des2ep3>; ++ vin7_ti9x4_des2ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des2ep3>; + }; + }; + }; @@ -16481,10 +16518,10 @@ index 0000000..df27324 +}; diff --git a/arch/arm64/boot/dts/renesas/ulcb-vb.dtsi b/arch/arm64/boot/dts/renesas/ulcb-vb.dtsi new file mode 100644 -index 0000000..ab52fff +index 0000000..07594447 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/ulcb-vb.dtsi -@@ -0,0 +1,1770 @@ +@@ -0,0 +1,1678 @@ +/* + * Device Tree Source for the ULCB Videobox board + * @@ -17013,11 +17050,8 @@ index 0000000..ab52fff + 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_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; + }; + }; + }; @@ -17037,11 +17071,8 @@ index 0000000..ab52fff + 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_ti9x4_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep1>; + }; + }; + }; @@ -17061,8 +17092,8 @@ index 0000000..ab52fff + ov106xx_max9286_des0ep2: endpoint@0 { + remote-endpoint = <&max9286_des0ep2>; + }; -+ ov106xx_ti964_des0ep2: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep2>; ++ ov106xx_ti9x4_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep2>; + }; + }; + }; @@ -17082,15 +17113,15 @@ index 0000000..ab52fff + ov106xx_max9286_des0ep3: endpoint@0 { + remote-endpoint = <&max9286_des0ep3>; + }; -+ ov106xx_ti964_des0ep3: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep3>; ++ ov106xx_ti9x4_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep3>; + }; + }; + }; + -+ /* DS90UB964 @ 0x3a */ -+ ti964-ti9x3@0 { -+ compatible = "ti,ti964-ti9x3"; ++ /* DS90UB9x4 @ 0x3a */ ++ ti9x4@0 { ++ compatible = "ti,ti9x4"; + reg = <0x3a>; + ti,links = <4>; + ti,lanes = <4>; @@ -17102,63 +17133,29 @@ index 0000000..ab52fff + POC3-supply = <&pwr3A>; + + port@0 { -+ ti964_des0ep0: endpoint@0 { ++ ti9x4_des0ep0: endpoint@0 { + ti9x3-addr = <0x0c>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in0>; + }; -+ ti964_des0ep1: endpoint@1 { ++ ti9x4_des0ep1: endpoint@1 { + ti9x3-addr = <0x0d>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in1>; + }; -+ ti964_des0ep2: endpoint@2 { ++ ti9x4_des0ep2: endpoint@2 { + ti9x3-addr = <0x0e>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in2>; + }; -+ ti964_des0ep3: endpoint@3 { ++ ti9x4_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 = <&gpio_exp_a_5c 10 GPIO_ACTIVE_HIGH>; */ -+ ti,links = <2>; -+ ti,lanes = <4>; -+ ti,forwarding-mode = "round-robin"; -+ ti,cable-mode = "stp"; -+ POC0-supply = <&pwr0A>; -+ POC1-supply = <&pwr1A>; -+ POC2-supply = <&pwr2A>; -+ POC3-supply = <&pwr3A>; -+ -+ port@0 { -+ ti954_des0ep0: endpoint@0 { -+ ti9x3-addr = <0x0c>; -+ dvp-order = <0>; -+ remote-endpoint = <&ov106xx_in0>; -+ }; -+ ti954_des0ep1: endpoint@1 { -+ ti9x3-addr = <0x0d>; -+ dvp-order = <0>; -+ remote-endpoint = <&ov106xx_in1>; -+ }; -+ }; -+ port@1 { -+ ti954_csi0ep0: endpoint { ++ ti9x4_csi0ep0: endpoint { + csi-rate = <1450>; + remote-endpoint = <&csi2_40_ep>; + }; @@ -17231,11 +17228,8 @@ index 0000000..ab52fff + 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_ti9x4_des1ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep0>; + }; + }; + }; @@ -17255,11 +17249,8 @@ index 0000000..ab52fff + 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_ti9x4_des1ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep1>; + }; + }; + }; @@ -17279,8 +17270,8 @@ index 0000000..ab52fff + ov106xx_max9286_des1ep2: endpoint@0 { + remote-endpoint = <&max9286_des1ep2>; + }; -+ ov106xx_ti964_des1ep2: endpoint@1 { -+ remote-endpoint = <&ti964_des1ep2>; ++ ov106xx_ti9x4_des1ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep2>; + }; + }; + }; @@ -17300,15 +17291,15 @@ index 0000000..ab52fff + ov106xx_max9286_des1ep3: endpoint@0 { + remote-endpoint = <&max9286_des1ep3>; + }; -+ ov106xx_ti964_des1ep3: endpoint@1 { -+ remote-endpoint = <&ti964_des1ep3>; ++ ov106xx_ti9x4_des1ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep3>; + }; + }; + }; + -+ /* DS90UB964 @ 0x3a */ -+ ti964-ti9x3@1 { -+ compatible = "ti,ti964-ti9x3"; ++ /* DS90UB9x4 @ 0x3a */ ++ ti9x4@1 { ++ compatible = "ti,ti9x4"; + reg = <0x3a>; + ti,links = <4>; + ti,lanes = <4>; @@ -17320,63 +17311,29 @@ index 0000000..ab52fff + POC3-supply = <&pwr3B>; + + port@0 { -+ ti964_des1ep0: endpoint@0 { ++ ti9x4_des1ep0: endpoint@0 { + ti9x3-addr = <0x0c>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in4>; + }; -+ ti964_des1ep1: endpoint@1 { ++ ti9x4_des1ep1: endpoint@1 { + ti9x3-addr = <0x0d>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in5>; + }; -+ ti964_des1ep2: endpoint@2 { ++ ti9x4_des1ep2: endpoint@2 { + ti9x3-addr = <0x0e>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in6>; + }; -+ ti964_des1ep3: endpoint@3 { ++ ti9x4_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 = <&gpio_exp_b_5c 10 GPIO_ACTIVE_HIGH>; */ -+ ti,links = <2>; -+ ti,lanes = <4>; -+ ti,forwarding-mode = "round-robin"; -+ ti,cable-mode = "stp"; -+ POC0-supply = <&pwr0B>; -+ POC1-supply = <&pwr1B>; -+ POC2-supply = <&pwr2B>; -+ POC3-supply = <&pwr3B>; -+ -+ port@0 { -+ ti954_des1ep0: endpoint@0 { -+ ti9x3-addr = <0x0c>; -+ dvp-order = <0>; -+ remote-endpoint = <&ov106xx_in4>; -+ }; -+ ti954_des1ep1: endpoint@1 { -+ ti9x3-addr = <0x0d>; -+ dvp-order = <0>; -+ remote-endpoint = <&ov106xx_in5>; -+ }; -+ }; -+ port@1 { -+ ti954_csi2ep0: endpoint { ++ ti9x4_csi2ep0: endpoint { + csi-rate = <1450>; + remote-endpoint = <&csi2_41_ep>; + }; @@ -17866,11 +17823,8 @@ index 0000000..ab52fff + 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>; ++ vin0_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; + }; + }; + }; @@ -17900,11 +17854,8 @@ index 0000000..ab52fff + 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>; ++ vin1_ti9x4_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep1>; + }; + }; + }; @@ -17934,8 +17885,8 @@ index 0000000..ab52fff + vin2_max9286_des0ep2: endpoint@0 { + remote-endpoint = <&max9286_des0ep2>; + }; -+ vin2_ti964_des0ep2: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep2>; ++ vin2_ti9x4_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep2>; + }; + }; + }; @@ -17965,8 +17916,8 @@ index 0000000..ab52fff + vin3_max9286_des0ep3: endpoint@0 { + remote-endpoint = <&max9286_des0ep3>; + }; -+ vin3_ti964_des0ep3: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep3>; ++ vin3_ti9x4_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep3>; + }; + }; + }; @@ -17996,11 +17947,8 @@ index 0000000..ab52fff + 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>; ++ vin4_ti9x4_des1ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep0>; + }; + }; + }; @@ -18030,11 +17978,8 @@ index 0000000..ab52fff + 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>; ++ vin5_ti9x4_des1ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep1>; + }; + }; + }; @@ -18064,8 +18009,8 @@ index 0000000..ab52fff + vin6_max9286_des1ep2: endpoint@0 { + remote-endpoint = <&max9286_des1ep2>; + }; -+ vin6_ti964_des1ep2: endpoint@1 { -+ remote-endpoint = <&ti964_des1ep2>; ++ vin6_ti9x4_des1ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep2>; + }; + }; + }; @@ -18095,8 +18040,8 @@ index 0000000..ab52fff + vin7_max9286_des1ep3: endpoint@0 { + remote-endpoint = <&max9286_des1ep3>; + }; -+ vin7_ti964_des1ep3: endpoint@1 { -+ remote-endpoint = <&ti964_des1ep3>; ++ vin7_ti9x4_des1ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep3>; + }; + }; + }; @@ -18257,10 +18202,10 @@ index 0000000..ab52fff +//#include "ulcb-vb-cn12.dtsi" diff --git a/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi b/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi new file mode 100644 -index 0000000..72045a7 +index 0000000..b0145a2 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi -@@ -0,0 +1,1820 @@ +@@ -0,0 +1,1724 @@ +/* + * Device Tree Source for the ULCB Videobox V2 board + * @@ -18807,11 +18752,8 @@ index 0000000..72045a7 + 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_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; + }; + }; + }; @@ -18831,11 +18773,8 @@ index 0000000..72045a7 + 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_ti9x4_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep1>; + }; + }; + }; @@ -18855,8 +18794,8 @@ index 0000000..72045a7 + ov106xx_max9286_des0ep2: endpoint@0 { + remote-endpoint = <&max9286_des0ep2>; + }; -+ ov106xx_ti964_des0ep2: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep2>; ++ ov106xx_ti9x4_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep2>; + }; + }; + }; @@ -18876,15 +18815,15 @@ index 0000000..72045a7 + ov106xx_max9286_des0ep3: endpoint@0 { + remote-endpoint = <&max9286_des0ep3>; + }; -+ ov106xx_ti964_des0ep3: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep3>; ++ ov106xx_ti9x4_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep3>; + }; + }; + }; + -+ /* DS90UB964 @ 0x3a */ -+ ti964-ti9x3@0 { -+ compatible = "ti,ti964-ti9x3"; ++ /* DS90UB9x4 @ 0x3a */ ++ ti9x4@0 { ++ compatible = "ti,ti9x4"; + reg = <0x3a>; + ti,links = <4>; + ti,lanes = <4>; @@ -18896,63 +18835,29 @@ index 0000000..72045a7 + POC3-supply = <&pwr3A>; + + port@0 { -+ ti964_des0ep0: endpoint@0 { ++ ti9x4_des0ep0: endpoint@0 { + ti9x3-addr = <0x0c>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in0>; + }; -+ ti964_des0ep1: endpoint@1 { ++ ti9x4_des0ep1: endpoint@1 { + ti9x3-addr = <0x0d>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in1>; + }; -+ ti964_des0ep2: endpoint@2 { ++ ti9x4_des0ep2: endpoint@2 { + ti9x3-addr = <0x0e>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in2>; + }; -+ ti964_des0ep3: endpoint@3 { ++ ti9x4_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 = <&gpio_exp_a_5c 10 GPIO_ACTIVE_HIGH>; */ -+ ti,links = <2>; -+ ti,lanes = <4>; -+ ti,forwarding-mode = "round-robin"; -+ ti,cable-mode = "stp"; -+ POC0-supply = <&pwr0A>; -+ POC1-supply = <&pwr1A>; -+ POC2-supply = <&pwr2A>; -+ POC3-supply = <&pwr3A>; -+ -+ port@0 { -+ ti954_des0ep0: endpoint@0 { -+ ti9x3-addr = <0x0c>; -+ dvp-order = <0>; -+ remote-endpoint = <&ov106xx_in0>; -+ }; -+ ti954_des0ep1: endpoint@1 { -+ ti9x3-addr = <0x0d>; -+ dvp-order = <0>; -+ remote-endpoint = <&ov106xx_in1>; -+ }; -+ }; -+ port@1 { -+ ti954_csi0ep0: endpoint { ++ ti9x4_csi0ep0: endpoint { + csi-rate = <1450>; + remote-endpoint = <&csi2_40_ep>; + }; @@ -19025,11 +18930,8 @@ index 0000000..72045a7 + 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_ti9x4_des1ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep0>; + }; + }; + }; @@ -19049,11 +18951,8 @@ index 0000000..72045a7 + 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_ti9x4_des1ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep1>; + }; + }; + }; @@ -19073,8 +18972,8 @@ index 0000000..72045a7 + ov106xx_max9286_des1ep2: endpoint@0 { + remote-endpoint = <&max9286_des1ep2>; + }; -+ ov106xx_ti964_des1ep2: endpoint@1 { -+ remote-endpoint = <&ti964_des1ep2>; ++ ov106xx_ti9x4_des1ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep2>; + }; + }; + }; @@ -19094,15 +18993,15 @@ index 0000000..72045a7 + ov106xx_max9286_des1ep3: endpoint@0 { + remote-endpoint = <&max9286_des1ep3>; + }; -+ ov106xx_ti964_des1ep3: endpoint@1 { -+ remote-endpoint = <&ti964_des1ep3>; ++ ov106xx_ti9x4_des1ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep3>; + }; + }; + }; + -+ /* DS90UB964 @ 0x3a */ -+ ti964-ti9x3@1 { -+ compatible = "ti,ti964-ti9x3"; ++ /* DS90UB9x4 @ 0x3a */ ++ ti9x4@1 { ++ compatible = "ti,ti9x4"; + reg = <0x3a>; + ti,links = <4>; + ti,lanes = <4>; @@ -19114,63 +19013,29 @@ index 0000000..72045a7 + POC3-supply = <&pwr3B>; + + port@0 { -+ ti964_des1ep0: endpoint@0 { ++ ti9x4_des1ep0: endpoint@0 { + ti9x3-addr = <0x0c>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in4>; + }; -+ ti964_des1ep1: endpoint@1 { ++ ti9x4_des1ep1: endpoint@1 { + ti9x3-addr = <0x0d>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in5>; + }; -+ ti964_des1ep2: endpoint@2 { ++ ti9x4_des1ep2: endpoint@2 { + ti9x3-addr = <0x0e>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in6>; + }; -+ ti964_des1ep3: endpoint@3 { ++ ti9x4_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 = <&gpio_exp_b_5c 10 GPIO_ACTIVE_HIGH>; */ -+ ti,links = <2>; -+ ti,lanes = <4>; -+ ti,forwarding-mode = "round-robin"; -+ ti,cable-mode = "stp"; -+ POC0-supply = <&pwr0B>; -+ POC1-supply = <&pwr1B>; -+ POC2-supply = <&pwr2B>; -+ POC3-supply = <&pwr3B>; -+ -+ port@0 { -+ ti954_des1ep0: endpoint@0 { -+ ti9x3-addr = <0x0c>; -+ dvp-order = <0>; -+ remote-endpoint = <&ov106xx_in4>; -+ }; -+ ti954_des1ep1: endpoint@1 { -+ ti9x3-addr = <0x0d>; -+ dvp-order = <0>; -+ remote-endpoint = <&ov106xx_in5>; -+ }; -+ }; -+ port@1 { -+ ti954_csi2ep0: endpoint { ++ ti9x4_csi2ep0: endpoint { + csi-rate = <1450>; + remote-endpoint = <&csi2_41_ep>; + }; @@ -19680,11 +19545,8 @@ index 0000000..72045a7 + 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>; ++ vin0_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; + }; + }; + }; @@ -19714,11 +19576,8 @@ index 0000000..72045a7 + 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>; ++ vin1_ti9x4_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep1>; + }; + }; + }; @@ -19748,8 +19607,8 @@ index 0000000..72045a7 + vin2_max9286_des0ep2: endpoint@0 { + remote-endpoint = <&max9286_des0ep2>; + }; -+ vin2_ti964_des0ep2: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep2>; ++ vin2_ti9x4_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep2>; + }; + }; + }; @@ -19779,8 +19638,8 @@ index 0000000..72045a7 + vin3_max9286_des0ep3: endpoint@0 { + remote-endpoint = <&max9286_des0ep3>; + }; -+ vin3_ti964_des0ep3: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep3>; ++ vin3_ti9x4_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep3>; + }; + }; + }; @@ -19810,11 +19669,8 @@ index 0000000..72045a7 + 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>; ++ vin4_ti9x4_des1ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep0>; + }; + }; + }; @@ -19844,11 +19700,8 @@ index 0000000..72045a7 + 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>; ++ vin5_ti9x4_des1ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep1>; + }; + }; + }; @@ -19878,8 +19731,8 @@ index 0000000..72045a7 + vin6_max9286_des1ep2: endpoint@0 { + remote-endpoint = <&max9286_des1ep2>; + }; -+ vin6_ti964_des1ep2: endpoint@1 { -+ remote-endpoint = <&ti964_des1ep2>; ++ vin6_ti9x4_des1ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep2>; + }; + }; + }; @@ -19909,8 +19762,8 @@ index 0000000..72045a7 + vin7_max9286_des1ep3: endpoint@0 { + remote-endpoint = <&max9286_des1ep3>; + }; -+ vin7_ti964_des1ep3: endpoint@1 { -+ remote-endpoint = <&ti964_des1ep3>; ++ vin7_ti9x4_des1ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des1ep3>; + }; + }; + }; @@ -20083,7 +19936,7 @@ index 0000000..72045a7 +//#include "ulcb-vb2-cn12.dtsi" diff --git a/arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi b/arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi new file mode 100644 -index 0000000..2be4a7c +index 0000000..bc36e95 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi @@ -0,0 +1,577 @@ @@ -20281,8 +20134,8 @@ index 0000000..2be4a7c + ov106xx_max9286_des0ep0: endpoint@0 { + remote-endpoint = <&max9286_des0ep0>; + }; -+ ov106xx_ti964_des0ep0: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep0>; ++ ov106xx_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; + }; + }; + }; @@ -20302,8 +20155,8 @@ index 0000000..2be4a7c + ov106xx_max9286_des0ep1: endpoint@0 { + remote-endpoint = <&max9286_des0ep1>; + }; -+ ov106xx_ti964_des0ep1: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep1>; ++ ov106xx_ti9x4_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep1>; + }; + }; + }; @@ -20323,8 +20176,8 @@ index 0000000..2be4a7c + ov106xx_max9286_des0ep2: endpoint@0 { + remote-endpoint = <&max9286_des0ep2>; + }; -+ ov106xx_ti964_des0ep2: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep2>; ++ ov106xx_ti9x4_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep2>; + }; + }; + }; @@ -20344,8 +20197,8 @@ index 0000000..2be4a7c + ov106xx_max9286_des0ep3: endpoint@0 { + remote-endpoint = <&max9286_des0ep3>; + }; -+ ov106xx_ti964_des0ep3: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep3>; ++ ov106xx_ti9x4_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep3>; + }; + }; + }; @@ -20393,8 +20246,8 @@ index 0000000..2be4a7c + }; + }; + -+ ti964-ti9x3@0 { -+ compatible = "ti,ti964-ti9x3"; ++ ti9x4@0 { ++ compatible = "ti,ti9x4"; + reg = <0x3a>; + ti,sensor_delay = <350>; + ti,links = <4>; @@ -20407,29 +20260,29 @@ index 0000000..2be4a7c + POC3-supply = <&pwr3>; + + port@0 { -+ ti964_des0ep0: endpoint@0 { ++ ti9x4_des0ep0: endpoint@0 { + ti9x3-addr = <0x0c>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in0>; + }; -+ ti964_des0ep1: endpoint@1 { ++ ti9x4_des0ep1: endpoint@1 { + ti9x3-addr = <0x0d>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in1>; + }; -+ ti964_des0ep2: endpoint@2 { ++ ti9x4_des0ep2: endpoint@2 { + ti9x3-addr = <0x0e>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in2>; + }; -+ ti964_des0ep3: endpoint@3 { ++ ti9x4_des0ep3: endpoint@3 { + ti9x3-addr = <0x0f>; + dvp-order = <0>; + remote-endpoint = <&ov106xx_in3>; + }; + }; + port@1 { -+ ti964_csi0ep0: endpoint { ++ ti9x4_csi0ep0: endpoint { + csi-rate = <1450>; + remote-endpoint = <&csi2_41_ep>; + }; @@ -20564,8 +20417,8 @@ index 0000000..2be4a7c + vin4_max9286_des0ep0: endpoint@0 { + remote-endpoint = <&max9286_des0ep0>; + }; -+ vin4_ti964_des0ep0: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep0>; ++ vin4_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; + }; + }; + }; @@ -20595,8 +20448,8 @@ index 0000000..2be4a7c + vin5_max9286_des0ep1: endpoint@0 { + remote-endpoint = <&max9286_des0ep1>; + }; -+ vin5_ti964_des0ep1: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep1>; ++ vin5_ti9x4_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep1>; + }; + }; + }; @@ -20626,8 +20479,8 @@ index 0000000..2be4a7c + vin6_max9286_des0ep2: endpoint@0 { + remote-endpoint = <&max9286_des0ep2>; + }; -+ vin6_ti964_des0ep2: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep2>; ++ vin6_ti9x4_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep2>; + }; + }; + }; @@ -20657,8 +20510,8 @@ index 0000000..2be4a7c + vin7_max9286_des0ep3: endpoint@0 { + remote-endpoint = <&max9286_des0ep3>; + }; -+ vin7_ti964_des0ep3: endpoint@1 { -+ remote-endpoint = <&ti964_des0ep3>; ++ vin7_ti9x4_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep3>; + }; + }; + }; diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/condor.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/condor.cfg index c32c426..9b2a6a9 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/condor.cfg +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/condor.cfg @@ -18,7 +18,7 @@ CONFIG_VIDEO_RCAR_CSI2_LEGACY=y CONFIG_SOC_CAMERA=y CONFIG_SOC_CAMERA_SCALE_CROP=y CONFIG_SOC_CAMERA_PLATFORM=y -CONFIG_SOC_CAMERA_MAX9286_MAX9271=y +CONFIG_SOC_CAMERA_MAX9286=y CONFIG_SOC_CAMERA_OV106XX=y CONFIG_VIDEO_RENESAS_IMR=y CONFIG_INPUT_TOUCHSCREEN=y 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 index ce08b0d..f6ae11f 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/eagle.cfg +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/eagle.cfg @@ -18,7 +18,7 @@ CONFIG_VIDEO_RCAR_CSI2_LEGACY=y CONFIG_SOC_CAMERA=y CONFIG_SOC_CAMERA_SCALE_CROP=y CONFIG_SOC_CAMERA_PLATFORM=y -CONFIG_SOC_CAMERA_MAX9286_MAX9271=y +CONFIG_SOC_CAMERA_MAX9286=y CONFIG_SOC_CAMERA_OV106XX=y CONFIG_VIDEO_RENESAS_IMR=y CONFIG_INPUT_TOUCHSCREEN=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 index a42b74c..36c6103 100644 --- 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 @@ -17,7 +17,7 @@ CONFIG_VIDEO_RCAR_CSI2_LEGACY=y CONFIG_SOC_CAMERA=y CONFIG_SOC_CAMERA_SCALE_CROP=y CONFIG_SOC_CAMERA_PLATFORM=y -CONFIG_SOC_CAMERA_MAX9286_MAX9271=y +CONFIG_SOC_CAMERA_MAX9286=y CONFIG_SOC_CAMERA_OV106XX=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_PLATFORM=y diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/ulcb.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/ulcb.cfg index ed9fcb8..49f841f 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/ulcb.cfg +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/ulcb.cfg @@ -27,9 +27,8 @@ CONFIG_VIDEO_RCAR_CSI2_LEGACY=y 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_MAX9286=y +CONFIG_SOC_CAMERA_TI9X4=y CONFIG_SOC_CAMERA_OV106XX=y CONFIG_SOC_CAMERA_OV5647=y CONFIG_SOC_CAMERA_OV5642=y diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3msk.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3msk.cfg index 7dea6e2..1a3ba75 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3msk.cfg +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3msk.cfg @@ -21,9 +21,8 @@ CONFIG_VIDEO_RCAR_CSI2_LEGACY=y 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_MAX9286=y +CONFIG_SOC_CAMERA_TI9X4=y CONFIG_SOC_CAMERA_OV106XX=y CONFIG_VIDEO_RENESAS_IMR=y CONFIG_INPUT_TOUCHSCREEN=y -- cgit 1.2.3-korg From 01234698d62d3315689b08ad5c648e253206310b Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Fri, 2 Feb 2018 15:54:14 +0300 Subject: LVDS: remove helper patches for vendor cameras Remove these helper patches since it is possible to adjust cameras feature in kernel command line now --- ...ts-Gen3-view-boards-TYPE1-first-4-cameras.patch | 302 ------------ ...s-Gen3-view-boards-TYPE1-second-4-cameras.patch | 206 -------- ...ts-Gen3-view-boards-TYPE2-first-4-cameras.patch | 527 --------------------- .../linux/linux-renesas_4.9.bbappend | 3 - 4 files changed, 1038 deletions(-) delete mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0050-arm64-dts-Gen3-view-boards-TYPE1-first-4-cameras.patch delete mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-dts-Gen3-view-boards-TYPE1-second-4-cameras.patch delete mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0052-arm64-dts-Gen3-view-boards-TYPE2-first-4-cameras.patch (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') 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 deleted file mode 100644 index d368b6a..0000000 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0050-arm64-dts-Gen3-view-boards-TYPE1-first-4-cameras.patch +++ /dev/null @@ -1,302 +0,0 @@ -From 67d29f4fe320f555366ea45f5439ac52641472ec Mon Sep 17 00:00:00 2001 -From: Vladimir Barinov -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 ---- - 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 deleted file mode 100644 index a09c485..0000000 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-dts-Gen3-view-boards-TYPE1-second-4-cameras.patch +++ /dev/null @@ -1,206 +0,0 @@ -From d9ec2149ffc47fd2ea4ab5e9a503a3be7c6f09f5 Mon Sep 17 00:00:00 2001 -From: Vladimir Barinov -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 ---- - 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 deleted file mode 100644 index 2c4d9f3..0000000 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0052-arm64-dts-Gen3-view-boards-TYPE2-first-4-cameras.patch +++ /dev/null @@ -1,527 +0,0 @@ -From fa7c75c71d40c8ce44b0fbaea79031daaede2ba7 Mon Sep 17 00:00:00 2001 -From: Vladimir Barinov -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 ---- - 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_4.9.bbappend b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas_4.9.bbappend index ce41fa8..2d0bdf6 100644 --- 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 @@ -53,9 +53,6 @@ SRC_URI_append = " \ file://0049-clk-r8a779x-add-IMP-clock.patch \ file://0050-arm64-dts-renesas-r8a779x-add-IMP-nodes.patch \ file://0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.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)} \ file://0062-IIO-lsm9ds0-add-IMU-driver.patch \ file://0063-ASoC-PCM3168A-add-TDM-modes-merge-ADC-and-DAC.patch \ file://0064-ADV7511-limit-maximum-pixelclock.patch \ -- cgit 1.2.3-korg From 9c717d4c64142e4599585256245b75cc122cacd4 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Fri, 2 Feb 2018 18:16:59 +0300 Subject: LVDS: move from poc-supply to poc-gpios Use gpiod instead of gpio regulator in LVDS drivers This is ruquired to remove patch: 0035-regulator-fixed-probe-after-i2c.patch The above patch breaks regulators support on Kingfisher board --- .../linux-renesas/0030-Gen3-LVDS-cameras.patch | 65 +-- .../0040-arm64-dts-renesas-add-ADAS-boards.patch | 592 +++++---------------- 2 files changed, 163 insertions(+), 494 deletions(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') 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 index 3c80601..2c3b903 100644 --- 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 @@ -18,7 +18,7 @@ Signed-off-by: Vladimir Barinov drivers/media/i2c/soc_camera/ar0132.h | 213 ++++ drivers/media/i2c/soc_camera/ar0220.c | 528 ++++++++++ drivers/media/i2c/soc_camera/ar0220.h | 309 ++++++ - drivers/media/i2c/soc_camera/max9286.c | 697 +++++++++++++ + drivers/media/i2c/soc_camera/max9286.c | 692 +++++++++++++ drivers/media/i2c/soc_camera/max9286.h | 244 +++++ drivers/media/i2c/soc_camera/ov10635.c | 759 ++++++++++++++ drivers/media/i2c/soc_camera/ov10635.h | 1139 ++++++++++++++++++++++ @@ -28,7 +28,7 @@ Signed-off-by: Vladimir Barinov drivers/media/i2c/soc_camera/ov490_ov10640.h | 102 ++ drivers/media/i2c/soc_camera/ov495_ov2775.c | 639 ++++++++++++ drivers/media/i2c/soc_camera/ov495_ov2775.h | 23 + - drivers/media/i2c/soc_camera/ti9x4.c | 520 ++++++++++ + drivers/media/i2c/soc_camera/ti9x4.c | 518 ++++++++++ drivers/media/i2c/soc_camera/ti9x4.h | 156 +++ drivers/media/platform/soc_camera/rcar_csi2.c | 297 ++++-- drivers/media/platform/soc_camera/rcar_vin.c | 194 +++- @@ -36,7 +36,7 @@ Signed-off-by: Vladimir Barinov drivers/media/platform/soc_camera/soc_mediabus.c | 16 + include/media/drv-intf/soc_mediabus.h | 3 + include/media/soc_camera.h | 1 + - 26 files changed, 8291 insertions(+), 109 deletions(-) + 26 files changed, 8284 insertions(+), 109 deletions(-) create mode 100644 drivers/media/i2c/soc_camera/ap0101_ar014x.c create mode 100644 drivers/media/i2c/soc_camera/ap0101_ar014x.h create mode 100644 drivers/media/i2c/soc_camera/ar0132.c @@ -2130,10 +2130,10 @@ index 0000000..29987a6 +}; diff --git a/drivers/media/i2c/soc_camera/max9286.c b/drivers/media/i2c/soc_camera/max9286.c new file mode 100644 -index 0000000..4dd80f5 +index 0000000..c850196 --- /dev/null +++ b/drivers/media/i2c/soc_camera/max9286.c -@@ -0,0 +1,697 @@ +@@ -0,0 +1,692 @@ +/* + * MAXIM max9286 GMSL driver + * @@ -2150,7 +2150,6 @@ index 0000000..4dd80f5 +#include +#include +#include -+#include +#include + +#include @@ -2193,7 +2192,7 @@ index 0000000..4dd80f5 + struct i2c_client *client; + int max9271_addr_map[4]; + int ser_id; -+ struct regulator *poc_supply[4]; /* PoC power supply */ ++ struct gpio_desc *poc_gpio[4]; /* PoC power supply */ +}; + +static char fsync_mode_default[20] = "manual"; /* manual, automatic, semi-automatic, external */ @@ -2355,12 +2354,10 @@ index 0000000..4dd80f5 + } + + if (timeout == priv->timeout / 2 && poc_trig) { -+ if (!IS_ERR(priv->poc_supply[idx])) { -+ if (regulator_disable(priv->poc_supply[idx])) -+ dev_err(&client->dev, "fail to disable POC%d regulator\n", idx); ++ if (!IS_ERR(priv->poc_gpio[idx])) { ++ gpiod_direction_output(priv->poc_gpio[idx], 0); /* POC power off */ + mdelay(200); -+ if (regulator_enable(priv->poc_supply[idx])) -+ dev_err(&client->dev, "fail to enable POC%d regulator\n", idx); ++ gpiod_direction_output(priv->poc_gpio[idx], 1); /* POC power on */ + mdelay(priv->poc_delay); + } + } @@ -2499,9 +2496,8 @@ index 0000000..4dd80f5 + max9286_initial_setup(client); + + for (idx = 0; idx < priv->links; idx++) { -+ if (!IS_ERR(priv->poc_supply[idx])) { -+ if (regulator_enable(priv->poc_supply[idx])) -+ dev_err(&client->dev, "fail to enable POC%d regulator\n", idx); ++ if (!IS_ERR(priv->poc_gpio[idx])) { ++ gpiod_direction_output(priv->poc_gpio[idx], 1); /* POC power on */ + mdelay(priv->poc_delay); + } + @@ -2609,8 +2605,8 @@ index 0000000..4dd80f5 + struct property *prop; + int err, pwen, i; + int sensor_delay, gpio0 = 1, gpio1 = 1; -+ + u8 val = 0; ++ char poc_name[10]; + + if (of_property_read_u32(np, "maxim,links", &priv->links)) + priv->links = 4; @@ -2627,6 +2623,11 @@ index 0000000..4dd80f5 + + mdelay(250); + ++ for (i = 0; i < 4; i++) { ++ sprintf(poc_name, "POC%d", i); ++ priv->poc_gpio[i] = devm_gpiod_get_optional(&client->dev, poc_name, 0); ++ } ++ + reg8_read(client, 0x1e, &val); /* read max9286 ID */ + if (val != MAX9286_ID) { + prop = of_find_property(np, "reg", NULL); @@ -2744,7 +2745,6 @@ index 0000000..4dd80f5 +{ + struct max9286_priv *priv; + int err, i; -+ char supply_name[10]; + + priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) @@ -2760,11 +2760,6 @@ index 0000000..4dd80f5 + if (err) + goto out; + -+ for (i = 0; i < 4; i++) { -+ sprintf(supply_name, "POC%d", i); -+ priv->poc_supply[i] = devm_regulator_get_optional(&client->dev, supply_name); -+ } -+ + err = max9286_initialize(client); + if (err < 0) + goto out; @@ -7108,11 +7103,11 @@ index 0000000..3f53689 +}; diff --git a/drivers/media/i2c/soc_camera/ti9x4.c b/drivers/media/i2c/soc_camera/ti9x4.c new file mode 100644 -index 0000000..aac892b +index 0000000..a4c7b3f --- /dev/null +++ b/drivers/media/i2c/soc_camera/ti9x4.c -@@ -0,0 +1,520 @@ -+/* +@@ -0,0 +1,518 @@ ++ /* + * TI DS90UB954/960/964 FPDLinkIII driver + * + * Copyright (C) 2017-2018 Cogent Embedded, Inc. @@ -7128,7 +7123,6 @@ index 0000000..aac892b +#include +#include +#include -+#include +#include + +#include @@ -7156,7 +7150,7 @@ index 0000000..aac892b + int ti9x3_addr_map[4]; + char chip_id[6]; + int ser_id; -+ struct regulator *poc_supply[4]; /* PoC power supply */ ++ struct gpio_desc *poc_gpio[4]; /* PoC power supply */ +}; + +static int ser_id; @@ -7350,9 +7344,8 @@ index 0000000..aac892b + ti9x4_initial_setup(client); + + for (idx = 0; idx < priv->links; idx++) { -+ if (!IS_ERR(priv->poc_supply[idx])) { -+ if (regulator_enable(priv->poc_supply[idx])) -+ dev_err(&client->dev, "fail to enable POC%d regulator\n", idx); ++ if (!IS_ERR(priv->poc_gpio[idx])) { ++ gpiod_direction_output(priv->poc_gpio[idx], 1); /* POC power on */ + mdelay(priv->poc_delay); + } + @@ -7443,6 +7436,7 @@ index 0000000..aac892b + char forwarding_mode_default[20] = "round-robin"; /* round-robin, synchronized */ + struct property *csi_rate_prop, *dvp_order_prop; + u8 val = 0; ++ char poc_name[10]; + + if (of_property_read_u32(np, "ti,links", &priv->links)) + priv->links = 4; @@ -7459,6 +7453,11 @@ index 0000000..aac892b + mdelay(250); + } + ++ for (i = 0; i < 4; i++) { ++ sprintf(poc_name, "POC%d", i); ++ priv->poc_gpio[i] = devm_gpiod_get_optional(&client->dev, poc_name, 0); ++ } ++ + reg8_read(client, 0x00, &val); /* read TI9x4 I2C address */ + if (val != (priv->des_addr << 1)) { + prop = of_find_property(np, "reg", NULL); @@ -7547,7 +7546,6 @@ index 0000000..aac892b +{ + struct ti9x4_priv *priv; + int err, i; -+ char supply_name[10]; + + priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) @@ -7562,11 +7560,6 @@ index 0000000..aac892b + if (err) + goto out; + -+ for (i = 0; i < 4; i++) { -+ sprintf(supply_name, "POC%d", i); -+ priv->poc_supply[i] = devm_regulator_get_optional(&client->dev, supply_name); -+ } -+ + err = ti9x4_initialize(client); + if (err < 0) + goto out; diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch index b351089..b33ccc9 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch @@ -33,11 +33,11 @@ Signed-off-by: Vladimir Barinov --- arch/arm64/boot/dts/renesas/Makefile | 22 + arch/arm64/boot/dts/renesas/legacy/Makefile | 8 + - .../renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts | 1624 ++++++++++++++++++ - .../renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts | 441 +++++ + .../renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts | 1624 +++++++++++++++++++ + .../renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts | 441 ++++++ .../dts/renesas/legacy/r8a7795-h3ulcb-kf-v0.dts | 1638 +++++++++++++++++++ .../dts/renesas/legacy/r8a7795-h3ulcb-kf-v1.dts | 465 ++++++ - .../dts/renesas/legacy/r8a7796-m3ulcb-kf-v0.dts | 1171 +++++++++++++ + .../dts/renesas/legacy/r8a7796-m3ulcb-kf-v0.dts | 1171 ++++++++++++++ .../dts/renesas/legacy/r8a7796-m3ulcb-kf-v1.dts | 465 ++++++ .../dts/renesas/legacy/r8a7797-v3msk-kf-v0.dts | 82 + .../boot/dts/renesas/legacy/ulcb-kf-cmos.dtsi | 75 + @@ -49,7 +49,7 @@ Signed-off-by: Vladimir Barinov .../boot/dts/renesas/r8a7795-es1-h3ulcb-vb.dts | 69 + .../boot/dts/renesas/r8a7795-es1-h3ulcb-vb2.dts | 77 + .../boot/dts/renesas/r8a7795-es1-h3ulcb-vbm.dts | 26 + - .../boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts | 544 ++++++ + .../boot/dts/renesas/r8a7795-es1-h3ulcb-view.dts | 544 +++++++ .../dts/renesas/r8a7795-es1-salvator-x-view.dts | 550 +++++++ .../boot/dts/renesas/r8a7795-h3ulcb-had-alfa.dts | 22 + .../boot/dts/renesas/r8a7795-h3ulcb-had-beta.dts | 23 + @@ -58,28 +58,28 @@ Signed-off-by: Vladimir Barinov arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vb.dts | 68 + arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vb2.dts | 68 + arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vbm.dts | 26 + - .../arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts | 544 ++++++ + .../arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts | 544 +++++++ .../boot/dts/renesas/r8a7795-salvator-x-view.dts | 550 +++++++ arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts | 40 + .../arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts | 286 ++++ .../boot/dts/renesas/r8a7796-salvator-x-view.dts | 317 ++++ .../boot/dts/renesas/r8a7797-eagle-function.dts | 62 + arch/arm64/boot/dts/renesas/r8a7797-eagle.dts | 575 +++++++ - arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts | 533 ++++++ - arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts | 548 +++++++ + arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts | 520 ++++++ + arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts | 513 ++++++ arch/arm64/boot/dts/renesas/r8a7797-v3msk-view.dts | 297 ++++ arch/arm64/boot/dts/renesas/r8a7797-v3msk.dts | 314 ++++ arch/arm64/boot/dts/renesas/r8a7797-v3mzf.dts | 424 +++++ - arch/arm64/boot/dts/renesas/r8a7798-condor.dts | 963 +++++++++++ - arch/arm64/boot/dts/renesas/ulcb-kf-cn11.dtsi | 498 ++++++ + arch/arm64/boot/dts/renesas/r8a7798-condor.dts | 963 ++++++++++++ + arch/arm64/boot/dts/renesas/ulcb-kf-cn11.dtsi | 462 ++++++ arch/arm64/boot/dts/renesas/ulcb-kf-most.dtsi | 30 + arch/arm64/boot/dts/renesas/ulcb-kf-sd3.dtsi | 46 + - arch/arm64/boot/dts/renesas/ulcb-kf.dtsi | 1492 +++++++++++++++++ - arch/arm64/boot/dts/renesas/ulcb-vb-cn12.dtsi | 495 ++++++ - arch/arm64/boot/dts/renesas/ulcb-vb.dtsi | 1678 +++++++++++++++++++ - arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi | 1724 ++++++++++++++++++++ - arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi | 577 +++++++ - 48 files changed, 20093 insertions(+) + arch/arm64/boot/dts/renesas/ulcb-kf.dtsi | 1458 +++++++++++++++++ + arch/arm64/boot/dts/renesas/ulcb-vb-cn12.dtsi | 459 ++++++ + arch/arm64/boot/dts/renesas/ulcb-vb.dtsi | 1610 +++++++++++++++++++ + arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi | 1656 ++++++++++++++++++++ + arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi | 543 +++++++ + 48 files changed, 19769 insertions(+) create mode 100644 arch/arm64/boot/dts/renesas/legacy/Makefile create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts @@ -10812,10 +10812,10 @@ index 0000000..ce7a88e +}; diff --git a/arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts new file mode 100644 -index 0000000..c61b613 +index 0000000..862236f --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts -@@ -0,0 +1,533 @@ +@@ -0,0 +1,520 @@ +/* + * Device Tree Source for the V3MSK Kingfisher board on r8a7797 + * @@ -10999,6 +10999,11 @@ index 0000000..c61b613 + ti,forwarding-mode = "round-robin"; + ti,cable-mode = "coax"; + ++ POC0-gpios = <&gpio_exp_a_5c 8 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_a_5c 9 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_a_5c 10 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_a_5c 11 GPIO_ACTIVE_HIGH>; ++ + port@0 { + ti9x4_des0ep0: endpoint@0 { + ti9x3-addr = <0x0c>; @@ -11039,6 +11044,11 @@ index 0000000..c61b613 + maxim,fsync-mode = "automatic"; + maxim,timeout = <100>; + ++ POC0-gpios = <&gpio_exp_a_5c 9 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_a_5c 8 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_a_5c 11 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_a_5c 10 GPIO_ACTIVE_HIGH>; ++ + port@0 { + max9286_des0ep0: endpoint@0 { + max9271-addr = <0x50>; @@ -11076,9 +11086,10 @@ index 0000000..c61b613 + reg = <6>; + /* Slot B (CN11) */ + -+ video_a_ext0: pca9535@27 { ++ /* PCA9535 is a redundant/deprecated card */ ++ gpio_exp_a_26: gpio@26 { + compatible = "nxp,pca9535"; -+ reg = <0x27>; ++ reg = <0x26>; + gpio-controller; + #gpio-cells = <2>; + @@ -11138,7 +11149,7 @@ index 0000000..c61b613 + }; + }; + -+ video_a_ext1: max7325@5c { ++ gpio_exp_a_5c: gpio@5c { + compatible = "maxim,max7325"; + reg = <0x5c>; + gpio-controller; @@ -11168,30 +11179,6 @@ index 0000000..c61b613 + output-high; + line-name = "Video-A PWR_SHDN"; + }; -+ video_a_cam_pwr0 { -+ gpio-hog; -+ gpios = <8 GPIO_ACTIVE_HIGH>; -+ output-high; -+ line-name = "Video-A PWR0"; -+ }; -+ video_a_cam_pwr1 { -+ gpio-hog; -+ gpios = <9 GPIO_ACTIVE_HIGH>; -+ output-high; -+ line-name = "Video-A PWR1"; -+ }; -+ video_a_cam_pwr2 { -+ gpio-hog; -+ gpios = <10 GPIO_ACTIVE_HIGH>; -+ output-high; -+ line-name = "Video-A PWR2"; -+ }; -+ video_a_cam_pwr3 { -+ gpio-hog; -+ gpios = <11 GPIO_ACTIVE_HIGH>; -+ output-high; -+ line-name = "Video-A PWR3"; -+ }; + video_a_des_shdn { + gpio-hog; + gpios = <13 GPIO_ACTIVE_HIGH>; @@ -11351,10 +11338,10 @@ index 0000000..c61b613 +}; diff --git a/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts new file mode 100644 -index 0000000..d355adb +index 0000000..226b659 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts -@@ -0,0 +1,548 @@ +@@ -0,0 +1,513 @@ +/* + * Device Tree Source for the V3MSK Videobox Mini board on r8a7797 + * @@ -11373,42 +11360,6 @@ index 0000000..d355adb + aliases { + serial1 = &scif3; + }; -+ -+ pwr0: regulator-pwr0 { -+ compatible = "regulator-fixed"; -+ regulator-name = "PWR0"; -+ regulator-min-microvolt = <9000000>; -+ regulator-max-microvolt = <9000000>; -+ gpio = <&gpio_exp_6c 8 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ }; -+ -+ pwr1: regulator-pwr1 { -+ compatible = "regulator-fixed"; -+ regulator-name = "PWR1"; -+ regulator-min-microvolt = <9000000>; -+ regulator-max-microvolt = <9000000>; -+ gpio = <&gpio_exp_6c 9 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ }; -+ -+ pwr2: regulator-pwr2 { -+ compatible = "regulator-fixed"; -+ regulator-name = "PWR2"; -+ regulator-min-microvolt = <9000000>; -+ regulator-max-microvolt = <9000000>; -+ gpio = <&gpio_exp_6c 10 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ }; -+ -+ pwr3: regulator-pwr3 { -+ compatible = "regulator-fixed"; -+ regulator-name = "PWR3"; -+ regulator-min-microvolt = <9000000>; -+ regulator-max-microvolt = <9000000>; -+ gpio = <&gpio_exp_6c 11 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ }; +}; + +&canfd { @@ -11570,10 +11521,11 @@ index 0000000..d355adb + maxim,resetb-gpio = <1>; + maxim,fsync-mode = "automatic"; + maxim,timeout = <100>; -+ POC0-supply = <&pwr0>; -+ POC1-supply = <&pwr1>; -+ POC2-supply = <&pwr2>; -+ POC3-supply = <&pwr3>; ++ ++ POC0-gpios = <&gpio_exp_6c 9 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_6c 8 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_6c 11 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_6c 10 GPIO_ACTIVE_HIGH>; + + port@0 { + max9286_des0ep0: endpoint@0 { @@ -11612,10 +11564,10 @@ index 0000000..d355adb + ti,lanes = <4>; + ti,forwarding-mode = "round-robin"; + ti,cable-mode = "coax"; -+ POC0-supply = <&pwr0>; -+ POC1-supply = <&pwr1>; -+ POC2-supply = <&pwr2>; -+ POC3-supply = <&pwr3>; ++ POC0-gpio = <&gpio_exp_6c 8 GPIO_ACTIVE_HIGH>; ++ POC1-gpio = <&gpio_exp_6c 9 GPIO_ACTIVE_HIGH>; ++ POC2-gpio = <&gpio_exp_6c 10 GPIO_ACTIVE_HIGH>; ++ POC3-gpio = <&gpio_exp_6c 11 GPIO_ACTIVE_HIGH>; + + port@0 { + ti9x4_des0ep0: endpoint@0 { @@ -13927,10 +13879,10 @@ index 0000000..cdd9844 +}; diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf-cn11.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf-cn11.dtsi new file mode 100644 -index 0000000..095a503 +index 0000000..a87c38b --- /dev/null +++ b/arch/arm64/boot/dts/renesas/ulcb-kf-cn11.dtsi -@@ -0,0 +1,498 @@ +@@ -0,0 +1,462 @@ +/* + * Device Tree Source for the H3ULCB Kingfisher board: + * this adding conflicting resource on VIN4/VIN5/VIN6/VIN7 for CN11 @@ -13944,44 +13896,6 @@ index 0000000..095a503 + * kind, whether express or implied. + */ + -+/ { -+ pwr0B: regulator-pwr0B { -+ compatible = "regulator-fixed"; -+ regulator-name = "PWR0B"; -+ regulator-min-microvolt = <9000000>; -+ regulator-max-microvolt = <9000000>; -+ gpio = <&gpio_exp_b_5c 8 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ }; -+ -+ pwr1B: regulator-pwr1B { -+ compatible = "regulator-fixed"; -+ regulator-name = "PWR1B"; -+ regulator-min-microvolt = <9000000>; -+ regulator-max-microvolt = <9000000>; -+ gpio = <&gpio_exp_b_5c 9 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ }; -+ -+ pwr2B: regulator-pwr2B { -+ compatible = "regulator-fixed"; -+ regulator-name = "PWR2B"; -+ regulator-min-microvolt = <9000000>; -+ regulator-max-microvolt = <9000000>; -+ gpio = <&gpio_exp_b_5c 10 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ }; -+ -+ pwr3B: regulator-pwr3B { -+ compatible = "regulator-fixed"; -+ regulator-name = "PWR3B"; -+ regulator-min-microvolt = <9000000>; -+ regulator-max-microvolt = <9000000>; -+ gpio = <&gpio_exp_b_5c 11 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ }; -+}; -+ +&i2cswitch4 { + i2c@2 { + #address-cells = <1>; @@ -14080,10 +13994,11 @@ index 0000000..095a503 + ti,lanes = <4>; + ti,forwarding-mode = "round-robin"; + ti,cable-mode = "coax"; -+ POC0-supply = <&pwr0B>; -+ POC1-supply = <&pwr1B>; -+ POC2-supply = <&pwr2B>; -+ POC3-supply = <&pwr3B>; ++ ++ POC0-gpios = <&gpio_exp_b_5c 8 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_b_5c 9 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_b_5c 10 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_b_5c 11 GPIO_ACTIVE_HIGH>; + + port@0 { + ti9x4_des1ep0: endpoint@0 { @@ -14125,10 +14040,11 @@ index 0000000..095a503 + maxim,resetb-gpio = <1>; + maxim,fsync-mode = "automatic"; + maxim,timeout = <100>; -+ POC0-supply = <&pwr1B>; -+ POC1-supply = <&pwr0B>; -+ POC2-supply = <&pwr3B>; -+ POC3-supply = <&pwr2B>; ++ ++ POC0-gpios = <&gpio_exp_b_5c 9 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_b_5c 8 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_b_5c 11 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_b_5c 10 GPIO_ACTIVE_HIGH>; + + port@0 { + max9286_des1ep0: endpoint@0 { @@ -14519,10 +14435,10 @@ index 0000000..b854216 +}; diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi new file mode 100644 -index 0000000..a33a2a0 +index 0000000..447cfc3 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi -@@ -0,0 +1,1492 @@ +@@ -0,0 +1,1458 @@ +/* + * Device Tree Source for the ULCB Kingfisher board + * @@ -14642,42 +14558,6 @@ index 0000000..a33a2a0 + enable-active-high; + }; + -+ pwr0A: regulator-pwr0A { -+ compatible = "regulator-fixed"; -+ regulator-name = "PWR0A"; -+ regulator-min-microvolt = <9000000>; -+ regulator-max-microvolt = <9000000>; -+ gpio = <&gpio_exp_a_5c 8 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ }; -+ -+ pwr1A: regulator-pwr1A { -+ compatible = "regulator-fixed"; -+ regulator-name = "PWR1A"; -+ regulator-min-microvolt = <9000000>; -+ regulator-max-microvolt = <9000000>; -+ gpio = <&gpio_exp_a_5c 9 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ }; -+ -+ pwr2A: regulator-pwr2A { -+ compatible = "regulator-fixed"; -+ regulator-name = "PWR2A"; -+ regulator-min-microvolt = <9000000>; -+ regulator-max-microvolt = <9000000>; -+ gpio = <&gpio_exp_a_5c 10 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ }; -+ -+ pwr3A: regulator-pwr3A { -+ compatible = "regulator-fixed"; -+ regulator-name = "PWR3A"; -+ regulator-min-microvolt = <9000000>; -+ regulator-max-microvolt = <9000000>; -+ gpio = <&gpio_exp_a_5c 11 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ }; -+ + kim { + compatible = "kim"; + shutdown-gpios = <&gpio_ext_74 3 GPIO_ACTIVE_HIGH>; @@ -15415,10 +15295,11 @@ index 0000000..a33a2a0 + ti,lanes = <4>; + ti,forwarding-mode = "round-robin"; + ti,cable-mode = "coax"; -+ POC0-supply = <&pwr0A>; -+ POC1-supply = <&pwr1A>; -+ POC2-supply = <&pwr2A>; -+ POC3-supply = <&pwr3A>; ++ ++ POC0-gpios = <&gpio_exp_a_5c 8 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_a_5c 9 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_a_5c 10 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_a_5c 11 GPIO_ACTIVE_HIGH>; + + port@0 { + ti9x4_des0ep0: endpoint@0 { @@ -15459,10 +15340,11 @@ index 0000000..a33a2a0 + maxim,resetb-gpio = <1>; + maxim,fsync-mode = "automatic"; + maxim,timeout = <100>; -+ POC0-supply = <&pwr1A>; -+ POC1-supply = <&pwr0A>; -+ POC2-supply = <&pwr3A>; -+ POC3-supply = <&pwr2A>; ++ ++ POC0-gpios = <&gpio_exp_a_5c 9 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_a_5c 8 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_a_5c 11 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_a_5c 10 GPIO_ACTIVE_HIGH>; + + port@0 { + max9286_des0ep0: endpoint@0 { @@ -16017,10 +15899,10 @@ index 0000000..a33a2a0 + diff --git a/arch/arm64/boot/dts/renesas/ulcb-vb-cn12.dtsi b/arch/arm64/boot/dts/renesas/ulcb-vb-cn12.dtsi new file mode 100644 -index 0000000..778a477 +index 0000000..b29fc18 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/ulcb-vb-cn12.dtsi -@@ -0,0 +1,495 @@ +@@ -0,0 +1,459 @@ +/* + * Device Tree Source for the H3ULCB Videobox board: + * this adding conflicting resource on VIN4/VIN5/VIN6/VIN7 for CN12 @@ -16033,44 +15915,6 @@ index 0000000..778a477 + * kind, whether express or implied. + */ + -+/ { -+ pwr0C: regulator-pwr0C { -+ compatible = "regulator-fixed"; -+ regulator-name = "PWR0C"; -+ regulator-min-microvolt = <9000000>; -+ regulator-max-microvolt = <9000000>; -+ gpio = <&gpio_exp_c_5c 8 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ }; -+ -+ pwr1C: regulator-pwr1C { -+ compatible = "regulator-fixed"; -+ regulator-name = "PWR1C"; -+ regulator-min-microvolt = <9000000>; -+ regulator-max-microvolt = <9000000>; -+ gpio = <&gpio_exp_c_5c 9 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ }; -+ -+ pwr2C: regulator-pwr2C { -+ compatible = "regulator-fixed"; -+ regulator-name = "PWR2C"; -+ regulator-min-microvolt = <9000000>; -+ regulator-max-microvolt = <9000000>; -+ gpio = <&gpio_exp_c_5c 10 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ }; -+ -+ pwr3C: regulator-pwr3C { -+ compatible = "regulator-fixed"; -+ regulator-name = "PWR3C"; -+ regulator-min-microvolt = <9000000>; -+ regulator-max-microvolt = <9000000>; -+ gpio = <&gpio_exp_c_5c 11 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ }; -+}; -+ +&i2cswitch2 { + i2c@3 { + #address-cells = <1>; @@ -16171,10 +16015,11 @@ index 0000000..778a477 + ti,lanes = <2>; + ti,forwarding-mode = "round-robin"; + ti,cable-mode = "coax"; -+ POC0-supply = <&pwr0C>; -+ POC1-supply = <&pwr1C>; -+ POC2-supply = <&pwr2C>; -+ POC3-supply = <&pwr3C>; ++ ++ POC0-gpios = <&gpio_exp_c_5c 8 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_c_5c 9 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_c_5c 10 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_c_5c 11 GPIO_ACTIVE_HIGH>; + + port@0 { + ti9x4_des2ep0: endpoint@0 { @@ -16216,10 +16061,11 @@ index 0000000..778a477 + maxim,resetb-gpio = <1>; + maxim,fsync-mode = "automatic"; + maxim,timeout = <100>; -+ POC0-supply = <&pwr1C>; -+ POC1-supply = <&pwr0C>; -+ POC2-supply = <&pwr3C>; -+ POC3-supply = <&pwr2C>; ++ ++ POC0-gpios = <&gpio_exp_c_5c 9 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_c_5c 8 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_c_5c 11 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_c_5c 10 GPIO_ACTIVE_HIGH>; + + port@0 { + max9286_des2ep0: endpoint@0 { @@ -16518,10 +16364,10 @@ index 0000000..778a477 +}; diff --git a/arch/arm64/boot/dts/renesas/ulcb-vb.dtsi b/arch/arm64/boot/dts/renesas/ulcb-vb.dtsi new file mode 100644 -index 0000000..07594447 +index 0000000..0185e46 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/ulcb-vb.dtsi -@@ -0,0 +1,1678 @@ +@@ -0,0 +1,1610 @@ +/* + * Device Tree Source for the ULCB Videobox board + * @@ -16624,78 +16470,6 @@ index 0000000..07594447 + regulator-always-on; + }; + -+ pwr0A: regulator-pwr0A { -+ compatible = "regulator-fixed"; -+ regulator-name = "PWR0A"; -+ regulator-min-microvolt = <9000000>; -+ regulator-max-microvolt = <9000000>; -+ gpio = <&gpio_exp_a_5c 8 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ }; -+ -+ pwr1A: regulator-pwr1A { -+ compatible = "regulator-fixed"; -+ regulator-name = "PWR1A"; -+ regulator-min-microvolt = <9000000>; -+ regulator-max-microvolt = <9000000>; -+ gpio = <&gpio_exp_a_5c 9 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ }; -+ -+ pwr2A: regulator-pwr2A { -+ compatible = "regulator-fixed"; -+ regulator-name = "PWR2A"; -+ regulator-min-microvolt = <9000000>; -+ regulator-max-microvolt = <9000000>; -+ gpio = <&gpio_exp_a_5c 10 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ }; -+ -+ pwr3A: regulator-pwr3A { -+ compatible = "regulator-fixed"; -+ regulator-name = "PWR3A"; -+ regulator-min-microvolt = <9000000>; -+ regulator-max-microvolt = <9000000>; -+ gpio = <&gpio_exp_a_5c 11 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ }; -+ -+ pwr0B: regulator-pwr0B { -+ compatible = "regulator-fixed"; -+ regulator-name = "PWR0B"; -+ regulator-min-microvolt = <9000000>; -+ regulator-max-microvolt = <9000000>; -+ gpio = <&gpio_exp_b_5c 8 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ }; -+ -+ pwr1B: regulator-pwr1B { -+ compatible = "regulator-fixed"; -+ regulator-name = "PWR1B"; -+ regulator-min-microvolt = <9000000>; -+ regulator-max-microvolt = <9000000>; -+ gpio = <&gpio_exp_b_5c 9 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ }; -+ -+ pwr2B: regulator-pwr2B { -+ compatible = "regulator-fixed"; -+ regulator-name = "PWR2B"; -+ regulator-min-microvolt = <9000000>; -+ regulator-max-microvolt = <9000000>; -+ gpio = <&gpio_exp_b_5c 10 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ }; -+ -+ pwr3B: regulator-pwr3B { -+ compatible = "regulator-fixed"; -+ regulator-name = "PWR3B"; -+ regulator-min-microvolt = <9000000>; -+ regulator-max-microvolt = <9000000>; -+ gpio = <&gpio_exp_b_5c 11 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ }; -+ + /delete-node/sound; + + rsnd_ak4613: sound@0 { @@ -17127,10 +16901,11 @@ index 0000000..07594447 + ti,lanes = <4>; + ti,forwarding-mode = "round-robin"; + ti,cable-mode = "stp"; -+ POC0-supply = <&pwr0A>; -+ POC1-supply = <&pwr1A>; -+ POC2-supply = <&pwr2A>; -+ POC3-supply = <&pwr3A>; ++ ++ POC0-gpios = <&gpio_exp_a_5c 8 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_a_5c 9 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_a_5c 10 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_a_5c 11 GPIO_ACTIVE_HIGH>; + + port@0 { + ti9x4_des0ep0: endpoint@0 { @@ -17171,10 +16946,11 @@ index 0000000..07594447 + maxim,resetb-gpio = <1>; + maxim,fsync-mode = "automatic"; + maxim,timeout = <100>; -+ POC0-supply = <&pwr1A>; -+ POC1-supply = <&pwr0A>; -+ POC2-supply = <&pwr3A>; -+ POC3-supply = <&pwr2A>; ++ ++ POC0-gpios = <&gpio_exp_a_5c 9 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_a_5c 8 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_a_5c 11 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_a_5c 10 GPIO_ACTIVE_HIGH>; + + port@0 { + max9286_des0ep0: endpoint@0 { @@ -17305,10 +17081,11 @@ index 0000000..07594447 + ti,lanes = <4>; + ti,forwarding-mode = "round-robin"; + ti,cable-mode = "stp"; -+ POC0-supply = <&pwr0B>; -+ POC1-supply = <&pwr1B>; -+ POC2-supply = <&pwr2B>; -+ POC3-supply = <&pwr3B>; ++ ++ POC0-gpios = <&gpio_exp_b_5c 8 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_b_5c 9 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_b_5c 10 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_b_5c 11 GPIO_ACTIVE_HIGH>; + + port@0 { + ti9x4_des1ep0: endpoint@0 { @@ -17349,10 +17126,11 @@ index 0000000..07594447 + maxim,resetb-gpio = <1>; + maxim,fsync-mode = "automatic"; + maxim,timeout = <100>; -+ POC0-supply = <&pwr1B>; -+ POC1-supply = <&pwr0B>; -+ POC2-supply = <&pwr3B>; -+ POC3-supply = <&pwr2B>; ++ ++ POC0-gpios = <&gpio_exp_b_5c 9 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_b_5c 8 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_b_5c 11 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_b_5c 10 GPIO_ACTIVE_HIGH>; + + port@0 { + max9286_des1ep0: endpoint@0 { @@ -18202,10 +17980,10 @@ index 0000000..07594447 +//#include "ulcb-vb-cn12.dtsi" diff --git a/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi b/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi new file mode 100644 -index 0000000..b0145a2 +index 0000000..92a3300 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi -@@ -0,0 +1,1724 @@ +@@ -0,0 +1,1656 @@ +/* + * Device Tree Source for the ULCB Videobox V2 board + * @@ -18302,78 +18080,6 @@ index 0000000..b0145a2 + regulator-always-on; + }; + -+ pwr0A: regulator-pwr0A { -+ compatible = "regulator-fixed"; -+ regulator-name = "PWR0A"; -+ regulator-min-microvolt = <9000000>; -+ regulator-max-microvolt = <9000000>; -+ gpio = <&gpio_exp_a_5c 8 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ }; -+ -+ pwr1A: regulator-pwr1A { -+ compatible = "regulator-fixed"; -+ regulator-name = "PWR1A"; -+ regulator-min-microvolt = <9000000>; -+ regulator-max-microvolt = <9000000>; -+ gpio = <&gpio_exp_a_5c 9 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ }; -+ -+ pwr2A: regulator-pwr2A { -+ compatible = "regulator-fixed"; -+ regulator-name = "PWR2A"; -+ regulator-min-microvolt = <9000000>; -+ regulator-max-microvolt = <9000000>; -+ gpio = <&gpio_exp_a_5c 10 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ }; -+ -+ pwr3A: regulator-pwr3A { -+ compatible = "regulator-fixed"; -+ regulator-name = "PWR3A"; -+ regulator-min-microvolt = <9000000>; -+ regulator-max-microvolt = <9000000>; -+ gpio = <&gpio_exp_a_5c 11 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ }; -+ -+ pwr0B: regulator-pwr0B { -+ compatible = "regulator-fixed"; -+ regulator-name = "PWR0B"; -+ regulator-min-microvolt = <9000000>; -+ regulator-max-microvolt = <9000000>; -+ gpio = <&gpio_exp_b_5c 8 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ }; -+ -+ pwr1B: regulator-pwr1B { -+ compatible = "regulator-fixed"; -+ regulator-name = "PWR1B"; -+ regulator-min-microvolt = <9000000>; -+ regulator-max-microvolt = <9000000>; -+ gpio = <&gpio_exp_b_5c 9 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ }; -+ -+ pwr2B: regulator-pwr2B { -+ compatible = "regulator-fixed"; -+ regulator-name = "PWR2B"; -+ regulator-min-microvolt = <9000000>; -+ regulator-max-microvolt = <9000000>; -+ gpio = <&gpio_exp_b_5c 10 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ }; -+ -+ pwr3B: regulator-pwr3B { -+ compatible = "regulator-fixed"; -+ regulator-name = "PWR3B"; -+ regulator-min-microvolt = <9000000>; -+ regulator-max-microvolt = <9000000>; -+ gpio = <&gpio_exp_b_5c 11 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ }; -+ + /delete-node/sound; + + rsnd_ak4613: sound@0 { @@ -18829,10 +18535,11 @@ index 0000000..b0145a2 + ti,lanes = <4>; + ti,forwarding-mode = "round-robin"; + ti,cable-mode = "stp"; -+ POC0-supply = <&pwr0A>; -+ POC1-supply = <&pwr1A>; -+ POC2-supply = <&pwr2A>; -+ POC3-supply = <&pwr3A>; ++ ++ POC0-gpios = <&gpio_exp_a_5c 8 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_a_5c 9 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_a_5c 10 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_a_5c 11 GPIO_ACTIVE_HIGH>; + + port@0 { + ti9x4_des0ep0: endpoint@0 { @@ -18873,10 +18580,11 @@ index 0000000..b0145a2 + maxim,resetb-gpio = <1>; + maxim,fsync-mode = "automatic"; + maxim,timeout = <100>; -+ POC0-supply = <&pwr1A>; -+ POC1-supply = <&pwr0A>; -+ POC2-supply = <&pwr3A>; -+ POC3-supply = <&pwr2A>; ++ ++ POC0-gpios = <&gpio_exp_a_5c 9 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_a_5c 8 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_a_5c 11 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_a_5c 10 GPIO_ACTIVE_HIGH>; + + port@0 { + max9286_des0ep0: endpoint@0 { @@ -19007,10 +18715,11 @@ index 0000000..b0145a2 + ti,lanes = <4>; + ti,forwarding-mode = "round-robin"; + ti,cable-mode = "stp"; -+ POC0-supply = <&pwr0B>; -+ POC1-supply = <&pwr1B>; -+ POC2-supply = <&pwr2B>; -+ POC3-supply = <&pwr3B>; ++ ++ POC0-gpios = <&gpio_exp_b_5c 8 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_b_5c 9 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_b_5c 10 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_b_5c 11 GPIO_ACTIVE_HIGH>; + + port@0 { + ti9x4_des1ep0: endpoint@0 { @@ -19051,10 +18760,11 @@ index 0000000..b0145a2 + maxim,resetb-gpio = <1>; + maxim,fsync-mode = "automatic"; + maxim,timeout = <100>; -+ POC0-supply = <&pwr1B>; -+ POC1-supply = <&pwr0B>; -+ POC2-supply = <&pwr3B>; -+ POC3-supply = <&pwr2B>; ++ ++ POC0-gpios = <&gpio_exp_b_5c 9 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_b_5c 8 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_b_5c 11 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_b_5c 10 GPIO_ACTIVE_HIGH>; + + port@0 { + max9286_des1ep0: endpoint@0 { @@ -19936,10 +19646,10 @@ index 0000000..b0145a2 +//#include "ulcb-vb2-cn12.dtsi" diff --git a/arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi b/arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi new file mode 100644 -index 0000000..bc36e95 +index 0000000..47e2b2d --- /dev/null +++ b/arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi -@@ -0,0 +1,577 @@ +@@ -0,0 +1,543 @@ +/* + * Device Tree Source for the ULCB Videobox Mini board + * @@ -19955,42 +19665,6 @@ index 0000000..bc36e95 + serial1 = &scif1; + }; + -+ pwr0: regulator-pwr0 { -+ compatible = "regulator-fixed"; -+ regulator-name = "PWR0"; -+ regulator-min-microvolt = <9000000>; -+ regulator-max-microvolt = <9000000>; -+ gpio = <&gpio_exp_6c 8 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ }; -+ -+ pwr1: regulator-pwr1 { -+ compatible = "regulator-fixed"; -+ regulator-name = "PWR1"; -+ regulator-min-microvolt = <9000000>; -+ regulator-max-microvolt = <9000000>; -+ gpio = <&gpio_exp_6c 9 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ }; -+ -+ pwr2: regulator-pwr2 { -+ compatible = "regulator-fixed"; -+ regulator-name = "PWR2"; -+ regulator-min-microvolt = <9000000>; -+ regulator-max-microvolt = <9000000>; -+ gpio = <&gpio_exp_6c 10 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ }; -+ -+ pwr3: regulator-pwr3 { -+ compatible = "regulator-fixed"; -+ regulator-name = "PWR3"; -+ regulator-min-microvolt = <9000000>; -+ regulator-max-microvolt = <9000000>; -+ gpio = <&gpio_exp_6c 11 GPIO_ACTIVE_HIGH>; -+ enable-active-high; -+ }; -+ + lvds-encoder { + compatible = "thine,thc63lvdm83d"; + @@ -20211,10 +19885,11 @@ index 0000000..bc36e95 + maxim,resetb-gpio = <1>; + maxim,fsync-mode = "automatic"; + maxim,timeout = <100>; -+ POC0-supply = <&pwr0>; -+ POC1-supply = <&pwr1>; -+ POC2-supply = <&pwr2>; -+ POC3-supply = <&pwr3>; ++ ++ POC0-gpios = <&gpio_exp_6c 8 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_6c 9 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_6c 10 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_6c 1 GPIO_ACTIVE_HIGH>; + + port@0 { + max9286_des0ep0: endpoint@0 { @@ -20254,10 +19929,11 @@ index 0000000..bc36e95 + ti,lanes = <4>; + ti,forwarding-mode = "round-robin"; + ti,cable-mode = "coax"; -+ POC0-supply = <&pwr0>; -+ POC1-supply = <&pwr1>; -+ POC2-supply = <&pwr2>; -+ POC3-supply = <&pwr3>; ++ ++ POC0-gpios = <&gpio_exp_6c 8 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_6c 9 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_6c 10 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_6c 1 GPIO_ACTIVE_HIGH>; + + port@0 { + ti9x4_des0ep0: endpoint@0 { -- cgit 1.2.3-korg From 8c7e2b3bfd0ea2868ccb6d11ec648d28931196c4 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Fri, 2 Feb 2018 18:20:09 +0300 Subject: Fix Kingfisher regulator The patch 0035-* breaks regulators on KF board. As a result the Multichannal audio was broken --- .../0035-regulator-fixed-probe-after-i2c.patch | 53 ---------------------- .../linux/linux-renesas_4.9.bbappend | 1 - 2 files changed, 54 deletions(-) delete mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0035-regulator-fixed-probe-after-i2c.patch (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0035-regulator-fixed-probe-after-i2c.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0035-regulator-fixed-probe-after-i2c.patch deleted file mode 100644 index 31c79ce..0000000 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0035-regulator-fixed-probe-after-i2c.patch +++ /dev/null @@ -1,53 +0,0 @@ -From ef0ae334de1e1b318f4fb26bc8045451318a60c4 Mon Sep 17 00:00:00 2001 -From: Vladimir Barinov -Date: Sun, 26 Nov 2017 21:35:54 +0300 -Subject: [PATCH] regulator: fixed: probe after i2c - -This is a workaround for LVDS cameras that use I2C gpio expanders. -Set fixed regulator booted after i2c expander to have PoC -power controlled in LVDS driver. - -Signed-off-by: Vladimir Barinov ---- - drivers/Makefile | 4 +++- - drivers/regulator/fixed.c | 2 +- - 2 files changed, 4 insertions(+), 2 deletions(-) - -diff --git a/drivers/Makefile b/drivers/Makefile -index 194d20b..f49ed8f 100644 ---- a/drivers/Makefile -+++ b/drivers/Makefile -@@ -41,6 +41,8 @@ obj-y += soc/ - obj-$(CONFIG_VIRTIO) += virtio/ - obj-$(CONFIG_XEN) += xen/ - -+obj-y += i2c/ -+ - # regulators early, since some subsystems rely on them to initialize - obj-$(CONFIG_REGULATOR) += regulator/ - -@@ -105,7 +107,7 @@ obj-$(CONFIG_SERIO) += input/serio/ - obj-$(CONFIG_GAMEPORT) += input/gameport/ - obj-$(CONFIG_INPUT) += input/ - obj-$(CONFIG_RTC_LIB) += rtc/ --obj-y += i2c/ media/ -+obj-y += media/ - obj-$(CONFIG_PPS) += pps/ - obj-$(CONFIG_PTP_1588_CLOCK) += ptp/ - obj-$(CONFIG_W1) += w1/ -diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c -index 988a747..44a169c 100644 ---- a/drivers/regulator/fixed.c -+++ b/drivers/regulator/fixed.c -@@ -211,7 +211,7 @@ static int __init regulator_fixed_voltage_init(void) - { - return platform_driver_register(®ulator_fixed_voltage_driver); - } --subsys_initcall(regulator_fixed_voltage_init); -+module_init(regulator_fixed_voltage_init); - - static void __exit regulator_fixed_voltage_exit(void) - { --- -1.9.1 - diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas_4.9.bbappend b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas_4.9.bbappend index 2d0bdf6..fee6dea 100644 --- 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 @@ -40,7 +40,6 @@ SRC_URI_append = " \ file://0032-media-i2c-Add-ov5642-sensor.patch \ file://0033-media-soc-camera-fix-parallel-i-f-in-VIN.patch \ file://0034-media-soc_camera-Fix-VIDIOC_S_SELECTION-ioctl-miscal.patch \ - file://0035-regulator-fixed-probe-after-i2c.patch \ file://0040-arm64-dts-renesas-add-ADAS-boards.patch \ file://0041-arm64-dts-renesas-ulcb-enlarge-cma-region.patch \ file://0042-arm64-dts-renesas-r8a7795-es1-h3ulcb-disable-eMMC.patch \ -- cgit 1.2.3-korg From 4ca6923b470abbf254d25dc205fe4a80d6f7139b Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Fri, 2 Feb 2018 20:27:00 +0300 Subject: Add V3MZF target --- meta-rcar-gen3-adas/conf/machine/v3mzf.conf | 35 +++ .../sample/conf/v3mzf/linaro-gcc/bsp/bblayers.conf | 16 ++ .../sample/conf/v3mzf/linaro-gcc/bsp/local.conf | 267 +++++++++++++++++++++ .../arm-trusted-firmware_git.bbappend | 1 + .../kernel-module-mmngr.bbappend | 1 + .../recipes-kernel/linux/linux-renesas/v3mzf.cfg | 24 ++ .../linux/linux-renesas_4.9.bbappend | 6 + 7 files changed, 350 insertions(+) create mode 100644 meta-rcar-gen3-adas/conf/machine/v3mzf.conf create mode 100644 meta-rcar-gen3-adas/docs/sample/conf/v3mzf/linaro-gcc/bsp/bblayers.conf create mode 100644 meta-rcar-gen3-adas/docs/sample/conf/v3mzf/linaro-gcc/bsp/local.conf create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3mzf.cfg (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/conf/machine/v3mzf.conf b/meta-rcar-gen3-adas/conf/machine/v3mzf.conf new file mode 100644 index 0000000..0f8974f --- /dev/null +++ b/meta-rcar-gen3-adas/conf/machine/v3mzf.conf @@ -0,0 +1,35 @@ +#@TYPE: Machine +#@NAME: V3MZF machine +#@DESCRIPTION: Machine configuration for running V3MZF + +DEFAULTTUNE ?= "cortexa53" +require conf/machine/include/tune-cortexa53.inc +require conf/machine/include/${SOC_FAMILY}.inc + +# 32BIT package install (default is disable) +# This variables can be used only in multilib. +USE_32BIT_PKGS ?= "0" +USE_32BIT_WAYLAND ?= "0" +USE_32BIT_MMP ?= "0" + +MACHINE_FEATURES = "" + +KERNEL_IMAGETYPE = "Image" +IMAGE_FSTYPES = "tar.bz2 ext4 cpio.gz" + +SERIAL_CONSOLE = "115200 ttySC0" + +# Configuration for kernel +PREFERRED_PROVIDER_virtual/kernel = "linux-renesas" +KERNEL_DEVICETREE = "renesas/r8a7797-v3mzf.dtb" + +# u-boot +PREFERRED_VERSION_u-boot = "v2015.04%" +EXTRA_IMAGEDEPENDS += " u-boot" +UBOOT_MACHINE = "v3mzf_defconfig" + +# libdrm +PREFERRED_VERSION_libdrm = "2.4.68" + +# Add variable to Build Configuration in build log +BUILDCFG_VARS_append = " SOC_FAMILY" diff --git a/meta-rcar-gen3-adas/docs/sample/conf/v3mzf/linaro-gcc/bsp/bblayers.conf b/meta-rcar-gen3-adas/docs/sample/conf/v3mzf/linaro-gcc/bsp/bblayers.conf new file mode 100644 index 0000000..96ff8ad --- /dev/null +++ b/meta-rcar-gen3-adas/docs/sample/conf/v3mzf/linaro-gcc/bsp/bblayers.conf @@ -0,0 +1,16 @@ +# POKY_BBLAYERS_CONF_VERSION is increased each time build/conf/bblayers.conf +# changes incompatibly +POKY_BBLAYERS_CONF_VERSION = "2" + +BBPATH = "${TOPDIR}" +BBFILES ?= "" + +BBLAYERS ?= " \ + ${TOPDIR}/../poky/meta \ + ${TOPDIR}/../poky/meta-poky \ + ${TOPDIR}/../poky/meta-yocto-bsp \ + ${TOPDIR}/../meta-renesas/meta-rcar-gen3 \ + ${TOPDIR}/../meta-linaro/meta-linaro-toolchain \ + ${TOPDIR}/../meta-linaro/meta-optee \ + ${TOPDIR}/../meta-openembedded/meta-oe \ + " diff --git a/meta-rcar-gen3-adas/docs/sample/conf/v3mzf/linaro-gcc/bsp/local.conf b/meta-rcar-gen3-adas/docs/sample/conf/v3mzf/linaro-gcc/bsp/local.conf new file mode 100644 index 0000000..4c38b26 --- /dev/null +++ b/meta-rcar-gen3-adas/docs/sample/conf/v3mzf/linaro-gcc/bsp/local.conf @@ -0,0 +1,267 @@ +# +# This file is your local configuration file and is where all local user settings +# are placed. The comments in this file give some guide to the options a new user +# to the system might want to change but pretty much any configuration option can +# be set in this file. More adventurous users can look at local.conf.extended +# which contains other examples of configuration which can be placed in this file +# but new users likely won't need any of them initially. +# +# Lines starting with the '#' character are commented out and in some cases the +# default values are provided as comments to show people example syntax. Enabling +# the option is a question of removing the # character and making any change to the +# variable as required. + +# +# Machine Selection +# +# You need to select a specific machine to target the build with. There are a selection +# of emulated machines available which can boot and run in the QEMU emulator: +# +#MACHINE ?= "qemuarm" +#MACHINE ?= "qemuarm64" +#MACHINE ?= "qemumips" +#MACHINE ?= "qemumips64" +#MACHINE ?= "qemuppc" +#MACHINE ?= "qemux86" +#MACHINE ?= "qemux86-64" +# +# There are also the following hardware board target machines included for +# demonstration purposes: +# +#MACHINE ?= "beaglebone" +#MACHINE ?= "genericx86" +#MACHINE ?= "genericx86-64" +#MACHINE ?= "mpc8315e-rdb" +#MACHINE ?= "edgerouter" +# +# This sets the default machine to be qemux86 if no other machine is selected: +MACHINE ??= "v3mzf" + +SOC_FAMILY = "r8a7797" + +# +# Where to place downloads +# +# During a first build the system will download many different source code tarballs +# from various upstream projects. This can take a while, particularly if your network +# connection is slow. These are all stored in DL_DIR. When wiping and rebuilding you +# can preserve this directory to speed up this part of subsequent builds. This directory +# is safe to share between multiple builds on the same machine too. +# +# The default is a downloads directory under TOPDIR which is the build directory. +# +#DL_DIR ?= "${TOPDIR}/downloads" + +# +# Where to place shared-state files +# +# BitBake has the capability to accelerate builds based on previously built output. +# This is done using "shared state" files which can be thought of as cache objects +# and this option determines where those files are placed. +# +# You can wipe out TMPDIR leaving this directory intact and the build would regenerate +# from these files if no changes were made to the configuration. If changes were made +# to the configuration, only shared state files where the state was still valid would +# be used (done using checksums). +# +# The default is a sstate-cache directory under TOPDIR. +# +#SSTATE_DIR ?= "${TOPDIR}/sstate-cache" + +# +# Where to place the build output +# +# This option specifies where the bulk of the building work should be done and +# where BitBake should place its temporary files and output. Keep in mind that +# this includes the extraction and compilation of many applications and the toolchain +# which can use Gigabytes of hard disk space. +# +# The default is a tmp directory under TOPDIR. +# +#TMPDIR = "${TOPDIR}/tmp" + +# +# Default policy config +# +# The distribution setting controls which policy settings are used as defaults. +# The default value is fine for general Yocto project use, at least initially. +# Ultimately when creating custom policy, people will likely end up subclassing +# these defaults. +# +DISTRO ?= "poky" +# As an example of a subclass there is a "bleeding" edge policy configuration +# where many versions are set to the absolute latest code from the upstream +# source control systems. This is just mentioned here as an example, its not +# useful to most new users. +# DISTRO ?= "poky-bleeding" + +# +# Package Management configuration +# +# This variable lists which packaging formats to enable. Multiple package backends +# can be enabled at once and the first item listed in the variable will be used +# to generate the root filesystems. +# Options are: +# - 'package_deb' for debian style deb files +# - 'package_ipk' for ipk files are used by opkg (a debian style embedded package manager) +# - 'package_rpm' for rpm style packages +# E.g.: PACKAGE_CLASSES ?= "package_rpm package_deb package_ipk" +# We default to rpm: +PACKAGE_CLASSES ?= "package_ipk" + +# +# SDK target architecture +# +# This variable specifies the architecture to build SDK items for and means +# you can build the SDK packages for architectures other than the machine you are +# running the build on (i.e. building i686 packages on an x86_64 host). +# Supported values are i686 and x86_64 +#SDKMACHINE ?= "i686" + +# +# Extra image configuration defaults +# +# The EXTRA_IMAGE_FEATURES variable allows extra packages to be added to the generated +# images. Some of these options are added to certain image types automatically. The +# variable can contain the following options: +# "dbg-pkgs" - add -dbg packages for all installed packages +# (adds symbol information for debugging/profiling) +# "dev-pkgs" - add -dev packages for all installed packages +# (useful if you want to develop against libs in the image) +# "ptest-pkgs" - add -ptest packages for all ptest-enabled packages +# (useful if you want to run the package test suites) +# "tools-sdk" - add development tools (gcc, make, pkgconfig etc.) +# "tools-debug" - add debugging tools (gdb, strace) +# "eclipse-debug" - add Eclipse remote debugging support +# "tools-profile" - add profiling tools (oprofile, lttng, valgrind) +# "tools-testapps" - add useful testing tools (ts_print, aplay, arecord etc.) +# "debug-tweaks" - make an image suitable for development +# e.g. ssh root access has a blank password +# There are other application targets that can be used here too, see +# meta/classes/image.bbclass and meta/classes/core-image.bbclass for more details. +# We default to enabling the debugging tweaks. +EXTRA_IMAGE_FEATURES ?= "debug-tweaks" + +# +# Additional image features +# +# The following is a list of additional classes to use when building images which +# enable extra features. Some available options which can be included in this variable +# are: +# - 'buildstats' collect build statistics +# - 'image-mklibs' to reduce shared library files size for an image +# - 'image-prelink' in order to prelink the filesystem image +# - 'image-swab' to perform host system intrusion detection +# NOTE: if listing mklibs & prelink both, then make sure mklibs is before prelink +# NOTE: mklibs also needs to be explicitly enabled for a given image, see local.conf.extended +# image-prelink disabled for now due to issues with IFUNC symbol relocation +USER_CLASSES ?= "buildstats image-mklibs" + +# +# Runtime testing of images +# +# The build system can test booting virtual machine images under qemu (an emulator) +# after any root filesystems are created and run tests against those images. To +# enable this uncomment this line. See classes/testimage(-auto).bbclass for +# further details. +#TEST_IMAGE = "1" +# +# Interactive shell configuration +# +# Under certain circumstances the system may need input from you and to do this it +# can launch an interactive shell. It needs to do this since the build is +# multithreaded and needs to be able to handle the case where more than one parallel +# process may require the user's attention. The default is iterate over the available +# terminal types to find one that works. +# +# Examples of the occasions this may happen are when resolving patches which cannot +# be applied, to use the devshell or the kernel menuconfig +# +# Supported values are auto, gnome, xfce, rxvt, screen, konsole (KDE 3.x only), none +# Note: currently, Konsole support only works for KDE 3.x due to the way +# newer Konsole versions behave +#OE_TERMINAL = "auto" +# By default disable interactive patch resolution (tasks will just fail instead): +PATCHRESOLVE = "noop" + +# +# Disk Space Monitoring during the build +# +# Monitor the disk space during the build. If there is less that 1GB of space or less +# than 100K inodes in any key build location (TMPDIR, DL_DIR, SSTATE_DIR), gracefully +# shutdown the build. If there is less that 100MB or 1K inodes, perform a hard abort +# of the build. The reason for this is that running completely out of space can corrupt +# files and damages the build in ways which may not be easily recoverable. +# It's necesary to monitor /tmp, if there is no space left the build will fail +# with very exotic errors. +BB_DISKMON_DIRS = "\ + STOPTASKS,${TMPDIR},1G,100K \ + STOPTASKS,${DL_DIR},1G,100K \ + STOPTASKS,${SSTATE_DIR},1G,100K \ + STOPTASKS,/tmp,100M,100K \ + ABORT,${TMPDIR},100M,1K \ + ABORT,${DL_DIR},100M,1K \ + ABORT,${SSTATE_DIR},100M,1K \ + ABORT,/tmp,10M,1K" + +# +# Shared-state files from other locations +# +# As mentioned above, shared state files are prebuilt cache data objects which can +# used to accelerate build time. This variable can be used to configure the system +# to search other mirror locations for these objects before it builds the data itself. +# +# This can be a filesystem directory, or a remote url such as http or ftp. These +# would contain the sstate-cache results from previous builds (possibly from other +# machines). This variable works like fetcher MIRRORS/PREMIRRORS and points to the +# cache locations to check for the shared objects. +# NOTE: if the mirror uses the same structure as SSTATE_DIR, you need to add PATH +# at the end as shown in the examples below. This will be substituted with the +# correct path within the directory structure. +#SSTATE_MIRRORS ?= "\ +#file://.* http://someserver.tld/share/sstate/PATH;downloadfilename=PATH \n \ +#file://.* file:///some/local/dir/sstate/PATH" + + +# +# Qemu configuration +# +# By default qemu will build with a builtin VNC server where graphical output can be +# seen. The two lines below enable the SDL backend too. By default libsdl-native will +# be built, if you want to use your host's libSDL instead of the minimal libsdl built +# by libsdl-native then uncomment the ASSUME_PROVIDED line below. +PACKAGECONFIG_append_pn-qemu-native = " sdl" +PACKAGECONFIG_append_pn-nativesdk-qemu = " sdl" +#ASSUME_PROVIDED += "libsdl-native" + +# CONF_VERSION is increased each time build/conf/ changes incompatibly and is used to +# track the version of this file when it was generated. This can safely be ignored if +# this doesn't mean anything to you. +CONF_VERSION = "1" + +# Add systemd configuration +DISTRO_FEATURES_append = " systemd" +VIRTUAL-RUNTIME_init_manager = "systemd" + +# Linaro GCC +GCCVERSION = "linaro-5.2" + +# add the static lib to SDK toolchain +SDKIMAGE_FEATURES_append = " staticdev-pkgs" + +# Disable optee in meta-linaro layer +BBMASK = "meta-linaro/meta-optee/recipes-security/optee" + +# Mask graphic Pkgs +BBMASK .= "|gles-user-module|kernel-module-gles|wayland-kms|libgbm" +# Mask MMP recipes +BBMASK .= "|kernel-module-uvcs-drv|omx-user-module" + +# Add for gstreamer plugins ugly +LICENSE_FLAGS_WHITELIST = "commercial" + +# Linux ICCOM driver (RCG3ZLIDL4001ZNO) +# Linux ICCOM library (RCG3ZLILL4001ZNO) +#DISTRO_FEATURES_append = " iccom" + +IMAGE_INSTALL_remove = "optee-linuxdriver optee-linuxdriver-armtz optee-client" 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 index d2ac495..3d26996 100644 --- 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 @@ -2,6 +2,7 @@ FILESEXTRAPATHS_prepend := "${THISDIR}/files:" COMPATIBLE_MACHINE_eagle = "eagle" COMPATIBLE_MACHINE_v3msk = "v3msk" +COMPATIBLE_MACHINE_v3mzf = "v3mzf" ATFW_OPT_r8a7797 = "LSI=V3M RCAR_DRAM_SPLIT=0 RCAR_LOSSY_ENABLE=0 PMIC_ROHM_BD9571=0 RCAR_SYSTEM_SUSPEND=0 SPD=none" ATFW_OPT_append = " ${@base_conditional("CA57CA53BOOT", "1", " PSCI_DISABLE_BIGLITTLE_IN_CA57BOOT=0", "", d)}" diff --git a/meta-rcar-gen3-adas/recipes-kernel/kernel-module-mmngr/kernel-module-mmngr.bbappend b/meta-rcar-gen3-adas/recipes-kernel/kernel-module-mmngr/kernel-module-mmngr.bbappend index 7118d46..d3991b4 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/kernel-module-mmngr/kernel-module-mmngr.bbappend +++ b/meta-rcar-gen3-adas/recipes-kernel/kernel-module-mmngr/kernel-module-mmngr.bbappend @@ -3,5 +3,6 @@ FILESEXTRAPATHS_prepend := "${THISDIR}/files:" MMNGR_CFG_eagle = "MMNGR_V3MSK" MMNGR_CFG_v3msk = "MMNGR_V3MSK" MMNGR_CFG_condor = "MMNGR_V3MSK" +MMNGR_CFG_v3mzf = "MMNGR_V3MSK" SRC_URI_append = " file://0002-mmngr-Add-V3MSK-board.patch" diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3mzf.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3mzf.cfg new file mode 100644 index 0000000..1d888cd --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3mzf.cfg @@ -0,0 +1,24 @@ +CONFIG_ARCH_R8A7797=y +CONFIG_CAN=y +CONFIG_CAN_BCM=y +CONFIG_CAN_RAW=y +CONFIG_CAN_DEV=y +CONFIG_CAN_CALC_BITTIMING=y +CONFIG_CAN_RCAR=y +CONFIG_CAN_RCAR_CANFD=y +CONFIG_DUMMY=y +CONFIG_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_TI9X4=y +CONFIG_SOC_CAMERA_OV106XX=y +CONFIG_VIDEO_RENESAS_IMR=y +CONFIG_SERIAL_SH_SCI_DMA=y +CONFIG_SPI_SLAVE=y +CONFIG_SPI_SLAVE_TIME=y +CONFIG_SPI_SLAVE_SYSTEM_CONTROL=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 index fee6dea..2444573 100644 --- 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 @@ -3,6 +3,7 @@ FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" COMPATIBLE_MACHINE_eagle = "eagle" COMPATIBLE_MACHINE_v3msk = "v3msk" COMPATIBLE_MACHINE_condor = "condor" +COMPATIBLE_MACHINE_v3mzf = "v3mzf" SRC_URI_append = " \ ${@bb.utils.contains('MACHINE_FEATURES', 'h3ulcb-had', ' file://hyperflash.cfg', '', d)} \ @@ -88,6 +89,7 @@ SRC_URI_append_salvator-x = " file://salvator-x.cfg" SRC_URI_append_eagle = " file://eagle.cfg" SRC_URI_append_v3msk = " file://v3msk.cfg" SRC_URI_append_condor = " file://condor.cfg" +SRC_URI_append_v3mzf = " file://v3mzf.cfg" KERNEL_DEVICETREE_append_h3ulcb = " \ renesas/r8a7795-es1-h3ulcb-view.dtb \ @@ -129,6 +131,10 @@ KERNEL_DEVICETREE_append_v3msk = " \ renesas/r8a7797-v3msk-view.dtb \ " +KERNEL_DEVICETREE_append_v3mzf = " \ + renesas/r8a7797-v3mzf.dtb \ +" + KERNEL_DEVICETREE_append_condor = " \ renesas/r8a7798-condor.dtb \ " -- cgit 1.2.3-korg From 39c18a8c2b230e21b2b4ba171fe4a300afcbe888 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Fri, 2 Feb 2018 20:27:28 +0300 Subject: Fix merge conflict Fix build fail --- .../linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch index b33ccc9..c9f9d8c 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch @@ -17983,7 +17983,7 @@ new file mode 100644 index 0000000..92a3300 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi -@@ -0,0 +1,1656 @@ +@@ -0,0 +1,1660 @@ +/* + * Device Tree Source for the ULCB Videobox V2 board + * -- cgit 1.2.3-korg From 584e34ade6b37fb75dfd2d12299f4a68d3fbc8f7 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Mon, 5 Feb 2018 16:08:54 +0300 Subject: VideoBoxMini: fix POC sequence typos This fixes POC sequence on following boards: - V3MSK + VideoBoxMini - ULCB + VideoBoxMini --- .../0040-arm64-dts-renesas-add-ADAS-boards.patch | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch index c9f9d8c..4f390e6 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch @@ -11522,10 +11522,10 @@ index 0000000..226b659 + maxim,fsync-mode = "automatic"; + maxim,timeout = <100>; + -+ POC0-gpios = <&gpio_exp_6c 9 GPIO_ACTIVE_HIGH>; -+ POC1-gpios = <&gpio_exp_6c 8 GPIO_ACTIVE_HIGH>; -+ POC2-gpios = <&gpio_exp_6c 11 GPIO_ACTIVE_HIGH>; -+ POC3-gpios = <&gpio_exp_6c 10 GPIO_ACTIVE_HIGH>; ++ POC0-gpios = <&gpio_exp_6c 8 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_6c 9 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_6c 10 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_6c 11 GPIO_ACTIVE_HIGH>; + + port@0 { + max9286_des0ep0: endpoint@0 { @@ -19889,7 +19889,7 @@ index 0000000..47e2b2d + POC0-gpios = <&gpio_exp_6c 8 GPIO_ACTIVE_HIGH>; + POC1-gpios = <&gpio_exp_6c 9 GPIO_ACTIVE_HIGH>; + POC2-gpios = <&gpio_exp_6c 10 GPIO_ACTIVE_HIGH>; -+ POC3-gpios = <&gpio_exp_6c 1 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_6c 11 GPIO_ACTIVE_HIGH>; + + port@0 { + max9286_des0ep0: endpoint@0 { @@ -19933,7 +19933,7 @@ index 0000000..47e2b2d + POC0-gpios = <&gpio_exp_6c 8 GPIO_ACTIVE_HIGH>; + POC1-gpios = <&gpio_exp_6c 9 GPIO_ACTIVE_HIGH>; + POC2-gpios = <&gpio_exp_6c 10 GPIO_ACTIVE_HIGH>; -+ POC3-gpios = <&gpio_exp_6c 1 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_6c 11 GPIO_ACTIVE_HIGH>; + + port@0 { + ti9x4_des0ep0: endpoint@0 { -- cgit 1.2.3-korg From 4d57c6dc3187d7b42a1cda1b4cfc20479f231c4e Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Tue, 6 Feb 2018 17:51:19 +0300 Subject: Add OV2775 camera This adds OV2775 sensor connected to TI953 seriliazer --- .../linux-renesas/0030-Gen3-LVDS-cameras.patch | 2480 +++++++++++++++++++- 1 file changed, 2425 insertions(+), 55 deletions(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') 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 index 2c3b903..a680635 100644 --- 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 @@ -6,37 +6,39 @@ Subject: [PATCH] Gen3: LVDS cameras This add Gen3 LVDS cameras support: - deserializers: MAX9286, DS90UB954/960/964 - cameras: ov10635, ov490+ov10640, ov495+OV2775, ar0132, ar0220, - ap0101+ar014x + ap0101+ar014x, ov2775 Signed-off-by: Vladimir Barinov --- - drivers/media/i2c/soc_camera/Kconfig | 41 + - drivers/media/i2c/soc_camera/Makefile | 6 + - drivers/media/i2c/soc_camera/ap0101_ar014x.c | 588 +++++++++++ + drivers/media/i2c/soc_camera/Kconfig | 19 + + drivers/media/i2c/soc_camera/Makefile | 3 + + drivers/media/i2c/soc_camera/ap0101_ar014x.c | 588 +++++++ drivers/media/i2c/soc_camera/ap0101_ar014x.h | 28 + - drivers/media/i2c/soc_camera/ar0132.c | 565 +++++++++++ - drivers/media/i2c/soc_camera/ar0132.h | 213 ++++ - drivers/media/i2c/soc_camera/ar0220.c | 528 ++++++++++ - drivers/media/i2c/soc_camera/ar0220.h | 309 ++++++ - drivers/media/i2c/soc_camera/max9286.c | 692 +++++++++++++ - drivers/media/i2c/soc_camera/max9286.h | 244 +++++ - drivers/media/i2c/soc_camera/ov10635.c | 759 ++++++++++++++ - drivers/media/i2c/soc_camera/ov10635.h | 1139 ++++++++++++++++++++++ + drivers/media/i2c/soc_camera/ar0132.c | 565 +++++++ + drivers/media/i2c/soc_camera/ar0132.h | 213 +++ + drivers/media/i2c/soc_camera/ar0220.c | 528 +++++++ + drivers/media/i2c/soc_camera/ar0220.h | 309 ++++ + drivers/media/i2c/soc_camera/max9286.c | 692 ++++++++ + drivers/media/i2c/soc_camera/max9286.h | 244 +++ + drivers/media/i2c/soc_camera/ov10635.c | 759 +++++++++ + drivers/media/i2c/soc_camera/ov10635.h | 1139 +++++++++++++ drivers/media/i2c/soc_camera/ov10635_debug.h | 54 + - drivers/media/i2c/soc_camera/ov106xx.c | 128 +++ - drivers/media/i2c/soc_camera/ov490_ov10640.c | 1133 +++++++++++++++++++++ + drivers/media/i2c/soc_camera/ov106xx.c | 139 ++ + drivers/media/i2c/soc_camera/ov2775.c | 527 +++++++ + drivers/media/i2c/soc_camera/ov2775.h | 1841 ++++++++++++++++++++++ + drivers/media/i2c/soc_camera/ov490_ov10640.c | 1133 +++++++++++++ drivers/media/i2c/soc_camera/ov490_ov10640.h | 102 ++ - drivers/media/i2c/soc_camera/ov495_ov2775.c | 639 ++++++++++++ + drivers/media/i2c/soc_camera/ov495_ov2775.c | 639 ++++++++ drivers/media/i2c/soc_camera/ov495_ov2775.h | 23 + - drivers/media/i2c/soc_camera/ti9x4.c | 518 ++++++++++ - drivers/media/i2c/soc_camera/ti9x4.h | 156 +++ - drivers/media/platform/soc_camera/rcar_csi2.c | 297 ++++-- - drivers/media/platform/soc_camera/rcar_vin.c | 194 +++- + drivers/media/i2c/soc_camera/ti9x4.c | 518 ++++++ + drivers/media/i2c/soc_camera/ti9x4.h | 156 ++ + drivers/media/platform/soc_camera/rcar_csi2.c | 297 ++-- + drivers/media/platform/soc_camera/rcar_vin.c | 194 ++- 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 + - 26 files changed, 8284 insertions(+), 109 deletions(-) + 28 files changed, 10638 insertions(+), 109 deletions(-) create mode 100644 drivers/media/i2c/soc_camera/ap0101_ar014x.c create mode 100644 drivers/media/i2c/soc_camera/ap0101_ar014x.h create mode 100644 drivers/media/i2c/soc_camera/ar0132.c @@ -49,6 +51,8 @@ Signed-off-by: Vladimir Barinov 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/ov2775.c + create mode 100644 drivers/media/i2c/soc_camera/ov2775.h 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 @@ -57,10 +61,10 @@ Signed-off-by: Vladimir Barinov create mode 100644 drivers/media/i2c/soc_camera/ti9x4.h diff --git a/drivers/media/i2c/soc_camera/Kconfig b/drivers/media/i2c/soc_camera/Kconfig -index 7704bcf..d6377e9 100644 +index 7704bcf..2249b40 100644 --- a/drivers/media/i2c/soc_camera/Kconfig +++ b/drivers/media/i2c/soc_camera/Kconfig -@@ -6,6 +6,47 @@ config SOC_CAMERA_IMX074 +@@ -6,6 +6,25 @@ config SOC_CAMERA_IMX074 help This driver supports IMX074 cameras from Sony @@ -82,37 +86,15 @@ index 7704bcf..d6377e9 100644 + depends on SOC_CAMERA && I2C + help + This is an Texas Instruments ti9X4 FPDLinkIII driver -+ -+if !SOC_CAMERA_OV106XX -+ -+config SOC_CAMERA_OV10635 -+ tristate "ov10635 camera support" -+ depends on SOC_CAMERA && I2C -+ help -+ This is an OmniVision ov10635 sensor camera driver -+ -+config SOC_CAMERA_OV490_OV10640 -+ tristate "ov490-ov10640 camera support" -+ depends on SOC_CAMERA && 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_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..58086d4 100644 +index 6f994f9..2b2583a 100644 --- a/drivers/media/i2c/soc_camera/Makefile +++ b/drivers/media/i2c/soc_camera/Makefile -@@ -1,8 +1,14 @@ +@@ -1,8 +1,11 @@ obj-$(CONFIG_SOC_CAMERA_IMX074) += imx074.o +obj-$(CONFIG_SOC_CAMERA_MAX9286) += max9286.o +obj-$(CONFIG_SOC_CAMERA_TI9X4) += ti9x4.o @@ -120,9 +102,6 @@ index 6f994f9..58086d4 100644 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 @@ -2081,12 +2060,12 @@ index 0000000..ef2eb51 +#endif diff --git a/drivers/media/i2c/soc_camera/ar0220.h b/drivers/media/i2c/soc_camera/ar0220.h new file mode 100644 -index 0000000..29987a6 +index 0000000..74bfdd2 --- /dev/null +++ b/drivers/media/i2c/soc_camera/ar0220.h @@ -0,0 +1,43 @@ +/* -+ * ON Semiconductor AR0220 sensor camera wizard 1820x940@44/RCCB/BT656 ++ * ON Semiconductor AR0220 sensor camera wizard 1820x940@44/RCCB/MIPI + * + * Copyright (C) 2017 Cogent Embedded, Inc. + * @@ -5048,10 +5027,10 @@ index 0000000..4c3515a +#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..1dca809 +index 0000000..fa775ae --- /dev/null +++ b/drivers/media/i2c/soc_camera/ov106xx.c -@@ -0,0 +1,128 @@ +@@ -0,0 +1,139 @@ +/* + * OmniVision ov10635/ov490-ov10640/ov495-ov2775 sensor camera driver + * @@ -5069,6 +5048,7 @@ index 0000000..1dca809 +#include "ar0132.c" +#include "ar0220.c" +#include "ap0101_ar014x.c" ++#include "ov2775.c" + +static enum { + ID_OV10635, @@ -5077,6 +5057,7 @@ index 0000000..1dca809 + ID_AR0132, + ID_AR0220, + ID_AP0101_AR014X, ++ ID_OV2775, +} chip_id; + +static int ov106xx_probe(struct i2c_client *client, @@ -5121,6 +5102,12 @@ index 0000000..1dca809 + goto out; + } + ++ ret = ov2775_probe(client, did); ++ if (!ret) { ++ chip_id = ID_OV2775; ++ goto out; ++ } ++ + v4l_err(client, "failed to probe @ 0x%02x (%s)\n", + client->addr, client->adapter->name); +out: @@ -5148,6 +5135,9 @@ index 0000000..1dca809 + case ID_AP0101_AR014X: + ap0101_remove(client); + break; ++ case ID_OV2775: ++ ov2775_remove(client); ++ break; + }; + + return 0; @@ -5180,6 +5170,2386 @@ index 0000000..1dca809 +MODULE_DESCRIPTION("SoC Camera driver for OV10635, OV490/OV10640, OV495/OV2775, AR0132, AR0220, AP0101/AR014X"); +MODULE_AUTHOR("Vladimir Barinov"); +MODULE_LICENSE("GPL"); +diff --git a/drivers/media/i2c/soc_camera/ov2775.c b/drivers/media/i2c/soc_camera/ov2775.c +new file mode 100644 +index 0000000..dac6d60 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov2775.c +@@ -0,0 +1,527 @@ ++/* ++ * OmniVision OV2775 sensor camera driver ++ * ++ * Copyright (C) 2018 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 ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "ov2775.h" ++ ++#define OV2775_I2C_ADDR 0x36 ++ ++#define OV2775_PID 0x300a ++#define OV2775_VER 0x300b ++#define OV2775_VERSION_REG 0x2770 ++ ++#define OV2775_MEDIA_BUS_FMT MEDIA_BUS_FMT_SBGGR8_1X8 ++ ++struct ov2775_priv { ++ struct v4l2_subdev sd; ++ struct v4l2_ctrl_handler hdl; ++ struct media_pad pad; ++ struct v4l2_rect rect; ++ int init_complete; ++ u8 id[6]; ++ int exposure; ++ int gain; ++ int autogain; ++ /* serializers */ ++ int ti9x4_addr; ++ int ti9x3_addr; ++ int port; ++ int gpio_resetb; ++ int gpio_fsin; ++ ++}; ++ ++static inline struct ov2775_priv *to_ov2775(const struct i2c_client *client) ++{ ++ return container_of(i2c_get_clientdata(client), struct ov2775_priv, sd); ++} ++ ++static int ov2775_set_regs(struct i2c_client *client, ++ const struct ov2775_reg *regs, int nr_regs) ++{ ++ int i; ++ ++ for (i = 0; i < nr_regs; i++) { ++ if (regs[i].reg == OV2775_DELAY) { ++ mdelay(regs[i].val); ++ continue; ++ } ++ ++ reg16_write(client, regs[i].reg, regs[i].val); ++ } ++ ++ return 0; ++} ++ ++static int ov2775_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ return 0; ++} ++ ++static int ov2775_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 ov2775_priv *priv = to_ov2775(client); ++ ++ if (format->pad) ++ return -EINVAL; ++ ++ mf->width = priv->rect.width; ++ mf->height = priv->rect.height; ++ mf->code = OV2775_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static int ov2775_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 = OV2775_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ if (format->which == V4L2_SUBDEV_FORMAT_TRY) ++ cfg->try_fmt = *mf; ++ ++ return 0; ++} ++ ++static int ov2775_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 = OV2775_MEDIA_BUS_FMT; ++ ++ return 0; ++} ++ ++static int ov2775_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov2775_priv *priv = to_ov2775(client); ++ ++ memcpy(edid->edid, priv->id, 6); ++ ++ edid->edid[6] = 0xff; ++ edid->edid[7] = client->addr; ++ edid->edid[8] = OV2775_VERSION_REG >> 8; ++ edid->edid[9] = OV2775_VERSION_REG & 0xff; ++ ++ return 0; ++} ++ ++static int ov2775_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 ov2775_priv *priv = to_ov2775(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 > OV2775_MAX_WIDTH) || ++ (rect->top + rect->height > OV2775_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 ov2775_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 ov2775_priv *priv = to_ov2775(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 = OV2775_MAX_WIDTH; ++ sel->r.height = OV2775_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = OV2775_MAX_WIDTH; ++ sel->r.height = OV2775_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP: ++ sel->r = priv->rect; ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int ov2775_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 ov2775_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(u8); ++ ++ return 0; ++} ++ ++static int ov2775_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 ov2775_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = ov2775_g_register, ++ .s_register = ov2775_s_register, ++#endif ++}; ++ ++static int ov2775_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct v4l2_subdev *sd = to_sd(ctrl); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov2775_priv *priv = to_ov2775(client); ++ int ret = -EINVAL; ++ ++ if (!priv->init_complete) ++ return 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_BRIGHTNESS: ++ case V4L2_CID_CONTRAST: ++ case V4L2_CID_SATURATION: ++ case V4L2_CID_HUE: ++ case V4L2_CID_GAMMA: ++ case V4L2_CID_SHARPNESS: ++ case V4L2_CID_AUTOGAIN: ++ case V4L2_CID_GAIN: ++ case V4L2_CID_EXPOSURE: ++ case V4L2_CID_HFLIP: ++ case V4L2_CID_VFLIP: ++ break; ++ } ++ ++ return ret; ++} ++ ++static const struct v4l2_ctrl_ops ov2775_ctrl_ops = { ++ .s_ctrl = ov2775_s_ctrl, ++}; ++ ++static struct v4l2_subdev_video_ops ov2775_video_ops = { ++ .s_stream = ov2775_s_stream, ++ .g_mbus_config = ov2775_g_mbus_config, ++}; ++ ++static const struct v4l2_subdev_pad_ops ov2775_subdev_pad_ops = { ++ .get_edid = ov2775_get_edid, ++ .enum_mbus_code = ov2775_enum_mbus_code, ++ .get_selection = ov2775_get_selection, ++ .set_selection = ov2775_set_selection, ++ .get_fmt = ov2775_get_fmt, ++ .set_fmt = ov2775_set_fmt, ++}; ++ ++static struct v4l2_subdev_ops ov2775_subdev_ops = { ++ .core = &ov2775_core_ops, ++ .video = &ov2775_video_ops, ++ .pad = &ov2775_subdev_pad_ops, ++}; ++ ++static void ov2775_otp_id_read(struct i2c_client *client) ++{ ++} ++ ++static ssize_t ov2775_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 ov2775_priv *priv = to_ov2775(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_ov2775, S_IRUGO, ov2775_otp_id_show, NULL); ++ ++static int ov2775_initialize(struct i2c_client *client) ++{ ++ struct ov2775_priv *priv = to_ov2775(client); ++ u8 val = 0; ++ u16 pid; ++ int ret = 0; ++ ++ /* check and show model ID */ ++ reg16_read(client, OV2775_PID, &val); ++ pid = val; ++ reg16_read(client, OV2775_VER, &val); ++ pid = (pid << 8) | val; ++ ++ if (pid != OV2775_VERSION_REG) { ++ dev_dbg(&client->dev, "Product ID error %x\n", pid); ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ /* Program wizard registers */ ++ ov2775_set_regs(client, ov2775_regs_wizard, ARRAY_SIZE(ov2775_regs_wizard)); ++ /* Read OTP IDs */ ++ ov2775_otp_id_read(client); ++ ++ dev_info(&client->dev, "ov2775 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, OV2775_MAX_WIDTH, OV2775_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 ov2775_parse_dt(struct device_node *np, struct ov2775_priv *priv) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); ++ int i; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ int tmp_addr = 0; ++ ++ for (i = 0; ; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; ++ ++ of_node_put(endpoint); ++ ++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); ++ if (!rendpoint) ++ continue; ++ ++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti9x4") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti9x4_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ } ++ ++ if (!priv->ti9x4_addr) { ++ dev_err(&client->dev, "deserializer does not present\n"); ++ return -EINVAL; ++ } ++ ++ /* setup I2C translator address */ ++ tmp_addr = client->addr; ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x4_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, OV2775_I2C_ADDR << 1); /* Sensor native I2C address */ ++// reg8_write(client, 0x6e, 0xa9); /* GPIO0 - reset, GPIO1 - fsin */ ++ ++ client->addr = priv->ti9x3_addr; /* Serializer I2C address */ ++ reg8_write(client, 0x0d, 0x03); /* unreset gpios */ ++ reg8_write(client, 0x0e, 0xf0); /* unreset gpios */ ++ } ++ client->addr = tmp_addr; ++ ++ mdelay(10); ++ ++ return 0; ++} ++ ++static int ov2775_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct ov2775_priv *priv; ++ int ret; ++ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ v4l2_i2c_subdev_init(&priv->sd, client, &ov2775_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, &ov2775_ctrl_ops, ++ V4L2_CID_BRIGHTNESS, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &ov2775_ctrl_ops, ++ V4L2_CID_CONTRAST, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &ov2775_ctrl_ops, ++ V4L2_CID_SATURATION, 0, 7, 1, 2); ++ v4l2_ctrl_new_std(&priv->hdl, &ov2775_ctrl_ops, ++ V4L2_CID_HUE, 0, 23, 1, 12); ++ v4l2_ctrl_new_std(&priv->hdl, &ov2775_ctrl_ops, ++ V4L2_CID_GAMMA, -128, 128, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ov2775_ctrl_ops, ++ V4L2_CID_SHARPNESS, 0, 10, 1, 3); ++ v4l2_ctrl_new_std(&priv->hdl, &ov2775_ctrl_ops, ++ V4L2_CID_AUTOGAIN, 0, 1, 1, priv->autogain); ++ v4l2_ctrl_new_std(&priv->hdl, &ov2775_ctrl_ops, ++ V4L2_CID_GAIN, 0, 0xffff, 1, priv->gain); ++ v4l2_ctrl_new_std(&priv->hdl, &ov2775_ctrl_ops, ++ V4L2_CID_EXPOSURE, 0, 0xffff, 1, priv->exposure); ++ v4l2_ctrl_new_std(&priv->hdl, &ov2775_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 1); ++ v4l2_ctrl_new_std(&priv->hdl, &ov2775_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 = ov2775_parse_dt(client->dev.of_node, priv); ++ if (ret) ++ goto cleanup; ++ ++ ret = ov2775_initialize(client); ++ if (ret < 0) ++ goto cleanup; ++ ++ priv->rect.left = 0; ++ priv->rect.top = 0; ++ priv->rect.width = OV2775_MAX_WIDTH; ++ priv->rect.height = OV2775_MAX_HEIGHT; ++ ++ ret = v4l2_async_register_subdev(&priv->sd); ++ if (ret) ++ goto cleanup; ++ ++ if (device_create_file(&client->dev, &dev_attr_otp_id_ov2775) != 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_OV2775 ++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", ++ client->addr, client->adapter->name); ++#endif ++ return ret; ++} ++ ++static int ov2775_remove(struct i2c_client *client) ++{ ++ struct ov2775_priv *priv = i2c_get_clientdata(client); ++ ++ device_remove_file(&client->dev, &dev_attr_otp_id_ov2775); ++ 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_OV2775 ++static const struct i2c_device_id ov2775_id[] = { ++ { "ov2775", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, ov2775_id); ++ ++static const struct of_device_id ov2775_of_ids[] = { ++ { .compatible = "ovti,ov2775", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ov2775_of_ids); ++ ++static struct i2c_driver ov2775_i2c_driver = { ++ .driver = { ++ .name = "ov2775", ++ .of_match_table = ov2775_of_ids, ++ }, ++ .probe = ov2775_probe, ++ .remove = ov2775_remove, ++ .id_table = ov2775_id, ++}; ++ ++module_i2c_driver(ov2775_i2c_driver); ++ ++MODULE_DESCRIPTION("SoC Camera driver for OV2775"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); ++#endif +diff --git a/drivers/media/i2c/soc_camera/ov2775.h b/drivers/media/i2c/soc_camera/ov2775.h +new file mode 100644 +index 0000000..1cdfb50 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov2775.h +@@ -0,0 +1,1841 @@ ++/* ++ * OmniVision OV2775 sensor camera wizard 1928x1088@30/RGGB/MIPI ++ * ++ * Copyright (C) 2018 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 OV2775_DISPLAY_PATTERN_COLOR_BAR ++ ++#define OV2775_MAX_WIDTH 2880 // (1928*1.5=2892) <- must be multiple of 16 - requred by R-CAR VIN ++#define OV2775_MAX_HEIGHT 1088 ++ ++#define OV2775_DELAY 0xffff ++#define OV2775_DT 0x2c // MIPI Data Type ++ ++struct ov2775_reg { ++ u16 reg; ++ u8 val; ++}; ++ ++/* wizard: MIPI 1928x1088 RAW12 Linear 30fps 960Mbps */ ++static const struct ov2775_reg ov2775_regs_wizard[] = { ++{0x3013, 0x01}, // s/w reset ++{OV2775_DELAY, 10}, // Wait 10ms ++{0x3000, 0x02}, ++{0x3001, 0x28}, ++{0x3002, 0x03}, ++{0x3003, 0x01}, ++{0x3004, 0x02}, ++{0x3005, 0x26}, ++{0x3006, 0x00}, ++{0x3007, 0x07}, ++{0x3008, 0x01}, ++{0x3009, 0x00}, ++{0x300c, 0x6c}, ++{0x300e, 0x80}, ++{0x300f, 0x00}, ++{0x3012, 0x00}, ++{0x3013, 0x00}, ++{0x3014, 0xc4}, ++{0x3015, 0x00}, ++{0x3017, 0x00}, ++{0x3018, 0x00}, ++{0x3019, 0x00}, ++{0x301a, 0x00}, ++{0x301b, 0x01}, ++{0x301e, 0x17}, ++{0x301f, 0xe1}, ++{0x3030, 0x02}, ++{0x3031, 0x72}, ++{0x3032, 0xf0}, ++{0x3033, 0x30}, ++{0x3034, 0x3f}, ++{0x3035, 0x5f}, ++{0x3036, 0x02}, ++{0x3037, 0x9f}, ++{0x3038, 0x04}, ++{0x3039, 0xb7}, ++{0x303a, 0x04}, ++{0x303b, 0x07}, ++{0x303c, 0xf0}, ++{0x303d, 0x00}, ++{0x303e, 0x0b}, ++{0x303f, 0xe3}, ++{0x3040, 0xf3}, ++{0x3041, 0x29}, ++{0x3042, 0xf6}, ++{0x3043, 0x65}, ++{0x3044, 0x06}, ++{0x3045, 0x0f}, ++{0x3046, 0x59}, ++{0x3047, 0x07}, ++{0x3048, 0x82}, ++{0x3049, 0xcf}, ++{0x304a, 0x12}, ++{0x304b, 0x40}, ++{0x304c, 0x33}, ++{0x304d, 0xa4}, ++{0x304e, 0x0b}, ++{0x304f, 0x3d}, ++{0x3050, 0x10}, ++{0x3060, 0x00}, ++{0x3061, 0x64}, ++{0x3062, 0x00}, ++{0x3063, 0xe4}, ++{0x3066, 0x80}, ++{0x3080, 0x00}, ++{0x3081, 0x00}, ++{0x3082, 0x01}, ++{0x3083, 0xe3}, ++{0x3084, 0x06}, ++{0x3085, 0x00}, ++{0x3086, 0x10}, ++{0x3087, 0x10}, ++{0x3089, 0x00}, ++{0x308a, 0x01}, ++{0x3093, 0x00}, ++{0x30a0, 0x00}, ++{0x30a1, 0x00}, ++{0x30a2, 0x00}, ++{0x30a3, 0x00}, ++{0x30a4, 0x07}, ++{0x30a5, 0x8f}, ++{0x30a6, 0x04}, ++{0x30a7, 0x47}, ++{0x30a8, 0x00}, ++{0x30a9, 0x00}, ++{0x30aa, 0x00}, ++{0x30ab, 0x00}, ++{0x30ac, 0x07}, ++{0x30ad, 0x90}, ++{0x30ae, 0x04}, ++{0x30af, 0x48}, ++{0x30b0, 0x04}, ++{0x30b1, 0x7e}, ++{0x30b2, 0x04}, ++{0x30b3, 0x65}, ++{0x30b4, 0x00}, ++{0x30b5, 0x00}, ++{0x30b6, 0x00}, ++{0x30b7, 0x10}, ++{0x30b8, 0x00}, ++{0x30b9, 0x02}, ++{0x30ba, 0x10}, ++{0x30bb, 0x00}, ++{0x30bc, 0x00}, ++{0x30bd, 0x03}, ++{0x30be, 0x5c}, ++{0x30bf, 0x00}, ++{0x30c0, 0x01}, ++{0x30c1, 0x00}, ++{0x30c2, 0x20}, ++{0x30c3, 0x00}, ++{0x30c4, 0x4a}, ++{0x30c5, 0x00}, ++{0x30c7, 0x00}, ++{0x30c8, 0x00}, ++{0x30d1, 0x00}, ++{0x30d2, 0x00}, ++{0x30d3, 0x80}, ++{0x30d4, 0x00}, ++{0x30d9, 0x09}, ++{0x30da, 0x64}, ++{0x30dd, 0x00}, ++{0x30de, 0x16}, ++{0x30df, 0x00}, ++{0x30e0, 0x17}, ++{0x30e1, 0x00}, ++{0x30e2, 0x18}, ++{0x30e3, 0x10}, ++{0x30e4, 0x04}, ++{0x30e5, 0x00}, ++{0x30e6, 0x00}, ++{0x30e7, 0x00}, ++{0x30e8, 0x00}, ++{0x30e9, 0x00}, ++{0x30ea, 0x00}, ++{0x30eb, 0x00}, ++{0x30ec, 0x00}, ++{0x30ed, 0x00}, ++{0x3101, 0x00}, ++{0x3102, 0x00}, ++{0x3103, 0x00}, ++{0x3104, 0x00}, ++{0x3105, 0x8c}, ++{0x3106, 0x87}, ++{0x3107, 0xc0}, ++{0x3108, 0x9d}, ++{0x3109, 0x8d}, ++{0x310a, 0x8d}, ++{0x310b, 0x6a}, ++{0x310c, 0x3a}, ++{0x310d, 0x5a}, ++{0x310e, 0x00}, ++{0x3120, 0x00}, ++{0x3121, 0x00}, ++{0x3122, 0x00}, ++{0x3123, 0xf0}, ++{0x3124, 0x00}, ++{0x3125, 0x70}, ++{0x3126, 0x1f}, ++{0x3127, 0x0f}, ++{0x3128, 0x00}, ++{0x3129, 0x3a}, ++{0x312a, 0x02}, ++{0x312b, 0x0f}, ++{0x312c, 0x00}, ++{0x312d, 0x0f}, ++{0x312e, 0x1d}, ++{0x312f, 0x00}, ++{0x3130, 0x00}, ++{0x3131, 0x00}, ++{0x3132, 0x00}, ++{0x3140, 0x0a}, ++{0x3141, 0x03}, ++{0x3142, 0x00}, ++{0x3143, 0x00}, ++{0x3144, 0x00}, ++{0x3145, 0x00}, ++{0x3146, 0x00}, ++{0x3147, 0x00}, ++{0x3148, 0x00}, ++{0x3149, 0x00}, ++{0x314a, 0x00}, ++{0x314b, 0x00}, ++{0x314c, 0x00}, ++{0x314d, 0x00}, ++{0x314e, 0x1c}, ++{0x314f, 0xff}, ++{0x3150, 0xff}, ++{0x3151, 0xff}, ++{0x3152, 0x10}, ++{0x3153, 0x10}, ++{0x3154, 0x10}, ++{0x3155, 0x00}, ++{0x3156, 0x03}, ++{0x3157, 0x00}, ++{0x3158, 0x0f}, ++{0x3159, 0xff}, ++{0x315a, 0x01}, ++{0x315b, 0x00}, ++{0x315c, 0x01}, ++{0x315d, 0x00}, ++{0x315e, 0x01}, ++{0x315f, 0x00}, ++{0x3160, 0x00}, ++{0x3161, 0x40}, ++{0x3162, 0x00}, ++{0x3163, 0x40}, ++{0x3164, 0x00}, ++{0x3165, 0x40}, ++{0x3190, 0x08}, ++{0x3191, 0x99}, ++{0x3193, 0x08}, ++{0x3194, 0x13}, ++{0x3195, 0x33}, ++{0x3196, 0x00}, ++{0x3197, 0x10}, ++{0x3198, 0x00}, ++{0x3199, 0x7f}, ++{0x319a, 0x80}, ++{0x319b, 0xff}, ++{0x319c, 0x80}, ++{0x319d, 0xbf}, ++{0x319e, 0xc0}, ++{0x319f, 0xff}, ++{0x31a0, 0x24}, ++{0x31a1, 0x55}, ++{0x31a2, 0x00}, ++{0x31a3, 0x00}, ++{0x31a6, 0x00}, ++{0x31a7, 0x00}, ++{0x31b0, 0x00}, ++{0x31b1, 0x00}, ++{0x31b2, 0x02}, ++{0x31b3, 0x00}, ++{0x31b4, 0x00}, ++{0x31b5, 0x01}, ++{0x31b6, 0x00}, ++{0x31b7, 0x00}, ++{0x31b8, 0x00}, ++{0x31b9, 0x00}, ++{0x31ba, 0x00}, ++{0x31d0, 0x3c}, ++{0x31d1, 0x34}, ++{0x31d2, 0x3c}, ++{0x31d3, 0x00}, ++{0x31d4, 0x2d}, ++{0x31d5, 0x00}, ++{0x31d6, 0x01}, ++{0x31d7, 0x06}, ++{0x31d8, 0x00}, ++{0x31d9, 0x64}, ++{0x31da, 0x00}, ++{0x31db, 0x30}, ++{0x31dc, 0x04}, ++{0x31dd, 0x69}, ++{0x31de, 0x0a}, ++{0x31df, 0x3c}, ++{0x31e0, 0x04}, ++{0x31e1, 0x32}, ++{0x31e2, 0x00}, ++{0x31e3, 0x00}, ++{0x31e4, 0x08}, ++{0x31e5, 0x80}, ++{0x31e6, 0x00}, ++{0x31e7, OV2775_DT}, ++{0x31e8, 0x6c}, ++{0x31e9, 0xac}, ++{0x31ea, 0xec}, ++{0x31eb, 0x3f}, ++{0x31ec, 0x0f}, ++{0x31ed, 0x20}, ++{0x31ee, 0x04}, ++{0x31ef, 0x48}, ++{0x31f0, 0x07}, ++{0x31f1, 0x90}, ++{0x31f2, 0x04}, ++{0x31f3, 0x48}, ++{0x31f4, 0x07}, ++{0x31f5, 0x90}, ++{0x31f6, 0x04}, ++{0x31f7, 0x48}, ++{0x31f8, 0x07}, ++{0x31f9, 0x90}, ++{0x31fa, 0x04}, ++{0x31fb, 0x48}, ++{0x31fd, 0xcb}, ++{0x31fe, 0x0f}, ++{0x31ff, 0x03}, ++{0x3200, 0x00}, ++{0x3201, 0xff}, ++{0x3202, 0x00}, ++{0x3203, 0xff}, ++{0x3204, 0xff}, ++{0x3205, 0xff}, ++{0x3206, 0xff}, ++{0x3207, 0xff}, ++{0x3208, 0xff}, ++{0x3209, 0xff}, ++{0x320a, 0xff}, ++{0x320b, 0x1b}, ++{0x320c, 0x1f}, ++{0x320d, 0x1e}, ++{0x320e, 0x30}, ++{0x320f, 0x2d}, ++{0x3210, OV2775_DT}, ++{0x3211, 0x2b}, ++{0x3212, 0x2a}, ++{0x3213, 0x24}, ++{0x3214, 0x22}, ++{0x3215, 0x00}, ++{0x3216, 0x04}, ++{0x3217, OV2775_DT}, ++{0x3218, 0x6c}, ++{0x3219, 0xac}, ++{0x321a, 0xec}, ++{0x321b, 0x00}, ++{0x3230, 0x3a}, ++{0x3231, 0x00}, ++{0x3232, 0x80}, ++{0x3233, 0x00}, ++{0x3234, 0x10}, ++{0x3235, 0xaa}, ++{0x3236, 0x55}, ++{0x3237, 0x99}, ++{0x3238, 0x66}, ++{0x3239, 0x08}, ++{0x323a, 0x88}, ++{0x323b, 0x00}, ++{0x323c, 0x00}, ++{0x323d, 0x03}, ++{0x3250, 0x33}, ++{0x3251, 0x00}, ++{0x3252, 0x20}, ++#ifdef OV2775_DISPLAY_PATTERN_COLOR_BAR ++{0x3253, 0x80}, ++#else ++{0x3253, 0x00}, ++#endif ++{0x3254, 0x00}, ++{0x3255, 0x01}, ++{0x3256, 0x00}, ++{0x3257, 0x00}, ++{0x3258, 0x00}, ++{0x3270, 0x01}, ++{0x3271, 0x60}, ++{0x3272, 0xc0}, ++{0x3273, 0x00}, ++{0x3274, 0x80}, ++{0x3275, 0x40}, ++{0x3276, 0x02}, ++{0x3277, 0x08}, ++{0x3278, 0x10}, ++{0x3279, 0x04}, ++{0x327a, 0x00}, ++{0x327b, 0x03}, ++{0x327c, 0x10}, ++{0x327d, 0x60}, ++{0x327e, 0xc0}, ++{0x327f, 0x06}, ++{0x3288, 0x10}, ++{0x3289, 0x00}, ++{0x328a, 0x08}, ++{0x328b, 0x00}, ++{0x328c, 0x04}, ++{0x328d, 0x00}, ++{0x328e, 0x02}, ++{0x328f, 0x00}, ++{0x3290, 0x20}, ++{0x3291, 0x00}, ++{0x3292, 0x10}, ++{0x3293, 0x00}, ++{0x3294, 0x08}, ++{0x3295, 0x00}, ++{0x3296, 0x04}, ++{0x3297, 0x00}, ++{0x3298, 0x40}, ++{0x3299, 0x00}, ++{0x329a, 0x20}, ++{0x329b, 0x00}, ++{0x329c, 0x10}, ++{0x329d, 0x00}, ++{0x329e, 0x08}, ++{0x329f, 0x00}, ++{0x32a0, 0x7f}, ++{0x32a1, 0xff}, ++{0x32a2, 0x40}, ++{0x32a3, 0x00}, ++{0x32a4, 0x20}, ++{0x32a5, 0x00}, ++{0x32a6, 0x10}, ++{0x32a7, 0x00}, ++{0x32a8, 0x00}, ++{0x32a9, 0x00}, ++{0x32aa, 0x00}, ++{0x32ab, 0x00}, ++{0x32ac, 0x00}, ++{0x32ad, 0x00}, ++{0x32ae, 0x00}, ++{0x32af, 0x00}, ++{0x32b0, 0x00}, ++{0x32b1, 0x00}, ++{0x32b2, 0x00}, ++{0x32b3, 0x00}, ++{0x32b4, 0x00}, ++{0x32b5, 0x00}, ++{0x32b6, 0x00}, ++{0x32b7, 0x00}, ++{0x32b8, 0x00}, ++{0x32b9, 0x00}, ++{0x32ba, 0x00}, ++{0x32bb, 0x00}, ++{0x32bc, 0x00}, ++{0x32bd, 0x00}, ++{0x32be, 0x00}, ++{0x32bf, 0x00}, ++{0x32c0, 0x00}, ++{0x32c1, 0x00}, ++{0x32c2, 0x00}, ++{0x32c3, 0x00}, ++{0x32c4, 0x00}, ++{0x32c5, 0x00}, ++{0x32c6, 0x00}, ++{0x32c7, 0x00}, ++{0x32c8, 0x87}, ++{0x32c9, 0x00}, ++{0x3330, 0x03}, ++{0x3331, 0xc8}, ++{0x3332, 0x02}, ++{0x3333, 0x24}, ++{0x3334, 0x00}, ++{0x3335, 0x00}, ++{0x3336, 0x00}, ++{0x3337, 0x00}, ++{0x3338, 0x03}, ++{0x3339, 0xc8}, ++{0x333a, 0x02}, ++{0x333b, 0x24}, ++{0x333c, 0x00}, ++{0x333d, 0x00}, ++{0x333e, 0x00}, ++{0x333f, 0x00}, ++{0x3340, 0x03}, ++{0x3341, 0xc8}, ++{0x3342, 0x02}, ++{0x3343, 0x24}, ++{0x3344, 0x00}, ++{0x3345, 0x00}, ++{0x3346, 0x00}, ++{0x3347, 0x00}, ++{0x3348, 0x40}, ++{0x3349, 0x00}, ++{0x334a, 0x00}, ++{0x334b, 0x00}, ++{0x334c, 0x00}, ++{0x334d, 0x00}, ++{0x334e, 0x80}, ++{0x3360, 0x01}, ++{0x3361, 0x00}, ++{0x3362, 0x01}, ++{0x3363, 0x00}, ++{0x3364, 0x01}, ++{0x3365, 0x00}, ++{0x3366, 0x01}, ++{0x3367, 0x00}, ++{0x3368, 0x01}, ++{0x3369, 0x00}, ++{0x336a, 0x01}, ++{0x336b, 0x00}, ++{0x336c, 0x01}, ++{0x336d, 0x00}, ++{0x336e, 0x01}, ++{0x336f, 0x00}, ++{0x3370, 0x01}, ++{0x3371, 0x00}, ++{0x3372, 0x01}, ++{0x3373, 0x00}, ++{0x3374, 0x01}, ++{0x3375, 0x00}, ++{0x3376, 0x01}, ++{0x3377, 0x00}, ++{0x3378, 0x00}, ++{0x3379, 0x00}, ++{0x337a, 0x00}, ++{0x337b, 0x00}, ++{0x337c, 0x00}, ++{0x337d, 0x00}, ++{0x337e, 0x00}, ++{0x337f, 0x00}, ++{0x3380, 0x00}, ++{0x3381, 0x00}, ++{0x3382, 0x00}, ++{0x3383, 0x00}, ++{0x3384, 0x00}, ++{0x3385, 0x00}, ++{0x3386, 0x00}, ++{0x3387, 0x00}, ++{0x3388, 0x00}, ++{0x3389, 0x00}, ++{0x338a, 0x00}, ++{0x338b, 0x00}, ++{0x338c, 0x00}, ++{0x338d, 0x00}, ++{0x338e, 0x00}, ++{0x338f, 0x00}, ++{0x3390, 0x00}, ++{0x3391, 0x00}, ++{0x3392, 0x00}, ++{0x3393, 0x00}, ++{0x3394, 0x00}, ++{0x3395, 0x00}, ++{0x3396, 0x00}, ++{0x3397, 0x00}, ++{0x3398, 0x00}, ++{0x3399, 0x00}, ++{0x339a, 0x00}, ++{0x339b, 0x00}, ++{0x33b0, 0x00}, ++{0x33b1, 0x50}, ++{0x33b2, 0x01}, ++{0x33b3, 0xff}, ++{0x33b4, 0xe0}, ++{0x33b5, 0x6b}, ++{0x33b6, 0x00}, ++{0x33b7, 0x00}, ++{0x33b8, 0x00}, ++{0x33b9, 0x00}, ++{0x33ba, 0x00}, ++{0x33bb, 0x1f}, ++{0x33bc, 0x01}, ++{0x33bd, 0x01}, ++{0x33be, 0x01}, ++{0x33bf, 0x01}, ++{0x33c0, 0x00}, ++{0x33c1, 0x00}, ++{0x33c2, 0x00}, ++{0x33c3, 0x00}, ++{0x33e0, 0x14}, ++{0x33e1, 0x0f}, ++{0x33e2, 0x02}, ++{0x33e3, 0x01}, ++{0x33e4, 0x01}, ++{0x33e5, 0x01}, ++{0x33e6, 0x00}, ++{0x33e7, 0x04}, ++{0x33e8, 0x0c}, ++{0x33e9, 0x02}, ++{0x33ea, 0x02}, ++{0x33eb, 0x02}, ++{0x33ec, 0x03}, ++{0x33ed, 0x01}, ++{0x33ee, 0x02}, ++{0x33ef, 0x08}, ++{0x33f0, 0x08}, ++{0x33f1, 0x04}, ++{0x33f2, 0x04}, ++{0x33f3, 0x00}, ++{0x33f4, 0x03}, ++{0x33f5, 0x14}, ++{0x33f6, 0x0f}, ++{0x33f7, 0x02}, ++{0x33f8, 0x01}, ++{0x33f9, 0x01}, ++{0x33fa, 0x01}, ++{0x33fb, 0x00}, ++{0x33fc, 0x04}, ++{0x33fd, 0x0c}, ++{0x33fe, 0x02}, ++{0x33ff, 0x02}, ++{0x3400, 0x02}, ++{0x3401, 0x03}, ++{0x3402, 0x01}, ++{0x3403, 0x02}, ++{0x3404, 0x08}, ++{0x3405, 0x08}, ++{0x3406, 0x04}, ++{0x3407, 0x04}, ++{0x3408, 0x00}, ++{0x3409, 0x03}, ++{0x340a, 0x14}, ++{0x340b, 0x0f}, ++{0x340c, 0x04}, ++{0x340d, 0x02}, ++{0x340e, 0x01}, ++{0x340f, 0x01}, ++{0x3410, 0x00}, ++{0x3411, 0x04}, ++{0x3412, 0x0c}, ++{0x3413, 0x00}, ++{0x3414, 0x01}, ++{0x3415, 0x02}, ++{0x3416, 0x03}, ++{0x3417, 0x02}, ++{0x3418, 0x05}, ++{0x3419, 0x0a}, ++{0x341a, 0x08}, ++{0x341b, 0x04}, ++{0x341c, 0x04}, ++{0x341d, 0x00}, ++{0x341e, 0x03}, ++{0x3440, 0x00}, ++{0x3441, 0x00}, ++{0x3442, 0x00}, ++{0x3443, 0x00}, ++{0x3444, 0x02}, ++{0x3445, 0xf0}, ++{0x3446, 0x02}, ++{0x3447, 0x08}, ++{0x3448, 0x00}, ++{0x3460, 0x40}, ++{0x3461, 0x40}, ++{0x3462, 0x40}, ++{0x3463, 0x40}, ++{0x3464, 0x03}, ++{0x3465, 0x01}, ++{0x3466, 0x01}, ++{0x3467, 0x02}, ++{0x3468, 0x30}, ++{0x3469, 0x00}, ++{0x346a, 0x33}, ++{0x346b, 0xbf}, ++{0x3480, 0x40}, ++{0x3481, 0x00}, ++{0x3482, 0x00}, ++{0x3483, 0x00}, ++{0x3484, 0x0d}, ++{0x3485, 0x00}, ++{0x3486, 0x00}, ++{0x3487, 0x00}, ++{0x3488, 0x00}, ++{0x3489, 0x00}, ++{0x348a, 0x00}, ++{0x348b, 0x04}, ++{0x348c, 0x00}, ++{0x348d, 0x01}, ++{0x348f, 0x01}, ++{0x3030, 0x0a}, ++{0x3030, 0x02}, ++{0x7000, 0x58}, ++{0x7001, 0x7a}, ++{0x7002, 0x1a}, ++{0x7003, 0xc1}, ++{0x7004, 0x03}, ++{0x7005, 0xda}, ++{0x7006, 0xbd}, ++{0x7007, 0x03}, ++{0x7008, 0xbd}, ++{0x7009, 0x06}, ++{0x700a, 0xe6}, ++{0x700b, 0xec}, ++{0x700c, 0xbc}, ++{0x700d, 0xff}, ++{0x700e, 0xbc}, ++{0x700f, 0x73}, ++{0x7010, 0xda}, ++{0x7011, 0x72}, ++{0x7012, 0x76}, ++{0x7013, 0xb6}, ++{0x7014, 0xee}, ++{0x7015, 0xcf}, ++{0x7016, 0xac}, ++{0x7017, 0xd0}, ++{0x7018, 0xac}, ++{0x7019, 0xd1}, ++{0x701a, 0x50}, ++{0x701b, 0xac}, ++{0x701c, 0xd2}, ++{0x701d, 0xbc}, ++{0x701e, 0x2e}, ++{0x701f, 0xb4}, ++{0x7020, 0x00}, ++{0x7021, 0xdc}, ++{0x7022, 0xdf}, ++{0x7023, 0xb0}, ++{0x7024, 0x6e}, ++{0x7025, 0xbd}, ++{0x7026, 0x01}, ++{0x7027, 0xd7}, ++{0x7028, 0xed}, ++{0x7029, 0xe1}, ++{0x702a, 0x36}, ++{0x702b, 0x30}, ++{0x702c, 0xd3}, ++{0x702d, 0x2e}, ++{0x702e, 0x54}, ++{0x702f, 0x46}, ++{0x7030, 0xbc}, ++{0x7031, 0x22}, ++{0x7032, 0x66}, ++{0x7033, 0xbc}, ++{0x7034, 0x24}, ++{0x7035, 0x2c}, ++{0x7036, 0x28}, ++{0x7037, 0xbc}, ++{0x7038, 0x3c}, ++{0x7039, 0xa1}, ++{0x703a, 0xac}, ++{0x703b, 0xd8}, ++{0x703c, 0xd6}, ++{0x703d, 0xb4}, ++{0x703e, 0x04}, ++{0x703f, 0x46}, ++{0x7040, 0xb7}, ++{0x7041, 0x04}, ++{0x7042, 0xbe}, ++{0x7043, 0x08}, ++{0x7044, 0xc3}, ++{0x7045, 0xd9}, ++{0x7046, 0xad}, ++{0x7047, 0xc3}, ++{0x7048, 0xbc}, ++{0x7049, 0x19}, ++{0x704a, 0xc1}, ++{0x704b, 0x27}, ++{0x704c, 0xe7}, ++{0x704d, 0x00}, ++{0x704e, 0x50}, ++{0x704f, 0x20}, ++{0x7050, 0xb8}, ++{0x7051, 0x02}, ++{0x7052, 0xbc}, ++{0x7053, 0x17}, ++{0x7054, 0xdb}, ++{0x7055, 0xc7}, ++{0x7056, 0xb8}, ++{0x7057, 0x00}, ++{0x7058, 0x28}, ++{0x7059, 0x54}, ++{0x705a, 0xb4}, ++{0x705b, 0x14}, ++{0x705c, 0xab}, ++{0x705d, 0xbe}, ++{0x705e, 0x06}, ++{0x705f, 0xd8}, ++{0x7060, 0xd6}, ++{0x7061, 0x00}, ++{0x7062, 0xb4}, ++{0x7063, 0xc7}, ++{0x7064, 0x07}, ++{0x7065, 0xb9}, ++{0x7066, 0x05}, ++{0x7067, 0xee}, ++{0x7068, 0xe6}, ++{0x7069, 0xad}, ++{0x706a, 0xb4}, ++{0x706b, 0x26}, ++{0x706c, 0x19}, ++{0x706d, 0xc1}, ++{0x706e, 0x3a}, ++{0x706f, 0xc3}, ++{0x7070, 0xaf}, ++{0x7071, 0x00}, ++{0x7072, 0xc0}, ++{0x7073, 0x3c}, ++{0x7074, 0xc3}, ++{0x7075, 0xbe}, ++{0x7076, 0xe7}, ++{0x7077, 0x00}, ++{0x7078, 0x15}, ++{0x7079, 0xc2}, ++{0x707a, 0x40}, ++{0x707b, 0xc3}, ++{0x707c, 0xa4}, ++{0x707d, 0xc0}, ++{0x707e, 0x3c}, ++{0x707f, 0x00}, ++{0x7080, 0xb9}, ++{0x7081, 0x64}, ++{0x7082, 0x29}, ++{0x7083, 0x00}, ++{0x7084, 0xb8}, ++{0x7085, 0x12}, ++{0x7086, 0xbe}, ++{0x7087, 0x01}, ++{0x7088, 0xd0}, ++{0x7089, 0xbc}, ++{0x708a, 0x01}, ++{0x708b, 0xac}, ++{0x708c, 0x37}, ++{0x708d, 0xd2}, ++{0x708e, 0xac}, ++{0x708f, 0x45}, ++{0x7090, 0xad}, ++{0x7091, 0x28}, ++{0x7092, 0x00}, ++{0x7093, 0xb8}, ++{0x7094, 0x00}, ++{0x7095, 0xbc}, ++{0x7096, 0x01}, ++{0x7097, 0x36}, ++{0x7098, 0xd3}, ++{0x7099, 0x30}, ++{0x709a, 0x04}, ++{0x709b, 0xe0}, ++{0x709c, 0xd8}, ++{0x709d, 0xb4}, ++{0x709e, 0xe9}, ++{0x709f, 0x00}, ++{0x70a0, 0xbe}, ++{0x70a1, 0x05}, ++{0x70a2, 0x62}, ++{0x70a3, 0x07}, ++{0x70a4, 0xb9}, ++{0x70a5, 0x05}, ++{0x70a6, 0xad}, ++{0x70a7, 0xc3}, ++{0x70a8, 0xcf}, ++{0x70a9, 0x00}, ++{0x70aa, 0x15}, ++{0x70ab, 0xc2}, ++{0x70ac, 0x59}, ++{0x70ad, 0xc3}, ++{0x70ae, 0xc9}, ++{0x70af, 0xc0}, ++{0x70b0, 0x55}, ++{0x70b1, 0x00}, ++{0x70b2, 0x46}, ++{0x70b3, 0xa1}, ++{0x70b4, 0xb9}, ++{0x70b5, 0x64}, ++{0x70b6, 0x29}, ++{0x70b7, 0x00}, ++{0x70b8, 0xb8}, ++{0x70b9, 0x02}, ++{0x70ba, 0xbe}, ++{0x70bb, 0x02}, ++{0x70bc, 0xd0}, ++{0x70bd, 0xdc}, ++{0x70be, 0xac}, ++{0x70bf, 0xbc}, ++{0x70c0, 0x01}, ++{0x70c1, 0x37}, ++{0x70c2, 0xac}, ++{0x70c3, 0xd2}, ++{0x70c4, 0x45}, ++{0x70c5, 0xad}, ++{0x70c6, 0x28}, ++{0x70c7, 0x00}, ++{0x70c8, 0xb8}, ++{0x70c9, 0x00}, ++{0x70ca, 0xbc}, ++{0x70cb, 0x01}, ++{0x70cc, 0x36}, ++{0x70cd, 0x30}, ++{0x70ce, 0xe0}, ++{0x70cf, 0xd8}, ++{0x70d0, 0xb5}, ++{0x70d1, 0x0b}, ++{0x70d2, 0xd6}, ++{0x70d3, 0xbe}, ++{0x70d4, 0x07}, ++{0x70d5, 0x00}, ++{0x70d6, 0x62}, ++{0x70d7, 0x07}, ++{0x70d8, 0xb9}, ++{0x70d9, 0x05}, ++{0x70da, 0xad}, ++{0x70db, 0xc3}, ++{0x70dc, 0xcf}, ++{0x70dd, 0x46}, ++{0x70de, 0xcd}, ++{0x70df, 0x07}, ++{0x70e0, 0xcd}, ++{0x70e1, 0x00}, ++{0x70e2, 0xe3}, ++{0x70e3, 0x18}, ++{0x70e4, 0xc2}, ++{0x70e5, 0xa2}, ++{0x70e6, 0xb9}, ++{0x70e7, 0x64}, ++{0x70e8, 0xd1}, ++{0x70e9, 0xdd}, ++{0x70ea, 0xac}, ++{0x70eb, 0xcf}, ++{0x70ec, 0xdf}, ++{0x70ed, 0xb5}, ++{0x70ee, 0x19}, ++{0x70ef, 0x46}, ++{0x70f0, 0x50}, ++{0x70f1, 0xb6}, ++{0x70f2, 0xee}, ++{0x70f3, 0xe8}, ++{0x70f4, 0xe6}, ++{0x70f5, 0xbc}, ++{0x70f6, 0x31}, ++{0x70f7, 0xe1}, ++{0x70f8, 0x36}, ++{0x70f9, 0x30}, ++{0x70fa, 0xd3}, ++{0x70fb, 0x2e}, ++{0x70fc, 0x54}, ++{0x70fd, 0xbd}, ++{0x70fe, 0x03}, ++{0x70ff, 0xec}, ++{0x7100, 0x2c}, ++{0x7101, 0x50}, ++{0x7102, 0x20}, ++{0x7103, 0x04}, ++{0x7104, 0xb8}, ++{0x7105, 0x02}, ++{0x7106, 0xbc}, ++{0x7107, 0x18}, ++{0x7108, 0xc7}, ++{0x7109, 0xb8}, ++{0x710a, 0x00}, ++{0x710b, 0x28}, ++{0x710c, 0x54}, ++{0x710d, 0xbc}, ++{0x710e, 0x02}, ++{0x710f, 0xb4}, ++{0x7110, 0xda}, ++{0x7111, 0xbe}, ++{0x7112, 0x04}, ++{0x7113, 0xd6}, ++{0x7114, 0xd8}, ++{0x7115, 0xab}, ++{0x7116, 0x00}, ++{0x7117, 0x62}, ++{0x7118, 0x07}, ++{0x7119, 0xb9}, ++{0x711a, 0x05}, ++{0x711b, 0xad}, ++{0x711c, 0xc3}, ++{0x711d, 0xbc}, ++{0x711e, 0xe7}, ++{0x711f, 0xb9}, ++{0x7120, 0x64}, ++{0x7121, 0x29}, ++{0x7122, 0x00}, ++{0x7123, 0xb8}, ++{0x7124, 0x02}, ++{0x7125, 0xbe}, ++{0x7126, 0x00}, ++{0x7127, 0x45}, ++{0x7128, 0xad}, ++{0x7129, 0xe2}, ++{0x712a, 0x28}, ++{0x712b, 0x00}, ++{0x712c, 0xb8}, ++{0x712d, 0x00}, ++{0x712e, 0xe0}, ++{0x712f, 0xd8}, ++{0x7130, 0xb4}, ++{0x7131, 0xe9}, ++{0x7132, 0xbe}, ++{0x7133, 0x03}, ++{0x7134, 0x00}, ++{0x7135, 0x30}, ++{0x7136, 0x62}, ++{0x7137, 0x07}, ++{0x7138, 0xb9}, ++{0x7139, 0x05}, ++{0x713a, 0xad}, ++{0x713b, 0xc3}, ++{0x713c, 0xcf}, ++{0x713d, 0x42}, ++{0x713e, 0xe4}, ++{0x713f, 0xcd}, ++{0x7140, 0x07}, ++{0x7141, 0xcd}, ++{0x7142, 0x00}, ++{0x7143, 0x00}, ++{0x7144, 0x17}, ++{0x7145, 0xc2}, ++{0x7146, 0xbb}, ++{0x7147, 0xde}, ++{0x7148, 0xcf}, ++{0x7149, 0xdf}, ++{0x714a, 0xac}, ++{0x714b, 0xd1}, ++{0x714c, 0x44}, ++{0x714d, 0xac}, ++{0x714e, 0xb9}, ++{0x714f, 0x76}, ++{0x7150, 0xb8}, ++{0x7151, 0x08}, ++{0x7152, 0xb6}, ++{0x7153, 0xfe}, ++{0x7154, 0xb4}, ++{0x7155, 0xca}, ++{0x7156, 0xd6}, ++{0x7157, 0xd8}, ++{0x7158, 0xab}, ++{0x7159, 0x00}, ++{0x715a, 0xe1}, ++{0x715b, 0x36}, ++{0x715c, 0x30}, ++{0x715d, 0xd3}, ++{0x715e, 0xbc}, ++{0x715f, 0x29}, ++{0x7160, 0xb4}, ++{0x7161, 0x1f}, ++{0x7162, 0xaa}, ++{0x7163, 0xbd}, ++{0x7164, 0x01}, ++{0x7165, 0xb8}, ++{0x7166, 0x0c}, ++{0x7167, 0x45}, ++{0x7168, 0xa4}, ++{0x7169, 0xbd}, ++{0x716a, 0x03}, ++{0x716b, 0xec}, ++{0x716c, 0xbc}, ++{0x716d, 0x3d}, ++{0x716e, 0xc3}, ++{0x716f, 0xcf}, ++{0x7170, 0x42}, ++{0x7171, 0xb8}, ++{0x7172, 0x00}, ++{0x7173, 0xe4}, ++{0x7174, 0xd5}, ++{0x7175, 0x00}, ++{0x7176, 0xb6}, ++{0x7177, 0x00}, ++{0x7178, 0x74}, ++{0x7179, 0xbd}, ++{0x717a, 0x03}, ++{0x717b, 0x40}, ++{0x717c, 0xb5}, ++{0x717d, 0x39}, ++{0x717e, 0x58}, ++{0x717f, 0xdd}, ++{0x7180, 0x19}, ++{0x7181, 0xc1}, ++{0x7182, 0xc8}, ++{0x7183, 0xbd}, ++{0x7184, 0x06}, ++{0x7185, 0x17}, ++{0x7186, 0xc1}, ++{0x7187, 0xc6}, ++{0x7188, 0xe8}, ++{0x7189, 0x00}, ++{0x718a, 0xc0}, ++{0x718b, 0xc8}, ++{0x718c, 0xe6}, ++{0x718d, 0x95}, ++{0x718e, 0x15}, ++{0x718f, 0x00}, ++{0x7190, 0xbc}, ++{0x7191, 0x19}, ++{0x7192, 0xb9}, ++{0x7193, 0xf6}, ++{0x7194, 0x14}, ++{0x7195, 0xc1}, ++{0x7196, 0xd0}, ++{0x7197, 0xd1}, ++{0x7198, 0xac}, ++{0x7199, 0x37}, ++{0x719a, 0xbc}, ++{0x719b, 0x35}, ++{0x719c, 0x36}, ++{0x719d, 0x30}, ++{0x719e, 0xe1}, ++{0x719f, 0xd3}, ++{0x71a0, 0x7a}, ++{0x71a1, 0xb6}, ++{0x71a2, 0x0c}, ++{0x71a3, 0xff}, ++{0x71a4, 0xb4}, ++{0x71a5, 0xc7}, ++{0x71a6, 0xd9}, ++{0x71a7, 0x00}, ++{0x71a8, 0xbd}, ++{0x71a9, 0x01}, ++{0x71aa, 0x56}, ++{0x71ab, 0xc0}, ++{0x71ac, 0xda}, ++{0x71ad, 0xb4}, ++{0x71ae, 0x1f}, ++{0x71af, 0x56}, ++{0x71b0, 0xaa}, ++{0x71b1, 0xbc}, ++{0x71b2, 0x08}, ++{0x71b3, 0x00}, ++{0x71b4, 0x57}, ++{0x71b5, 0xe8}, ++{0x71b6, 0xb5}, ++{0x71b7, 0x36}, ++{0x71b8, 0x00}, ++{0x71b9, 0x54}, ++{0x71ba, 0xe7}, ++{0x71bb, 0xc8}, ++{0x71bc, 0xb4}, ++{0x71bd, 0x1f}, ++{0x71be, 0x56}, ++{0x71bf, 0xaa}, ++{0x71c0, 0xbc}, ++{0x71c1, 0x08}, ++{0x71c2, 0x57}, ++{0x71c3, 0x00}, ++{0x71c4, 0xb5}, ++{0x71c5, 0x36}, ++{0x71c6, 0x00}, ++{0x71c7, 0x54}, ++{0x71c8, 0xc8}, ++{0x71c9, 0xb5}, ++{0x71ca, 0x18}, ++{0x71cb, 0xd9}, ++{0x71cc, 0x00}, ++{0x71cd, 0xbd}, ++{0x71ce, 0x01}, ++{0x71cf, 0x56}, ++{0x71d0, 0x08}, ++{0x71d1, 0x57}, ++{0x71d2, 0xe8}, ++{0x71d3, 0xb4}, ++{0x71d4, 0x42}, ++{0x71d5, 0x00}, ++{0x71d6, 0x54}, ++{0x71d7, 0xe7}, ++{0x71d8, 0xc8}, ++{0x71d9, 0xab}, ++{0x71da, 0x00}, ++{0x71db, 0x66}, ++{0x71dc, 0x62}, ++{0x71dd, 0x06}, ++{0x71de, 0x74}, ++{0x71df, 0xb9}, ++{0x71e0, 0x05}, ++{0x71e1, 0xb7}, ++{0x71e2, 0x14}, ++{0x71e3, 0x0e}, ++{0x71e4, 0xb7}, ++{0x71e5, 0x04}, ++{0x71e6, 0xc8}, ++{0x7600, 0x04}, ++{0x7601, 0x80}, ++{0x7602, 0x07}, ++{0x7603, 0x44}, ++{0x7604, 0x05}, ++{0x7605, 0x33}, ++{0x7606, 0x0f}, ++{0x7607, 0x00}, ++{0x7608, 0x07}, ++{0x7609, 0x40}, ++{0x760a, 0x04}, ++{0x760b, 0xe5}, ++{0x760c, 0x06}, ++{0x760d, 0x50}, ++{0x760e, 0x04}, ++{0x760f, 0xe4}, ++{0x7610, 0x00}, ++{0x7611, 0x00}, ++{0x7612, 0x06}, ++{0x7613, 0x5c}, ++{0x7614, 0x00}, ++{0x7615, 0x0f}, ++{0x7616, 0x06}, ++{0x7617, 0x1c}, ++{0x7618, 0x00}, ++{0x7619, 0x02}, ++{0x761a, 0x06}, ++{0x761b, 0xa2}, ++{0x761c, 0x00}, ++{0x761d, 0x01}, ++{0x761e, 0x06}, ++{0x761f, 0xae}, ++{0x7620, 0x00}, ++{0x7621, 0x0e}, ++{0x7622, 0x05}, ++{0x7623, 0x30}, ++{0x7624, 0x07}, ++{0x7625, 0x00}, ++{0x7626, 0x0f}, ++{0x7627, 0x00}, ++{0x7628, 0x04}, ++{0x7629, 0xe5}, ++{0x762a, 0x05}, ++{0x762b, 0x33}, ++{0x762c, 0x06}, ++{0x762d, 0x12}, ++{0x762e, 0x00}, ++{0x762f, 0x01}, ++{0x7630, 0x06}, ++{0x7631, 0x52}, ++{0x7632, 0x00}, ++{0x7633, 0x01}, ++{0x7634, 0x06}, ++{0x7635, 0x5e}, ++{0x7636, 0x04}, ++{0x7637, 0xe4}, ++{0x7638, 0x00}, ++{0x7639, 0x01}, ++{0x763a, 0x05}, ++{0x763b, 0x30}, ++{0x763c, 0x0f}, ++{0x763d, 0x00}, ++{0x763e, 0x06}, ++{0x763f, 0xa6}, ++{0x7640, 0x00}, ++{0x7641, 0x02}, ++{0x7642, 0x06}, ++{0x7643, 0x26}, ++{0x7644, 0x00}, ++{0x7645, 0x02}, ++{0x7646, 0x05}, ++{0x7647, 0x33}, ++{0x7648, 0x06}, ++{0x7649, 0x20}, ++{0x764a, 0x0f}, ++{0x764b, 0x00}, ++{0x764c, 0x06}, ++{0x764d, 0x56}, ++{0x764e, 0x00}, ++{0x764f, 0x02}, ++{0x7650, 0x06}, ++{0x7651, 0x16}, ++{0x7652, 0x05}, ++{0x7653, 0x33}, ++{0x7654, 0x06}, ++{0x7655, 0x10}, ++{0x7656, 0x0f}, ++{0x7657, 0x00}, ++{0x7658, 0x06}, ++{0x7659, 0x10}, ++{0x765a, 0x0f}, ++{0x765b, 0x00}, ++{0x765c, 0x06}, ++{0x765d, 0x20}, ++{0x765e, 0x0f}, ++{0x765f, 0x00}, ++{0x7660, 0x00}, ++{0x7661, 0x00}, ++{0x7662, 0x00}, ++{0x7663, 0x02}, ++{0x7664, 0x04}, ++{0x7665, 0xe5}, ++{0x7666, 0x04}, ++{0x7667, 0xe4}, ++{0x7668, 0x0f}, ++{0x7669, 0x00}, ++{0x766a, 0x00}, ++{0x766b, 0x00}, ++{0x766c, 0x00}, ++{0x766d, 0x01}, ++{0x766e, 0x04}, ++{0x766f, 0xe5}, ++{0x7670, 0x04}, ++{0x7671, 0xe4}, ++{0x7672, 0x0f}, ++{0x7673, 0x00}, ++{0x7674, 0x00}, ++{0x7675, 0x02}, ++{0x7676, 0x04}, ++{0x7677, 0xe4}, ++{0x7678, 0x00}, ++{0x7679, 0x02}, ++{0x767a, 0x04}, ++{0x767b, 0xc4}, ++{0x767c, 0x00}, ++{0x767d, 0x02}, ++{0x767e, 0x04}, ++{0x767f, 0xc4}, ++{0x7680, 0x05}, ++{0x7681, 0x83}, ++{0x7682, 0x0f}, ++{0x7683, 0x00}, ++{0x7684, 0x00}, ++{0x7685, 0x02}, ++{0x7686, 0x04}, ++{0x7687, 0xe4}, ++{0x7688, 0x00}, ++{0x7689, 0x02}, ++{0x768a, 0x04}, ++{0x768b, 0xc4}, ++{0x768c, 0x00}, ++{0x768d, 0x02}, ++{0x768e, 0x04}, ++{0x768f, 0xc4}, ++{0x7690, 0x05}, ++{0x7691, 0x83}, ++{0x7692, 0x03}, ++{0x7693, 0x0b}, ++{0x7694, 0x05}, ++{0x7695, 0x83}, ++{0x7696, 0x00}, ++{0x7697, 0x07}, ++{0x7698, 0x05}, ++{0x7699, 0x03}, ++{0x769a, 0x00}, ++{0x769b, 0x05}, ++{0x769c, 0x05}, ++{0x769d, 0x32}, ++{0x769e, 0x05}, ++{0x769f, 0x30}, ++{0x76a0, 0x00}, ++{0x76a1, 0x02}, ++{0x76a2, 0x05}, ++{0x76a3, 0x78}, ++{0x76a4, 0x00}, ++{0x76a5, 0x01}, ++{0x76a6, 0x05}, ++{0x76a7, 0x7c}, ++{0x76a8, 0x03}, ++{0x76a9, 0x9a}, ++{0x76aa, 0x05}, ++{0x76ab, 0x83}, ++{0x76ac, 0x00}, ++{0x76ad, 0x04}, ++{0x76ae, 0x05}, ++{0x76af, 0x03}, ++{0x76b0, 0x00}, ++{0x76b1, 0x03}, ++{0x76b2, 0x05}, ++{0x76b3, 0x32}, ++{0x76b4, 0x05}, ++{0x76b5, 0x30}, ++{0x76b6, 0x00}, ++{0x76b7, 0x02}, ++{0x76b8, 0x05}, ++{0x76b9, 0x78}, ++{0x76ba, 0x00}, ++{0x76bb, 0x01}, ++{0x76bc, 0x05}, ++{0x76bd, 0x7c}, ++{0x76be, 0x03}, ++{0x76bf, 0x99}, ++{0x76c0, 0x05}, ++{0x76c1, 0x83}, ++{0x76c2, 0x00}, ++{0x76c3, 0x03}, ++{0x76c4, 0x05}, ++{0x76c5, 0x03}, ++{0x76c6, 0x00}, ++{0x76c7, 0x01}, ++{0x76c8, 0x05}, ++{0x76c9, 0x32}, ++{0x76ca, 0x05}, ++{0x76cb, 0x30}, ++{0x76cc, 0x00}, ++{0x76cd, 0x02}, ++{0x76ce, 0x05}, ++{0x76cf, 0x78}, ++{0x76d0, 0x00}, ++{0x76d1, 0x01}, ++{0x76d2, 0x05}, ++{0x76d3, 0x7c}, ++{0x76d4, 0x03}, ++{0x76d5, 0x98}, ++{0x76d6, 0x05}, ++{0x76d7, 0x83}, ++{0x76d8, 0x00}, ++{0x76d9, 0x00}, ++{0x76da, 0x05}, ++{0x76db, 0x03}, ++{0x76dc, 0x00}, ++{0x76dd, 0x01}, ++{0x76de, 0x05}, ++{0x76df, 0x32}, ++{0x76e0, 0x05}, ++{0x76e1, 0x30}, ++{0x76e2, 0x00}, ++{0x76e3, 0x02}, ++{0x76e4, 0x05}, ++{0x76e5, 0x78}, ++{0x76e6, 0x00}, ++{0x76e7, 0x01}, ++{0x76e8, 0x05}, ++{0x76e9, 0x7c}, ++{0x76ea, 0x03}, ++{0x76eb, 0x97}, ++{0x76ec, 0x05}, ++{0x76ed, 0x83}, ++{0x76ee, 0x00}, ++{0x76ef, 0x00}, ++{0x76f0, 0x05}, ++{0x76f1, 0x03}, ++{0x76f2, 0x05}, ++{0x76f3, 0x32}, ++{0x76f4, 0x05}, ++{0x76f5, 0x30}, ++{0x76f6, 0x00}, ++{0x76f7, 0x02}, ++{0x76f8, 0x05}, ++{0x76f9, 0x78}, ++{0x76fa, 0x00}, ++{0x76fb, 0x01}, ++{0x76fc, 0x05}, ++{0x76fd, 0x7c}, ++{0x76fe, 0x03}, ++{0x76ff, 0x96}, ++{0x7700, 0x05}, ++{0x7701, 0x83}, ++{0x7702, 0x05}, ++{0x7703, 0x03}, ++{0x7704, 0x05}, ++{0x7705, 0x32}, ++{0x7706, 0x05}, ++{0x7707, 0x30}, ++{0x7708, 0x00}, ++{0x7709, 0x02}, ++{0x770a, 0x05}, ++{0x770b, 0x78}, ++{0x770c, 0x00}, ++{0x770d, 0x01}, ++{0x770e, 0x05}, ++{0x770f, 0x7c}, ++{0x7710, 0x03}, ++{0x7711, 0x95}, ++{0x7712, 0x05}, ++{0x7713, 0x83}, ++{0x7714, 0x05}, ++{0x7715, 0x03}, ++{0x7716, 0x05}, ++{0x7717, 0x32}, ++{0x7718, 0x05}, ++{0x7719, 0x30}, ++{0x771a, 0x00}, ++{0x771b, 0x02}, ++{0x771c, 0x05}, ++{0x771d, 0x78}, ++{0x771e, 0x00}, ++{0x771f, 0x01}, ++{0x7720, 0x05}, ++{0x7721, 0x7c}, ++{0x7722, 0x03}, ++{0x7723, 0x94}, ++{0x7724, 0x05}, ++{0x7725, 0x83}, ++{0x7726, 0x00}, ++{0x7727, 0x01}, ++{0x7728, 0x05}, ++{0x7729, 0x03}, ++{0x772a, 0x00}, ++{0x772b, 0x01}, ++{0x772c, 0x05}, ++{0x772d, 0x32}, ++{0x772e, 0x05}, ++{0x772f, 0x30}, ++{0x7730, 0x00}, ++{0x7731, 0x02}, ++{0x7732, 0x05}, ++{0x7733, 0x78}, ++{0x7734, 0x00}, ++{0x7735, 0x01}, ++{0x7736, 0x05}, ++{0x7737, 0x7c}, ++{0x7738, 0x03}, ++{0x7739, 0x93}, ++{0x773a, 0x05}, ++{0x773b, 0x83}, ++{0x773c, 0x00}, ++{0x773d, 0x00}, ++{0x773e, 0x05}, ++{0x773f, 0x03}, ++{0x7740, 0x00}, ++{0x7741, 0x00}, ++{0x7742, 0x05}, ++{0x7743, 0x32}, ++{0x7744, 0x05}, ++{0x7745, 0x30}, ++{0x7746, 0x00}, ++{0x7747, 0x02}, ++{0x7748, 0x05}, ++{0x7749, 0x78}, ++{0x774a, 0x00}, ++{0x774b, 0x01}, ++{0x774c, 0x05}, ++{0x774d, 0x7c}, ++{0x774e, 0x03}, ++{0x774f, 0x92}, ++{0x7750, 0x05}, ++{0x7751, 0x83}, ++{0x7752, 0x05}, ++{0x7753, 0x03}, ++{0x7754, 0x00}, ++{0x7755, 0x00}, ++{0x7756, 0x05}, ++{0x7757, 0x32}, ++{0x7758, 0x05}, ++{0x7759, 0x30}, ++{0x775a, 0x00}, ++{0x775b, 0x02}, ++{0x775c, 0x05}, ++{0x775d, 0x78}, ++{0x775e, 0x00}, ++{0x775f, 0x01}, ++{0x7760, 0x05}, ++{0x7761, 0x7c}, ++{0x7762, 0x03}, ++{0x7763, 0x91}, ++{0x7764, 0x05}, ++{0x7765, 0x83}, ++{0x7766, 0x05}, ++{0x7767, 0x03}, ++{0x7768, 0x05}, ++{0x7769, 0x32}, ++{0x776a, 0x05}, ++{0x776b, 0x30}, ++{0x776c, 0x00}, ++{0x776d, 0x02}, ++{0x776e, 0x05}, ++{0x776f, 0x78}, ++{0x7770, 0x00}, ++{0x7771, 0x01}, ++{0x7772, 0x05}, ++{0x7773, 0x7c}, ++{0x7774, 0x03}, ++{0x7775, 0x90}, ++{0x7776, 0x05}, ++{0x7777, 0x83}, ++{0x7778, 0x05}, ++{0x7779, 0x03}, ++{0x777a, 0x05}, ++{0x777b, 0x32}, ++{0x777c, 0x05}, ++{0x777d, 0x30}, ++{0x777e, 0x00}, ++{0x777f, 0x02}, ++{0x7780, 0x05}, ++{0x7781, 0x78}, ++{0x7782, 0x00}, ++{0x7783, 0x01}, ++{0x7784, 0x05}, ++{0x7785, 0x7c}, ++{0x7786, 0x02}, ++{0x7787, 0x90}, ++{0x7788, 0x05}, ++{0x7789, 0x03}, ++{0x778a, 0x07}, ++{0x778b, 0x00}, ++{0x778c, 0x0f}, ++{0x778d, 0x00}, ++{0x778e, 0x08}, ++{0x778f, 0x30}, ++{0x7790, 0x08}, ++{0x7791, 0xee}, ++{0x7792, 0x0f}, ++{0x7793, 0x00}, ++{0x7794, 0x05}, ++{0x7795, 0x33}, ++{0x7796, 0x04}, ++{0x7797, 0xe5}, ++{0x7798, 0x06}, ++{0x7799, 0x52}, ++{0x779a, 0x04}, ++{0x779b, 0xe4}, ++{0x779c, 0x00}, ++{0x779d, 0x00}, ++{0x779e, 0x06}, ++{0x779f, 0x5e}, ++{0x77a0, 0x00}, ++{0x77a1, 0x0f}, ++{0x77a2, 0x06}, ++{0x77a3, 0x1e}, ++{0x77a4, 0x00}, ++{0x77a5, 0x02}, ++{0x77a6, 0x06}, ++{0x77a7, 0xa2}, ++{0x77a8, 0x00}, ++{0x77a9, 0x01}, ++{0x77aa, 0x06}, ++{0x77ab, 0xae}, ++{0x77ac, 0x00}, ++{0x77ad, 0x03}, ++{0x77ae, 0x05}, ++{0x77af, 0x30}, ++{0x77b0, 0x09}, ++{0x77b1, 0x19}, ++{0x77b2, 0x0f}, ++{0x77b3, 0x00}, ++{0x77b4, 0x05}, ++{0x77b5, 0x33}, ++{0x77b6, 0x04}, ++{0x77b7, 0xe5}, ++{0x77b8, 0x06}, ++{0x77b9, 0x52}, ++{0x77ba, 0x04}, ++{0x77bb, 0xe4}, ++{0x77bc, 0x00}, ++{0x77bd, 0x00}, ++{0x77be, 0x06}, ++{0x77bf, 0x5e}, ++{0x77c0, 0x00}, ++{0x77c1, 0x0f}, ++{0x77c2, 0x06}, ++{0x77c3, 0x1e}, ++{0x77c4, 0x00}, ++{0x77c5, 0x02}, ++{0x77c6, 0x06}, ++{0x77c7, 0xa2}, ++{0x77c8, 0x00}, ++{0x77c9, 0x01}, ++{0x77ca, 0x06}, ++{0x77cb, 0xae}, ++{0x77cc, 0x00}, ++{0x77cd, 0x03}, ++{0x77ce, 0x05}, ++{0x77cf, 0x30}, ++{0x77d0, 0x0f}, ++{0x77d1, 0x00}, ++{0x77d2, 0x00}, ++{0x77d3, 0x00}, ++{0x77d4, 0x00}, ++{0x77d5, 0x02}, ++{0x77d6, 0x04}, ++{0x77d7, 0xe5}, ++{0x77d8, 0x04}, ++{0x77d9, 0xe4}, ++{0x77da, 0x05}, ++{0x77db, 0x33}, ++{0x77dc, 0x07}, ++{0x77dd, 0x10}, ++{0x77de, 0x00}, ++{0x77df, 0x00}, ++{0x77e0, 0x01}, ++{0x77e1, 0xbb}, ++{0x77e2, 0x00}, ++{0x77e3, 0x00}, ++{0x77e4, 0x01}, ++{0x77e5, 0xaa}, ++{0x77e6, 0x00}, ++{0x77e7, 0x00}, ++{0x77e8, 0x01}, ++{0x77e9, 0x99}, ++{0x77ea, 0x00}, ++{0x77eb, 0x00}, ++{0x77ec, 0x01}, ++{0x77ed, 0x88}, ++{0x77ee, 0x00}, ++{0x77ef, 0x00}, ++{0x77f0, 0x01}, ++{0x77f1, 0x77}, ++{0x77f2, 0x00}, ++{0x77f3, 0x00}, ++{0x77f4, 0x01}, ++{0x77f5, 0x66}, ++{0x77f6, 0x00}, ++{0x77f7, 0x00}, ++{0x77f8, 0x01}, ++{0x77f9, 0x55}, ++{0x77fa, 0x00}, ++{0x77fb, 0x00}, ++{0x77fc, 0x01}, ++{0x77fd, 0x44}, ++{0x77fe, 0x00}, ++{0x77ff, 0x00}, ++{0x7800, 0x01}, ++{0x7801, 0x33}, ++{0x7802, 0x00}, ++{0x7803, 0x00}, ++{0x7804, 0x01}, ++{0x7805, 0x22}, ++{0x7806, 0x00}, ++{0x7807, 0x00}, ++{0x7808, 0x01}, ++{0x7809, 0x11}, ++{0x780a, 0x00}, ++{0x780b, 0x00}, ++{0x780c, 0x01}, ++{0x780d, 0x00}, ++{0x780e, 0x01}, ++{0x780f, 0xff}, ++{0x7810, 0x07}, ++{0x7811, 0x00}, ++{0x7812, 0x02}, ++{0x7813, 0xa0}, ++{0x7814, 0x0f}, ++{0x7815, 0x00}, ++{0x7816, 0x08}, ++{0x7817, 0x35}, ++{0x7818, 0x06}, ++{0x7819, 0x52}, ++{0x781a, 0x04}, ++{0x781b, 0xe4}, ++{0x781c, 0x00}, ++{0x781d, 0x00}, ++{0x781e, 0x06}, ++{0x781f, 0x5e}, ++{0x7820, 0x05}, ++{0x7821, 0x33}, ++{0x7822, 0x09}, ++{0x7823, 0x19}, ++{0x7824, 0x06}, ++{0x7825, 0x1e}, ++{0x7826, 0x05}, ++{0x7827, 0x33}, ++{0x7828, 0x00}, ++{0x7829, 0x01}, ++{0x782a, 0x06}, ++{0x782b, 0x24}, ++{0x782c, 0x06}, ++{0x782d, 0x20}, ++{0x782e, 0x0f}, ++{0x782f, 0x00}, ++{0x7830, 0x08}, ++{0x7831, 0x35}, ++{0x7832, 0x07}, ++{0x7833, 0x10}, ++{0x7834, 0x00}, ++{0x7835, 0x00}, ++{0x7836, 0x01}, ++{0x7837, 0xbb}, ++{0x7838, 0x00}, ++{0x7839, 0x00}, ++{0x783a, 0x01}, ++{0x783b, 0xaa}, ++{0x783c, 0x00}, ++{0x783d, 0x00}, ++{0x783e, 0x01}, ++{0x783f, 0x99}, ++{0x7840, 0x00}, ++{0x7841, 0x00}, ++{0x7842, 0x01}, ++{0x7843, 0x88}, ++{0x7844, 0x00}, ++{0x7845, 0x00}, ++{0x7846, 0x01}, ++{0x7847, 0x77}, ++{0x7848, 0x00}, ++{0x7849, 0x00}, ++{0x784a, 0x01}, ++{0x784b, 0x66}, ++{0x784c, 0x00}, ++{0x784d, 0x00}, ++{0x784e, 0x01}, ++{0x784f, 0x55}, ++{0x7850, 0x00}, ++{0x7851, 0x00}, ++{0x7852, 0x01}, ++{0x7853, 0x44}, ++{0x7854, 0x00}, ++{0x7855, 0x00}, ++{0x7856, 0x01}, ++{0x7857, 0x33}, ++{0x7858, 0x00}, ++{0x7859, 0x00}, ++{0x785a, 0x01}, ++{0x785b, 0x22}, ++{0x785c, 0x00}, ++{0x785d, 0x00}, ++{0x785e, 0x01}, ++{0x785f, 0x11}, ++{0x7860, 0x00}, ++{0x7861, 0x00}, ++{0x7862, 0x01}, ++{0x7863, 0x00}, ++{0x7864, 0x07}, ++{0x7865, 0x00}, ++{0x7866, 0x01}, ++{0x7867, 0xff}, ++{0x7868, 0x02}, ++{0x7869, 0xa0}, ++{0x786a, 0x0f}, ++{0x786b, 0x00}, ++{0x786c, 0x08}, ++{0x786d, 0x3a}, ++{0x786e, 0x08}, ++{0x786f, 0x6a}, ++{0x7870, 0x0f}, ++{0x7871, 0x00}, ++{0x7872, 0x04}, ++{0x7873, 0xc0}, ++{0x7874, 0x09}, ++{0x7875, 0x19}, ++{0x7876, 0x04}, ++{0x7877, 0x99}, ++{0x7878, 0x07}, ++{0x7879, 0x14}, ++{0x787a, 0x00}, ++{0x787b, 0x01}, ++{0x787c, 0x04}, ++{0x787d, 0xa4}, ++{0x787e, 0x00}, ++{0x787f, 0x0f}, ++{0x7880, 0x00}, ++{0x7881, 0x0f}, ++{0x7882, 0x04}, ++{0x7883, 0xa6}, ++{0x7884, 0x00}, ++{0x7885, 0x00}, ++{0x7886, 0x04}, ++{0x7887, 0xa0}, ++{0x7888, 0x04}, ++{0x7889, 0x80}, ++{0x788a, 0x04}, ++{0x788b, 0x00}, ++{0x788c, 0x05}, ++{0x788d, 0x03}, ++{0x788e, 0x06}, ++{0x788f, 0x00}, ++{0x7890, 0x0f}, ++{0x7891, 0x00}, ++{0x7892, 0x0f}, ++{0x7893, 0x00}, ++{0x7894, 0x0f}, ++{0x7895, 0x00}, ++{0x30a0, 0x00}, ++{0x30a1, 0x00}, ++{0x30a2, 0x00}, ++{0x30a3, 0x00}, ++{0x30a4, 0x07}, ++{0x30a5, 0x8f}, ++{0x30a6, 0x04}, ++{0x30a7, 0x47}, ++{0x30a8, 0x00}, ++{0x30a9, 0x04}, ++{0x30aa, 0x00}, ++{0x30ab, 0x04}, ++{0x30ac, 0x07}, ++{0x30ad, 0x88}, ++{0x30ae, 0x04}, ++{0x30af, 0x40}, ++{0x30b0, 0x0d}, ++{0x30b1, 0xde}, ++{0x30b2, 0x04}, ++{0x30b3, 0x66}, ++{0x3196, 0x00}, ++{0x3197, 0x0a}, ++{0x3195, 0x29}, ++{0x315a, 0x02}, ++{0x315b, 0x00}, ++{0x30bb, 0x40}, ++{0x3250, 0xf7}, ++{0x3012, 0x01}, ++}; 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..812f367 @@ -7074,12 +9444,12 @@ index 0000000..e53c482 +#endif diff --git a/drivers/media/i2c/soc_camera/ov495_ov2775.h b/drivers/media/i2c/soc_camera/ov495_ov2775.h new file mode 100644 -index 0000000..3f53689 +index 0000000..17c94ae --- /dev/null +++ b/drivers/media/i2c/soc_camera/ov495_ov2775.h @@ -0,0 +1,23 @@ +/* -+ * OmniVision ov495-ov2775 sensor camera wizard 1280x1080@30/UYVY/BT601/8bit ++ * OmniVision ov495-ov2775 sensor camera wizard 1920x1080@30/UYVY/MIPI + * + * Copyright (C) 2017 Cogent Embedded, Inc. + * -- cgit 1.2.3-korg From e2886a6764e9209e81258eafed4c908f887cbca7 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Tue, 6 Feb 2018 17:54:07 +0300 Subject: Add V3M based Video Box Mini V2 board This cleans up VideoBoxMini board and add VideoBoxMini V2 board --- .../0040-arm64-dts-renesas-add-ADAS-boards.patch | 164 ++++++++++++++++----- .../recipes-kernel/linux/linux-renesas/v3msk.cfg | 1 + 2 files changed, 126 insertions(+), 39 deletions(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch index 4f390e6..608db41 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch @@ -25,13 +25,14 @@ V3MZF board on R8A7797 SoC Videobox Mini board on R8A7795 ES1.x SoC Videobox Mini board on R8A7795 SoC Videobox Mini board on R8A7797 SoC +Videobox Mini V2 board on R8A7797 SoC Videobox2 board on R8A7795 ES1.x SoC Videobox2 board on R8A7795 SoC Condor board on R8A7798 SoC Signed-off-by: Vladimir Barinov --- - arch/arm64/boot/dts/renesas/Makefile | 22 + + arch/arm64/boot/dts/renesas/Makefile | 23 + arch/arm64/boot/dts/renesas/legacy/Makefile | 8 + .../renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts | 1624 +++++++++++++++++++ .../renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts | 441 ++++++ @@ -66,7 +67,8 @@ Signed-off-by: Vladimir Barinov .../boot/dts/renesas/r8a7797-eagle-function.dts | 62 + arch/arm64/boot/dts/renesas/r8a7797-eagle.dts | 575 +++++++ arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts | 520 ++++++ - arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts | 513 ++++++ + .../boot/dts/renesas/r8a7797-v3msk-vbm-v2.dts | 82 + + arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts | 507 ++++++ arch/arm64/boot/dts/renesas/r8a7797-v3msk-view.dts | 297 ++++ arch/arm64/boot/dts/renesas/r8a7797-v3msk.dts | 314 ++++ arch/arm64/boot/dts/renesas/r8a7797-v3mzf.dts | 424 +++++ @@ -77,9 +79,9 @@ Signed-off-by: Vladimir Barinov arch/arm64/boot/dts/renesas/ulcb-kf.dtsi | 1458 +++++++++++++++++ arch/arm64/boot/dts/renesas/ulcb-vb-cn12.dtsi | 459 ++++++ arch/arm64/boot/dts/renesas/ulcb-vb.dtsi | 1610 +++++++++++++++++++ - arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi | 1656 ++++++++++++++++++++ + arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi | 1660 ++++++++++++++++++++ arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi | 543 +++++++ - 48 files changed, 19769 insertions(+) + 49 files changed, 19850 insertions(+) create mode 100644 arch/arm64/boot/dts/renesas/legacy/Makefile create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts @@ -114,6 +116,7 @@ Signed-off-by: Vladimir Barinov create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-eagle-function.dts create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-eagle.dts create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm-v2.dts create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-v3msk-view.dts create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-v3msk.dts @@ -129,10 +132,10 @@ Signed-off-by: Vladimir Barinov create mode 100644 arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile -index f9c71df..6ca2c60 100644 +index f9c71df..8af9300 100644 --- a/arch/arm64/boot/dts/renesas/Makefile +++ b/arch/arm64/boot/dts/renesas/Makefile -@@ -6,5 +6,27 @@ dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-xs.dtb +@@ -6,5 +6,28 @@ dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-xs.dtb dtb-$(CONFIG_ARCH_R8A77965) += r8a77965-salvator-x.dtb dtb-$(CONFIG_ARCH_R8A77965) += r8a77965-salvator-xs.dtb @@ -152,6 +155,7 @@ index f9c71df..6ca2c60 100644 +dtb-$(CONFIG_ARCH_R8A7797) += r8a7797-v3msk-view.dtb +dtb-$(CONFIG_ARCH_R8A7797) += r8a7797-v3msk-kf.dtb +dtb-$(CONFIG_ARCH_R8A7797) += r8a7797-v3msk-vbm.dtb ++dtb-$(CONFIG_ARCH_R8A7797) += r8a7797-v3msk-vbm-v2.dtb +dtb-$(CONFIG_ARCH_R8A7797) += r8a7797-v3mzf.dtb +dtb-$(CONFIG_ARCH_R8A7798) += r8a7798-condor.dtb + @@ -11336,12 +11340,100 @@ index 0000000..862236f + }; + }; +}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm-v2.dts b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm-v2.dts +new file mode 100644 +index 0000000..49d6dda +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm-v2.dts +@@ -0,0 +1,82 @@ ++/* ++ * Device Tree Source for the V3MSK Videobox Mini board V2 on r8a7797 ++ * ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7797-v3msk-vbm.dts" ++ ++/ { ++ model = "Renesas V3MSK Videobox Mini board V2 based on r8a7797"; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led5 { ++ label = "board:status"; ++ gpios = <&gpio3 16 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "heartbeat"; ++ }; ++ }; ++}; ++ ++&gpio0 { ++ /delete-node/can0stby; ++ ++ can0_stby { ++ gpio-hog; ++ gpios = <12 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "CAN0STBY"; ++ }; ++ ++ can1_stby { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "CAN1STBY"; ++ }; ++}; ++ ++&pfc { ++ msiof1_pins: msiof1 { ++ groups = "msiof1_clk", "msiof1_txd", "msiof1_rxd"; ++ function = "msiof1"; ++ }; ++ ++ msiof2_pins: msiof2 { ++ groups = "msiof2_clk", "msiof2_sync", "msiof2_txd", "msiof2_rxd"; ++ function = "msiof2"; ++ }; ++}; ++ ++&scif3 { ++ /* pin conflict with msiof2 */ ++ /* set R240 and remove R241 before enabling */ ++ status = "disabled"; ++}; ++ ++&msiof1 { ++ pinctrl-0 = <&msiof1_pins>; ++ pinctrl-names = "default"; ++ cs-gpios = <&gpio3 3 0>; ++ ++ status = "okay"; ++ spidev@0 { ++ compatible = "spidev"; ++ reg = <0>; ++ spi-max-frequency = <66666666>; ++ }; ++}; ++ ++&msiof2 { ++ pinctrl-0 = <&msiof2_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++ slave; ++}; diff --git a/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts new file mode 100644 -index 0000000..226b659 +index 0000000..c987799 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts -@@ -0,0 +1,513 @@ +@@ -0,0 +1,507 @@ +/* + * Device Tree Source for the V3MSK Videobox Mini board on r8a7797 + * @@ -11643,6 +11735,18 @@ index 0000000..226b659 + }; + }; + }; ++ ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ ++ /* fan node - lm96063 */ ++ fan_ctrl: lm96063@4c { ++ compatible = "lm96163"; ++ reg = <0x4c>; ++ }; ++ }; + }; +}; + @@ -11669,28 +11773,20 @@ index 0000000..226b659 + output-low; + line-name = "can0_120R_load"; + }; -+}; -+ -+&msiof1 { -+ pinctrl-0 = <&msiof1_pins>; -+ pinctrl-names = "default"; -+ cs-gpios = <&gpio3 3 0>; + -+ status = "okay"; -+ spidev@0 { -+ compatible = "renesas,sh-msiof"; -+ reg = <0>; -+ spi-max-frequency = <66666666>; ++ wake_pin_7 { ++ gpio-hog; ++ gpios = <8 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "WAKE INPUT PIN 7"; + }; + -+}; -+ -+&msiof3 { -+ pinctrl-0 = <&msiof3_pins>; -+ pinctrl-names = "default"; -+ -+ status = "okay"; -+ slave; ++ wake_pin_8 { ++ gpio-hog; ++ gpios = <9 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "WAKE INPUT PIN 8"; ++ }; +}; + +&pfc { @@ -11709,16 +11805,6 @@ index 0000000..226b659 + function = "i2c1"; + }; + -+ msiof1_pins: msiof1 { -+ groups = "msiof1_clk", "msiof1_txd", "msiof1_rxd"; -+ function = "msiof1"; -+ }; -+ -+ msiof3_pins: msiof3 { -+ groups = "msiof3_clk", "msiof3_txd", "msiof3_rxd", "msiof3_sync"; -+ function = "msiof3"; -+ }; -+ + scif3_pins: scif3 { + groups = "scif3_data"; + function = "scif3"; @@ -17980,7 +18066,7 @@ index 0000000..0185e46 +//#include "ulcb-vb-cn12.dtsi" diff --git a/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi b/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi new file mode 100644 -index 0000000..92a3300 +index 0000000..280c3b7 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi @@ -0,0 +1,1660 @@ @@ -19646,7 +19732,7 @@ index 0000000..92a3300 +//#include "ulcb-vb2-cn12.dtsi" diff --git a/arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi b/arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi new file mode 100644 -index 0000000..47e2b2d +index 0000000..ed04695 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi @@ -0,0 +1,543 @@ diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3msk.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3msk.cfg index 1a3ba75..ab640b3 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3msk.cfg +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3msk.cfg @@ -34,3 +34,4 @@ CONFIG_UIO=y CONFIG_SPI_SLAVE=y CONFIG_SPI_SLAVE_TIME=y CONFIG_SPI_SLAVE_SYSTEM_CONTROL=y +CONFIG_SENSORS_LM63=y -- cgit 1.2.3-korg From fde2ed05f7f4abdea0fd5622809fd171bc5fae6e Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Tue, 6 Feb 2018 18:07:25 +0300 Subject: Adds RSE support for V3H IMR This adds RSE support for V3H IMR --- ...as-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch | 4 +- .../0106-media-rcar-imr-Add-RSE-support.patch | 327 +++++++++++++++++++++ .../linux/linux-renesas_4.9.bbappend | 1 + 3 files changed, 331 insertions(+), 1 deletion(-) create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0106-media-rcar-imr-Add-RSE-support.patch (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch index 5a27c48..9d0db6d 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch @@ -79,7 +79,7 @@ new file mode 100644 index 0000000..e2b3404 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7798.dtsi -@@ -0,0 +1,1628 @@ +@@ -0,0 +1,1630 @@ +/* + * Device Tree Source for the r8a7798 SoC + * @@ -1697,6 +1697,7 @@ index 0000000..e2b3404 + interrupts = ; + clocks = <&cpg CPG_MOD 707>; + power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ rse; + }; + + imrlx4_ch5: imr-lx4@fe8b0000 { @@ -1705,6 +1706,7 @@ index 0000000..e2b3404 + interrupts = ; + clocks = <&cpg CPG_MOD 706>; + power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ rse; + }; + }; +}; diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0106-media-rcar-imr-Add-RSE-support.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0106-media-rcar-imr-Add-RSE-support.patch new file mode 100644 index 0000000..37ce02b --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0106-media-rcar-imr-Add-RSE-support.patch @@ -0,0 +1,327 @@ +From a6fd88487f2dda6f8c5ec28230129478711206fb Mon Sep 17 00:00:00 2001 +From: Andrey Dolnikov +Date: Tue, 6 Feb 2018 13:38:34 +0300 +Subject: [PATCH] media: rcar-imr: Add RSE support + +This adds RSE support for V3H IMR + +Signed-off-by: Andrey Dolnikov +--- + drivers/media/platform/rcar_imr.c | 143 +++++++++++++++++++++++++++++++ + include/uapi/linux/rcar-imr.h | 22 ++++- + 2 files changed, 165 insertions(+), 2 deletions(-) + +diff --git a/drivers/media/platform/rcar_imr.c b/drivers/media/platform/rcar_imr.c +index 9b601da..7b16765 100644 +--- a/drivers/media/platform/rcar_imr.c ++++ b/drivers/media/platform/rcar_imr.c +@@ -17,6 +17,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -38,6 +39,9 @@ MODULE_PARM_DESC(debug, "Debug level (0-4)"); + * Local types definitions + ******************************************************************************/ + ++/* Number of RSE planes on V3H (non scaled, 1/2, 1/4, 1/8) */ ++#define RSE_PLANES_NUM 4 ++ + /* ...configuration data */ + struct imr_cfg { + /* ...display-list main program data */ +@@ -49,6 +53,21 @@ struct imr_cfg { + /* ...pointers to the source/destination planes */ + u32 *src_pa_ptr[2]; + u32 *dst_pa_ptr[2]; ++ /* ...pointers to the RSE destination planes */ ++ u32 *dstn_pa_ptr[RSE_PLANES_NUM]; ++ u32 *dstr_pa_ptr[RSE_PLANES_NUM]; ++ ++ /* ...offsets to RSE destination planes */ ++ u32 dstnr_offsets[IMR_EXTDST_NUM]; ++ ++ /* ...RSE logical right shift data */ ++ u32 *rscr_ptr; ++ u8 rscr_sc8, rscr_sc4, rscr_sc2; ++ ++ /* ...RSE destination stride values */ ++ u32 dstnr_strides[IMR_EXTDST_NUM]; ++ u32 *striden_ptr[RSE_PLANES_NUM]; ++ u32 *strider_ptr[RSE_PLANES_NUM]; + + /* ...subpixel destination coordinates space */ + int dst_subpixel; +@@ -96,6 +115,8 @@ struct imr_device { + struct v4l2_m2m_dev *m2m_dev; + struct device *alloc_dev; + ++ bool rse; ++ + /* ...do we need that counter really? framework counts fh structures for us - tbd */ + int refcount; + +@@ -219,6 +240,18 @@ struct imr_ctx { + + #define IMR_TPOR 0xF0 + ++#define IMR_RSCSR 0x204 ++#define IMR_RSCCR 0x208 ++#define IMR_RSCR_RSE 31 ++#define IMR_RSCR_SC8 25 ++#define IMR_RSCR_SC4 21 ++#define IMR_RSCR_SC2 17 ++ ++#define IMR_DSANRR0 0x210 ++#define IMR_DSTNRR0 0x214 ++#define IMR_DSARR0 0x218 ++#define IMR_DSTRR0 0x21C ++ + /******************************************************************************* + * Auxiliary helpers + ******************************************************************************/ +@@ -398,6 +431,7 @@ static int imr_queue_setup(struct vb2_queue *vq, + case V4L2_PIX_FMT_YVYU: + case V4L2_PIX_FMT_NV16: + case V4L2_PIX_FMT_Y10: ++ case V4L2_PIX_FMT_Y12: + case V4L2_PIX_FMT_Y16: + sizes[0] = w * h * 2; + break; +@@ -750,6 +784,7 @@ static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg + int W = ctx->queue[1].fmt.width; + int H = ctx->queue[1].fmt.height; + u32 tricr = ctx->color & 0xFFFFFF; ++ int i; + + v4l2_dbg(2, debug, &ctx->imr->v4l2_dev, "setup %u*%u -> %u*%u mapping (type=%x)\n", w, h, W, H, type); + +@@ -775,6 +810,38 @@ static inline void imr_dl_program_setup(struct imr_ctx *ctx, struct imr_cfg *cfg + *dl++ = IMR_OP_WTS(IMR_CMRCCR, 0xFFFF); + *dl++ = IMR_OP_WTS(IMR_CMRCCR2, 0xFFFF); + ++ if (type & IMR_MAP_RSE) { ++ /* ...enable RSE */ ++ *dl++ = IMR_OP_WTL(IMR_RSCCR, 1); ++ *dl++ = 0xffffffff; ++ *dl++ = IMR_OP_WTL(IMR_RSCSR, 1); ++ cfg->rscr_ptr = dl++; ++ ++ for (i = 0; i < RSE_PLANES_NUM; i++) { ++ /* ...set destination planes base address and strides */ ++ *dl++ = IMR_OP_WTL(IMR_DSANRR0 + i * 0x10, 4); ++ cfg->dstn_pa_ptr[i] = dl++; ++ cfg->striden_ptr[i] = dl++; ++ cfg->dstr_pa_ptr[i] = dl++; ++ cfg->strider_ptr[i] = dl++; ++ } ++ ++ cfg->rscr_sc8 = cfg->rscr_sc4 = cfg->rscr_sc2 = 0; ++ memset(cfg->dstnr_offsets, 0, sizeof(cfg->dstnr_offsets)); ++ memset(cfg->dstnr_strides, 0, sizeof(cfg->dstnr_strides)); ++ } else { ++ /* ...disable RSE */ ++ *dl++ = IMR_OP_WTL(IMR_RSCCR, 1); ++ *dl++ = 0xffffffff; ++ ++ for (i = 0; i < RSE_PLANES_NUM; i++) { ++ cfg->dstn_pa_ptr[i] = NULL; ++ cfg->striden_ptr[i] = NULL; ++ cfg->dstr_pa_ptr[i] = NULL; ++ cfg->strider_ptr[i] = NULL; ++ } ++ cfg->rscr_ptr = NULL; ++ } + /* ...set source/destination addresses of Y/UV plane */ + *dl++ = IMR_OP_WTL(IMR_DSAR, 2); + cfg->dst_pa_ptr[0] = dl++; +@@ -907,6 +974,12 @@ static int imr_ioctl_map(struct imr_ctx *ctx, struct imr_map_desc *desc) + + type = desc->type; + ++ /* ...check for RSE */ ++ if ((type & IMR_MAP_RSE) && !imr->rse) { ++ v4l2_err(&imr->v4l2_dev, "Rotator & Scaler extension not supported\n"); ++ return -EINVAL; ++ } ++ + /* ...mesh item size calculation */ + item_size = (type & IMR_MAP_LUCE ? 4 : 0) + (type & IMR_MAP_CLCE ? 4 : 0); + +@@ -1055,6 +1128,12 @@ static int imr_ioctl_map_raw(struct imr_ctx *ctx, struct imr_map_desc *desc) + u32 dl_start_offset; + dma_addr_t dl_dma_addr; + ++ /* ...check RSE */ ++ if ((type & IMR_MAP_RSE) && !imr->rse) { ++ v4l2_err(&imr->v4l2_dev, "Rotator & Scaler extension not supported\n"); ++ return -EINVAL; ++ } ++ + /* ...calculate main routine length */ + dl_size = imr_dl_program_length(ctx); + if (!dl_size) { +@@ -1103,6 +1182,46 @@ static int imr_ioctl_color(struct imr_ctx *ctx, u32 color) + return 0; + } + ++static int imr_extdst_set(struct imr_ctx *ctx, u32 *extdst) ++{ ++ struct imr_device *imr = ctx->imr; ++ struct imr_cfg *cfg = ctx->cfg; ++ ++ if (!cfg) { ++ v4l2_err(&imr->v4l2_dev, "failed to set V3H extension dst buffers: No active confguration.\n"); ++ return -EINVAL; ++ } ++ ++ if (copy_from_user((void *) cfg->dstnr_offsets, (void __user *) extdst, sizeof(cfg->dstnr_offsets))) { ++ v4l2_err(&imr->v4l2_dev, "failed to read V3H extension dst buffers\n"); ++ return -EFAULT; ++ } ++ ++ return 0; ++} ++ ++static int imr_extstride_set(struct imr_ctx *ctx, struct imr_rse_param *param) ++{ ++ struct imr_device *imr = ctx->imr; ++ struct imr_cfg *cfg = ctx->cfg; ++ ++ if (!cfg) { ++ v4l2_err(&imr->v4l2_dev, "failed to set V3H extension buffers params: No active confguration.\n"); ++ return -EINVAL; ++ } ++ ++ cfg->rscr_sc8 = param->sc8; ++ cfg->rscr_sc4 = param->sc4; ++ cfg->rscr_sc2 = param->sc2; ++ ++ if (copy_from_user((void *) cfg->dstnr_strides, (void __user *) param->strides, sizeof(cfg->dstnr_strides))) { ++ v4l2_err(&imr->v4l2_dev, "failed to read V3H extension buffers strides\n"); ++ return -EFAULT; ++ } ++ ++ return 0; ++} ++ + /******************************************************************************* + * V4L2 I/O controls + ******************************************************************************/ +@@ -1356,6 +1475,14 @@ static long imr_default(struct file *file, void *fh, bool valid_prio, unsigned i + /* ...set solid color code */ + return imr_ioctl_color(ctx, *(u32 *)arg); + ++ case VIDIOC_IMR_EXTDST: ++ /* ...set V3H extension dst buffers */ ++ return imr_extdst_set(ctx, *(u32 **)arg); ++ ++ case VIDIOC_IMR_EXTSTRIDE: ++ /* ...set V3H extension dst strides */ ++ return imr_extstride_set(ctx, (struct imr_rse_param *)arg); ++ + default: + return -ENOIOCTLCMD; + } +@@ -1579,6 +1706,7 @@ static void imr_device_run(void *priv) + struct vb2_v4l2_buffer *src_buf, *dst_buf; + u32 src_addr, dst_addr; + unsigned long flags; ++ int i; + + v4l2_dbg(3, debug, &imr->v4l2_dev, "run next job...\n"); + +@@ -1608,6 +1736,17 @@ static void imr_device_run(void *priv) + *cfg->src_pa_ptr[0] = src_addr = (u32)vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0); + *cfg->dst_pa_ptr[0] = dst_addr = (u32)vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0); + ++ for (i = 0; i < RSE_PLANES_NUM; i++) { ++ if (cfg->rscr_ptr) *cfg->rscr_ptr = (1 << IMR_RSCR_RSE) | (cfg->rscr_sc8 << IMR_RSCR_SC8) | ++ (cfg->rscr_sc4 << IMR_RSCR_SC4) |(cfg->rscr_sc2 << IMR_RSCR_SC2); ++ ++ if (cfg->dstn_pa_ptr[i]) *cfg->dstn_pa_ptr[i] = dst_addr + cfg->dstnr_offsets[i]; ++ if (cfg->dstr_pa_ptr[i]) *cfg->dstr_pa_ptr[i] = dst_addr + cfg->dstnr_offsets[i + RSE_PLANES_NUM]; ++ ++ if (cfg->striden_ptr[i]) *cfg->striden_ptr[i] = cfg->dstnr_strides[i]; ++ if (cfg->strider_ptr[i]) *cfg->strider_ptr[i] = cfg->dstnr_strides[i + RSE_PLANES_NUM]; ++ } ++ + /* ...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; +@@ -1776,6 +1915,7 @@ static int imr_probe(struct platform_device *pdev) + { + struct imr_device *imr; + struct resource *res; ++ struct device_node *np = pdev->dev.of_node; + int ret; + + imr = devm_kzalloc(&pdev->dev, sizeof(*imr), GFP_KERNEL); +@@ -1786,6 +1926,9 @@ static int imr_probe(struct platform_device *pdev) + spin_lock_init(&imr->lock); + imr->dev = &pdev->dev; + ++ /* Check RSE support */ ++ imr->rse = of_property_read_bool(np, "rse"); ++ + /* ...memory-mapped registers */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { +diff --git a/include/uapi/linux/rcar-imr.h b/include/uapi/linux/rcar-imr.h +index 7b8ed0c..19fdbae 100644 +--- a/include/uapi/linux/rcar-imr.h ++++ b/include/uapi/linux/rcar-imr.h +@@ -25,8 +25,8 @@ struct imr_map_desc { + /* ...total size of the mesh structure */ + u32 size; + +- /* ...map-specific user-pointer */ +- void *data; ++ /* ...map-specific user-pointer */ ++ void *data; + + } __attribute__((packed)); + +@@ -54,6 +54,9 @@ struct imr_map_desc { + /* ...bilinear filtration enable flag */ + #define IMR_MAP_BFE (1 << 7) + ++/* ...extended functionality (rotation/scaling) enable flag */ ++#define IMR_MAP_RSE (1 << 8) ++ + /* ...source coordinate decimal point position bit index */ + #define __IMR_MAP_UVDPOR_SHIFT 8 + #define __IMR_MAP_UVDPOR(v) (((v) >> __IMR_MAP_UVDPOR_SHIFT) & 0x7) +@@ -88,11 +91,26 @@ struct imr_mesh { + } __attribute__((packed)); + + /******************************************************************************* ++ * V3H Extension destination data ++ ******************************************************************************/ ++/* ...number of V3H extension destination buffers (rotated/non-rotated, scaled 1/1, 1/2, 1/4, 1/8) */ ++#define IMR_EXTDST_NUM 8 ++ ++struct imr_rse_param { ++ /* ...logical right shift data */ ++ u8 sc8, sc4, sc2; ++ /* ...destination buffers stride */ ++ u32 *strides; ++}; ++ ++/******************************************************************************* + * Private IOCTL codes + ******************************************************************************/ + + #define VIDIOC_IMR_MESH _IOW('V', BASE_VIDIOC_PRIVATE + 0, struct imr_map_desc) + #define VIDIOC_IMR_MESH_RAW _IOW('V', BASE_VIDIOC_PRIVATE + 1, struct imr_map_desc) + #define VIDIOC_IMR_COLOR _IOW('V', BASE_VIDIOC_PRIVATE + 2, u32) ++#define VIDIOC_IMR_EXTDST _IOW('V', BASE_VIDIOC_PRIVATE + 3, u32 *) ++#define VIDIOC_IMR_EXTSTRIDE _IOW('V', BASE_VIDIOC_PRIVATE + 4, struct imr_rse_param) + + #endif /* RCAR_IMR_USER_H */ +-- +2.7.4 + 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 index 2444573..cc376ab 100644 --- 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 @@ -81,6 +81,7 @@ SRC_URI_append = " \ file://0103-gpu-drm-rcar-du-Extend-VSP1-DRM-interface.patch \ file://0104-media-vsp1-extend-DRM-VSP1-interface.patch \ file://0105-media-rcar-imr-IMR-driver-updates-for-raw-DL.patch \ + file://0106-media-rcar-imr-Add-RSE-support.patch \ " SRC_URI_append_h3ulcb = " file://ulcb.cfg" -- cgit 1.2.3-korg From 6fc3068b7168a52f4ae102f9a2a2f0b68525afed Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Tue, 6 Feb 2018 21:05:28 +0300 Subject: V3M Eagle: add PMIC This adds PMIC devices (regulator,wdt,rtc) on Eagle --- .../0040-arm64-dts-renesas-add-ADAS-boards.patch | 38 +++++++++++++++++++--- .../recipes-kernel/linux/linux-renesas/eagle.cfg | 5 +++ 2 files changed, 39 insertions(+), 4 deletions(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch index 608db41..46dba8d 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch @@ -65,7 +65,7 @@ Signed-off-by: Vladimir Barinov .../arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts | 286 ++++ .../boot/dts/renesas/r8a7796-salvator-x-view.dts | 317 ++++ .../boot/dts/renesas/r8a7797-eagle-function.dts | 62 + - arch/arm64/boot/dts/renesas/r8a7797-eagle.dts | 575 +++++++ + arch/arm64/boot/dts/renesas/r8a7797-eagle.dts | 605 +++++++ arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts | 520 ++++++ .../boot/dts/renesas/r8a7797-v3msk-vbm-v2.dts | 82 + arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts | 507 ++++++ @@ -81,7 +81,7 @@ Signed-off-by: Vladimir Barinov arch/arm64/boot/dts/renesas/ulcb-vb.dtsi | 1610 +++++++++++++++++++ arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi | 1660 ++++++++++++++++++++ arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi | 543 +++++++ - 49 files changed, 19850 insertions(+) + 49 files changed, 19880 insertions(+) create mode 100644 arch/arm64/boot/dts/renesas/legacy/Makefile create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts @@ -10235,10 +10235,10 @@ index 0000000..82d6513 +}; diff --git a/arch/arm64/boot/dts/renesas/r8a7797-eagle.dts b/arch/arm64/boot/dts/renesas/r8a7797-eagle.dts new file mode 100644 -index 0000000..ce7a88e +index 0000000..db17b03 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7797-eagle.dts -@@ -0,0 +1,575 @@ +@@ -0,0 +1,605 @@ +/* + * Device Tree Source for the Eagle board + * @@ -10503,6 +10503,36 @@ index 0000000..ce7a88e + gpio-controller; + #gpio-cells = <2>; + }; ++ ++ pmic@5A { ++ compatible = "dlg,da9063"; ++ reg = <0x5A>; ++ interrupt-parent = <&intc_ex>; ++ interrupts = <0 IRQ_TYPE_LEVEL_LOW>; ++ interrupt-controller; ++ ++ rtc { ++ compatible = "dlg,da9063-rtc"; ++ }; ++ ++ wdt { ++ compatible = "dlg,da9063-watchdog"; ++ }; ++ ++ regulators { ++ DA9063_LDO11: bmem { ++ regulator-name = "bmem"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ }; ++ ++ onkey { ++ compatible = "dlg,da9063-onkey"; ++ }; ++ }; +}; + +&i2c3 { 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 index f6ae11f..ca8cee8 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/eagle.cfg +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/eagle.cfg @@ -27,3 +27,8 @@ CONFIG_TOUCHSCREEN_PROPERTIES=y CONFIG_HID_MULTITOUCH=y CONFIG_SERIAL_SH_SCI_DMA=y CONFIG_UIO=y +CONFIG_MFD_DA9063=y +CONFIG_INPUT_DA9063_ONKEY=y +CONFIG_DA9063_WATCHDOG=y +CONFIG_REGULATOR_DA9063=y +CONFIG_RTC_DRV_DA9063=y -- cgit 1.2.3-korg From 0a5fdaadc4a535cfb693d98738fde8d48b77447f Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Wed, 7 Feb 2018 19:38:59 +0300 Subject: V3M/V3H: sysc workaround for power down, cpu clock fixup This adds SYSC workaround for power domains power down sequence on V3M/V3H and add cpu clock fixup on V3H. Also add VisionIP nodes and fix VSP i/f on V3H --- ...as-r8a7797-Add-Renesas-R8A7797-SoC-suppor.patch | 26 +- ...as-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch | 231 ++++++++++++----- ...-rcar-sysc-Add-workaround-for-A3-PD-issue.patch | 278 +++++++++++++++++++++ ...0104-media-vsp1-extend-DRM-VSP1-interface.patch | 2 +- .../linux/linux-renesas_4.9.bbappend | 1 + 5 files changed, 460 insertions(+), 78 deletions(-) create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0052-soc-renesas-rcar-sysc-Add-workaround-for-A3-PD-issue.patch (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') 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 index 88d2a52..1f2b11c 100644 --- 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 @@ -7,11 +7,11 @@ This adds Renesas R8A7797 SoC support Signed-off-by: Vladimir Barinov --- - arch/arm64/Kconfig.platforms | 6 + + arch/arm64/Kconfig.platforms | 8 + arch/arm64/boot/dts/renesas/r8a7797.dtsi | 1156 +++++++++++ drivers/clk/renesas/Kconfig | 1 + drivers/clk/renesas/Makefile | 1 + - drivers/clk/renesas/r8a7797-cpg-mssr.c | 231 +++ + drivers/clk/renesas/r8a7797-cpg-mssr.c | 232 +++ drivers/clk/renesas/rcar-gen3-cpg.c | 41 +- drivers/clk/renesas/rcar-gen3-cpg.h | 6 + drivers/clk/renesas/renesas-cpg-mssr.c | 6 + @@ -47,7 +47,7 @@ Signed-off-by: Vladimir Barinov drivers/thermal/rcar_gen3_thermal.c | 29 + include/dt-bindings/clock/r8a7797-cpg-mssr.h | 48 + include/dt-bindings/power/r8a7797-sysc.h | 32 + - 40 files changed, 4486 insertions(+), 29 deletions(-) + 40 files changed, 4489 insertions(+), 29 deletions(-) create mode 100644 arch/arm64/boot/dts/renesas/r8a7797.dtsi create mode 100644 drivers/clk/renesas/r8a7797-cpg-mssr.c create mode 100644 drivers/pinctrl/sh-pfc/pfc-r8a7797.c @@ -56,7 +56,7 @@ Signed-off-by: Vladimir Barinov create mode 100644 include/dt-bindings/power/r8a7797-sysc.h diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms -index ebe0a37..d3b6771 100644 +index ebe0a37..9cebaad 100644 --- a/arch/arm64/Kconfig.platforms +++ b/arch/arm64/Kconfig.platforms @@ -166,6 +166,14 @@ config ARCH_R8A77965 @@ -76,7 +76,7 @@ index ebe0a37..d3b6771 100644 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..0dd374f +index 0000000..5319b1a --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7797.dtsi @@ -0,0 +1,1156 @@ @@ -1262,7 +1262,7 @@ index 2c224e9..c2ef11e 100644 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..6f481a4 +index 0000000..0460ed4 --- /dev/null +++ b/drivers/clk/renesas/r8a7797-cpg-mssr.c @@ -0,0 +1,232 @@ @@ -5032,7 +5032,7 @@ index 29b8a4d..2ba6a76 100644 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 +index 0000000..cde7d9e --- /dev/null +++ b/drivers/soc/renesas/r8a7797-sysc.c @@ -0,0 +1,39 @@ @@ -5063,12 +5063,12 @@ index 0000000..b71bdedb + 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 }, ++ { "a2ir0", 0x400, 0, R8A7797_PD_A2IR0, R8A7797_PD_A3IR }, ++ { "a2ir1", 0x400, 1, R8A7797_PD_A2IR1, R8A7797_PD_A3IR }, ++ { "a2ir2", 0x400, 2, R8A7797_PD_A2IR2, R8A7797_PD_A3IR }, ++ { "a2ir3", 0x400, 3, R8A7797_PD_A2IR3, R8A7797_PD_A3IR }, ++ { "a2sc0", 0x400, 4, R8A7797_PD_A2SC0, R8A7797_PD_A3IR }, ++ { "a2sc1", 0x400, 5, R8A7797_PD_A2SC1, R8A7797_PD_A3IR }, +}; + +const struct rcar_sysc_info r8a7797_sysc_info __initconst = { diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch index 9d0db6d..7d57c38 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch @@ -9,11 +9,11 @@ Signed-off-by: Vladimir Barinov Signed-off-by: Mikhail Ulyanov --- arch/arm64/Kconfig.platforms | 8 + - arch/arm64/boot/dts/renesas/r8a7798.dtsi | 1628 +++++++++++++ + arch/arm64/boot/dts/renesas/r8a7798.dtsi | 1700 +++++++++++++ drivers/clk/renesas/Kconfig | 1 + drivers/clk/renesas/Makefile | 1 + - drivers/clk/renesas/r8a7798-cpg-mssr.c | 282 +++ - drivers/clk/renesas/rcar-gen3-cpg.c | 10 + + drivers/clk/renesas/r8a7798-cpg-mssr.c | 292 +++ + drivers/clk/renesas/rcar-gen3-cpg.c | 19 +- drivers/clk/renesas/renesas-cpg-mssr.c | 6 + drivers/clk/renesas/renesas-cpg-mssr.h | 1 + drivers/cpufreq/cpufreq-dt-platdev.c | 1 + @@ -25,7 +25,7 @@ Signed-off-by: Mikhail Ulyanov drivers/media/platform/soc_camera/Kconfig | 2 +- drivers/media/platform/soc_camera/rcar_csi2.c | 15 +- drivers/media/platform/soc_camera/rcar_vin.c | 97 +- - drivers/media/platform/vsp1/vsp1_lif.c | 7 +- + drivers/media/platform/vsp1/vsp1_lif.c | 8 +- drivers/mmc/host/sh_mobile_sdhi.c | 1 + drivers/net/ethernet/renesas/ravb_main.c | 1 + drivers/net/ethernet/renesas/sh_eth.c | 53 +- @@ -47,7 +47,7 @@ Signed-off-by: Mikhail Ulyanov drivers/thermal/rcar_gen3_thermal.c | 10 + include/dt-bindings/clock/r8a7798-cpg-mssr.h | 56 + include/dt-bindings/power/r8a7798-sysc.h | 46 + - 39 files changed, 5525 insertions(+), 34 deletions(-) + 39 files changed, 5618 insertions(+), 33 deletions(-) create mode 100644 arch/arm64/boot/dts/renesas/r8a7798.dtsi create mode 100644 drivers/clk/renesas/r8a7798-cpg-mssr.c create mode 100644 drivers/pinctrl/sh-pfc/pfc-r8a7798.c @@ -76,10 +76,10 @@ index 9cebaad..3646b6e 100644 help diff --git a/arch/arm64/boot/dts/renesas/r8a7798.dtsi b/arch/arm64/boot/dts/renesas/r8a7798.dtsi new file mode 100644 -index 0000000..e2b3404 +index 0000000..6412a24 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7798.dtsi -@@ -0,0 +1,1630 @@ +@@ -0,0 +1,1700 @@ +/* + * Device Tree Source for the r8a7798 SoC + * @@ -1276,7 +1276,7 @@ index 0000000..e2b3404 + compatible = "renesas,vin-r8a7798"; + reg = <0 0xe6ef9000 0 0x1000>; + interrupts = ; -+ clocks = <&cpg CPG_MOD 625>; ++ clocks = <&cpg CPG_MOD 627>; + power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; + status = "disabled"; + }; @@ -1285,7 +1285,7 @@ index 0000000..e2b3404 + compatible = "renesas,vin-r8a7798"; + reg = <0 0xe6efa000 0 0x1000>; + interrupts = ; -+ clocks = <&cpg CPG_MOD 808>; ++ clocks = <&cpg CPG_MOD 625>; + power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; + status = "disabled"; + }; @@ -1708,6 +1708,76 @@ index 0000000..e2b3404 + power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; + rse; + }; ++ ++ disp { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a00000 0 0x10000>; ++ clocks = <&cpg CPG_MOD 101>; ++ power-domains = <&sysc R8A7798_PD_A3VIP>; ++ }; ++ ++ umf { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a10000 0 0x10000>; ++ clocks = <&cpg CPG_MOD 102>; ++ power-domains = <&sysc R8A7798_PD_A3VIP1>; ++ }; ++ ++ smd_ps { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a20000 0 0x10000>; ++ clocks = <&cpg CPG_MOD 1102>; ++ power-domains = <&sysc R8A7798_PD_A3VIP1>; ++ }; ++ ++ smd_est { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a30000 0 0x10000>; ++ clocks = <&cpg CPG_MOD 1101>; ++ power-domains = <&sysc R8A7798_PD_A3VIP1>; ++ }; ++ ++ smd_post { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a40000 0 0x10000>; ++ clocks = <&cpg CPG_MOD 1100>; ++ power-domains = <&sysc R8A7798_PD_A3VIP1>; ++ }; ++ ++ cle0 { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a50000 0 0x10000>; ++ clocks = <&cpg CPG_MOD 1004>; ++ power-domains = <&sysc R8A7798_PD_A3VIP2>; ++ }; ++ ++ cle1 { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a60000 0 0x10000>; ++ clocks = <&cpg CPG_MOD 1003>; ++ power-domains = <&sysc R8A7798_PD_A3VIP2>; ++ }; ++ ++ cle2 { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a70000 0 0x10000>; ++ clocks = <&cpg CPG_MOD 1002>; ++ power-domains = <&sysc R8A7798_PD_A3VIP2>; ++ }; ++ ++ cle3 { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a80000 0 0x10000>; ++ clocks = <&cpg CPG_MOD 1001>; ++ power-domains = <&sysc R8A7798_PD_A3VIP2>; ++ }; ++ ++ cle4 { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a90000 0 0x10000>; ++ clocks = <&cpg CPG_MOD 1000>; ++ power-domains = <&sysc R8A7798_PD_A3VIP2>; ++ }; + }; +}; diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig @@ -1736,10 +1806,10 @@ index c2ef11e..9f659d5 100644 obj-$(CONFIG_CLK_RENESAS_CPG_MSSR) += renesas-cpg-mssr.o clk-div6.o diff --git a/drivers/clk/renesas/r8a7798-cpg-mssr.c b/drivers/clk/renesas/r8a7798-cpg-mssr.c new file mode 100644 -index 0000000..e407916 +index 0000000..40ad314 --- /dev/null +++ b/drivers/clk/renesas/r8a7798-cpg-mssr.c -@@ -0,0 +1,282 @@ +@@ -0,0 +1,292 @@ +/* + * r8a7798 Clock Pulse Generator / Module Standby and Software Reset + * @@ -1847,6 +1917,8 @@ index 0000000..e407916 + +static const struct mssr_mod_clk r8a7798_mod_clks[] __initconst = { + /*... skip crc, umf, disp, rt-sram, cle, smd_ */ ++ DEF_MOD("disp", 101, R8A7798_CLK_S1D1), ++ DEF_MOD("umf", 102, R8A7798_CLK_S1D1), + DEF_MOD("tmu4", 121, R8A7798_CLK_S0D6), + DEF_MOD("tmu3", 122, R8A7798_CLK_S0D6), + DEF_MOD("tmu2", 123, R8A7798_CLK_S0D6), @@ -1943,6 +2015,14 @@ index 0000000..e407916 + DEF_MOD("i2c2", 929, R8A7798_CLK_S3D2), + DEF_MOD("i2c1", 930, R8A7798_CLK_S3D2), + DEF_MOD("i2c0", 931, R8A7798_CLK_S3D2), ++ DEF_MOD("cle4", 1000, R8A7798_CLK_S1D1), ++ DEF_MOD("cle3", 1001, R8A7798_CLK_S1D1), ++ DEF_MOD("cle2", 1002, R8A7798_CLK_S1D1), ++ DEF_MOD("cle1", 1003, R8A7798_CLK_S1D1), ++ DEF_MOD("cle0", 1004, R8A7798_CLK_S1D1), ++ DEF_MOD("smd_post", 1100, R8A7798_CLK_S0D3), ++ DEF_MOD("smd_est", 1101, R8A7798_CLK_S0D3), ++ DEF_MOD("smd_ps", 1102, R8A7798_CLK_S0D3), +}; + +static const unsigned int r8a7798_crit_mod_clks[] __initconst = { @@ -2023,7 +2103,7 @@ index 0000000..e407916 + .cpg_clk_register = rcar_gen3_cpg_clk_register, +}; diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c -index b145f14..99acba2 100644 +index b145f14..930fa3d 100644 --- a/drivers/clk/renesas/rcar-gen3-cpg.c +++ b/drivers/clk/renesas/rcar-gen3-cpg.c @@ -33,6 +33,11 @@ @@ -2038,7 +2118,37 @@ index b145f14..99acba2 100644 #define CPG_PLL0CR 0x00d8 #define CPG_PLL2CR 0x002c #define CPG_PLL4CR 0x01f4 -@@ -916,6 +921,11 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, +@@ -242,6 +247,10 @@ static unsigned long cpg_z2_clk_recalc_rate(struct clk_hw *hw, + mult = 32 - val; + + rate = div_u64((u64)parent_rate * mult + 16, 32); ++ ++ if (soc_device_match(r8a7798)) ++ rate /= 2; ++ + /* Round to closest value at 100MHz unit */ + rate = 100000000*DIV_ROUND_CLOSEST(rate, 100000000); + return rate; +@@ -303,6 +312,9 @@ static long cpg_z2_clk_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long prate = *parent_rate; + unsigned int mult; + ++ if (soc_device_match(r8a7798)) ++ prate /= 2; ++ + mult = div_u64((u64)rate * 32 + prate/2, prate); + mult = clamp(mult, 1U, 32U); + +@@ -382,7 +394,7 @@ static int cpg_z2_clk_set_rate(struct clk_hw *hw, unsigned long rate, + u32 val, kick; + unsigned int i; + +- if (soc_device_match(r8a7797)){ ++ if (soc_device_match(r8a7797) || soc_device_match(r8a7798)){ + pr_info("Do not support V3M's Z2 clock changing\n"); + return 0; + } +@@ -916,6 +928,11 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, if (cpg_quirks & RCLK_CKSEL_RESEVED) break; @@ -2243,7 +2353,7 @@ index 2ef27e8..98f271f 100644 { "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 7bd8a77..1e098ef 100644 +index b7ec03c..37f1a11 100644 --- a/drivers/media/platform/soc_camera/rcar_vin.c +++ b/drivers/media/platform/soc_camera/rcar_vin.c @@ -162,7 +162,7 @@ @@ -2378,7 +2488,7 @@ index 7bd8a77..1e098ef 100644 if (priv->pdata_flags & RCAR_VIN_CSI2) vnmc &= ~VNMC_DPINE; else -@@ -1462,7 +1526,7 @@ static int rcar_vin_add_device(struct soc_camera_device *icd) +@@ -1457,7 +1521,7 @@ 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 || @@ -2387,7 +2497,7 @@ index 7bd8a77..1e098ef 100644 struct v4l2_subdev *csi2_sd = find_csi2(priv); struct v4l2_subdev *deser_sd = find_deser(priv); int ret = 0; -@@ -1725,7 +1789,7 @@ static int rcar_vin_set_rect(struct soc_camera_device *icd) +@@ -1720,7 +1784,7 @@ static int rcar_vin_set_rect(struct soc_camera_device *icd) } if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || @@ -2396,7 +2506,7 @@ index 7bd8a77..1e098ef 100644 if ((icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_NV12) && (icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_SBGGR8) && (icd->current_fmt->host_fmt->fourcc != V4L2_PIX_FMT_SBGGR12) -@@ -1883,7 +1947,7 @@ static int rcar_vin_set_bus_param(struct soc_camera_device *icd) +@@ -1878,7 +1942,7 @@ static int rcar_vin_set_bus_param(struct soc_camera_device *icd) return ret; if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || @@ -2405,7 +2515,7 @@ index 7bd8a77..1e098ef 100644 if (cfg.type == V4L2_MBUS_CSI2) vnmc &= ~VNMC_DPINE; else -@@ -1891,7 +1955,7 @@ static int rcar_vin_set_bus_param(struct soc_camera_device *icd) +@@ -1886,7 +1950,7 @@ static int rcar_vin_set_bus_param(struct soc_camera_device *icd) } if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || @@ -2414,7 +2524,7 @@ index 7bd8a77..1e098ef 100644 val = VNDMR2_FTEV; else val = VNDMR2_FTEV | VNDMR2_VLV(1); -@@ -2489,7 +2553,7 @@ static int rcar_vin_try_fmt(struct soc_camera_device *icd, +@@ -2484,7 +2548,7 @@ static int rcar_vin_try_fmt(struct soc_camera_device *icd, return ret; if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || @@ -2423,7 +2533,7 @@ index 7bd8a77..1e098ef 100644 /* Adjust max scaling size for Gen3 */ if (pix->width > 4096) pix->width = priv->max_width; -@@ -2668,6 +2732,7 @@ static int rcar_vin_get_edid(struct soc_camera_device *icd, +@@ -2663,6 +2727,7 @@ static int rcar_vin_get_edid(struct soc_camera_device *icd, #ifdef CONFIG_OF static const struct of_device_id rcar_vin_of_table[] = { @@ -2431,7 +2541,7 @@ index 7bd8a77..1e098ef 100644 { .compatible = "renesas,vin-r8a7797", .data = (void *)RCAR_V3M }, { .compatible = "renesas,vin-r8a7796", .data = (void *)RCAR_M3 }, { .compatible = "renesas,vin-r8a7795", .data = (void *)RCAR_H3 }, -@@ -2989,7 +3054,7 @@ static int rcar_vin_probe(struct platform_device *pdev) +@@ -2978,7 +3043,7 @@ static int rcar_vin_probe(struct platform_device *pdev) } if (priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || @@ -2440,7 +2550,7 @@ index 7bd8a77..1e098ef 100644 priv->max_width = 4096; priv->max_height = 4096; } else { -@@ -2998,7 +3063,8 @@ static int rcar_vin_probe(struct platform_device *pdev) +@@ -2987,7 +3052,8 @@ static int rcar_vin_probe(struct platform_device *pdev) } if ((priv->chip == RCAR_H3 || priv->chip == RCAR_M3 || @@ -2450,7 +2560,7 @@ index 7bd8a77..1e098ef 100644 u32 ifmd = 0; bool match_flag = false; const struct vin_gen3_ifmd *gen3_ifmd_table = NULL; -@@ -3073,6 +3139,8 @@ static int rcar_vin_probe(struct platform_device *pdev) +@@ -3062,6 +3128,8 @@ static int rcar_vin_probe(struct platform_device *pdev) gen3_ifmd_table = vin_m3_vc_ifmd; else if (priv->chip == RCAR_V3M) gen3_ifmd_table = vin_v3_vc_ifmd; @@ -2459,7 +2569,7 @@ index 7bd8a77..1e098ef 100644 for (i = 0; i < num; i++) { if ((gen3_ifmd_table[i].v_sel[priv->index].csi2_ch -@@ -3236,6 +3304,9 @@ static int rcar_vin_resume(struct device *dev) +@@ -3219,6 +3287,9 @@ static int rcar_vin_resume(struct device *dev) } else if (priv->chip == RCAR_V3M) { ifmd = VNCSI_IFMD_DES1; gen3_ifmd_table = vin_v3_vc_ifmd; @@ -2470,38 +2580,31 @@ index 7bd8a77..1e098ef 100644 for (i = 0; i < num; i++) { diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c -index e79f9e6..4802899 100644 +index e79f9e6..22fb76a 100644 --- a/drivers/media/platform/vsp1/vsp1_lif.c +++ b/drivers/media/platform/vsp1/vsp1_lif.c -@@ -24,8 +24,9 @@ - #define LIF_MIN_SIZE 2U - #define LIF_MAX_SIZE 8190U - --static const struct soc_device_attribute r8a7797[] = { -+static const struct soc_device_attribute r8a7797_8[] = { - { .soc_id = "r8a7797" }, -+ { .soc_id = "r8a7798" }, +@@ -29,6 +29,11 @@ { } }; -@@ -151,7 +152,7 @@ static void lif_configure(struct vsp1_entity *entity, ++static const struct soc_device_attribute r8a7798[] = { ++ { .soc_id = "r8a7798" }, ++ { } ++}; ++ + /* ----------------------------------------------------------------------------- + * Device Access + */ +@@ -151,7 +156,8 @@ static void lif_configure(struct vsp1_entity *entity, format = vsp1_entity_get_pad_format(&lif->entity, lif->entity.config, LIF_PAD_SOURCE); - if (vsp1_gen3_vspdl_check(vsp1) || soc_device_match(r8a7797)) -+ if (vsp1_gen3_vspdl_check(vsp1) || soc_device_match(r8a7797_8)) ++ if (vsp1_gen3_vspdl_check(vsp1) || ++ soc_device_match(r8a7797) || soc_device_match(r8a7798)) obth = 1500; else obth = 3000; -@@ -165,7 +166,7 @@ static void lif_configure(struct vsp1_entity *entity, - (format->code == 0 ? VI6_LIF_CTRL_CFMT : 0) | - VI6_LIF_CTRL_REQSEL | VI6_LIF_CTRL_LIF_EN); - -- if (soc_device_match(r8a7797)) -+ if (soc_device_match(r8a7797_8)) - vsp1_lif_write(lif, dl, VI6_LIF_LBA, VI6_LIF_LBA_LBA0 | - VI6_LIF_LBA_LBA1); - } diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c index 040f474..72b46bb 100644 --- a/drivers/mmc/host/sh_mobile_sdhi.c @@ -6066,7 +6169,7 @@ index 2ba6a76..164b3e7 100644 obj-$(CONFIG_RCAR_DDR_BACKUP) += s2ram_ddr_backup.o diff --git a/drivers/soc/renesas/r8a7798-sysc.c b/drivers/soc/renesas/r8a7798-sysc.c new file mode 100644 -index 0000000..e663c74 +index 0000000..128e79d --- /dev/null +++ b/drivers/soc/renesas/r8a7798-sysc.c @@ -0,0 +1,57 @@ @@ -6102,25 +6205,25 @@ index 0000000..e663c74 + PD_CPU_NOCR }, + { "cr7", 0x240, 0, R8A7798_PD_CR7, R8A7798_PD_ALWAYS_ON }, + -+ { "a3ir", 0x180, 0, R8A7798_PD_A3IR, R8A7798_PD_ALWAYS_ON }, -+ { "a2ir0", 0x400, 0, R8A7798_PD_A2IR0, R8A7798_PD_ALWAYS_ON }, -+ { "a2ir1", 0x400, 1, R8A7798_PD_A2IR1, R8A7798_PD_A2IR0 }, -+ { "a2ir2", 0x400, 2, R8A7798_PD_A2IR2, R8A7798_PD_A2IR0 }, -+ { "a2ir3", 0x400, 3, R8A7798_PD_A2IR3, R8A7798_PD_A2IR0 }, -+ { "a2ir4", 0x400, 4, R8A7798_PD_A2IR4, R8A7798_PD_A2IR0 }, -+ { "a2ir5", 0x400, 5, R8A7798_PD_A2IR5, R8A7798_PD_A2IR0 }, -+ { "a2sc0", 0x400, 6, R8A7798_PD_A2SC0, R8A7798_PD_ALWAYS_ON }, -+ { "a2sc1", 0x400, 7, R8A7798_PD_A2SC1, R8A7798_PD_A2SC0 }, -+ { "a2sc2", 0x400, 8, R8A7798_PD_A2SC2, R8A7798_PD_A2SC0 }, -+ { "a2sc3", 0x400, 9, R8A7798_PD_A2SC3, R8A7798_PD_A2SC0 }, -+ { "a2sc4", 0x400, 10, R8A7798_PD_A2SC4, R8A7798_PD_A2SC0 }, -+ { "a2pd0", 0x400, 11, R8A7798_PD_A2PD0, R8A7798_PD_ALWAYS_ON }, /* OK? */ -+ { "a2pd1", 0x400, 12, R8A7798_PD_A2PD1, R8A7798_PD_A2PD0 }, /* OK? */ -+ { "a2cn", 0x400, 13, R8A7798_PD_A2CN, R8A7798_PD_ALWAYS_ON }, /* OK? */ -+ -+ { "a3vip", 0x2c0, 0, R8A7798_PD_A3VIP, R8A7798_PD_ALWAYS_ON }, /* OK? */ -+ { "a3vip1", 0x300, 0, R8A7798_PD_A3VIP1, R8A7798_PD_A3VIP }, /* OK? */ -+ { "a3vip2", 0x280, 0, R8A7798_PD_A3VIP2, R8A7798_PD_A3VIP }, /* OK? */ ++ { "a3ir", 0x180, 0, R8A7798_PD_A3IR, R8A7798_PD_ALWAYS_ON }, ++ { "a2ir0", 0x400, 0, R8A7798_PD_A2IR0, R8A7798_PD_A3IR }, ++ { "a2ir1", 0x400, 1, R8A7798_PD_A2IR1, R8A7798_PD_A3IR }, ++ { "a2ir2", 0x400, 2, R8A7798_PD_A2IR2, R8A7798_PD_A3IR }, ++ { "a2ir3", 0x400, 3, R8A7798_PD_A2IR3, R8A7798_PD_A3IR }, ++ { "a2ir4", 0x400, 4, R8A7798_PD_A2IR4, R8A7798_PD_A3IR }, ++ { "a2ir5", 0x400, 5, R8A7798_PD_A2IR5, R8A7798_PD_A3IR }, ++ { "a2sc0", 0x400, 6, R8A7798_PD_A2SC0, R8A7798_PD_A3IR }, ++ { "a2sc1", 0x400, 7, R8A7798_PD_A2SC1, R8A7798_PD_A3IR }, ++ { "a2sc2", 0x400, 8, R8A7798_PD_A2SC2, R8A7798_PD_A3IR }, ++ { "a2sc3", 0x400, 9, R8A7798_PD_A2SC3, R8A7798_PD_A3IR }, ++ { "a2sc4", 0x400, 10, R8A7798_PD_A2SC4, R8A7798_PD_A3IR }, ++ { "a2pd0", 0x400, 11, R8A7798_PD_A2PD0, R8A7798_PD_A3IR }, ++ { "a2pd1", 0x400, 12, R8A7798_PD_A2PD1, R8A7798_PD_A3IR }, ++ { "a2cn", 0x400, 13, R8A7798_PD_A2CN, R8A7798_PD_A3IR }, ++ ++ { "a3vip", 0x2c0, 0, R8A7798_PD_A3VIP, R8A7798_PD_ALWAYS_ON }, ++ { "a3vip1", 0x300, 0, R8A7798_PD_A3VIP1, R8A7798_PD_ALWAYS_ON }, ++ { "a3vip2", 0x280, 0, R8A7798_PD_A3VIP2, R8A7798_PD_ALWAYS_ON }, +}; + +const struct rcar_sysc_info r8a7798_sysc_info __initconst = { diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0052-soc-renesas-rcar-sysc-Add-workaround-for-A3-PD-issue.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0052-soc-renesas-rcar-sysc-Add-workaround-for-A3-PD-issue.patch new file mode 100644 index 0000000..9cad500 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0052-soc-renesas-rcar-sysc-Add-workaround-for-A3-PD-issue.patch @@ -0,0 +1,278 @@ +From 01fdcd06bd73807c03a6c8cf077fa53841861b58 Mon Sep 17 00:00:00 2001 +From: Shinyu Ninomiya +Date: Fri, 26 Jan 2018 21:38:58 +0900 +Subject: [PATCH] soc: renesas: rcar-sysc: Add workaround for A3 PD issue + +Before turning ON/OFF power domain of A3VIP0, A3VIP1, A3VIP2 the clock is supplied for BoschIP +by deactivating MSTP assigned for BoschIP before. This issue is also occurred at A3IR. +MSTP for impdes0 and impc0 should be deactivated before turning off A3IR domain. +This implements workaround to implement the sequence above. + +Signed-off-by: Shinyu Ninomiya +--- + drivers/soc/renesas/r8a7797-sysc.c | 3 +- + drivers/soc/renesas/r8a7798-sysc.c | 12 +++-- + drivers/soc/renesas/rcar-sysc.c | 108 ++++++++++++++++++++++++++++++++++++- + drivers/soc/renesas/rcar-sysc.h | 6 +++ + 4 files changed, 123 insertions(+), 6 deletions(-) + +diff --git a/drivers/soc/renesas/r8a7797-sysc.c b/drivers/soc/renesas/r8a7797-sysc.c +index cde7d9e..5725ad0 100644 +--- a/drivers/soc/renesas/r8a7797-sysc.c ++++ b/drivers/soc/renesas/r8a7797-sysc.c +@@ -24,7 +24,8 @@ static const struct rcar_sysc_area r8a7797_areas[] __initconst = { + { "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 }, ++ { "a3ir", 0x180, 0, R8A7797_PD_A3IR, R8A7797_PD_ALWAYS_ON, ++ PD_WA_CLK, {"impram"} }, + { "a2ir0", 0x400, 0, R8A7797_PD_A2IR0, R8A7797_PD_A3IR }, + { "a2ir1", 0x400, 1, R8A7797_PD_A2IR1, R8A7797_PD_A3IR }, + { "a2ir2", 0x400, 2, R8A7797_PD_A2IR2, R8A7797_PD_A3IR }, +diff --git a/drivers/soc/renesas/r8a7798-sysc.c b/drivers/soc/renesas/r8a7798-sysc.c +index 128e79d..2affaa2 100644 +--- a/drivers/soc/renesas/r8a7798-sysc.c ++++ b/drivers/soc/renesas/r8a7798-sysc.c +@@ -30,7 +30,8 @@ static const struct rcar_sysc_area r8a7798_areas[] __initconst = { + PD_CPU_NOCR }, + { "cr7", 0x240, 0, R8A7798_PD_CR7, R8A7798_PD_ALWAYS_ON }, + +- { "a3ir", 0x180, 0, R8A7798_PD_A3IR, R8A7798_PD_ALWAYS_ON }, ++ { "a3ir", 0x180, 0, R8A7798_PD_A3IR, R8A7798_PD_ALWAYS_ON, ++ PD_WA_CLK, {"impram"} }, + { "a2ir0", 0x400, 0, R8A7798_PD_A2IR0, R8A7798_PD_A3IR }, + { "a2ir1", 0x400, 1, R8A7798_PD_A2IR1, R8A7798_PD_A3IR }, + { "a2ir2", 0x400, 2, R8A7798_PD_A2IR2, R8A7798_PD_A3IR }, +@@ -46,9 +47,12 @@ static const struct rcar_sysc_area r8a7798_areas[] __initconst = { + { "a2pd1", 0x400, 12, R8A7798_PD_A2PD1, R8A7798_PD_A3IR }, + { "a2cn", 0x400, 13, R8A7798_PD_A2CN, R8A7798_PD_A3IR }, + +- { "a3vip", 0x2c0, 0, R8A7798_PD_A3VIP, R8A7798_PD_ALWAYS_ON }, +- { "a3vip1", 0x300, 0, R8A7798_PD_A3VIP1, R8A7798_PD_ALWAYS_ON }, +- { "a3vip2", 0x280, 0, R8A7798_PD_A3VIP2, R8A7798_PD_ALWAYS_ON }, ++ { "a3vip", 0x2c0, 0, R8A7798_PD_A3VIP, R8A7798_PD_ALWAYS_ON, ++ PD_WA_CLK, {"disp"} }, ++ { "a3vip1", 0x300, 0, R8A7798_PD_A3VIP1, R8A7798_PD_ALWAYS_ON, ++ PD_WA_CLK, {"umf", "smd_post", "smd_est", "smd_ps"} }, ++ { "a3vip2", 0x280, 0, R8A7798_PD_A3VIP2, R8A7798_PD_ALWAYS_ON, ++ PD_WA_CLK, {"cle0", "cle1", "cle2", "cle3", "cle4"} }, + }; + + const struct rcar_sysc_info r8a7798_sysc_info __initconst = { +diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c +index bfde184..f3f18d0 100644 +--- a/drivers/soc/renesas/rcar-sysc.c ++++ b/drivers/soc/renesas/rcar-sysc.c +@@ -20,6 +20,8 @@ + #include + #include + #include ++#include ++#include + + #include "rcar-sysc.h" + +@@ -64,6 +66,7 @@ static DEFINE_SPINLOCK(rcar_sysc_lock); /* SMP CPUs + I/O devices */ + + + static const char *to_pd_name(const struct rcar_sysc_ch *sysc_ch); ++static int rcar_sysc_wa_clk(const struct rcar_sysc_ch *sysc_ch, int en); + + static int rcar_sysc_pwr_on_off(const struct rcar_sysc_ch *sysc_ch, bool on) + { +@@ -110,6 +113,12 @@ static int rcar_sysc_power(const struct rcar_sysc_ch *sysc_ch, bool on) + int ret = 0; + int k; + ++ ret = rcar_sysc_wa_clk(sysc_ch, 1); ++ if (ret) { ++ pr_err("%s: Failed to enable clock for workaround\n", to_pd_name(sysc_ch)); ++ return ret; ++ } ++ + spin_lock_irqsave(&rcar_sysc_lock, flags); + + iowrite32(isr_mask, rcar_sysc_base + SYSCISCR); +@@ -148,6 +157,8 @@ static int rcar_sysc_power(const struct rcar_sysc_ch *sysc_ch, bool on) + out: + spin_unlock_irqrestore(&rcar_sysc_lock, flags); + ++ rcar_sysc_wa_clk(sysc_ch, 0); ++ + pr_debug("sysc power %s domain %d: %08x -> %d\n", on ? "on" : "off", + sysc_ch->isr_bit, ioread32(rcar_sysc_base + SYSCISR), ret); + return ret; +@@ -178,9 +189,35 @@ struct rcar_sysc_pd { + struct generic_pm_domain genpd; + struct rcar_sysc_ch ch; + unsigned int flags; ++ struct clk *wa_clk[RCAR_SYSC_MAX_WA_CLKS]; + char name[0]; + }; + ++static int rcar_sysc_wa_clk(const struct rcar_sysc_ch *sysc_ch, int en) ++{ ++ int i, ret; ++ struct rcar_sysc_pd *pd = container_of(sysc_ch, struct rcar_sysc_pd, ch); ++ ++ if (pd->flags & PD_WA_CLK) { ++ if (!(pd->flags & PD_WA_CLK_RDY)) ++ return -EBUSY; ++ ++ for (i = 0; i < RCAR_SYSC_MAX_WA_CLKS; i++) { ++ if (!pd->wa_clk[i]) ++ break; ++ ++ if (en) { ++ ret = clk_enable(pd->wa_clk[i]); ++ if (ret) ++ return ret; ++ } else ++ clk_disable(pd->wa_clk[i]); ++ } ++ } ++ ++ return 0; ++} ++ + static inline struct rcar_sysc_pd *to_rcar_pd(struct generic_pm_domain *d) + { + return container_of(d, struct rcar_sysc_pd, genpd); +@@ -231,6 +268,7 @@ static void __init rcar_sysc_pd_setup(struct rcar_sysc_pd *pd) + struct generic_pm_domain *genpd = &pd->genpd; + const char *name = pd->genpd.name; + struct dev_power_governor *gov = &simple_qos_governor; ++ bool is_off = false; + + if (pd->flags & PD_CPU) { + /* +@@ -278,6 +316,12 @@ static void __init rcar_sysc_pd_setup(struct rcar_sysc_pd *pd) + goto finalize; + } + ++ if (pd->flags & PD_NO_INIT_ON) { ++ is_off = rcar_sysc_power_is_off(&pd->ch); ++ pr_debug("%s: %s is initialy %s\n", __func__, genpd->name, is_off ? "off" : "on"); ++ goto finalize; ++ } ++ + if (!rcar_sysc_power_is_off(&pd->ch)) { + pr_debug("%s: %s is already powered\n", __func__, genpd->name); + goto finalize; +@@ -286,7 +330,7 @@ static void __init rcar_sysc_pd_setup(struct rcar_sysc_pd *pd) + rcar_sysc_power_up(&pd->ch); + + finalize: +- pm_genpd_init(genpd, gov, false); ++ pm_genpd_init(genpd, gov, is_off); + } + + static const struct of_device_id rcar_sysc_matches[] = { +@@ -442,6 +486,12 @@ static int __init rcar_sysc_pd_init(void) + pd->ch.isr_bit = area->isr_bit; + pd->flags = area->flags; + ++ if ((pd->flags & PD_WA_CLK) || ++ (area->parent >= 0 && (container_of(domains->domains[area->parent], ++ struct rcar_sysc_pd, genpd)->flags & PD_NO_INIT_ON)) ++ ) ++ pd->flags |= PD_NO_INIT_ON; ++ + rcar_sysc_pd_setup(pd); + if (area->parent >= 0) + pm_genpd_add_subdomain(domains->domains[area->parent], +@@ -479,6 +529,62 @@ static int __init rcar_sysc_pd_init2(void) + postcore_initcall(rcar_sysc_pd_init2); + #endif + ++#if IS_ENABLED(CONFIG_ARCH_R8A7797) || \ ++ IS_ENABLED(CONFIG_ARCH_R8A7798) ++static int __init rcar_sysc_pd_init3(void) ++{ ++ const struct rcar_sysc_info *info; ++ const struct of_device_id *match; ++ struct device_node *np; ++ unsigned int i, j; ++ ++ np = of_find_matching_node_and_match(NULL, rcar_sysc_matches, &match); ++ if (!np) ++ return -ENODEV; ++ ++ info = match->data; ++ ++ for (i = 0; i < info->num_areas; i++) { ++ const struct rcar_sysc_area *area = &info->areas[i]; ++ struct rcar_sysc_pd *pd = rcar_domains[i]; ++ ++ if (pd->flags & PD_WA_CLK) { ++ int err = 0; ++ ++ for (j = 0; j < RCAR_SYSC_MAX_WA_CLKS; j++) { ++ struct clk *wa_clk; ++ const char *wa_clk_name = area->wa_clk_names[j]; ++ ++ if (!wa_clk_name) ++ break; ++ ++ wa_clk = __clk_lookup(wa_clk_name); ++ if (!wa_clk) { ++ err = -ENODEV; ++ pr_err("%s: Unable to get clock %s for workaround\n", pd->name, wa_clk_name); ++ break; ++ } ++ ++ err = clk_prepare(wa_clk); ++ if (err) { ++ pr_err("%s: Unable to prepare clock %s for workaround\n", pd->name, wa_clk_name); ++ break; ++ } ++ ++ pd->wa_clk[j] = wa_clk; ++ } ++ ++ if (!err) ++ pd->flags |= PD_WA_CLK_RDY; ++ } ++ } ++ ++ return 0; ++} ++/* Should be called after cpg_mssr_driver is initialized */ ++subsys_initcall_sync(rcar_sysc_pd_init3); ++#endif ++ + void __init rcar_sysc_init(phys_addr_t base, u32 syscier) + { + u32 syscimr; +diff --git a/drivers/soc/renesas/rcar-sysc.h b/drivers/soc/renesas/rcar-sysc.h +index dc58a58..b991103 100644 +--- a/drivers/soc/renesas/rcar-sysc.h ++++ b/drivers/soc/renesas/rcar-sysc.h +@@ -23,10 +23,15 @@ + #define PD_BUSY BIT(3) /* Busy, for internal use only */ + #define PD_ON_ONCE BIT(4) /* Turned on once at boot */ + ++#define PD_WA_CLK BIT(5) /* Use clocks for workaround */ ++#define PD_WA_CLK_RDY BIT(6) /* Clock ready, for internal use only */ ++#define PD_NO_INIT_ON BIT(7) /* Do not power on at initialization, for internal use */ ++ + #define PD_CPU_CR PD_CPU /* CPU area has CR (R-Car H1) */ + #define PD_CPU_NOCR PD_CPU | PD_NO_CR /* CPU area lacks CR (R-Car Gen2/3) */ + #define PD_ALWAYS_ON PD_NO_CR /* Always-on area */ + ++#define RCAR_SYSC_MAX_WA_CLKS 8 + + /* + * Description of a Power Area +@@ -39,6 +44,7 @@ struct rcar_sysc_area { + u8 isr_bit; /* Bit in SYSCI*R */ + int parent; /* -1 if none */ + unsigned int flags; /* See PD_* */ ++ const char* wa_clk_names[RCAR_SYSC_MAX_WA_CLKS]; /* Clocks needed by workaround for A3 PD issue */ + }; + + +-- +2.7.4 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0104-media-vsp1-extend-DRM-VSP1-interface.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0104-media-vsp1-extend-DRM-VSP1-interface.patch index ecd0fd5..2f6fa35 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0104-media-vsp1-extend-DRM-VSP1-interface.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0104-media-vsp1-extend-DRM-VSP1-interface.patch @@ -198,7 +198,7 @@ index e79f9e6..753763d 100644 + (format->code != MEDIA_BUS_FMT_ARGB8888_1X32 ? VI6_LIF_CTRL_CFMT : 0) | VI6_LIF_CTRL_REQSEL | VI6_LIF_CTRL_LIF_EN); - if (soc_device_match(r8a7797_8)) + if (soc_device_match(r8a7797)) diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c index 8379962..86d4a85 100644 --- a/drivers/media/platform/vsp1/vsp1_pipe.c 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 index 89f437f..f9a99b9 100644 --- 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 @@ -53,6 +53,7 @@ SRC_URI_append = " \ file://0049-clk-r8a779x-add-IMP-clock.patch \ file://0050-arm64-dts-renesas-r8a779x-add-IMP-nodes.patch \ file://0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch \ + file://0052-soc-renesas-rcar-sysc-Add-workaround-for-A3-PD-issue.patch \ file://0062-IIO-lsm9ds0-add-IMU-driver.patch \ file://0063-ASoC-PCM3168A-add-TDM-modes-merge-ADC-and-DAC.patch \ file://0064-ADV7511-limit-maximum-pixelclock.patch \ -- cgit 1.2.3-korg From 53a48e7eaf7a3c5f81d367ae13780d89a7b0f2a0 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Sun, 11 Feb 2018 00:41:34 +0300 Subject: IMR: push rotation-scaling-enable flag up The flag number 8 is already busy with another option, hence push RSE flag up --- .../linux/linux-renesas/0106-media-rcar-imr-Add-RSE-support.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0106-media-rcar-imr-Add-RSE-support.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0106-media-rcar-imr-Add-RSE-support.patch index 37ce02b..1c8d800 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0106-media-rcar-imr-Add-RSE-support.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0106-media-rcar-imr-Add-RSE-support.patch @@ -290,7 +290,7 @@ index 7b8ed0c..19fdbae 100644 #define IMR_MAP_BFE (1 << 7) +/* ...extended functionality (rotation/scaling) enable flag */ -+#define IMR_MAP_RSE (1 << 8) ++#define IMR_MAP_RSE (1 << 21) + /* ...source coordinate decimal point position bit index */ #define __IMR_MAP_UVDPOR_SHIFT 8 -- cgit 1.2.3-korg From 7f779a355481c0c4eb4372c57df34c5c1a5ab642 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Sun, 11 Feb 2018 01:31:08 +0300 Subject: V3MSK and Condor have 2GB memory --- .../linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch index 46dba8d..3d3d263 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch @@ -12312,7 +12312,7 @@ index 0000000..91d10c5 + memory@48000000 { + device_type = "memory"; + /* first 128MB is reserved for secure area. */ -+ reg = <0x0 0x48000000 0x0 0x38000000>; ++ reg = <0x0 0x48000000 0x0 0x78000000>; + }; + + reserved-memory { @@ -13064,7 +13064,7 @@ index 0000000..cdd9844 + memory@48000000 { + device_type = "memory"; + /* first 128MB is reserved for secure area. */ -+ reg = <0x0 0x48000000 0x0 0x38000000>; ++ reg = <0x0 0x48000000 0x0 0x78000000>; + }; + + reserved-memory { -- cgit 1.2.3-korg From 191ce28ed6869c9d613c7cae57fce58c061579c4 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Sun, 11 Feb 2018 01:44:30 +0300 Subject: V3MSK: add PMIC This add DA9063 PMIC on V3MSK I2C0 bus --- .../0040-arm64-dts-renesas-add-ADAS-boards.patch | 41 +++++++++++++++++++--- 1 file changed, 36 insertions(+), 5 deletions(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch index 3d3d263..d69dd6f 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch @@ -70,7 +70,7 @@ Signed-off-by: Vladimir Barinov .../boot/dts/renesas/r8a7797-v3msk-vbm-v2.dts | 82 + arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts | 507 ++++++ arch/arm64/boot/dts/renesas/r8a7797-v3msk-view.dts | 297 ++++ - arch/arm64/boot/dts/renesas/r8a7797-v3msk.dts | 314 ++++ + arch/arm64/boot/dts/renesas/r8a7797-v3msk.dts | 345 ++++ arch/arm64/boot/dts/renesas/r8a7797-v3mzf.dts | 424 +++++ arch/arm64/boot/dts/renesas/r8a7798-condor.dts | 963 ++++++++++++ arch/arm64/boot/dts/renesas/ulcb-kf-cn11.dtsi | 462 ++++++ @@ -81,7 +81,7 @@ Signed-off-by: Vladimir Barinov arch/arm64/boot/dts/renesas/ulcb-vb.dtsi | 1610 +++++++++++++++++++ arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi | 1660 ++++++++++++++++++++ arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi | 543 +++++++ - 49 files changed, 19880 insertions(+) + 49 files changed, 19911 insertions(+) create mode 100644 arch/arm64/boot/dts/renesas/legacy/Makefile create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts @@ -12276,10 +12276,10 @@ index 0000000..58f82bf +}; diff --git a/arch/arm64/boot/dts/renesas/r8a7797-v3msk.dts b/arch/arm64/boot/dts/renesas/r8a7797-v3msk.dts new file mode 100644 -index 0000000..91d10c5 +index 0000000..c1e805d --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7797-v3msk.dts -@@ -0,0 +1,314 @@ +@@ -0,0 +1,345 @@ +/* + * Device Tree Source for the V3M Starter Kit board on r8a7797 + * @@ -12547,6 +12547,37 @@ index 0000000..91d10c5 + }; + }; + }; ++ ++ pmic@5A { ++ compatible = "dlg,da9063"; ++ reg = <0x5A>; ++ interrupt-parent = <&intc_ex>; ++ interrupts = <0 IRQ_TYPE_LEVEL_LOW>; ++ interrupt-controller; ++ ++ rtc { ++ compatible = "dlg,da9063-rtc"; ++ }; ++ ++ wdt { ++ compatible = "dlg,da9063-watchdog"; ++ }; ++ ++ regulators { ++ DA9063_LDO11: bmem { ++ regulator-name = "bmem"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ }; ++ ++ onkey { ++ compatible = "dlg,da9063-onkey"; ++ }; ++ }; ++ +}; + +&wdt0 { @@ -13026,7 +13057,7 @@ index 0000000..7926d2e +}; diff --git a/arch/arm64/boot/dts/renesas/r8a7798-condor.dts b/arch/arm64/boot/dts/renesas/r8a7798-condor.dts new file mode 100644 -index 0000000..cdd9844 +index 0000000..4dd7a28 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7798-condor.dts @@ -0,0 +1,963 @@ -- cgit 1.2.3-korg From 4dc42a265ea6d709da55e1803092c95384684186 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Mon, 12 Feb 2018 01:16:17 +0300 Subject: V3M VidoeoBoxMiniV2: user proper compatible the "spidev" is prohibbited to use for binding --- .../linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch index d69dd6f..b006f23 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch @@ -11445,7 +11445,7 @@ index 0000000..49d6dda + + status = "okay"; + spidev@0 { -+ compatible = "spidev"; ++ compatible = "renesas,sh-msiof"; + reg = <0>; + spi-max-frequency = <66666666>; + }; -- cgit 1.2.3-korg From ad815218bacf47249d3260f651e12eafd15207db Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Mon, 12 Feb 2018 01:18:01 +0300 Subject: V3M VideoBoxMiniV2: set POCx-gpios instead POCx-gpio It is already used for all POCx-gpios and not POCx-gpio. Both are functonal for 1 gpio used. This change just syncs with others. --- .../linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch index b006f23..0c52f42 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch @@ -11686,10 +11686,10 @@ index 0000000..c987799 + ti,lanes = <4>; + ti,forwarding-mode = "round-robin"; + ti,cable-mode = "coax"; -+ POC0-gpio = <&gpio_exp_6c 8 GPIO_ACTIVE_HIGH>; -+ POC1-gpio = <&gpio_exp_6c 9 GPIO_ACTIVE_HIGH>; -+ POC2-gpio = <&gpio_exp_6c 10 GPIO_ACTIVE_HIGH>; -+ POC3-gpio = <&gpio_exp_6c 11 GPIO_ACTIVE_HIGH>; ++ POC0-gpios = <&gpio_exp_6c 8 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_6c 9 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_6c 10 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_6c 11 GPIO_ACTIVE_HIGH>; + + port@0 { + ti9x4_des0ep0: endpoint@0 { -- cgit 1.2.3-korg From 0e2c192c58b0fca722d7b60a98da921dcfd90741 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Mon, 12 Feb 2018 03:07:23 +0300 Subject: V3M: Support ES1.0 SoC --- .../0040-arm64-dts-renesas-add-ADAS-boards.patch | 336 +++++++++++++++++++-- .../linux/linux-renesas_4.9.bbappend | 7 + 2 files changed, 325 insertions(+), 18 deletions(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch index 0c52f42..5e17f76 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch @@ -14,25 +14,25 @@ H3ULCB.HAD board on R8A7795 SoC Kingfisher board on R8A7795 ES1.x SoC Kingfisher board on R8A7795 SoC Kingfisher board on R8A7796 SoC -Kingfisher board on R8A7797 SoC +Kingfisher board on R8A7797 ES1.0/2.0 SoC Videobox board on R8A7795 ES1.x SoC Videobox board on R8A7795 SoC -Eagle board on R8A7797 SoC -Eagle Function board on R8A7797 SoC -V3MSK board on R8A7797 SoC -V3MSK.View board on R8A7797 SoC +Eagle board on R8A7797 ES1.0/2.0 SoC +Eagle Function board on R8A7797 ES1.0/2.0 SoC +V3MSK board on R8A7797 ES1.0/2.0 SoC +V3MSK.View board on R8A7797 ES1.0/2.0 SoC V3MZF board on R8A7797 SoC Videobox Mini board on R8A7795 ES1.x SoC Videobox Mini board on R8A7795 SoC -Videobox Mini board on R8A7797 SoC -Videobox Mini V2 board on R8A7797 SoC +Videobox Mini board on R8A7797 ES1.0/2.0 SoC +Videobox Mini V2 board on R8A7797 ES1.0/2.0 SoC Videobox2 board on R8A7795 ES1.x SoC Videobox2 board on R8A7795 SoC Condor board on R8A7798 SoC Signed-off-by: Vladimir Barinov --- - arch/arm64/boot/dts/renesas/Makefile | 23 + + arch/arm64/boot/dts/renesas/Makefile | 24 + arch/arm64/boot/dts/renesas/legacy/Makefile | 8 + .../renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts | 1624 +++++++++++++++++++ .../renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts | 441 ++++++ @@ -66,6 +66,14 @@ Signed-off-by: Vladimir Barinov .../boot/dts/renesas/r8a7796-salvator-x-view.dts | 317 ++++ .../boot/dts/renesas/r8a7797-eagle-function.dts | 62 + arch/arm64/boot/dts/renesas/r8a7797-eagle.dts | 605 +++++++ + .../dts/renesas/r8a7797-es1-eagle-function.dts | 17 + + arch/arm64/boot/dts/renesas/r8a7797-es1-eagle.dts | 17 + + .../boot/dts/renesas/r8a7797-es1-v3msk-kf.dts | 17 + + .../boot/dts/renesas/r8a7797-es1-v3msk-vbm-v2.dts | 17 + + .../boot/dts/renesas/r8a7797-es1-v3msk-vbm.dts | 17 + + .../boot/dts/renesas/r8a7797-es1-v3msk-view.dts | 17 + + arch/arm64/boot/dts/renesas/r8a7797-es1-v3msk.dts | 17 + + arch/arm64/boot/dts/renesas/r8a7797-es1.dtsi | 116 ++ arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts | 520 ++++++ .../boot/dts/renesas/r8a7797-v3msk-vbm-v2.dts | 82 + arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts | 507 ++++++ @@ -81,7 +89,7 @@ Signed-off-by: Vladimir Barinov arch/arm64/boot/dts/renesas/ulcb-vb.dtsi | 1610 +++++++++++++++++++ arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi | 1660 ++++++++++++++++++++ arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi | 543 +++++++ - 49 files changed, 19911 insertions(+) + 57 files changed, 20147 insertions(+) create mode 100644 arch/arm64/boot/dts/renesas/legacy/Makefile create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts @@ -115,6 +123,14 @@ Signed-off-by: Vladimir Barinov create mode 100644 arch/arm64/boot/dts/renesas/r8a7796-salvator-x-view.dts create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-eagle-function.dts create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-eagle.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-es1-eagle-function.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-es1-eagle.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-es1-v3msk-kf.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-es1-v3msk-vbm-v2.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-es1-v3msk-vbm.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-es1-v3msk-view.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-es1-v3msk.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-es1.dtsi create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm-v2.dts create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts @@ -132,10 +148,10 @@ Signed-off-by: Vladimir Barinov create mode 100644 arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile -index f9c71df..8af9300 100644 +index f9c71df..6cdbdaf 100644 --- a/arch/arm64/boot/dts/renesas/Makefile +++ b/arch/arm64/boot/dts/renesas/Makefile -@@ -6,5 +6,28 @@ dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-xs.dtb +@@ -6,5 +6,29 @@ dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-xs.dtb dtb-$(CONFIG_ARCH_R8A77965) += r8a77965-salvator-x.dtb dtb-$(CONFIG_ARCH_R8A77965) += r8a77965-salvator-xs.dtb @@ -151,11 +167,12 @@ index f9c71df..8af9300 100644 +dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-vb2.dtb r8a7795-es1-h3ulcb-vb2.dtb +dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-h3ulcb-vbm.dtb r8a7795-es1-h3ulcb-vbm.dtb +dtb-$(CONFIG_ARCH_R8A7797) += r8a7797-eagle.dtb r8a7797-eagle-function.dtb -+dtb-$(CONFIG_ARCH_R8A7797) += r8a7797-v3msk.dtb -+dtb-$(CONFIG_ARCH_R8A7797) += r8a7797-v3msk-view.dtb -+dtb-$(CONFIG_ARCH_R8A7797) += r8a7797-v3msk-kf.dtb -+dtb-$(CONFIG_ARCH_R8A7797) += r8a7797-v3msk-vbm.dtb -+dtb-$(CONFIG_ARCH_R8A7797) += r8a7797-v3msk-vbm-v2.dtb ++dtb-$(CONFIG_ARCH_R8A7797) += r8a7797-es1-eagle.dtb r8a7797-es1-eagle-function.dtb ++dtb-$(CONFIG_ARCH_R8A7797) += r8a7797-v3msk.dtb r8a7797-es1-v3msk.dtb ++dtb-$(CONFIG_ARCH_R8A7797) += r8a7797-v3msk-view.dtb r8a7797-es1-v3msk-view.dtb ++dtb-$(CONFIG_ARCH_R8A7797) += r8a7797-v3msk-kf.dtb r8a7797-es1-v3msk-kf.dtb ++dtb-$(CONFIG_ARCH_R8A7797) += r8a7797-v3msk-vbm.dtb r8a7797-es1-v3msk-vbm.dtb ++dtb-$(CONFIG_ARCH_R8A7797) += r8a7797-v3msk-vbm-v2.dtb r8a7797-es1-v3msk-vbm-v2.dtb +dtb-$(CONFIG_ARCH_R8A7797) += r8a7797-v3mzf.dtb +dtb-$(CONFIG_ARCH_R8A7798) += r8a7798-condor.dtb + @@ -10844,6 +10861,289 @@ index 0000000..db17b03 + }; + }; +}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7797-es1-eagle-function.dts b/arch/arm64/boot/dts/renesas/r8a7797-es1-eagle-function.dts +new file mode 100644 +index 0000000..74351b8 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7797-es1-eagle-function.dts +@@ -0,0 +1,17 @@ ++/* ++ * Device Tree Source for the Eagle Function board on r8a7797 ES1.0 ++ * ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7797-eagle-function.dts" ++#include "r8a7797-es1.dtsi" ++ ++/ { ++ model = "Renesas Eagle Function board based on r8a7797 ES1.0"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7797-es1-eagle.dts b/arch/arm64/boot/dts/renesas/r8a7797-es1-eagle.dts +new file mode 100644 +index 0000000..f65f69d +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7797-es1-eagle.dts +@@ -0,0 +1,17 @@ ++/* ++ * Device Tree Source for the Eagle board on r8a7797 ES1.0 ++ * ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7797-eagle.dts" ++#include "r8a7797-es1.dtsi" ++ ++/ { ++ model = "Renesas Eagle board based on r8a7797 ES1.0"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7797-es1-v3msk-kf.dts b/arch/arm64/boot/dts/renesas/r8a7797-es1-v3msk-kf.dts +new file mode 100644 +index 0000000..c811e6f +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7797-es1-v3msk-kf.dts +@@ -0,0 +1,17 @@ ++/* ++ * Device Tree Source for the V3MSK Kingfisher board on r8a7797 ES1.0 ++ * ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7797-v3msk-kf.dts" ++#include "r8a7797-es1.dtsi" ++ ++/ { ++ model = "Renesas V3MSK Kingfisher board based on r8a7797 ES1.0"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7797-es1-v3msk-vbm-v2.dts b/arch/arm64/boot/dts/renesas/r8a7797-es1-v3msk-vbm-v2.dts +new file mode 100644 +index 0000000..c6fcffd +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7797-es1-v3msk-vbm-v2.dts +@@ -0,0 +1,17 @@ ++/* ++ * Device Tree Source for the V3MSK Videobox Mini V2 board on r8a7797 ES1.0 ++ * ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7797-v3msk-vbm-v2.dts" ++#include "r8a7797-es1.dtsi" ++ ++/ { ++ model = "Renesas V3MSK Videobox Mini V2 board based on r8a7797 ES1.0"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7797-es1-v3msk-vbm.dts b/arch/arm64/boot/dts/renesas/r8a7797-es1-v3msk-vbm.dts +new file mode 100644 +index 0000000..90b7439 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7797-es1-v3msk-vbm.dts +@@ -0,0 +1,17 @@ ++/* ++ * Device Tree Source for the V3MSK Videobox Mini board on r8a7797 ES1.0 ++ * ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7797-v3msk-vbm.dts" ++#include "r8a7797-es1.dtsi" ++ ++/ { ++ model = "Renesas V3MSK Videobox Mini board based on r8a7797 ES1.0"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7797-es1-v3msk-view.dts b/arch/arm64/boot/dts/renesas/r8a7797-es1-v3msk-view.dts +new file mode 100644 +index 0000000..576d21c +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7797-es1-v3msk-view.dts +@@ -0,0 +1,17 @@ ++/* ++ * Device Tree Source for the V3MSK View board on r8a7797 ES1.0 ++ * ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7797-v3msk-view.dts" ++#include "r8a7797-es1.dtsi" ++ ++/ { ++ model = "Renesas V3MSK View board based on r8a7797 ES1.0"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7797-es1-v3msk.dts b/arch/arm64/boot/dts/renesas/r8a7797-es1-v3msk.dts +new file mode 100644 +index 0000000..3257d7e +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7797-es1-v3msk.dts +@@ -0,0 +1,17 @@ ++/* ++ * Device Tree Source for the V3M Starter Kit board on r8a7797 ES1.0 ++ * ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7797-v3msk.dts" ++#include "r8a7797-es1.dtsi" ++ ++/ { ++ model = "Renesas V3M Starter Kit board based on r8a7797 ES1.0"; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7797-es1.dtsi b/arch/arm64/boot/dts/renesas/r8a7797-es1.dtsi +new file mode 100644 +index 0000000..dab9adc +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7797-es1.dtsi +@@ -0,0 +1,116 @@ ++/* ++ * Device Tree Source for the r8a7797 SoC ES1.0 SoC ++ * (append to r8a7797 SoC ES2.0 SoC) ++ * ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 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. ++ */ ++ ++/ { ++ soc { ++ imp_distributer: impdes0 { ++ compatible = "renesas,impx4-distributer"; ++ reg = <0 0xffa00000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 830>; ++ power-domains = <&sysc R8A7797_PD_A3IR>; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ }; ++ ++ imp0 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff900000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <0>; ++ clocks = <&cpg CPG_MOD 827>; ++ power-domains = <&sysc R8A7797_PD_A2IR0>; ++ }; ++ ++ imp1 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff920000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <1>; ++ clocks = <&cpg CPG_MOD 826>; ++ power-domains = <&sysc R8A7797_PD_A2IR1>; ++ }; ++ ++ imp2 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff940000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <2>; ++ clocks = <&cpg CPG_MOD 825>; ++ power-domains = <&sysc R8A7797_PD_A2IR2>; ++ }; ++ ++ imp3 { ++ compatible = "renesas,impx4-legacy"; ++ reg = <0 0xff960000 0 0x20000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <3>; ++ clocks = <&cpg CPG_MOD 824>; ++ power-domains = <&sysc R8A7797_PD_A2IR3>; ++ }; ++ ++ impsc0 { ++ compatible = "renesas,impx4-shader"; ++ reg = <0 0xff980000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <4>; ++ clocks = <&cpg CPG_MOD 829>; ++ power-domains = <&sysc R8A7797_PD_A2SC0>; ++ }; ++ ++ impsc1 { ++ compatible = "renesas,impx4-shader"; ++ reg = <0 0xff990000 0 0x10000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <5>; ++ clocks = <&cpg CPG_MOD 828>; ++ power-domains = <&sysc R8A7797_PD_A2SC1>; ++ }; ++ ++ impdm0 { ++ compatible = "renesas,impx5-dmac"; ++ reg = <0 0xffa10000 0 0x1000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <16>; ++ clocks = <&cpg CPG_MOD 830>; ++ power-domains = <&sysc R8A7797_PD_A3IR>; ++ }; ++ ++ impdm1 { ++ compatible = "renesas,impx5-dmac"; ++ reg = <0 0xffa10000 0 0x1000>, ++ <0 0xffa10800 0 0x0800>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <17>; ++ clocks = <&cpg CPG_MOD 830>; ++ power-domains = <&sysc R8A7797_PD_A3IR>; ++ }; ++ ++ imppsc0 { ++ compatible = "renesas,impx5+-psc"; ++ reg = <0 0xffa20000 0 0x4000>; ++ interrupt-parent = <&imp_distributer>; ++ interrupts = <12>; ++ clocks = <&cpg CPG_MOD 830>; ++ power-domains = <&sysc R8A7797_PD_A3IR>; ++ }; ++ ++ /delete-node/impcnn0; ++ ++ impc0 { ++ compatible = "renesas,impx4-memory"; ++ reg = <0 0xed000000 0 0xe0000>; ++ clocks = <&cpg CPG_MOD 830>; ++ power-domains = <&sysc R8A7797_PD_A3IR>; ++ }; ++ }; ++}; diff --git a/arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts new file mode 100644 index 0000000..862236f @@ -11372,7 +11672,7 @@ index 0000000..862236f +}; diff --git a/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm-v2.dts b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm-v2.dts new file mode 100644 -index 0000000..49d6dda +index 0000000..dbbd3d2 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm-v2.dts @@ -0,0 +1,82 @@ @@ -11460,7 +11760,7 @@ index 0000000..49d6dda +}; diff --git a/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts new file mode 100644 -index 0000000..c987799 +index 0000000..70c0f66 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts @@ -0,0 +1,507 @@ 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 index f9a99b9..b73f77e 100644 --- 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 @@ -122,11 +122,18 @@ KERNEL_DEVICETREE_append_salvator-x = " \ " KERNEL_DEVICETREE_append_eagle = " \ + renesas/r8a7797-es1-eagle.dtb \ + renesas/r8a7797-es1-eagle-function.dtb \ renesas/r8a7797-eagle.dtb \ renesas/r8a7797-eagle-function.dtb \ " KERNEL_DEVICETREE_append_v3msk = " \ + renesas/r8a7797-es1-v3msk.dtb \ + renesas/r8a7797-es1-v3msk-kf.dtb \ + renesas/r8a7797-es1-v3msk-vbm.dtb \ + renesas/r8a7797-es1-v3msk-vbm-v2.dtb \ + renesas/r8a7797-es1-v3msk-view.dtb \ renesas/r8a7797-v3msk.dtb \ renesas/r8a7797-v3msk-kf.dtb \ renesas/r8a7797-v3msk-vbm.dtb \ -- cgit 1.2.3-korg From 99ae91e5245ff2610d3e6dd283d7494fdc007b40 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Tue, 13 Feb 2018 19:20:00 +0300 Subject: Add V3H Starter Kit board This adds V3H Starter Kit board support --- meta-rcar-gen3-adas/conf/machine/v3hsk.conf | 41 ++ .../sample/conf/v3hsk/linaro-gcc/bsp/bblayers.conf | 16 + .../sample/conf/v3hsk/linaro-gcc/bsp/local.conf | 267 ++++++++++ .../arm-trusted-firmware_git.bbappend | 6 + .../recipes-bsp/cr7-loader/cr7-loader_git.bb | 2 +- .../00201-board-renesas-Add-V3HSK-board.patch | 548 +++++++++++++++++++++ .../recipes-bsp/u-boot/u-boot_2015.04.bbappend | 1 + .../kernel-module-mmngr.bbappend | 1 + .../0040-arm64-dts-renesas-add-ADAS-boards.patch | 380 +++++++++++++- .../recipes-kernel/linux/linux-renesas/v3hsk.cfg | 40 ++ .../linux/linux-renesas_4.9.bbappend | 6 + 11 files changed, 1301 insertions(+), 7 deletions(-) create mode 100644 meta-rcar-gen3-adas/conf/machine/v3hsk.conf create mode 100644 meta-rcar-gen3-adas/docs/sample/conf/v3hsk/linaro-gcc/bsp/bblayers.conf create mode 100644 meta-rcar-gen3-adas/docs/sample/conf/v3hsk/linaro-gcc/bsp/local.conf create mode 100644 meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/00201-board-renesas-Add-V3HSK-board.patch create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3hsk.cfg (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/conf/machine/v3hsk.conf b/meta-rcar-gen3-adas/conf/machine/v3hsk.conf new file mode 100644 index 0000000..2e70003 --- /dev/null +++ b/meta-rcar-gen3-adas/conf/machine/v3hsk.conf @@ -0,0 +1,41 @@ +#@TYPE: Machine +#@NAME: V3HSK machine +#@DESCRIPTION: Machine configuration for running V3HSK + +DEFAULTTUNE ?= "cortexa53" +require conf/machine/include/tune-cortexa53.inc +require conf/machine/include/${SOC_FAMILY}.inc + +# 32BIT package install (default is disable) +# This variables can be used only in multilib. +USE_32BIT_PKGS ?= "0" +USE_32BIT_WAYLAND ?= "0" +USE_32BIT_MMP ?= "0" + +MACHINE_FEATURES = "" + +KERNEL_IMAGETYPE = "Image" +IMAGE_FSTYPES = "tar.bz2 ext4 cpio.gz" + +SERIAL_CONSOLE = "115200 ttySC0" + +# Configuration for kernel +PREFERRED_PROVIDER_virtual/kernel = "linux-renesas" +KERNEL_DEVICETREE = "renesas/r8a7798-v3hsk.dtb" + +# Configuration for CR7 Loader +EXTRA_IMAGEDEPENDS += " cr7-loader" + +# Configuration for ARM Trusted Firmware +EXTRA_IMAGEDEPENDS += " arm-trusted-firmware" + +# u-boot +PREFERRED_VERSION_u-boot = "v2015.04%" +EXTRA_IMAGEDEPENDS += " u-boot" +UBOOT_MACHINE = "v3hsk_defconfig" + +# libdrm +PREFERRED_VERSION_libdrm = "2.4.68" + +# Add variable to Build Configuration in build log +BUILDCFG_VARS_append = " SOC_FAMILY" diff --git a/meta-rcar-gen3-adas/docs/sample/conf/v3hsk/linaro-gcc/bsp/bblayers.conf b/meta-rcar-gen3-adas/docs/sample/conf/v3hsk/linaro-gcc/bsp/bblayers.conf new file mode 100644 index 0000000..96ff8ad --- /dev/null +++ b/meta-rcar-gen3-adas/docs/sample/conf/v3hsk/linaro-gcc/bsp/bblayers.conf @@ -0,0 +1,16 @@ +# POKY_BBLAYERS_CONF_VERSION is increased each time build/conf/bblayers.conf +# changes incompatibly +POKY_BBLAYERS_CONF_VERSION = "2" + +BBPATH = "${TOPDIR}" +BBFILES ?= "" + +BBLAYERS ?= " \ + ${TOPDIR}/../poky/meta \ + ${TOPDIR}/../poky/meta-poky \ + ${TOPDIR}/../poky/meta-yocto-bsp \ + ${TOPDIR}/../meta-renesas/meta-rcar-gen3 \ + ${TOPDIR}/../meta-linaro/meta-linaro-toolchain \ + ${TOPDIR}/../meta-linaro/meta-optee \ + ${TOPDIR}/../meta-openembedded/meta-oe \ + " diff --git a/meta-rcar-gen3-adas/docs/sample/conf/v3hsk/linaro-gcc/bsp/local.conf b/meta-rcar-gen3-adas/docs/sample/conf/v3hsk/linaro-gcc/bsp/local.conf new file mode 100644 index 0000000..69fee74 --- /dev/null +++ b/meta-rcar-gen3-adas/docs/sample/conf/v3hsk/linaro-gcc/bsp/local.conf @@ -0,0 +1,267 @@ +# +# This file is your local configuration file and is where all local user settings +# are placed. The comments in this file give some guide to the options a new user +# to the system might want to change but pretty much any configuration option can +# be set in this file. More adventurous users can look at local.conf.extended +# which contains other examples of configuration which can be placed in this file +# but new users likely won't need any of them initially. +# +# Lines starting with the '#' character are commented out and in some cases the +# default values are provided as comments to show people example syntax. Enabling +# the option is a question of removing the # character and making any change to the +# variable as required. + +# +# Machine Selection +# +# You need to select a specific machine to target the build with. There are a selection +# of emulated machines available which can boot and run in the QEMU emulator: +# +#MACHINE ?= "qemuarm" +#MACHINE ?= "qemuarm64" +#MACHINE ?= "qemumips" +#MACHINE ?= "qemumips64" +#MACHINE ?= "qemuppc" +#MACHINE ?= "qemux86" +#MACHINE ?= "qemux86-64" +# +# There are also the following hardware board target machines included for +# demonstration purposes: +# +#MACHINE ?= "beaglebone" +#MACHINE ?= "genericx86" +#MACHINE ?= "genericx86-64" +#MACHINE ?= "mpc8315e-rdb" +#MACHINE ?= "edgerouter" +# +# This sets the default machine to be qemux86 if no other machine is selected: +MACHINE ??= "v3hsk" + +SOC_FAMILY = "r8a7798" + +# +# Where to place downloads +# +# During a first build the system will download many different source code tarballs +# from various upstream projects. This can take a while, particularly if your network +# connection is slow. These are all stored in DL_DIR. When wiping and rebuilding you +# can preserve this directory to speed up this part of subsequent builds. This directory +# is safe to share between multiple builds on the same machine too. +# +# The default is a downloads directory under TOPDIR which is the build directory. +# +#DL_DIR ?= "${TOPDIR}/downloads" + +# +# Where to place shared-state files +# +# BitBake has the capability to accelerate builds based on previously built output. +# This is done using "shared state" files which can be thought of as cache objects +# and this option determines where those files are placed. +# +# You can wipe out TMPDIR leaving this directory intact and the build would regenerate +# from these files if no changes were made to the configuration. If changes were made +# to the configuration, only shared state files where the state was still valid would +# be used (done using checksums). +# +# The default is a sstate-cache directory under TOPDIR. +# +#SSTATE_DIR ?= "${TOPDIR}/sstate-cache" + +# +# Where to place the build output +# +# This option specifies where the bulk of the building work should be done and +# where BitBake should place its temporary files and output. Keep in mind that +# this includes the extraction and compilation of many applications and the toolchain +# which can use Gigabytes of hard disk space. +# +# The default is a tmp directory under TOPDIR. +# +#TMPDIR = "${TOPDIR}/tmp" + +# +# Default policy config +# +# The distribution setting controls which policy settings are used as defaults. +# The default value is fine for general Yocto project use, at least initially. +# Ultimately when creating custom policy, people will likely end up subclassing +# these defaults. +# +DISTRO ?= "poky" +# As an example of a subclass there is a "bleeding" edge policy configuration +# where many versions are set to the absolute latest code from the upstream +# source control systems. This is just mentioned here as an example, its not +# useful to most new users. +# DISTRO ?= "poky-bleeding" + +# +# Package Management configuration +# +# This variable lists which packaging formats to enable. Multiple package backends +# can be enabled at once and the first item listed in the variable will be used +# to generate the root filesystems. +# Options are: +# - 'package_deb' for debian style deb files +# - 'package_ipk' for ipk files are used by opkg (a debian style embedded package manager) +# - 'package_rpm' for rpm style packages +# E.g.: PACKAGE_CLASSES ?= "package_rpm package_deb package_ipk" +# We default to rpm: +PACKAGE_CLASSES ?= "package_ipk" + +# +# SDK target architecture +# +# This variable specifies the architecture to build SDK items for and means +# you can build the SDK packages for architectures other than the machine you are +# running the build on (i.e. building i686 packages on an x86_64 host). +# Supported values are i686 and x86_64 +#SDKMACHINE ?= "i686" + +# +# Extra image configuration defaults +# +# The EXTRA_IMAGE_FEATURES variable allows extra packages to be added to the generated +# images. Some of these options are added to certain image types automatically. The +# variable can contain the following options: +# "dbg-pkgs" - add -dbg packages for all installed packages +# (adds symbol information for debugging/profiling) +# "dev-pkgs" - add -dev packages for all installed packages +# (useful if you want to develop against libs in the image) +# "ptest-pkgs" - add -ptest packages for all ptest-enabled packages +# (useful if you want to run the package test suites) +# "tools-sdk" - add development tools (gcc, make, pkgconfig etc.) +# "tools-debug" - add debugging tools (gdb, strace) +# "eclipse-debug" - add Eclipse remote debugging support +# "tools-profile" - add profiling tools (oprofile, lttng, valgrind) +# "tools-testapps" - add useful testing tools (ts_print, aplay, arecord etc.) +# "debug-tweaks" - make an image suitable for development +# e.g. ssh root access has a blank password +# There are other application targets that can be used here too, see +# meta/classes/image.bbclass and meta/classes/core-image.bbclass for more details. +# We default to enabling the debugging tweaks. +EXTRA_IMAGE_FEATURES ?= "debug-tweaks" + +# +# Additional image features +# +# The following is a list of additional classes to use when building images which +# enable extra features. Some available options which can be included in this variable +# are: +# - 'buildstats' collect build statistics +# - 'image-mklibs' to reduce shared library files size for an image +# - 'image-prelink' in order to prelink the filesystem image +# - 'image-swab' to perform host system intrusion detection +# NOTE: if listing mklibs & prelink both, then make sure mklibs is before prelink +# NOTE: mklibs also needs to be explicitly enabled for a given image, see local.conf.extended +# image-prelink disabled for now due to issues with IFUNC symbol relocation +USER_CLASSES ?= "buildstats image-mklibs" + +# +# Runtime testing of images +# +# The build system can test booting virtual machine images under qemu (an emulator) +# after any root filesystems are created and run tests against those images. To +# enable this uncomment this line. See classes/testimage(-auto).bbclass for +# further details. +#TEST_IMAGE = "1" +# +# Interactive shell configuration +# +# Under certain circumstances the system may need input from you and to do this it +# can launch an interactive shell. It needs to do this since the build is +# multithreaded and needs to be able to handle the case where more than one parallel +# process may require the user's attention. The default is iterate over the available +# terminal types to find one that works. +# +# Examples of the occasions this may happen are when resolving patches which cannot +# be applied, to use the devshell or the kernel menuconfig +# +# Supported values are auto, gnome, xfce, rxvt, screen, konsole (KDE 3.x only), none +# Note: currently, Konsole support only works for KDE 3.x due to the way +# newer Konsole versions behave +#OE_TERMINAL = "auto" +# By default disable interactive patch resolution (tasks will just fail instead): +PATCHRESOLVE = "noop" + +# +# Disk Space Monitoring during the build +# +# Monitor the disk space during the build. If there is less that 1GB of space or less +# than 100K inodes in any key build location (TMPDIR, DL_DIR, SSTATE_DIR), gracefully +# shutdown the build. If there is less that 100MB or 1K inodes, perform a hard abort +# of the build. The reason for this is that running completely out of space can corrupt +# files and damages the build in ways which may not be easily recoverable. +# It's necesary to monitor /tmp, if there is no space left the build will fail +# with very exotic errors. +BB_DISKMON_DIRS = "\ + STOPTASKS,${TMPDIR},1G,100K \ + STOPTASKS,${DL_DIR},1G,100K \ + STOPTASKS,${SSTATE_DIR},1G,100K \ + STOPTASKS,/tmp,100M,100K \ + ABORT,${TMPDIR},100M,1K \ + ABORT,${DL_DIR},100M,1K \ + ABORT,${SSTATE_DIR},100M,1K \ + ABORT,/tmp,10M,1K" + +# +# Shared-state files from other locations +# +# As mentioned above, shared state files are prebuilt cache data objects which can +# used to accelerate build time. This variable can be used to configure the system +# to search other mirror locations for these objects before it builds the data itself. +# +# This can be a filesystem directory, or a remote url such as http or ftp. These +# would contain the sstate-cache results from previous builds (possibly from other +# machines). This variable works like fetcher MIRRORS/PREMIRRORS and points to the +# cache locations to check for the shared objects. +# NOTE: if the mirror uses the same structure as SSTATE_DIR, you need to add PATH +# at the end as shown in the examples below. This will be substituted with the +# correct path within the directory structure. +#SSTATE_MIRRORS ?= "\ +#file://.* http://someserver.tld/share/sstate/PATH;downloadfilename=PATH \n \ +#file://.* file:///some/local/dir/sstate/PATH" + + +# +# Qemu configuration +# +# By default qemu will build with a builtin VNC server where graphical output can be +# seen. The two lines below enable the SDL backend too. By default libsdl-native will +# be built, if you want to use your host's libSDL instead of the minimal libsdl built +# by libsdl-native then uncomment the ASSUME_PROVIDED line below. +PACKAGECONFIG_append_pn-qemu-native = " sdl" +PACKAGECONFIG_append_pn-nativesdk-qemu = " sdl" +#ASSUME_PROVIDED += "libsdl-native" + +# CONF_VERSION is increased each time build/conf/ changes incompatibly and is used to +# track the version of this file when it was generated. This can safely be ignored if +# this doesn't mean anything to you. +CONF_VERSION = "1" + +# Add systemd configuration +DISTRO_FEATURES_append = " systemd" +VIRTUAL-RUNTIME_init_manager = "systemd" + +# Linaro GCC +GCCVERSION = "linaro-5.2" + +# add the static lib to SDK toolchain +SDKIMAGE_FEATURES_append = " staticdev-pkgs" + +# Disable optee in meta-linaro layer +BBMASK = "meta-linaro/meta-optee/recipes-security/optee" + +# Mask graphic Pkgs +BBMASK .= "|gles-user-module|kernel-module-gles|wayland-kms|libgbm" +# Mask MMP recipes +BBMASK .= "|kernel-module-uvcs-drv|omx-user-module" + +# Add for gstreamer plugins ugly +LICENSE_FLAGS_WHITELIST = "commercial" + +# Linux ICCOM driver (RCG3ZLIDL4001ZNO) +# Linux ICCOM library (RCG3ZLILL4001ZNO) +#DISTRO_FEATURES_append = " iccom" + +IMAGE_INSTALL_remove = "optee-linuxdriver optee-linuxdriver-armtz optee-client" 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 index 253762c..0de1218 100644 --- 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 @@ -4,6 +4,7 @@ COMPATIBLE_MACHINE_eagle = "eagle" COMPATIBLE_MACHINE_v3msk = "v3msk" COMPATIBLE_MACHINE_v3mzf = "v3mzf" COMPATIBLE_MACHINE_condor = "condor" +COMPATIBLE_MACHINE_v3hsk = "v3hsk" ATFW_OPT_r8a7797 = "LSI=V3M RCAR_DRAM_SPLIT=0 RCAR_LOSSY_ENABLE=0 PMIC_ROHM_BD9571=0 RCAR_SYSTEM_SUSPEND=0 SPD=none" ATFW_OPT_r8a7798 = "LSI=V3H RCAR_DRAM_SPLIT=0 RCAR_LOSSY_ENABLE=0 PMIC_ROHM_BD9571=0 RCAR_SYSTEM_SUSPEND=0 SPD=none RCAR_SECURE_BOOT=0" @@ -27,3 +28,8 @@ do_deploy_append_condor() { rm ${DEPLOYDIR}/bootparam_sa0.bin rm ${DEPLOYDIR}/bootparam_sa0.srec } + +do_deploy_append_v3hsk() { + rm ${DEPLOYDIR}/bootparam_sa0.bin + rm ${DEPLOYDIR}/bootparam_sa0.srec +} diff --git a/meta-rcar-gen3-adas/recipes-bsp/cr7-loader/cr7-loader_git.bb b/meta-rcar-gen3-adas/recipes-bsp/cr7-loader/cr7-loader_git.bb index bc80d42..e990273 100644 --- a/meta-rcar-gen3-adas/recipes-bsp/cr7-loader/cr7-loader_git.bb +++ b/meta-rcar-gen3-adas/recipes-bsp/cr7-loader/cr7-loader_git.bb @@ -15,7 +15,7 @@ SRCREV = "9570cd170e876801370560bb0c417816cbfe21d2" PV = "v1.0+renesas+git" -COMPATIBLE_MACHINE = "condor" +COMPATIBLE_MACHINE = "condor|v3hsk" PLATFORM = "rcar" do_compile() { diff --git a/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/00201-board-renesas-Add-V3HSK-board.patch b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/00201-board-renesas-Add-V3HSK-board.patch new file mode 100644 index 0000000..94067dc --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-bsp/u-boot/u-boot/00201-board-renesas-Add-V3HSK-board.patch @@ -0,0 +1,548 @@ +From 519ee2d3ff6049263277b24dd8326a27a8d102e2 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Tue, 13 Feb 2018 17:17:39 +0300 +Subject: [PATCH] board: renesas: Add V3H Starter Kit board + +V3H Starter Kit is a board based on R-Car V3H SoC (R8A7798) + +Signed-off-by: Vladimir Barinov +--- + arch/arm/cpu/armv8/Kconfig | 4 + + board/renesas/v3hsk/Kconfig | 15 +++ + board/renesas/v3hsk/MAINTAINERS | 6 + + board/renesas/v3hsk/Makefile | 10 ++ + board/renesas/v3hsk/v3hsk.c | 263 ++++++++++++++++++++++++++++++++++++++++ + configs/v3hsk_defconfig | 10 ++ + include/configs/v3hsk.h | 160 ++++++++++++++++++++++++ + 7 files changed, 468 insertions(+) + create mode 100644 board/renesas/v3hsk/Kconfig + create mode 100644 board/renesas/v3hsk/MAINTAINERS + create mode 100644 board/renesas/v3hsk/Makefile + create mode 100644 board/renesas/v3hsk/v3hsk.c + create mode 100644 configs/v3hsk_defconfig + create mode 100644 include/configs/v3hsk.h + +diff --git a/arch/arm/cpu/armv8/Kconfig b/arch/arm/cpu/armv8/Kconfig +index a2706a6..7309838 100644 +--- a/arch/arm/cpu/armv8/Kconfig ++++ b/arch/arm/cpu/armv8/Kconfig +@@ -28,6 +28,9 @@ config TARGET_V3MZF + config TARGET_CONDOR + bool "CONDOR board" + ++config TARGET_V3HSK ++ bool "V3HSK board" ++ + endchoice + + config R8A7796X +@@ -64,5 +67,6 @@ source "board/renesas/eagle/Kconfig" + source "board/renesas/v3msk/Kconfig" + source "board/renesas/condor/Kconfig" + source "board/renesas/v3mzf/Kconfig" ++source "board/renesas/v3hsk/Kconfig" + + endif +diff --git a/board/renesas/v3hsk/Kconfig b/board/renesas/v3hsk/Kconfig +new file mode 100644 +index 0000000..2346ee8 +--- /dev/null ++++ b/board/renesas/v3hsk/Kconfig +@@ -0,0 +1,15 @@ ++if TARGET_V3HSK ++ ++config SYS_SOC ++ default "rcar_gen3" ++ ++config SYS_BOARD ++ default "v3hsk" ++ ++config SYS_VENDOR ++ default "renesas" ++ ++config SYS_CONFIG_NAME ++ default "v3hsk" if R8A7798 ++ ++endif +diff --git a/board/renesas/v3hsk/MAINTAINERS b/board/renesas/v3hsk/MAINTAINERS +new file mode 100644 +index 0000000..f9176b5 +--- /dev/null ++++ b/board/renesas/v3hsk/MAINTAINERS +@@ -0,0 +1,6 @@ ++CONDOR BOARD ++M: Cogent Embedded, Inc. ++S: Maintained ++F: board/renesas/v3hsk/ ++F: include/configs/v3hsk.h ++F: configs/v3hsk_defconfig +diff --git a/board/renesas/v3hsk/Makefile b/board/renesas/v3hsk/Makefile +new file mode 100644 +index 0000000..0ac2642 +--- /dev/null ++++ b/board/renesas/v3hsk/Makefile +@@ -0,0 +1,10 @@ ++# ++# board/renesas/v3hsk/Makefile ++# ++# Copyright (C) 2018 Renesas Electronics Corp. ++# Copyright (C) 2018 Cogent Embedded, Inc. ++# ++# SPDX-License-Identifier: GPL-2.0+ ++# ++ ++obj-y := v3hsk.o ../rcar-gen3-common/common.o +diff --git a/board/renesas/v3hsk/v3hsk.c b/board/renesas/v3hsk/v3hsk.c +new file mode 100644 +index 0000000..df61428 +--- /dev/null ++++ b/board/renesas/v3hsk/v3hsk.c +@@ -0,0 +1,263 @@ ++/* ++ * board/renesas/v3hsk/v3hsk.c ++ * This is V3HSK board support. ++ * ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++DECLARE_GLOBAL_DATA_PTR; ++ ++#define SCIF0_MSTP207 (1 << 7) ++#define GETHER_MSTP813 (1 << 13) ++#define RPC_MSTP917 (1 << 17) ++#define SD0_MSTP314 (1 << 14) ++ ++#define SD0CKCR 0xE6150074 ++ ++#define PFC_PMMR 0xe6060000 ++#define PFC_POC1 0xe6060384 ++#define POC_MMC_3V3 0x00fff800 ++ ++void s_init(void) ++{ ++ struct rcar_rwdt *rwdt = (struct rcar_rwdt *)RWDT_BASE; ++ struct rcar_swdt *swdt = (struct rcar_swdt *)SWDT_BASE; ++ ++ /* Watchdog init */ ++ writel(0xA5A5A500, &rwdt->rwtcsra); ++ writel(0xA5A5A500, &swdt->swtcsra); ++} ++ ++int board_early_init_f(void) ++{ ++ int freq; ++ ++ rcar_prr_init(); ++ ++ writel(0xa5a5ffff, 0xe6150900); ++ writel(0x5a5a0000, 0xe6150904); ++ mstp_clrbits_le32(MSTPSR1, SMSTPCR1, 0x02000000); ++ /* SCIF0 */ ++ mstp_clrbits_le32(MSTPSR2, SMSTPCR2, SCIF0_MSTP207); ++ /* SDHI0/MMC */ ++ mstp_clrbits_le32(MSTPSR3, SMSTPCR3, SD0_MSTP314); ++#if defined(CONFIG_RAVB) ++ /* RAVB Ethernet */ ++ mstp_clrbits_le32(MSTPSR8, SMSTPCR8, RAVB_MSTP812); ++#elif defined(CONFIG_SH_ETHER) ++ /* Gigabit Ethernet */ ++ mstp_clrbits_le32(MSTPSR8, SMSTPCR8, GETHER_MSTP813); ++#endif ++ /* QSPI/RPC */ ++ mstp_clrbits_le32(MSTPSR9, SMSTPCR9, RPC_MSTP917); ++ ++ freq = rcar_get_sdhi_config_clk(); ++ writel(freq, SD0CKCR); ++ ++ return 0; ++} ++ ++int board_init(void) ++{ ++ /* address of boot parameters */ ++ gd->bd->bi_boot_params = CONFIG_SYS_TEXT_BASE + 0x50000; ++ ++ /* Init PFC controller */ ++ pinmux_init(); ++#if defined(CONFIG_RAVB) ++ gpio_request(GPIO_GFN_AVB0_AVTP_CAPTURE, NULL); ++ gpio_request(GPIO_GFN_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); - PHY reset gpio */ ++ 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); ++ gpio_request(GPIO_IFN_AVB0_AVTP_CAPTURE, NULL); ++ gpio_request(GPIO_FN_AVB0_AVTP_PPS, NULL); ++ ++ /* 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); ++#elif defined(CONFIG_SH_ETHER) ++ gpio_request(GPIO_FN_GETHER_LINK_A, NULL); ++ gpio_request(GPIO_FN_GETHER_PHY_INT_A, NULL); ++ /* gpio_request(GPIO_FN_GETHER_MAGIC, NULL); - PHY reset gpio */ ++ gpio_request(GPIO_FN_GETHER_MDC_A, NULL); ++ gpio_request(GPIO_FN_GETHER_MDIO_A, NULL); ++ gpio_request(GPIO_FN_GETHER_TXCREFCLK, NULL); ++ gpio_request(GPIO_FN_GETHER_TXCREFCLK_MEGA, NULL); ++ gpio_request(GPIO_FN_GETHER_TD3, NULL); ++ gpio_request(GPIO_FN_GETHER_TD2, NULL); ++ gpio_request(GPIO_FN_GETHER_TD1, NULL); ++ gpio_request(GPIO_FN_GETHER_TD0, NULL); ++ gpio_request(GPIO_FN_GETHER_TXC, NULL); ++ gpio_request(GPIO_FN_GETHER_TX_CTL, NULL); ++ gpio_request(GPIO_FN_GETHER_RD3, NULL); ++ gpio_request(GPIO_FN_GETHER_RD2, NULL); ++ gpio_request(GPIO_FN_GETHER_RD1, NULL); ++ gpio_request(GPIO_FN_GETHER_RD0, NULL); ++ gpio_request(GPIO_FN_GETHER_RXC, NULL); ++ gpio_request(GPIO_FN_GETHER_RX_CTL, NULL); ++ ++ /* PHY_RST */ ++ gpio_request(GPIO_GP_4_22, NULL); ++ gpio_direction_output(GPIO_GP_4_22, 0); ++ mdelay(20); ++ gpio_set_value(GPIO_GP_4_22, 1); ++ udelay(1); ++#endif ++ /* QSPI/RPC */ ++ 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); ++ ++ return 0; ++} ++ ++#if defined(CONFIG_RAVB) ++#define MAHR 0xE68005C0 ++#define MALR 0xE68005C8 ++#elif defined(CONFIG_SH_ETHER) ++#define MAHR 0xE74005C0 ++#define MALR 0xE74005C8 ++#endif ++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); ++#if defined(CONFIG_RAVB) ++ ret = ravb_initialize(bis); ++#elif defined(CONFIG_SH_ETHER) ++ ret = sh_eth_initialize(bis); ++#endif ++ return ret; ++} ++ ++/* V3HSK has KSZ9031RNX */ ++int board_phy_config(struct phy_device *phydev) ++{ ++ return 0; ++} ++ ++int board_mmc_init(bd_t *bis) ++{ ++ int ret = -ENODEV; ++#ifdef CONFIG_SH_SDHI ++ u32 val; ++ ++ /* SDHI2/eMMC */ ++ gpio_request(GPIO_FN_MMC_D0, NULL); ++ gpio_request(GPIO_FN_MMC_D1, NULL); ++ gpio_request(GPIO_FN_MMC_D2, NULL); ++ gpio_request(GPIO_FN_MMC_D3, NULL); ++ gpio_request(GPIO_FN_MMC_D4, NULL); ++ gpio_request(GPIO_FN_MMC_D5, NULL); ++ gpio_request(GPIO_FN_MMC_D6, NULL); ++ gpio_request(GPIO_FN_MMC_D7, NULL); ++ gpio_request(GPIO_FN_MMC_CLK, NULL); ++ gpio_request(GPIO_FN_MMC_CMD, NULL); ++ gpio_request(GPIO_FN_MMC_CD, NULL); ++ gpio_request(GPIO_FN_MMC_WP, NULL); ++ ++ val = readl(PFC_POC1); ++ val &= ~POC_MMC_3V3; /* POC = 1.8V */ ++ writel(~val, PFC_PMMR); ++ writel(val, PFC_POC1); ++ ++ ret = sh_sdhi_init(CONFIG_SYS_SH_SDHI2_BASE, 0, ++ SH_SDHI_QUIRK_64BIT_BUF); ++#endif ++ return ret; ++} ++ ++int dram_init(void) ++{ ++ gd->ram_size = PHYS_SDRAM_1_SIZE; ++ ++ 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; ++} ++ ++const struct rcar_sysinfo sysinfo = { ++ CONFIG_RCAR_BOARD_STRING ++}; ++ ++void reset_cpu(ulong addr) ++{ ++} ++ ++#if defined(CONFIG_DISPLAY_BOARDINFO) ++int checkboard(void) ++{ ++ printf("Board: %s\n", sysinfo.board_string); ++ return 0; ++} ++#endif +diff --git a/configs/v3hsk_defconfig b/configs/v3hsk_defconfig +new file mode 100644 +index 0000000..938ffe9 +--- /dev/null ++++ b/configs/v3hsk_defconfig +@@ -0,0 +1,10 @@ ++CONFIG_ARM=y ++CONFIG_RCAR_GEN3=y ++CONFIG_DM_SERIAL=y ++CONFIG_TARGET_V3HSK=y ++CONFIG_R8A7798=y ++CONFIG_SPL=y ++CONFIG_SH_SDHI=y ++CONFIG_SPI_FLASH=y ++CONFIG_SPI_FLASH_SPANSION=y ++CONFIG_SPI_FLASH_BAR=y +diff --git a/include/configs/v3hsk.h b/include/configs/v3hsk.h +new file mode 100644 +index 0000000..6aa6625 +--- /dev/null ++++ b/include/configs/v3hsk.h +@@ -0,0 +1,160 @@ ++/* ++ * include/configs/v3hsk.h ++ * This file is V3HSK board configuration. ++ * CPU r8a7798. ++ * ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ */ ++ ++#ifndef __V3HSK_H ++#define __V3HSK_H ++ ++#undef DEBUG ++#define CONFIG_RCAR_BOARD_STRING "V3HSK" ++#define CONFIG_RCAR_TARGET_STRING "r8a7798" ++ ++#include "rcar-gen3-common.h" ++ ++//#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 ++ ++#if 0 ++/* 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 ++#else ++/* GETHER */ ++#define CONFIG_NET_MULTI ++#define CONFIG_SH_ETHER ++#define CONFIG_SH_ETHER_USE_PORT 0 ++#define CONFIG_SH_ETHER_PHY_ADDR 0x0 ++#define CONFIG_SH_ETHER_PHY_MODE PHY_INTERFACE_MODE_RGMII_ID ++#define CONFIG_SH_ETHER_ALIGNE_SIZE 64 ++#define CONFIG_SH_ETHER_CACHE_WRITEBACK ++#define CONFIG_SH_ETHER_CACHE_INVALIDATE ++#define CONFIG_PHYLIB ++#define CONFIG_PHY_MICREL ++#define CONFIG_BITBANGMII ++#define CONFIG_BITBANGMII_MULTI ++#endif ++ ++/* 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 ++ ++/* SDHI */ ++#define CONFIG_MMC ++#define CONFIG_CMD_MMC ++#define CONFIG_GENERIC_MMC ++#define CONFIG_SH_SDHI_FREQ 200000000 ++#define CONFIG_SH_SDHI_MMC ++ ++/* ENV setting */ ++#define CONFIG_ENV_OVERWRITE ++#define CONFIG_ENV_SECT_SIZE (256 * 1024) ++#define CONFIG_ENV_SIZE (CONFIG_ENV_SECT_SIZE) ++#define CONFIG_ENV_SIZE_REDUND (CONFIG_ENV_SIZE) ++ ++//#define CONFIG_ENV_IS_IN_MMC ++#define CONFIG_ENV_IS_IN_SPI_FLASH ++ ++#if defined(CONFIG_ENV_IS_IN_MMC) ++/* Environment in eMMC, at the end of 2nd "boot sector" */ ++#define CONFIG_ENV_OFFSET (-CONFIG_ENV_SIZE) ++#define CONFIG_SYS_MMC_ENV_DEV 0 ++#define CONFIG_SYS_MMC_ENV_PART 2 ++#elif defined(CONFIG_ENV_IS_IN_SPI_FLASH) ++/* Environment in QSPI */ ++#define CONFIG_ENV_ADDR 0x700000 ++#define CONFIG_ENV_OFFSET (CONFIG_ENV_ADDR) ++#else ++#define CONFIG_ENV_IS_NOWHERE ++#endif ++ ++/* 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 ++ ++#define CONFIG_EXTRA_ENV_SETTINGS \ ++ "fdt_high=0xffffffffffffffff\0" \ ++ "initrd_high=0xffffffffffffffff\0" \ ++ "ethaddr=2E:11:22:33:44:55\0" ++ ++#define CONFIG_BOOTARGS \ ++ "root=/dev/nfs rw ip=dhcp" ++ ++#define CONFIG_BOOTCOMMAND \ ++ "bootp 0x48080000 Image; tftp 0x48000000 r8a7798-v3hsk.dtb; " \ ++ "booti 0x48080000 - 0x48000000" ++ ++#endif /* __V3HSK_H */ +-- +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 index d912f32..146c392 100644 --- 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 @@ -21,6 +21,7 @@ SRC_URI_append = " \ file://0018-arm-renesas-Add-Renesas-R8A7798-SoC-support.patch \ file://0019-board-renesas-Add-Condor-board.patch \ file://0020-board-renesas-Add-V3MZF-board.patch \ + file://00201-board-renesas-Add-V3HSK-board.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 \ diff --git a/meta-rcar-gen3-adas/recipes-kernel/kernel-module-mmngr/kernel-module-mmngr.bbappend b/meta-rcar-gen3-adas/recipes-kernel/kernel-module-mmngr/kernel-module-mmngr.bbappend index d3991b4..6f05e72 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/kernel-module-mmngr/kernel-module-mmngr.bbappend +++ b/meta-rcar-gen3-adas/recipes-kernel/kernel-module-mmngr/kernel-module-mmngr.bbappend @@ -4,5 +4,6 @@ MMNGR_CFG_eagle = "MMNGR_V3MSK" MMNGR_CFG_v3msk = "MMNGR_V3MSK" MMNGR_CFG_condor = "MMNGR_V3MSK" MMNGR_CFG_v3mzf = "MMNGR_V3MSK" +MMNGR_CFG_v3hsk = "MMNGR_V3MSK" SRC_URI_append = " file://0002-mmngr-Add-V3MSK-board.patch" diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch index 5e17f76..c4c19cb 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch @@ -29,10 +29,11 @@ Videobox Mini V2 board on R8A7797 ES1.0/2.0 SoC Videobox2 board on R8A7795 ES1.x SoC Videobox2 board on R8A7795 SoC Condor board on R8A7798 SoC +V3HSK board on R8A7798 SoC Signed-off-by: Vladimir Barinov --- - arch/arm64/boot/dts/renesas/Makefile | 24 + + arch/arm64/boot/dts/renesas/Makefile | 25 + arch/arm64/boot/dts/renesas/legacy/Makefile | 8 + .../renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts | 1624 +++++++++++++++++++ .../renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts | 441 ++++++ @@ -81,6 +82,7 @@ Signed-off-by: Vladimir Barinov arch/arm64/boot/dts/renesas/r8a7797-v3msk.dts | 345 ++++ arch/arm64/boot/dts/renesas/r8a7797-v3mzf.dts | 424 +++++ arch/arm64/boot/dts/renesas/r8a7798-condor.dts | 963 ++++++++++++ + arch/arm64/boot/dts/renesas/r8a7798-v3hsk.dts | 358 +++++ arch/arm64/boot/dts/renesas/ulcb-kf-cn11.dtsi | 462 ++++++ arch/arm64/boot/dts/renesas/ulcb-kf-most.dtsi | 30 + arch/arm64/boot/dts/renesas/ulcb-kf-sd3.dtsi | 46 + @@ -89,7 +91,7 @@ Signed-off-by: Vladimir Barinov arch/arm64/boot/dts/renesas/ulcb-vb.dtsi | 1610 +++++++++++++++++++ arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi | 1660 ++++++++++++++++++++ arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi | 543 +++++++ - 57 files changed, 20147 insertions(+) + 58 files changed, 20506 insertions(+) create mode 100644 arch/arm64/boot/dts/renesas/legacy/Makefile create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts @@ -138,6 +140,7 @@ Signed-off-by: Vladimir Barinov create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-v3msk.dts create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-v3mzf.dts create mode 100644 arch/arm64/boot/dts/renesas/r8a7798-condor.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7798-v3hsk.dts create mode 100644 arch/arm64/boot/dts/renesas/ulcb-kf-cn11.dtsi create mode 100644 arch/arm64/boot/dts/renesas/ulcb-kf-most.dtsi create mode 100644 arch/arm64/boot/dts/renesas/ulcb-kf-sd3.dtsi @@ -148,10 +151,10 @@ Signed-off-by: Vladimir Barinov create mode 100644 arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile -index f9c71df..6cdbdaf 100644 +index f9c71df..b37dae1 100644 --- a/arch/arm64/boot/dts/renesas/Makefile +++ b/arch/arm64/boot/dts/renesas/Makefile -@@ -6,5 +6,29 @@ dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-xs.dtb +@@ -6,5 +6,30 @@ dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-xs.dtb dtb-$(CONFIG_ARCH_R8A77965) += r8a77965-salvator-x.dtb dtb-$(CONFIG_ARCH_R8A77965) += r8a77965-salvator-xs.dtb @@ -175,6 +178,7 @@ index f9c71df..6cdbdaf 100644 +dtb-$(CONFIG_ARCH_R8A7797) += r8a7797-v3msk-vbm-v2.dtb r8a7797-es1-v3msk-vbm-v2.dtb +dtb-$(CONFIG_ARCH_R8A7797) += r8a7797-v3mzf.dtb +dtb-$(CONFIG_ARCH_R8A7798) += r8a7798-condor.dtb ++dtb-$(CONFIG_ARCH_R8A7798) += r8a7798-v3hsk.dtb + +# ADAS legacy boards +subdir-y := legacy @@ -12576,7 +12580,7 @@ index 0000000..58f82bf +}; diff --git a/arch/arm64/boot/dts/renesas/r8a7797-v3msk.dts b/arch/arm64/boot/dts/renesas/r8a7797-v3msk.dts new file mode 100644 -index 0000000..c1e805d +index 0000000..33c6c0d --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7797-v3msk.dts @@ -0,0 +1,345 @@ @@ -12709,7 +12713,7 @@ index 0000000..c1e805d + + port { + hdmi_con: endpoint { -+ remote-endpoint = <&adv7511_out>; ++ remote-endpoint = <&adv7511_out>; + }; + }; + }; @@ -14324,6 +14328,370 @@ index 0000000..4dd7a28 + }; + }; +}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7798-v3hsk.dts b/arch/arm64/boot/dts/renesas/r8a7798-v3hsk.dts +new file mode 100644 +index 0000000..bf8abe6 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7798-v3hsk.dts +@@ -0,0 +1,358 @@ ++/* ++ * Device Tree Source for the V3H Starter Kit board on r8a7798 ++ * ++ * Copyright (C) 2018 Renesas Electronics Corp. ++ * Copyright (C) 2018 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++/dts-v1/; ++#include "r8a7798.dtsi" ++#include ++ ++/ { ++ model = "Renesas V3H Starter Kit board based on r8a7798"; ++ compatible = "renesas,v3hsk", "renesas,r8a7798"; ++ ++ aliases { ++ serial0 = &scif0; ++ ethernet0 = &gether; ++ }; ++ ++ 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>; ++ }; ++ ++ reserved-memory { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ /* device specific region for Lossy Decompression */ ++ lossy_decompress: linux,lossy_decompress { ++ no-map; ++ reg = <0x00000000 0x6c000000 0x0 0x03000000>; ++ }; ++ ++ /* global autoconfigured region for contiguous allocations */ ++ linux,cma { ++ compatible = "shared-dma-pool"; ++ reusable; ++ reg = <0x00000000 0x6f000000 0x0 0x10000000>; ++ linux,cma-default; ++ }; ++ ++ /* device specific region for contiguous allocations */ ++ linux,multimedia { ++ compatible = "shared-dma-pool"; ++ reusable; ++ reg = <0x00000000 0x7f000000 0x0 0x01000000>; ++ }; ++ }; ++ ++ mmngr { ++ compatible = "renesas,mmngr"; ++ memory-region = <&lossy_decompress>; ++ }; ++ ++ mmngrbuf { ++ compatible = "renesas,mmngrbuf"; ++ }; ++ ++ vspm_if { ++ compatible = "renesas,vspm_if"; ++ }; ++ ++ lvds-encoder { ++ compatible = "thine,thc63lvdm83d"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ lvds_enc_in: endpoint { ++ remote-endpoint = <&du_out_lvds0>; ++ }; ++ }; ++ port@1 { ++ reg = <1>; ++ lvds_enc_out: endpoint { ++ remote-endpoint = <&lvds_in>; ++ }; ++ }; ++ }; ++ }; ++ ++ lvds { ++ compatible = "lvds-connector"; ++ ++ width-mm = <210>; ++ height-mm = <158>; ++ ++ panel-timing { ++ clock-frequency = <65000000>; ++ hactive = <1280>; ++ vactive = <720>; ++ hsync-len = <40>; ++ hfront-porch = <80>; ++ hback-porch = <40>; ++ vfront-porch = <14>; ++ vback-porch = <14>; ++ vsync-len = <4>; ++ }; ++ ++ port { ++ lvds_in: endpoint { ++ remote-endpoint = <&lvds_enc_out>; ++ }; ++ }; ++ }; ++ ++ hdmi-out { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi_con: endpoint { ++ remote-endpoint = <&adv7511_out>; ++ }; ++ }; ++ }; ++ ++ dclkin_p0: clock-out0 { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <148500000>; ++ }; ++ ++ msiof_ref_clk: msiof-ref-clock { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <66666666>; ++ }; ++ ++ vcc_3v3: regulator0 { ++ compatible = "regulator-fixed"; ++ regulator-name = "fixed-VCC3V3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ vcc_vddq_vin0: regulator1 { ++ compatible = "regulator-fixed"; ++ regulator-name = "VCC-VDDQ-VIN0"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++}; ++ ++&du { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ endpoint { ++ remote-endpoint = <&adv7511_in>; ++// remote-endpoint = <&lvds_in>; ++ }; ++ }; ++ }; ++}; ++ ++&extal_clk { ++ clock-frequency = <16666666>; ++}; ++ ++&extalr_clk { ++ clock-frequency = <32768>; ++}; ++ ++&pfc { ++ pinctrl-0 = <&scif_clk_pins>; ++ pinctrl-names = "default"; ++ ++ scif0_pins: scif0 { ++ groups = "scif0_data"; ++ function = "scif0"; ++ }; ++ ++ scif_clk_pins: scif_clk { ++ groups = "scif_clk_b"; ++ function = "scif_clk"; ++ }; ++ ++ i2c0_pins: i2c0 { ++ groups = "i2c0"; ++ function = "i2c0"; ++ }; ++ ++ gether_pins: gether { ++ groups = "gether_mdc_a"; ++ function = "gether"; ++ }; ++ ++ sdhi2_pins_1v8: sdhi2_1v8 { ++ groups = "mmc_data8", "mmc_ctrl", "mmc_ds"; ++ function = "mmc"; ++ power-source = <1800>; ++ }; ++ ++ sdhi2_pins_3v3: sdhi2_3v3 { ++ groups = "mmc_data8", "mmc_ctrl", "mmc_ds"; ++ function = "mmc"; ++ power-source = <3300>; ++ }; ++ ++ tpu_pins: tpu { ++ /* GP1_19 pin; CP4 test point */ ++ groups = "tpu_to0"; ++ function = "tpu"; ++ }; ++}; ++ ++&scif0 { ++ pinctrl-0 = <&scif0_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&scif_clk { ++ clock-frequency = <14745600>; ++ status = "okay"; ++}; ++ ++&sdhi2 { ++ /* used for on-board eMMC */ ++ pinctrl-0 = <&sdhi2_pins_3v3>; ++ pinctrl-1 = <&sdhi2_pins_1v8>; ++ pinctrl-names = "default", "state_uhs"; ++ ++ vmmc-supply = <&vcc_3v3>; ++ vqmmc-supply = <&vcc_vddq_vin0>; ++ mmc-hs200-1_8v; ++ bus-width = <8>; ++ non-removable; ++ status = "okay"; ++}; ++ ++&i2c0 { ++ pinctrl-0 = <&i2c0_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++ clock-frequency = <400000>; ++ ++ hdmi@39{ ++ compatible = "adi,adv7511w"; ++ #sound-dai-cells = <0>; ++ reg = <0x39>; ++ interrupt-parent = <&gpio1>; ++ interrupts = <20 IRQ_TYPE_LEVEL_LOW>; ++ ++ adi,input-depth = <8>; ++ adi,input-colorspace = "rgb"; ++ adi,input-clock = "1x"; ++ adi,input-style = <1>; ++ adi,input-justification = "evenly"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ adv7511_in: endpoint { ++ remote-endpoint = <&lvds_enc_out>; ++ }; ++ }; ++ port@1 { ++ reg = <1>; ++ adv7511_out: endpoint { ++ remote-endpoint = <&hdmi_con>; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&wdt0 { ++ timeout-sec = <60>; ++ status = "okay"; ++}; ++ ++&cmt0 { ++ status = "okay"; ++}; ++ ++&cmt1 { ++ status = "okay"; ++}; ++ ++&cmt2 { ++ status = "okay"; ++}; ++ ++&cmt3 { ++ status = "okay"; ++}; ++ ++&tpu { ++ pinctrl-0 = <&tpu_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++}; ++ ++&tmu0 { ++ status = "okay"; ++}; ++ ++&tmu1 { ++ status = "okay"; ++}; ++ ++&tmu2 { ++ status = "okay"; ++}; ++ ++&tmu3 { ++ status = "okay"; ++}; ++ ++&tmu4 { ++ status = "okay"; ++}; ++ ++&gether { ++ pinctrl-0 = <&gether_pins>; ++ pinctrl-names = "default"; ++ renesas,no-ether-link; ++ phy-handle = <&gether_phy>; ++ status = "okay"; ++ phy-gpios = <&gpio4 23 GPIO_ACTIVE_LOW>; ++ phy-reset-gpios = <&gpio4 22 GPIO_ACTIVE_LOW>; ++ ++ gether_phy: ethernet-phy@0 { ++ reg = <0>; ++ interrupt-parent = <&gpio4>; ++ interrupts = <23 IRQ_TYPE_LEVEL_LOW>; ++ max-speed = <1000>; ++ }; ++}; diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf-cn11.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf-cn11.dtsi new file mode 100644 index 0000000..a87c38b diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3hsk.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3hsk.cfg new file mode 100644 index 0000000..9558ce6 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3hsk.cfg @@ -0,0 +1,40 @@ +CONFIG_ARCH_R8A7798=y +CONFIG_CAN=y +CONFIG_CAN_PEAK_USB=y +CONFIG_CAN_BCM=y +CONFIG_CAN_RAW=y +CONFIG_CAN_DEV=y +CONFIG_CAN_CALC_BITTIMING=y +CONFIG_CAN_RCAR=y +CONFIG_CAN_RCAR_CANFD=y +CONFIG_DUMMY=y +CONFIG_DRM_I2C_ADV7511=y +CONFIG_GPIO_MAX732X=y +CONFIG_GPIO_MAX732X_IRQ=y +CONFIG_GPIO_PCA953X=y +CONFIG_GPIO_PCA953X_IRQ=y +CONFIG_VIDEO_ADV_DEBUG=y +CONFIG_VIDEO_RCAR_VIN_LEGACY=y +CONFIG_VIDEO_RCAR_CSI2_LEGACY=y +# CONFIG_VIDEO_RCAR_VIN is not set +# CONFIG_VIDEO_RCAR_CSI2 is not set +CONFIG_SOC_CAMERA=y +CONFIG_SOC_CAMERA_SCALE_CROP=y +CONFIG_SOC_CAMERA_PLATFORM=y +CONFIG_SOC_CAMERA_MAX9286=y +CONFIG_SOC_CAMERA_TI9X4=y +CONFIG_SOC_CAMERA_OV106XX=y +CONFIG_VIDEO_RENESAS_IMR=y +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_INPUT_UINPUT=y +CONFIG_TOUCHSCREEN_PROPERTIES=y +CONFIG_HID_MULTITOUCH=y +CONFIG_SERIAL_SH_SCI_DMA=y +CONFIG_UIO=y +CONFIG_SPI_SLAVE=y +CONFIG_SPI_SLAVE_TIME=y +CONFIG_SPI_SLAVE_SYSTEM_CONTROL=y +CONFIG_SENSORS_LM63=y +CONFIG_SH_ETH=y +CONFIG_BLK_DEV_NVME=m +CONFIG_SATA_ACARD_AHCI=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 index b73f77e..45eb436 100644 --- 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 @@ -4,6 +4,7 @@ COMPATIBLE_MACHINE_eagle = "eagle" COMPATIBLE_MACHINE_v3msk = "v3msk" COMPATIBLE_MACHINE_condor = "condor" COMPATIBLE_MACHINE_v3mzf = "v3mzf" +COMPATIBLE_MACHINE_v3hsk = "v3hsk" SRC_URI_append = " \ ${@bb.utils.contains('MACHINE_FEATURES', 'h3ulcb-had', ' file://hyperflash.cfg', '', d)} \ @@ -92,6 +93,7 @@ SRC_URI_append_eagle = " file://eagle.cfg" SRC_URI_append_v3msk = " file://v3msk.cfg" SRC_URI_append_condor = " file://condor.cfg" SRC_URI_append_v3mzf = " file://v3mzf.cfg" +SRC_URI_append_v3hsk = " file://v3hsk.cfg" KERNEL_DEVICETREE_append_h3ulcb = " \ renesas/r8a7795-es1-h3ulcb-view.dtb \ @@ -148,3 +150,7 @@ KERNEL_DEVICETREE_append_v3mzf = " \ KERNEL_DEVICETREE_append_condor = " \ renesas/r8a7798-condor.dtb \ " + +KERNEL_DEVICETREE_append_v3hsk = " \ + renesas/r8a7798-v3hsk.dtb \ +" -- cgit 1.2.3-korg From 773ddddbbb9562540f95bf9516c3183eb492af5d Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Wed, 14 Feb 2018 11:22:05 +0300 Subject: V3M Eagle: remove du_pins htat are not used Remove dependencey on RGB pins since theare are not used on Eagle board. The LVDS interface is used. --- .../linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch index c4c19cb..dec4b09 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch @@ -10259,7 +10259,7 @@ new file mode 100644 index 0000000..db17b03 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7797-eagle.dts -@@ -0,0 +1,605 @@ +@@ -0,0 +1,588 @@ +/* + * Device Tree Source for the Eagle board + * @@ -10406,8 +10406,6 @@ index 0000000..db17b03 +}; + +&du { -+ pinctrl-0 = <&du_pins>; -+ pinctrl-names = "default"; + status = "okay"; + + ports { @@ -10460,11 +10458,6 @@ index 0000000..db17b03 + groups = "avb0_mdc"; + function = "avb0"; + }; -+ -+ du_pins: du { -+ groups = "du_rgb666", "du_sync", "du_clk_out_0", "du_disp"; -+ function = "du"; -+ }; +}; + +&scif0 { -- cgit 1.2.3-korg From 40525ae2c50c8b641b68a32795dd424e28fb0a56 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Wed, 14 Feb 2018 11:38:08 +0300 Subject: Fix typo This fixes the typo during patch update --- .../linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch index dec4b09..c82c95e 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch @@ -10259,7 +10259,7 @@ new file mode 100644 index 0000000..db17b03 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7797-eagle.dts -@@ -0,0 +1,588 @@ +@@ -0,0 +1,598 @@ +/* + * Device Tree Source for the Eagle board + * -- cgit 1.2.3-korg From 5f2ae3356b9645cb0a4b0d3e3af843f32c72cf8f Mon Sep 17 00:00:00 2001 From: Andrey Dolnikov Date: Wed, 14 Feb 2018 13:34:28 +0300 Subject: Enable thermal sensor driver for V3M --- meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3msk.cfg | 1 + 1 file changed, 1 insertion(+) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3msk.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3msk.cfg index ab640b3..a3c72d5 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3msk.cfg +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3msk.cfg @@ -35,3 +35,4 @@ CONFIG_SPI_SLAVE=y CONFIG_SPI_SLAVE_TIME=y CONFIG_SPI_SLAVE_SYSTEM_CONTROL=y CONFIG_SENSORS_LM63=y +CONFIG_RCAR_THERMAL=y -- cgit 1.2.3-korg From 60344d4f8d7605b5533441fbfc0cbb2723eaf9d9 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Thu, 15 Feb 2018 23:08:29 +0300 Subject: V3MZF: add eMMC in kernel --- .../0040-arm64-dts-renesas-add-ADAS-boards.patch | 50 +++++++++++++++++++--- 1 file changed, 44 insertions(+), 6 deletions(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch index c82c95e..d27f4ab 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch @@ -66,7 +66,7 @@ Signed-off-by: Vladimir Barinov .../arm64/boot/dts/renesas/r8a7796-m3ulcb-view.dts | 286 ++++ .../boot/dts/renesas/r8a7796-salvator-x-view.dts | 317 ++++ .../boot/dts/renesas/r8a7797-eagle-function.dts | 62 + - arch/arm64/boot/dts/renesas/r8a7797-eagle.dts | 605 +++++++ + arch/arm64/boot/dts/renesas/r8a7797-eagle.dts | 598 +++++++ .../dts/renesas/r8a7797-es1-eagle-function.dts | 17 + arch/arm64/boot/dts/renesas/r8a7797-es1-eagle.dts | 17 + .../boot/dts/renesas/r8a7797-es1-v3msk-kf.dts | 17 + @@ -80,7 +80,7 @@ Signed-off-by: Vladimir Barinov arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts | 507 ++++++ arch/arm64/boot/dts/renesas/r8a7797-v3msk-view.dts | 297 ++++ arch/arm64/boot/dts/renesas/r8a7797-v3msk.dts | 345 ++++ - arch/arm64/boot/dts/renesas/r8a7797-v3mzf.dts | 424 +++++ + arch/arm64/boot/dts/renesas/r8a7797-v3mzf.dts | 444 ++++++ arch/arm64/boot/dts/renesas/r8a7798-condor.dts | 963 ++++++++++++ arch/arm64/boot/dts/renesas/r8a7798-v3hsk.dts | 358 +++++ arch/arm64/boot/dts/renesas/ulcb-kf-cn11.dtsi | 462 ++++++ @@ -91,7 +91,7 @@ Signed-off-by: Vladimir Barinov arch/arm64/boot/dts/renesas/ulcb-vb.dtsi | 1610 +++++++++++++++++++ arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi | 1660 ++++++++++++++++++++ arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi | 543 +++++++ - 58 files changed, 20506 insertions(+) + 58 files changed, 20519 insertions(+) create mode 100644 arch/arm64/boot/dts/renesas/legacy/Makefile create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts @@ -10256,7 +10256,7 @@ index 0000000..82d6513 +}; diff --git a/arch/arm64/boot/dts/renesas/r8a7797-eagle.dts b/arch/arm64/boot/dts/renesas/r8a7797-eagle.dts new file mode 100644 -index 0000000..db17b03 +index 0000000..a982db9 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7797-eagle.dts @@ -0,0 +1,598 @@ @@ -12924,10 +12924,10 @@ index 0000000..33c6c0d +}; diff --git a/arch/arm64/boot/dts/renesas/r8a7797-v3mzf.dts b/arch/arm64/boot/dts/renesas/r8a7797-v3mzf.dts new file mode 100644 -index 0000000..7926d2e +index 0000000..48895dd --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7797-v3mzf.dts -@@ -0,0 +1,424 @@ +@@ -0,0 +1,462 @@ +/* + * Device Tree Source for the V3MZF board + * @@ -13053,6 +13053,24 @@ index 0000000..7926d2e + #clock-cells = <0>; + clock-frequency = <66666666>; + }; ++ ++ vcc_3v3: regulator0 { ++ compatible = "regulator-fixed"; ++ regulator-name = "fixed-VCC3V3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ vcc_vddq_vin0: regulator1 { ++ compatible = "regulator-fixed"; ++ regulator-name = "VCC-VDDQ-VIN0"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; +}; + +&avb { @@ -13307,6 +13325,12 @@ index 0000000..7926d2e + groups = "scif_clk_b"; + function = "scif_clk"; + }; ++ ++ sdhi2_pins_3v3: sdhi2_3v3 { ++ groups = "mmc_data8", "mmc_ctrl"; ++ function = "mmc"; ++ power-source = <3300>; ++ }; +}; + +&scif0 { @@ -13321,6 +13345,20 @@ index 0000000..7926d2e + status = "okay"; +}; + ++&sdhi2 { ++ /* used for on-board eMMC */ ++ pinctrl-0 = <&sdhi2_pins_3v3>; ++ pinctrl-names = "default"; ++ ++ vmmc-supply = <&vcc_3v3>; ++ vqmmc-supply = <&vcc_vddq_vin0>; ++ no-1-8-v; ++ cap-mmc-highspeed; ++ bus-width = <8>; ++ non-removable; ++ status = "okay"; ++}; ++ +&vin0 { + status = "okay"; + -- cgit 1.2.3-korg From 630c6b51f35ac186937319a9e4761cfc3f83175c Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Fri, 16 Feb 2018 21:22:32 +0300 Subject: V3H: Add VideoBoxMini and VideoBoxMini V2 boards This adds V3HSK exapsion boards --- .../0040-arm64-dts-renesas-add-ADAS-boards.patch | 610 ++++++++++++++++++++- .../recipes-kernel/linux/linux-renesas/v3hsk.cfg | 1 + .../linux/linux-renesas_4.9.bbappend | 2 + 3 files changed, 607 insertions(+), 6 deletions(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch index d27f4ab..99313d6 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch @@ -30,10 +30,12 @@ Videobox2 board on R8A7795 ES1.x SoC Videobox2 board on R8A7795 SoC Condor board on R8A7798 SoC V3HSK board on R8A7798 SoC +Videobox Mini board on R8A7798 SoC +Videobox Mini V2 board on R8A7798 SoC Signed-off-by: Vladimir Barinov --- - arch/arm64/boot/dts/renesas/Makefile | 25 + + arch/arm64/boot/dts/renesas/Makefile | 27 + arch/arm64/boot/dts/renesas/legacy/Makefile | 8 + .../renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts | 1624 +++++++++++++++++++ .../renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts | 441 ++++++ @@ -80,8 +82,10 @@ Signed-off-by: Vladimir Barinov arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts | 507 ++++++ arch/arm64/boot/dts/renesas/r8a7797-v3msk-view.dts | 297 ++++ arch/arm64/boot/dts/renesas/r8a7797-v3msk.dts | 345 ++++ - arch/arm64/boot/dts/renesas/r8a7797-v3mzf.dts | 444 ++++++ + arch/arm64/boot/dts/renesas/r8a7797-v3mzf.dts | 462 ++++++ arch/arm64/boot/dts/renesas/r8a7798-condor.dts | 963 ++++++++++++ + .../boot/dts/renesas/r8a7798-v3hsk-vbm-v2.dts | 73 + + arch/arm64/boot/dts/renesas/r8a7798-v3hsk-vbm.dts | 505 ++++++ arch/arm64/boot/dts/renesas/r8a7798-v3hsk.dts | 358 +++++ arch/arm64/boot/dts/renesas/ulcb-kf-cn11.dtsi | 462 ++++++ arch/arm64/boot/dts/renesas/ulcb-kf-most.dtsi | 30 + @@ -91,7 +95,7 @@ Signed-off-by: Vladimir Barinov arch/arm64/boot/dts/renesas/ulcb-vb.dtsi | 1610 +++++++++++++++++++ arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi | 1660 ++++++++++++++++++++ arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi | 543 +++++++ - 58 files changed, 20519 insertions(+) + 60 files changed, 21117 insertions(+) create mode 100644 arch/arm64/boot/dts/renesas/legacy/Makefile create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts @@ -140,6 +144,8 @@ Signed-off-by: Vladimir Barinov create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-v3msk.dts create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-v3mzf.dts create mode 100644 arch/arm64/boot/dts/renesas/r8a7798-condor.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7798-v3hsk-vbm-v2.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7798-v3hsk-vbm.dts create mode 100644 arch/arm64/boot/dts/renesas/r8a7798-v3hsk.dts create mode 100644 arch/arm64/boot/dts/renesas/ulcb-kf-cn11.dtsi create mode 100644 arch/arm64/boot/dts/renesas/ulcb-kf-most.dtsi @@ -151,10 +157,10 @@ Signed-off-by: Vladimir Barinov create mode 100644 arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile -index f9c71df..b37dae1 100644 +index f9c71df..6219e6f 100644 --- a/arch/arm64/boot/dts/renesas/Makefile +++ b/arch/arm64/boot/dts/renesas/Makefile -@@ -6,5 +6,30 @@ dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-xs.dtb +@@ -6,5 +6,32 @@ dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-xs.dtb dtb-$(CONFIG_ARCH_R8A77965) += r8a77965-salvator-x.dtb dtb-$(CONFIG_ARCH_R8A77965) += r8a77965-salvator-xs.dtb @@ -179,6 +185,8 @@ index f9c71df..b37dae1 100644 +dtb-$(CONFIG_ARCH_R8A7797) += r8a7797-v3mzf.dtb +dtb-$(CONFIG_ARCH_R8A7798) += r8a7798-condor.dtb +dtb-$(CONFIG_ARCH_R8A7798) += r8a7798-v3hsk.dtb ++dtb-$(CONFIG_ARCH_R8A7798) += r8a7798-v3hsk-vbm.dtb ++dtb-$(CONFIG_ARCH_R8A7798) += r8a7798-v3hsk-vbm-v2.dtb + +# ADAS legacy boards +subdir-y := legacy @@ -12924,7 +12932,7 @@ index 0000000..33c6c0d +}; diff --git a/arch/arm64/boot/dts/renesas/r8a7797-v3mzf.dts b/arch/arm64/boot/dts/renesas/r8a7797-v3mzf.dts new file mode 100644 -index 0000000..48895dd +index 0000000..246e71d --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7797-v3mzf.dts @@ -0,0 +1,462 @@ @@ -14359,6 +14367,596 @@ index 0000000..4dd7a28 + }; + }; +}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7798-v3hsk-vbm-v2.dts b/arch/arm64/boot/dts/renesas/r8a7798-v3hsk-vbm-v2.dts +new file mode 100644 +index 0000000..56d4253 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7798-v3hsk-vbm-v2.dts +@@ -0,0 +1,73 @@ ++/* ++ * Device Tree Source for the V3HSK Videobox Mini board V2 on r8a7798 ++ * ++ * Copyright (C) 2018 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 "r8a7798-v3hsk-vbm.dts" ++ ++/ { ++ model = "Renesas V3HSK Videobox Mini board V2 based on r8a7798"; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led5 { ++ label = "board:status"; ++ gpios = <&gpio2 26 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "heartbeat"; ++ }; ++ }; ++}; ++ ++&gpio0 { ++ can1_stby { ++ gpio-hog; ++ gpios = <21 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "CAN1STBY"; ++ }; ++}; ++ ++&pfc { ++ msiof1_pins: msiof1 { ++ groups = "msiof1_clk", "msiof1_txd", "msiof1_rxd"; ++ function = "msiof1"; ++ }; ++ ++ msiof2_pins: msiof2 { ++ groups = "msiof2_clk", "msiof2_sync", "msiof2_txd", "msiof2_rxd"; ++ function = "msiof2"; ++ }; ++}; ++ ++&scif3 { ++ /* pin conflict with msiof2 */ ++ /* set R240 and remove R241 before enabling */ ++ status = "disabled"; ++}; ++ ++&msiof1 { ++ pinctrl-0 = <&msiof1_pins>; ++ pinctrl-names = "default"; ++ cs-gpios = <&gpio3 3 0>; ++ ++ status = "okay"; ++ spidev@0 { ++ compatible = "renesas,sh-msiof"; ++ reg = <0>; ++ spi-max-frequency = <66666666>; ++ }; ++}; ++ ++&msiof2 { ++ pinctrl-0 = <&msiof2_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++ slave; ++}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7798-v3hsk-vbm.dts b/arch/arm64/boot/dts/renesas/r8a7798-v3hsk-vbm.dts +new file mode 100644 +index 0000000..16b2616 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7798-v3hsk-vbm.dts +@@ -0,0 +1,505 @@ ++/* ++ * Device Tree Source for the V3HSK Videobox Mini board on r8a7798 ++ * ++ * Copyright (C) 2018 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 "r8a7798-v3hsk.dts" ++ ++/ { ++ model = "Renesas V3HSK Videobox Mini board based on r8a7798"; ++ ++ aliases { ++ serial1 = &scif3; ++ }; ++}; ++ ++&canfd { ++ pinctrl-0 = <&canfd0_pins &canfd1_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ channel0 { ++ status = "okay"; ++ }; ++ ++ channel1 { ++ status = "okay"; ++ }; ++}; ++ ++&csi2_41 { ++ status = "okay"; ++ ++ virtual,channel { ++ csi2_vc0 { ++ data,type = "ycbcr422"; ++ receive,vc = <0>; ++ }; ++ csi2_vc1 { ++ data,type = "ycbcr422"; ++ receive,vc = <1>; ++ }; ++ csi2_vc2 { ++ data,type = "ycbcr422"; ++ receive,vc = <2>; ++ }; ++ csi2_vc3 { ++ data,type = "ycbcr422"; ++ receive,vc = <3>; ++ }; ++ }; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi2_41_ep: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ csi-rate = <300>; ++ }; ++ }; ++}; ++ ++&i2c1 { ++ pinctrl-0 = <&i2c1_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ ++ clock-frequency = <400000>; ++ ++ i2cswitch1: i2c-switch@74 { ++ compatible = "nxp,pca9548"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x74>; ++ reset-gpios = <&gpio2 28 GPIO_ACTIVE_LOW>; ++ ++ i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ ++ ov106xx@0 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x60>; ++ ++ port@0 { ++ ov106xx_in0: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin4ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ ov106xx_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; ++ }; ++ }; ++ }; ++ ++ ov106xx@1 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x61>; ++ ++ port@0 { ++ ov106xx_in1: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin5ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ ov106xx_ti9x4_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep1>; ++ }; ++ }; ++ }; ++ ++ ov106xx@2 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x62>; ++ ++ port@0 { ++ ov106xx_in2: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin6ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ ov106xx_ti9x4_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep2>; ++ }; ++ }; ++ }; ++ ++ ov106xx@3 { ++ compatible = "ovti,ov106xx"; ++ reg = <0x63>; ++ ++ port@0 { ++ ov106xx_in3: endpoint { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&vin7ep0>; ++ }; ++ }; ++ port@1 { ++ ov106xx_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ ov106xx_ti9x4_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep3>; ++ }; ++ }; ++ }; ++ ++ max9286@0 { ++ compatible = "maxim,max9286"; ++ reg = <0x2c>; ++ maxim,links = <4>; ++ maxim,lanes = <4>; ++ maxim,resetb-gpio = <1>; ++ maxim,fsync-mode = "automatic"; ++ maxim,timeout = <100>; ++ ++ POC0-gpios = <&gpio_exp_6c 8 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_6c 9 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_6c 10 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_6c 11 GPIO_ACTIVE_HIGH>; ++ ++ port@0 { ++ max9286_des0ep0: endpoint@0 { ++ max9271-addr = <0x50>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ max9286_des0ep1: endpoint@1 { ++ max9271-addr = <0x51>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ max9286_des0ep2: endpoint@2 { ++ max9271-addr = <0x52>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ max9286_des0ep3: endpoint@3 { ++ max9271-addr = <0x53>; ++ dvp-order = <1>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ max9286_csi0ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ }; ++ ++ ti9x4@0 { ++ compatible = "ti,ti9x4"; ++ reg = <0x3a>; ++ ti,links = <4>; ++ ti,lanes = <4>; ++ ti,forwarding-mode = "round-robin"; ++ ti,cable-mode = "coax"; ++ POC0-gpios = <&gpio_exp_6c 8 GPIO_ACTIVE_HIGH>; ++ POC1-gpios = <&gpio_exp_6c 9 GPIO_ACTIVE_HIGH>; ++ POC2-gpios = <&gpio_exp_6c 10 GPIO_ACTIVE_HIGH>; ++ POC3-gpios = <&gpio_exp_6c 11 GPIO_ACTIVE_HIGH>; ++ ++ port@0 { ++ ti9x4_des0ep0: endpoint@0 { ++ ti9x3-addr = <0x0c>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ ti9x4_des0ep1: endpoint@1 { ++ ti9x3-addr = <0x0d>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ ti9x4_des0ep2: endpoint@2 { ++ ti9x3-addr = <0x0e>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ ti9x4_des0ep3: endpoint@3 { ++ ti9x3-addr = <0x0f>; ++ dvp-order = <0>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ ti9x4_csi0ep0: endpoint { ++ csi-rate = <700>; ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ }; ++ }; ++ ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ ++ gpio_exp_6c: gpio@6c { ++ compatible = "maxim,max7325"; ++ reg = <0x6c>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ virq { ++ gpio-hog; ++ gpios = <5 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "VIRQ"; ++ }; ++ des_cfg { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "CNFG0"; ++ }; ++ pwr_shdn { ++ gpio-hog; ++ gpios = <14 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "PWR_SHDN"; ++ }; ++ des_shdn { ++ gpio-hog; ++ gpios = <13 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "Des_SHDN"; ++ }; ++ fpdl_shdn { ++ gpio-hog; ++ gpios = <15 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "FPDL_SHDN"; ++ }; ++ }; ++ }; ++ ++ i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ ++ /* fan node - lm96063 */ ++ fan_ctrl: lm96063@4c { ++ compatible = "lm96163"; ++ reg = <0x4c>; ++ }; ++ }; ++ }; ++}; ++ ++&gpio2 { ++ can0_load { ++ gpio-hog; ++ gpios = <16 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "can0_120R_load"; ++ }; ++ ++ can0stby { ++ gpio-hog; ++ gpios = <27 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "CAN0STBY"; ++ }; ++ ++ can1_load { ++ gpio-hog; ++ gpios = <29 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "can1_120R_load"; ++ }; ++ ++ wake_pin_7 { ++ gpio-hog; ++ gpios = <8 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "WAKE INPUT PIN 7"; ++ }; ++ ++ wake_pin_8 { ++ gpio-hog; ++ gpios = <9 GPIO_ACTIVE_HIGH>; ++ input; ++ line-name = "WAKE INPUT PIN 8"; ++ }; ++}; ++ ++&pfc { ++ canfd0_pins: canfd0 { ++ groups = "canfd0_data_a"; ++ function = "canfd0"; ++ }; ++ ++ canfd1_pins: canfd1 { ++ groups = "canfd1_data"; ++ function = "canfd1"; ++ }; ++ ++ i2c1_pins: i2c1 { ++ groups = "i2c1"; ++ function = "i2c1"; ++ }; ++ ++ scif3_pins: scif3 { ++ groups = "scif3_data"; ++ function = "scif3"; ++ }; ++}; ++ ++&scif3 { ++ pinctrl-0 = <&scif3_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&vin4 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin4ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ }; ++ port@1 { ++ csi0ep0: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ vin4_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ vin4_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin5 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin5ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <1>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in1>; ++ }; ++ }; ++ port@1 { ++ csi0ep1: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ vin5_max9286_des0ep1: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep1>; ++ }; ++ vin5_ti9x4_des0ep1: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep1>; ++ }; ++ }; ++ }; ++}; ++ ++&vin6 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin6ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <2>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in2>; ++ }; ++ }; ++ port@1 { ++ csi0ep2: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ vin6_max9286_des0ep2: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep2>; ++ }; ++ vin6_ti9x4_des0ep2: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep2>; ++ }; ++ }; ++ }; ++}; ++ ++&vin7 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ vin7ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <3>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in3>; ++ }; ++ }; ++ port@1 { ++ csi0ep3: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ vin7_max9286_des0ep3: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep3>; ++ }; ++ vin7_ti9x4_des0ep3: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep3>; ++ }; ++ }; ++ }; ++}; diff --git a/arch/arm64/boot/dts/renesas/r8a7798-v3hsk.dts b/arch/arm64/boot/dts/renesas/r8a7798-v3hsk.dts new file mode 100644 index 0000000..bf8abe6 diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3hsk.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3hsk.cfg index 9558ce6..7f04bb1 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3hsk.cfg +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3hsk.cfg @@ -35,6 +35,7 @@ CONFIG_SPI_SLAVE=y CONFIG_SPI_SLAVE_TIME=y CONFIG_SPI_SLAVE_SYSTEM_CONTROL=y CONFIG_SENSORS_LM63=y +CONFIG_RCAR_THERMAL=y CONFIG_SH_ETH=y CONFIG_BLK_DEV_NVME=m CONFIG_SATA_ACARD_AHCI=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 index 45eb436..60a97e5 100644 --- 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 @@ -153,4 +153,6 @@ KERNEL_DEVICETREE_append_condor = " \ KERNEL_DEVICETREE_append_v3hsk = " \ renesas/r8a7798-v3hsk.dtb \ + renesas/r8a7798-v3hsk-vbm.dtb \ + renesas/r8a7798-v3hsk-vbm-v2.dtb \ " -- cgit 1.2.3-korg From 781b63a5f56a13a7211979ab3f90d40b4c376fc9 Mon Sep 17 00:00:00 2001 From: Andrey Gusakov Date: Wed, 7 Mar 2018 17:12:46 +0300 Subject: VB2: enable USB23 (labeled "USB2") on H3 ES20 On ES1.1 this port is USB3.0. On ES2.0 this port is USB2.0 --- .../0040-arm64-dts-renesas-add-ADAS-boards.patch | 36 +++++++++++++++++++--- 1 file changed, 31 insertions(+), 5 deletions(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch index 99313d6..9bdc9d0 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch @@ -1,4 +1,4 @@ -From 9872a94a414d6d94423f52d59cb09cdb64cf2930 Mon Sep 17 00:00:00 2001 +From ed78d27af12a2637fe9ae17e96a9af35a046d486 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Fri, 14 Jul 2017 15:05:42 +0300 Subject: [PATCH] arm64: dts: renesas: add ADAS boards @@ -60,7 +60,7 @@ Signed-off-by: Vladimir Barinov .../arm64/boot/dts/renesas/r8a7795-h3ulcb-had.dtsi | 215 +++ arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts | 39 + arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vb.dts | 68 + - arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vb2.dts | 68 + + arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vb2.dts | 94 ++ arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vbm.dts | 26 + .../arm64/boot/dts/renesas/r8a7795-h3ulcb-view.dts | 544 +++++++ .../boot/dts/renesas/r8a7795-salvator-x-view.dts | 550 +++++++ @@ -95,7 +95,7 @@ Signed-off-by: Vladimir Barinov arch/arm64/boot/dts/renesas/ulcb-vb.dtsi | 1610 +++++++++++++++++++ arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi | 1660 ++++++++++++++++++++ arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi | 543 +++++++ - 60 files changed, 21117 insertions(+) + 60 files changed, 21143 insertions(+) create mode 100644 arch/arm64/boot/dts/renesas/legacy/Makefile create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts @@ -8323,10 +8323,10 @@ index 0000000..330bba2 +}; diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vb2.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vb2.dts new file mode 100644 -index 0000000..e862d3e +index 0000000..726a2a6 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vb2.dts -@@ -0,0 +1,68 @@ +@@ -0,0 +1,94 @@ +/* + * Device Tree Source for the H3ULCB Videobox board V2 on r8a7795 + * @@ -8355,6 +8355,13 @@ index 0000000..e862d3e + }; +}; + ++&pfc { ++ usb3_pins: usb3 { ++ groups = "usb3"; ++ function = "usb3"; ++ }; ++}; ++ +&du { + ports { + port@2 { @@ -8392,9 +8399,28 @@ index 0000000..e862d3e + }; +}; + ++&usb2_phy3 { ++ pinctrl-0 = <&usb3_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++}; ++ ++&ehci3 { ++ status = "okay"; ++}; ++ ++&ohci3 { ++ status = "okay"; ++}; ++ +&hsusb0 { + status = "okay"; +}; ++ ++&hsusb3 { ++ status = "okay"; ++}; diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vbm.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-vbm.dts new file mode 100644 index 0000000..87f1889 -- cgit 1.2.3-korg From 9681c03f421a3def0bd21ff87a40293b7f38e09c Mon Sep 17 00:00:00 2001 From: Andrey Dolnikov Date: Fri, 9 Mar 2018 17:21:11 +0300 Subject: Add V3H VIP devices support. --- ...0107-V3H-device-tree-Add-VIP-devices-IRQs.patch | 189 +++++++++++++++++++++ .../recipes-kernel/linux/linux-renesas/condor.cfg | 1 + .../recipes-kernel/linux/linux-renesas/v3hsk.cfg | 1 + .../linux/linux-renesas_4.9.bbappend | 6 + 4 files changed, 197 insertions(+) create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0107-V3H-device-tree-Add-VIP-devices-IRQs.patch (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0107-V3H-device-tree-Add-VIP-devices-IRQs.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0107-V3H-device-tree-Add-VIP-devices-IRQs.patch new file mode 100644 index 0000000..7198428 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0107-V3H-device-tree-Add-VIP-devices-IRQs.patch @@ -0,0 +1,189 @@ +From 2ef84c77a4c536dc1996c2e6ca2dc3cfa743fe7e Mon Sep 17 00:00:00 2001 +From: Andrey Dolnikov +Date: Fri, 9 Mar 2018 15:50:29 +0300 +Subject: [PATCH] V3H device tree: Add VIP devices IRQs. + +--- + arch/arm64/boot/dts/renesas/r8a7798.dtsi | 110 ++++++++++++++++++++++++++++--- + 1 file changed, 100 insertions(+), 10 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/r8a7798.dtsi b/arch/arm64/boot/dts/renesas/r8a7798.dtsi +index 6412a24..b8b0665 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7798.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a7798.dtsi +@@ -1627,72 +1627,162 @@ + rse; + }; + +- disp { ++ vip_disp_status { + compatible = "generic-uio"; + reg = <0 0xe7a00000 0 0x10000>; ++ interrupts = ; + clocks = <&cpg CPG_MOD 101>; + power-domains = <&sysc R8A7798_PD_A3VIP>; + }; + +- umf { ++ vip_disp_error { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a00000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 101>; ++ power-domains = <&sysc R8A7798_PD_A3VIP>; ++ }; ++ ++ vip_umf_status { + compatible = "generic-uio"; + reg = <0 0xe7a10000 0 0x10000>; ++ interrupts = ; + clocks = <&cpg CPG_MOD 102>; + power-domains = <&sysc R8A7798_PD_A3VIP1>; + }; + +- smd_ps { ++ vip_umf_error { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a10000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 102>; ++ power-domains = <&sysc R8A7798_PD_A3VIP1>; ++ }; ++ ++ vip_smd_ps_status { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a20000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 1102>; ++ power-domains = <&sysc R8A7798_PD_A3VIP1>; ++ }; ++ ++ vip_smd_ps_error { + compatible = "generic-uio"; + reg = <0 0xe7a20000 0 0x10000>; ++ interrupts = ; + clocks = <&cpg CPG_MOD 1102>; + power-domains = <&sysc R8A7798_PD_A3VIP1>; + }; + +- smd_est { ++ vip_smd_est_status { + compatible = "generic-uio"; + reg = <0 0xe7a30000 0 0x10000>; ++ interrupts = ; + clocks = <&cpg CPG_MOD 1101>; + power-domains = <&sysc R8A7798_PD_A3VIP1>; + }; + +- smd_post { ++ vip_smd_est_error { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a30000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 1101>; ++ power-domains = <&sysc R8A7798_PD_A3VIP1>; ++ }; ++ ++ vip_smd_post_status { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a40000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 1100>; ++ power-domains = <&sysc R8A7798_PD_A3VIP1>; ++ }; ++ ++ vip_smd_post_error { + compatible = "generic-uio"; + reg = <0 0xe7a40000 0 0x10000>; ++ interrupts = ; + clocks = <&cpg CPG_MOD 1100>; + power-domains = <&sysc R8A7798_PD_A3VIP1>; + }; + +- cle0 { ++ vip_cle0_status { + compatible = "generic-uio"; + reg = <0 0xe7a50000 0 0x10000>; ++ interrupts = ; + clocks = <&cpg CPG_MOD 1004>; + power-domains = <&sysc R8A7798_PD_A3VIP2>; + }; + +- cle1 { ++ vip_cle0_error { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a50000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 1004>; ++ power-domains = <&sysc R8A7798_PD_A3VIP2>; ++ }; ++ ++ vip_cle1_status { + compatible = "generic-uio"; + reg = <0 0xe7a60000 0 0x10000>; ++ interrupts = ; + clocks = <&cpg CPG_MOD 1003>; + power-domains = <&sysc R8A7798_PD_A3VIP2>; + }; + +- cle2 { ++ vip_cle1_error { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a60000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 1003>; ++ power-domains = <&sysc R8A7798_PD_A3VIP2>; ++ }; ++ ++ vip_cle2_status { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a70000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 1002>; ++ power-domains = <&sysc R8A7798_PD_A3VIP2>; ++ }; ++ ++ vip_cle2_error { + compatible = "generic-uio"; + reg = <0 0xe7a70000 0 0x10000>; ++ interrupts = ; + clocks = <&cpg CPG_MOD 1002>; + power-domains = <&sysc R8A7798_PD_A3VIP2>; + }; + +- cle3 { ++ vip_cle3_status { + compatible = "generic-uio"; + reg = <0 0xe7a80000 0 0x10000>; ++ interrupts = ; + clocks = <&cpg CPG_MOD 1001>; + power-domains = <&sysc R8A7798_PD_A3VIP2>; + }; + +- cle4 { ++ vip_cle3_erorr { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a80000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 1001>; ++ power-domains = <&sysc R8A7798_PD_A3VIP2>; ++ }; ++ ++ vip_cle4_status { ++ compatible = "generic-uio"; ++ reg = <0 0xe7a90000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 1000>; ++ power-domains = <&sysc R8A7798_PD_A3VIP2>; ++ }; ++ ++ vip_cle4_error { + compatible = "generic-uio"; + reg = <0 0xe7a90000 0 0x10000>; ++ interrupts = ; + clocks = <&cpg CPG_MOD 1000>; + power-domains = <&sysc R8A7798_PD_A3VIP2>; + }; +-- +2.7.4 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/condor.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/condor.cfg index 9b2a6a9..7322e21 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/condor.cfg +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/condor.cfg @@ -27,6 +27,7 @@ CONFIG_TOUCHSCREEN_PROPERTIES=y CONFIG_HID_MULTITOUCH=y CONFIG_SERIAL_SH_SCI_DMA=y CONFIG_UIO=y +CONFIG_UIO_PDRV_GENIRQ=m CONFIG_SH_ETH=y CONFIG_BLK_DEV_NVME=m CONFIG_SATA_ACARD_AHCI=y diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3hsk.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3hsk.cfg index 7f04bb1..3713001 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3hsk.cfg +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3hsk.cfg @@ -31,6 +31,7 @@ CONFIG_TOUCHSCREEN_PROPERTIES=y CONFIG_HID_MULTITOUCH=y CONFIG_SERIAL_SH_SCI_DMA=y CONFIG_UIO=y +CONFIG_UIO_PDRV_GENIRQ=m CONFIG_SPI_SLAVE=y CONFIG_SPI_SLAVE_TIME=y CONFIG_SPI_SLAVE_SYSTEM_CONTROL=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 index 60a97e5..61a87e5 100644 --- 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 @@ -84,6 +84,7 @@ SRC_URI_append = " \ file://0104-media-vsp1-extend-DRM-VSP1-interface.patch \ file://0105-media-rcar-imr-IMR-driver-updates-for-raw-DL.patch \ file://0106-media-rcar-imr-Add-RSE-support.patch \ + file://0107-V3H-device-tree-Add-VIP-devices-IRQs.patch \ " SRC_URI_append_h3ulcb = " file://ulcb.cfg" @@ -156,3 +157,8 @@ KERNEL_DEVICETREE_append_v3hsk = " \ renesas/r8a7798-v3hsk-vbm.dtb \ renesas/r8a7798-v3hsk-vbm-v2.dtb \ " + +# V3H VIP devices +KERNEL_MODULE_AUTOLOAD_r8a7798 += "uio_pdrv_genirq" +KERNEL_MODULE_PROBECONF_r8a7798 += "uio_pdrv_genirq" +module_conf_uio_pdrv_genirq_r8a7798 = 'options uio_pdrv_genirq of_id="generic-uio"' -- cgit 1.2.3-korg From 60f32331c2479edeca99d2d63bf328772a0ee482 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Tue, 13 Mar 2018 15:22:27 +0300 Subject: AR0132: add FLIP fix --- .../recipes-kernel/linux/linux-renesas/0030-Gen3-LVDS-cameras.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') 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 index a680635..fe71743 100644 --- 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 @@ -1463,7 +1463,7 @@ index 0000000..bafa193 +{0x302E, AR0132_PLL_Pre_Clk_Div}, +{0x3030, AR0132_PLL_Multiplier}, +{0x3032, 0x0000}, // SCALING_MODE = 0 -+{0x3040, 0xC000}, // READ_MODE = read_mode_vert_flip | read_mode_horiz_mirror ++{0x3040, 0x0000}, // READ_MODE = read_mode_vert_flip | read_mode_horiz_mirror +{0x3044, 0x0404}, // Dark Control = 1028 +{0x30A6, 0x0001}, // Y Odd Inc. (A) = 1 +{0x30A8, 0x0001}, // Y Odd Inc. (B) = 1 -- cgit 1.2.3-korg From dd5445c6db1a39c12d81d8cac8dc35ae84dddad7 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Thu, 15 Mar 2018 13:39:48 +0300 Subject: SPI: fix perfromance and fix SPI slave packets loss - this fixes SPI performance when small chunks are used during transfer under heavy cpu load - fix spi slave<->master packets loss under heavy load --- .../linux-renesas/0001-spi-sh-msiof-fixes.patch | 16 +- .../0086-spi-sh-msiof-Add-slave-mode-support.patch | 325 ++++++++++++++++++--- 2 files changed, 305 insertions(+), 36 deletions(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') 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 index d8806ba..411d0ee 100644 --- 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 @@ -3,7 +3,8 @@ From: Vladimir Barinov Date: Sun, 15 May 2016 21:53:13 +0300 Subject: [PATCH] spi: sh-msiof: fixes -speed up polling of CTR register +speed up polling of CTR register and allow scheduling instead of +busy loop Signed-off-by: Vladimir Barinov --- @@ -19,15 +20,24 @@ index d096f5a..6817304 100644 sh_msiof_write(p, CTR, data); - for (k = 100; k > 0; k--) { -+ for (k = 1000; k > 0; k--) { ++ for (k = 100000; k > 0; k--) { if ((sh_msiof_read(p, CTR) & mask) == set) break; - udelay(10); -+ udelay(1); ++ usleep_range(1, 2); } return k > 0 ? 0 : -ETIMEDOUT; +@@ -295,7 +295,7 @@ static void sh_msiof_spi_reset_regs(struct sh_msiof_spi_priv *p) + if (!(sh_msiof_read(p, CTR) & mask)) + break; + +- udelay(10); ++ usleep_range(10, 20); + } + } + -- 1.9.1 diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0086-spi-sh-msiof-Add-slave-mode-support.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0086-spi-sh-msiof-Add-slave-mode-support.patch index af15bae..ef0b74b 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0086-spi-sh-msiof-Add-slave-mode-support.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0086-spi-sh-msiof-Add-slave-mode-support.patch @@ -1,29 +1,32 @@ -From 383d0d23b9292dab56a2fdf5f6fecf898be6d142 Mon Sep 17 00:00:00 2001 +From cf9e4784f3bde3e4749163384f27450ddffe746c Mon Sep 17 00:00:00 2001 From: Hisashi Nakamura -Date: Mon, 28 Jul 2014 14:47:56 +0900 -Subject: [PATCH 4/7] spi: sh-msiof: Add slave mode support +Date: Mon, 22 May 2017 15:11:43 +0200 +Subject: [PATCH] spi: sh-msiof: Add slave mode support Add slave mode support to the MSIOF driver, in both PIO and DMA mode. For now this only supports the transmission of messages with a size that is known in advance. +Signed-off-by: Vladimir Barinov Signed-off-by: Hisashi Nakamura Signed-off-by: Hiromitsu Yamasaki [geert: Timeout handling cleanup, spi core integration, cancellation, rewording] Signed-off-by: Geert Uytterhoeven Acked-by: Rob Herring +Signed-off-by: Mark Brown --- - Documentation/devicetree/bindings/spi/sh-msiof.txt | 2 + - drivers/spi/spi-sh-msiof.c | 79 ++++++++++++++------ - 2 files changed, 60 insertions(+), 21 deletions(-) + Documentation/devicetree/bindings/spi/sh-msiof.txt | 2 + + drivers/spi/spi-sh-msiof.c | 193 +++++++++------------ + include/linux/spi/sh_msiof.h | 4 +- + 3 files changed, 90 insertions(+), 109 deletions(-) diff --git a/Documentation/devicetree/bindings/spi/sh-msiof.txt b/Documentation/devicetree/bindings/spi/sh-msiof.txt -index c2b6251..74ee3cd 100644 +index f1dbc15..9e43f30 100644 --- a/Documentation/devicetree/bindings/spi/sh-msiof.txt +++ b/Documentation/devicetree/bindings/spi/sh-msiof.txt -@@ -33,6 +33,8 @@ Optional properties: +@@ -34,6 +34,8 @@ Optional properties: specifiers, one for transmission, and one for reception. - dma-names : Must contain a list of two DMA names, "tx" and "rx". @@ -33,19 +36,20 @@ index c2b6251..74ee3cd 100644 Must contain one of the following values: 0 (no bit delay) diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c -index 3281dc7..3b87024 100644 +index 13fd706..916377b 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c -@@ -3,7 +3,7 @@ +@@ -3,7 +3,8 @@ * * Copyright (C) 2016-2017 Renesas Electronics Corporation * Copyright (c) 2009 Magnus Damm - * Copyright (C) 2014 Glider bvba ++ * Copyright (C) 2014 Renesas Electronics Corporation + * Copyright (C) 2014-2017 Glider bvba * * 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 -@@ -35,7 +35,6 @@ +@@ -35,7 +36,6 @@ #include @@ -53,7 +57,7 @@ index 3281dc7..3b87024 100644 struct sh_msiof_chipdata { u16 tx_fifo_size; u16 rx_fifo_size; -@@ -62,6 +61,7 @@ struct sh_msiof_spi_priv { +@@ -62,6 +62,7 @@ struct sh_msiof_spi_priv { void *rx_dma_page; dma_addr_t tx_dma_addr; dma_addr_t rx_dma_addr; @@ -61,7 +65,101 @@ index 3281dc7..3b87024 100644 unsigned int quirks; }; -@@ -712,6 +712,33 @@ static int sh_msiof_spi_stop(struct sh_msiof_spi_priv *p, void *rx_buf) +@@ -402,18 +403,21 @@ static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p, + tmp |= lsb_first << MDR1_BITLSB_SHIFT; + tmp |= sh_msiof_spi_get_dtdl_and_syncdl(p); + if (p->quirks & TRANSFER_WORKAROUND_H3WS10) { +- if (p->mode == SPI_MSIOF_MASTER) { ++ if (!spi_controller_is_slave(p->master)) { + tmp &= ~MDR1_DTDL_MASK; + tmp |= 0 << MDR1_DTDL_SHIFT; + } + } + if (p->quirks & TRANSFER_WORKAROUND_H3WS11) { +- if (p->mode == SPI_MSIOF_MASTER) { ++ if (!spi_controller_is_slave(p->master)) { + tmp &= ~MDR1_DTDL_MASK; + tmp |= 1 << MDR1_DTDL_SHIFT; + } + } +- if (p->mode == SPI_MSIOF_MASTER) { ++ ++ if (spi_controller_is_slave(p->master)) { ++ sh_msiof_write(p, TMDR1, tmp | TMDR1_PCON); ++ } else { + if (p->cs == 1) + tmp |= MDR1_SYNCCH_SS1; + else if (p->cs == 2) +@@ -421,16 +425,15 @@ static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p, + else + tmp &= ~MDR1_SYNCCH_MASK; + sh_msiof_write(p, TMDR1, tmp | MDR1_TRMD | TMDR1_PCON); +- } else +- sh_msiof_write(p, TMDR1, tmp | TMDR1_PCON); ++ } + if (p->quirks & TRANSFER_WORKAROUND_H3WS10) { +- if (p->mode == SPI_MSIOF_MASTER) { ++ if (!spi_controller_is_slave(p->master)) { + tmp &= ~MDR1_DTDL_MASK; + tmp |= 2 << MDR1_DTDL_SHIFT; + } + } + if (p->quirks & TRANSFER_WORKAROUND_H3WS11) { +- if (p->mode == SPI_MSIOF_MASTER) { ++ if (!spi_controller_is_slave(p->master)) { + tmp &= ~MDR1_DTDL_MASK; + tmp |= 1 << MDR1_DTDL_SHIFT; + } +@@ -443,7 +446,7 @@ static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p, + + tmp = 0; + if (p->quirks & TRANSFER_WORKAROUND_H3WS10) { +- if (p->mode == SPI_MSIOF_MASTER) { ++ if (!spi_controller_is_slave(p->master)) { + tmp |= 0 << CTR_TSCKIZ_POL_SHIFT; + tmp |= 0 << CTR_RSCKIZ_POL_SHIFT; + } else { +@@ -680,10 +683,11 @@ static int sh_msiof_prepare_message(struct spi_master *master, + + static int sh_msiof_spi_start(struct sh_msiof_spi_priv *p, void *rx_buf) + { ++ bool slave = spi_controller_is_slave(p->master); + int ret = 0; + + /* setup clock and rx/tx signals */ +- if (p->mode == SPI_MSIOF_MASTER) ++ if (!slave) + ret = sh_msiof_modify_ctr_wait(p, 0, CTR_TSCKE); + if (rx_buf && !ret) + ret = sh_msiof_modify_ctr_wait(p, 0, CTR_RXE); +@@ -691,7 +695,7 @@ static int sh_msiof_spi_start(struct sh_msiof_spi_priv *p, void *rx_buf) + ret = sh_msiof_modify_ctr_wait(p, 0, CTR_TXE); + + /* start by setting frame bit */ +- if (!ret && p->mode == SPI_MSIOF_MASTER) ++ if (!ret && !slave) + ret = sh_msiof_modify_ctr_wait(p, 0, CTR_TFSE); + + return ret; +@@ -699,21 +703,50 @@ static int sh_msiof_spi_start(struct sh_msiof_spi_priv *p, void *rx_buf) + + static int sh_msiof_spi_stop(struct sh_msiof_spi_priv *p, void *rx_buf) + { ++ bool slave = spi_controller_is_slave(p->master); + int ret = 0; + + /* shut down frame, rx/tx and clock signals */ +- if (p->mode == SPI_MSIOF_MASTER) ++ if (!slave) + ret = sh_msiof_modify_ctr_wait(p, CTR_TFSE, 0); + if (!ret) + ret = sh_msiof_modify_ctr_wait(p, CTR_TXE, 0); + if (rx_buf && !ret) + ret = sh_msiof_modify_ctr_wait(p, CTR_RXE, 0); +- if (!ret && p->mode == SPI_MSIOF_MASTER) ++ if (!ret && !slave) + ret = sh_msiof_modify_ctr_wait(p, CTR_TSCKE, 0); + return ret; } @@ -74,16 +172,17 @@ index 3281dc7..3b87024 100644 + return 0; +} + -+static int sh_msiof_wait_for_completion(struct sh_msiof_spi_priv *p) ++static int sh_msiof_wait_for_completion(struct sh_msiof_spi_priv *p, ++ struct completion *done) +{ + if (spi_controller_is_slave(p->master)) { -+ if (wait_for_completion_interruptible(&p->done) || ++ if (wait_for_completion_interruptible(done) || + p->slave_aborted) { + dev_dbg(&p->pdev->dev, "interrupted\n"); + return -EINTR; + } + } else { -+ if (!wait_for_completion_timeout(&p->done, HZ)) { ++ if (!wait_for_completion_timeout(done, HZ)) { + dev_err(&p->pdev->dev, "timeout\n"); + return -ETIMEDOUT; + } @@ -95,7 +194,17 @@ index 3281dc7..3b87024 100644 static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p, void (*tx_fifo)(struct sh_msiof_spi_priv *, const void *, int, int), -@@ -747,6 +774,7 @@ static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p, +@@ -724,9 +757,6 @@ static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p, + { + int fifo_shift; + int ret; +- unsigned long timeout; +- +- timeout = (p->mode == SPI_MSIOF_MASTER) ? HZ : MAX_SCHEDULE_TIMEOUT; + + /* limit maximum word transfer to rx/tx fifo size */ + if (tx_buf) +@@ -749,6 +779,7 @@ static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p, tx_fifo(p, tx_buf, words, fifo_shift); reinit_completion(&p->done); @@ -103,7 +212,41 @@ index 3281dc7..3b87024 100644 ret = sh_msiof_spi_start(p, rx_buf); if (ret) { -@@ -867,6 +895,7 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, +@@ -757,21 +788,9 @@ static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p, + } + + /* wait for tx fifo to be emptied / rx fifo to be filled */ +- if (p->mode == SPI_MSIOF_MASTER) +- ret = wait_for_completion_timeout(&p->done, timeout); +- else { +- ret = wait_for_completion_interruptible_timeout( +- &p->done, timeout); +- if (ret == -ERESTARTSYS) { +- dev_err(&p->pdev->dev, "PIO mode. Task interrupt\n"); +- goto stop_reset; +- } +- } +- if (!ret) { +- dev_err(&p->pdev->dev, "PIO timeout\n"); +- ret = -ETIMEDOUT; ++ ret = sh_msiof_wait_for_completion(p, &p->done); ++ if (ret) + goto stop_reset; +- } + + /* read rx fifo */ + if (rx_buf) +@@ -817,9 +836,6 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, + struct dma_async_tx_descriptor *desc_tx = NULL, *desc_rx = NULL; + dma_cookie_t cookie; + int ret; +- unsigned long timeout; +- +- timeout = (p->mode == SPI_MSIOF_MASTER) ? HZ : MAX_SCHEDULE_TIMEOUT; + + /* First prepare and submit the DMA request(s), as this may fail */ + if (rx) { +@@ -869,6 +885,7 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, reinit_completion(&p->done); reinit_completion(&p->done_dma_tx); reinit_completion(&p->done_dma_rx); @@ -111,23 +254,121 @@ index 3281dc7..3b87024 100644 /* Now start DMA */ if (rx) -@@ -1205,8 +1234,14 @@ static struct sh_msiof_spi_info *sh_msiof_spi_parse_dt(struct device *dev) +@@ -884,64 +901,23 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, + + /* wait for Tx/Rx DMA completion */ + if (tx) { +- if (p->mode == SPI_MSIOF_MASTER) +- ret = wait_for_completion_timeout( +- &p->done_dma_tx, timeout); +- else { +- ret = wait_for_completion_interruptible_timeout( +- &p->done_dma_tx, timeout); +- if (ret == -ERESTARTSYS) { +- dev_err(&p->pdev->dev, "Tx DMA. Task interrupt\n"); +- goto stop_reset; +- } +- } +- if (!ret) { +- dev_err(&p->pdev->dev, "Tx DMA timeout\n"); +- ret = -ETIMEDOUT; ++ ret = sh_msiof_wait_for_completion(p, &p->done_dma_tx); ++ if (ret) + goto stop_reset; +- } ++ + if (!rx) { + ier_bits = IER_TEOFE; + sh_msiof_write(p, IER, ier_bits); + + /* wait for tx fifo to be emptied */ +- if (p->mode == SPI_MSIOF_MASTER) +- ret = wait_for_completion_timeout( +- &p->done, timeout); +- else { +- ret = wait_for_completion_interruptible_timeout( +- &p->done, timeout); +- if (ret == -ERESTARTSYS) { +- dev_err(&p->pdev->dev, +- "Tx fifo to be emptied. Task interrupt\n"); +- goto stop_reset; +- } +- } +- if (!ret) { +- dev_err(&p->pdev->dev, +- "Tx fifo to be emptied timeout\n"); +- ret = -ETIMEDOUT; ++ if (sh_msiof_wait_for_completion(p, &p->done)) + goto stop_reset; +- } + } + } + if (rx) { +- if (p->mode == SPI_MSIOF_MASTER) +- ret = wait_for_completion_timeout( +- &p->done_dma_rx, timeout); +- else { +- ret = wait_for_completion_interruptible_timeout( +- &p->done_dma_rx, timeout); +- if (ret == -ERESTARTSYS) { +- dev_err(&p->pdev->dev, "Rx DMA. Task interrupt\n"); +- goto stop_reset; +- } +- } +- if (!ret) { +- dev_err(&p->pdev->dev, "Rx DMA timeout\n"); +- ret = -ETIMEDOUT; ++ ret = sh_msiof_wait_for_completion(p, &p->done_dma_rx); ++ if (ret) + goto stop_reset; +- } + } + + sh_msiof_write(p, IER, 0); +@@ -1040,7 +1016,7 @@ static int sh_msiof_transfer_one(struct spi_master *master, + sh_msiof_spi_reset_regs(p); + + /* setup clocks (clock already enabled in chipselect()) */ +- if (p->mode == SPI_MSIOF_MASTER) ++ if (!spi_controller_is_slave(p->master)) + sh_msiof_spi_set_clk_regs(p, clk_get_rate(p->clk), t->speed_hz); + + while (master->dma_tx && len > 15) { +@@ -1071,7 +1047,7 @@ static int sh_msiof_transfer_one(struct spi_master *master, + copy32(p->tx_dma_page, tx_buf, l / 4); + + #ifdef CONFIG_SPI_SH_MSIOF_TRANSFER_SYNC_DEBUG +- if (p->mode == SPI_MSIOF_MASTER) ++ if (!spi_controller_is_slave(p->master)) + msleep(TRANSFAR_SYNC_DELAY); + #endif /* CONFIG_SPI_SH_MSIOF_TRANSFER_SYNC_DEBUG */ + +@@ -1148,9 +1124,8 @@ static int sh_msiof_transfer_one(struct spi_master *master, + words = len / bytes_per_word; + + while (words > 0) { +- + #ifdef CONFIG_SPI_SH_MSIOF_TRANSFER_SYNC_DEBUG +- if (p->mode == SPI_MSIOF_MASTER) ++ if (!spi_controller_is_slave(p->master)) + msleep(TRANSFAR_SYNC_DELAY); + #endif /* CONFIG_SPI_SH_MSIOF_TRANSFER_SYNC_DEBUG */ + +@@ -1209,8 +1184,12 @@ static struct sh_msiof_spi_info *sh_msiof_spi_parse_dt(struct device *dev) if (!info) return NULL; -+ if (of_property_read_bool(np, "slave")) -+ info->mode = SPI_MSIOF_SLAVE; -+ else -+ info->mode = SPI_MSIOF_MASTER; ++ info->mode = of_property_read_bool(np, "spi-slave") ? MSIOF_SPI_SLAVE ++ : MSIOF_SPI_MASTER; + /* Parse the MSIOF properties */ - of_property_read_u32(np, "num-cs", &num_cs); -+ if (info->mode == SPI_MSIOF_MASTER) ++ if (info->mode == MSIOF_SPI_MASTER) + of_property_read_u32(np, "num-cs", &num_cs); of_property_read_u32(np, "renesas,tx-fifo-size", &info->tx_fifo_override); of_property_read_u32(np, "renesas,rx-fifo-size", -@@ -1214,10 +1249,6 @@ static struct sh_msiof_spi_info *sh_msiof_spi_parse_dt(struct device *dev) +@@ -1218,11 +1197,6 @@ static struct sh_msiof_spi_info *sh_msiof_spi_parse_dt(struct device *dev) of_property_read_u32(np, "renesas,dtdl", &info->dtdl); of_property_read_u32(np, "renesas,syncdl", &info->syncdl); @@ -135,10 +376,11 @@ index 3281dc7..3b87024 100644 - info->mode = SPI_MSIOF_SLAVE; - else - info->mode = SPI_MSIOF_MASTER; - +- info->num_chipselect = num_cs; -@@ -1368,6 +1399,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) + return info; +@@ -1372,6 +1346,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) struct spi_master *master; const struct sh_msiof_chipdata *chipdata; const struct of_device_id *of_id; @@ -146,7 +388,7 @@ index 3281dc7..3b87024 100644 struct sh_msiof_spi_priv *p; struct clk *ref_clk; u32 clk_rate = 0; -@@ -1375,32 +1407,36 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) +@@ -1379,32 +1354,35 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) int ret; const struct soc_device_attribute *attr; @@ -175,11 +417,12 @@ index 3281dc7..3b87024 100644 - if (!p->info) { + if (!info) { dev_err(&pdev->dev, "failed to obtain device info\n"); - ret = -ENXIO; - goto err1; +- ret = -ENXIO; +- goto err1; ++ return -ENXIO; } -+ if (info->mode == SPI_MSIOF_SLAVE) ++ if (info->mode == MSIOF_SPI_SLAVE) + master = spi_alloc_slave(&pdev->dev, + sizeof(struct sh_msiof_spi_priv)); + else @@ -197,7 +440,7 @@ index 3281dc7..3b87024 100644 attr = soc_device_match(rcar_quirks_match); if (attr) p->quirks = (uintptr_t)attr->data; -@@ -1458,6 +1494,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) +@@ -1462,6 +1440,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) master->num_chipselect = p->info->num_chipselect; master->setup = sh_msiof_spi_setup; master->prepare_message = sh_msiof_prepare_message; @@ -205,5 +448,21 @@ index 3281dc7..3b87024 100644 master->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 32); master->auto_runtime_pm = true; master->transfer_one = sh_msiof_transfer_one; +diff --git a/include/linux/spi/sh_msiof.h b/include/linux/spi/sh_msiof.h +index f723aa4..f74b581 100644 +--- a/include/linux/spi/sh_msiof.h ++++ b/include/linux/spi/sh_msiof.h +@@ -2,8 +2,8 @@ + #define __SPI_SH_MSIOF_H__ + + enum { +- SPI_MSIOF_MASTER, +- SPI_MSIOF_SLAVE, ++ MSIOF_SPI_MASTER, ++ MSIOF_SPI_SLAVE, + }; + + struct sh_msiof_spi_info { -- -1.7.10.4 +1.9.1 + -- cgit 1.2.3-korg From dcafcaa269d12d38c2374c594f7d6992b035a645 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Thu, 15 Mar 2018 13:46:21 +0300 Subject: V3MSK VBM and V3MZF: update spi slave after fixes 1) Use h/w spi chip-select frame instead gpio 2) update filed name for spi slave device --- .../0040-arm64-dts-renesas-add-ADAS-boards.patch | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch index 9bdc9d0..65e6f8e 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch @@ -11753,7 +11753,7 @@ index 0000000..dbbd3d2 + +&pfc { + msiof1_pins: msiof1 { -+ groups = "msiof1_clk", "msiof1_txd", "msiof1_rxd"; ++ groups = "msiof1_clk", "msiof1_sync", "msiof1_txd", "msiof1_rxd"; + function = "msiof1"; + }; + @@ -11772,7 +11772,6 @@ index 0000000..dbbd3d2 +&msiof1 { + pinctrl-0 = <&msiof1_pins>; + pinctrl-names = "default"; -+ cs-gpios = <&gpio3 3 0>; + + status = "okay"; + spidev@0 { @@ -11787,7 +11786,7 @@ index 0000000..dbbd3d2 + pinctrl-names = "default"; + + status = "okay"; -+ slave; ++ spi-slave; +}; diff --git a/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts new file mode 100644 @@ -13293,12 +13292,11 @@ index 0000000..246e71d +&msiof2 { + pinctrl-0 = <&msiof2_pins>; + pinctrl-names = "default"; -+ cs-gpios = <&gpio2 4 0>; + + status = "okay"; + spidev@0 { + compatible = "renesas,sh-msiof"; -+ reg = <0>; ++ reg = <1>; + spi-max-frequency = <66666666>; + }; +}; @@ -13308,7 +13306,7 @@ index 0000000..246e71d + pinctrl-names = "default"; + + status = "okay"; -+ slave; ++ spi-slave; +}; + +&pfc { @@ -13341,7 +13339,7 @@ index 0000000..246e71d + }; + + msiof2_pins: msiof2 { -+ groups = "msiof2_clk", "msiof2_txd", "msiof2_rxd"; ++ groups = "msiof2_clk", "msiof2_txd", "msiof2_rxd", "msiof2_ss1"; + function = "msiof2"; + }; + @@ -14436,7 +14434,7 @@ index 0000000..56d4253 + +&pfc { + msiof1_pins: msiof1 { -+ groups = "msiof1_clk", "msiof1_txd", "msiof1_rxd"; ++ groups = "msiof1_clk", "msiof1_sync", "msiof1_txd", "msiof1_rxd"; + function = "msiof1"; + }; + @@ -14455,7 +14453,6 @@ index 0000000..56d4253 +&msiof1 { + pinctrl-0 = <&msiof1_pins>; + pinctrl-names = "default"; -+ cs-gpios = <&gpio3 3 0>; + + status = "okay"; + spidev@0 { @@ -14470,7 +14467,7 @@ index 0000000..56d4253 + pinctrl-names = "default"; + + status = "okay"; -+ slave; ++ spi-slave; +}; diff --git a/arch/arm64/boot/dts/renesas/r8a7798-v3hsk-vbm.dts b/arch/arm64/boot/dts/renesas/r8a7798-v3hsk-vbm.dts new file mode 100644 -- cgit 1.2.3-korg From 92a74efc3600aa31a19ce51435da5223ba43ae78 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Fri, 16 Mar 2018 12:53:27 +0300 Subject: Build fix for previouse commit --- .../linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch index 65e6f8e..cff692c 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch @@ -11706,7 +11706,7 @@ new file mode 100644 index 0000000..dbbd3d2 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm-v2.dts -@@ -0,0 +1,82 @@ +@@ -0,0 +1,81 @@ +/* + * Device Tree Source for the V3MSK Videobox Mini board V2 on r8a7797 + * @@ -12960,7 +12960,7 @@ new file mode 100644 index 0000000..246e71d --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7797-v3mzf.dts -@@ -0,0 +1,462 @@ +@@ -0,0 +1,461 @@ +/* + * Device Tree Source for the V3MZF board + * @@ -14396,7 +14396,7 @@ new file mode 100644 index 0000000..56d4253 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7798-v3hsk-vbm-v2.dts -@@ -0,0 +1,73 @@ +@@ -0,0 +1,72 @@ +/* + * Device Tree Source for the V3HSK Videobox Mini board V2 on r8a7798 + * -- cgit 1.2.3-korg From b3fe8f278bcafa67262ce8c9d9f555c200be4c2e Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Tue, 20 Mar 2018 19:58:45 +0300 Subject: V3MZF: update dts file to use CS1 in hardware --- .../linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch index cff692c..46f5477 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch @@ -12960,7 +12960,7 @@ new file mode 100644 index 0000000..246e71d --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7797-v3mzf.dts -@@ -0,0 +1,461 @@ +@@ -0,0 +1,462 @@ +/* + * Device Tree Source for the V3MZF board + * @@ -13294,6 +13294,7 @@ index 0000000..246e71d + pinctrl-names = "default"; + + status = "okay"; ++ num-cs = <2>; + spidev@0 { + compatible = "renesas,sh-msiof"; + reg = <1>; -- cgit 1.2.3-korg From facc465f679b7058c2afd953ccdaaec959c832ab Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Wed, 21 Mar 2018 10:33:56 +0300 Subject: ULCB-KF: ULCB has cs2000 with 100khz i2c clk ULCB has CS2000 onboard with maximum allowed i2c clk rate 100khz. Hence the parent (KF) must follow this restriction. --- .../linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch index 46f5477..c45344b 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch @@ -15906,7 +15906,7 @@ new file mode 100644 index 0000000..447cfc3 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi -@@ -0,0 +1,1458 @@ +@@ -0,0 +1,1456 @@ +/* + * Device Tree Source for the ULCB Kingfisher board + * @@ -16341,8 +16341,6 @@ index 0000000..447cfc3 +}; + +&i2c2 { -+ clock-frequency = <400000>; -+ + gpio_ext_74: pca9539@74 { + compatible = "nxp,pca9539"; + reg = <0x74>; -- cgit 1.2.3-korg From 3ff7e5c8369180d3e399a67a2170700fe902d5a5 Mon Sep 17 00:00:00 2001 From: Andrey Gusakov Date: Mon, 26 Mar 2018 15:11:28 +0300 Subject: VB2: fix can2 and can3 coldstart probe fail Reset pins of external mcp251x can adapters are driven by i2c gpio extender pins which is probed later than mcp251x. So at probe time reset pins are low causing probe fail. Add reset-gpio support to driver. Adjust VB2 dtb. --- .../0040-arm64-dts-renesas-add-ADAS-boards.patch | 38 +++++------- .../0108-can-mcp251x-add-reset-gpio-support.patch | 72 ++++++++++++++++++++++ .../linux/linux-renesas_4.9.bbappend | 1 + 3 files changed, 87 insertions(+), 24 deletions(-) create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0108-can-mcp251x-add-reset-gpio-support.patch (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch index c45344b..bd872ac 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch @@ -1,4 +1,4 @@ -From ed78d27af12a2637fe9ae17e96a9af35a046d486 Mon Sep 17 00:00:00 2001 +From fbc9403a97c602447751b49aa9d4d9cea56fef4c Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Fri, 14 Jul 2017 15:05:42 +0300 Subject: [PATCH] arm64: dts: renesas: add ADAS boards @@ -78,24 +78,24 @@ Signed-off-by: Vladimir Barinov arch/arm64/boot/dts/renesas/r8a7797-es1-v3msk.dts | 17 + arch/arm64/boot/dts/renesas/r8a7797-es1.dtsi | 116 ++ arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts | 520 ++++++ - .../boot/dts/renesas/r8a7797-v3msk-vbm-v2.dts | 82 + + .../boot/dts/renesas/r8a7797-v3msk-vbm-v2.dts | 81 + arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts | 507 ++++++ arch/arm64/boot/dts/renesas/r8a7797-v3msk-view.dts | 297 ++++ arch/arm64/boot/dts/renesas/r8a7797-v3msk.dts | 345 ++++ arch/arm64/boot/dts/renesas/r8a7797-v3mzf.dts | 462 ++++++ arch/arm64/boot/dts/renesas/r8a7798-condor.dts | 963 ++++++++++++ - .../boot/dts/renesas/r8a7798-v3hsk-vbm-v2.dts | 73 + + .../boot/dts/renesas/r8a7798-v3hsk-vbm-v2.dts | 72 + arch/arm64/boot/dts/renesas/r8a7798-v3hsk-vbm.dts | 505 ++++++ arch/arm64/boot/dts/renesas/r8a7798-v3hsk.dts | 358 +++++ arch/arm64/boot/dts/renesas/ulcb-kf-cn11.dtsi | 462 ++++++ arch/arm64/boot/dts/renesas/ulcb-kf-most.dtsi | 30 + arch/arm64/boot/dts/renesas/ulcb-kf-sd3.dtsi | 46 + - arch/arm64/boot/dts/renesas/ulcb-kf.dtsi | 1458 +++++++++++++++++ + arch/arm64/boot/dts/renesas/ulcb-kf.dtsi | 1456 +++++++++++++++++ arch/arm64/boot/dts/renesas/ulcb-vb-cn12.dtsi | 459 ++++++ arch/arm64/boot/dts/renesas/ulcb-vb.dtsi | 1610 +++++++++++++++++++ - arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi | 1660 ++++++++++++++++++++ + arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi | 1650 ++++++++++++++++++++ arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi | 543 +++++++ - 60 files changed, 21143 insertions(+) + 60 files changed, 21129 insertions(+) create mode 100644 arch/arm64/boot/dts/renesas/legacy/Makefile create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts @@ -11703,7 +11703,7 @@ index 0000000..862236f +}; diff --git a/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm-v2.dts b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm-v2.dts new file mode 100644 -index 0000000..dbbd3d2 +index 0000000..74a3df6 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm-v2.dts @@ -0,0 +1,81 @@ @@ -12957,7 +12957,7 @@ index 0000000..33c6c0d +}; diff --git a/arch/arm64/boot/dts/renesas/r8a7797-v3mzf.dts b/arch/arm64/boot/dts/renesas/r8a7797-v3mzf.dts new file mode 100644 -index 0000000..246e71d +index 0000000..71d7bad --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7797-v3mzf.dts @@ -0,0 +1,462 @@ @@ -14394,7 +14394,7 @@ index 0000000..4dd7a28 +}; diff --git a/arch/arm64/boot/dts/renesas/r8a7798-v3hsk-vbm-v2.dts b/arch/arm64/boot/dts/renesas/r8a7798-v3hsk-vbm-v2.dts new file mode 100644 -index 0000000..56d4253 +index 0000000..7bf1d6f --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7798-v3hsk-vbm-v2.dts @@ -0,0 +1,72 @@ @@ -15903,7 +15903,7 @@ index 0000000..b854216 +}; diff --git a/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi new file mode 100644 -index 0000000..447cfc3 +index 0000000..0a927e2 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi @@ -0,0 +1,1456 @@ @@ -19446,10 +19446,10 @@ index 0000000..0185e46 +//#include "ulcb-vb-cn12.dtsi" diff --git a/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi b/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi new file mode 100644 -index 0000000..280c3b7 +index 0000000..509c7f3 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi -@@ -0,0 +1,1660 @@ +@@ -0,0 +1,1650 @@ +/* + * Device Tree Source for the ULCB Videobox V2 board + * @@ -19654,6 +19654,7 @@ index 0000000..280c3b7 + spican0: spidev@0 { + compatible = "microchip,mcp2515"; + reg = <0>; ++ reset-gpios = <&gpio_ext_pwr 8 GPIO_ACTIVE_HIGH>; + clocks = <&excan_ref_clk>; + interrupt-parent = <&gpio0>; + interrupts = <15 GPIO_ACTIVE_LOW>; @@ -19662,6 +19663,7 @@ index 0000000..280c3b7 + spican1: spidev@1 { + compatible = "microchip,mcp2515"; + reg = <1>; ++ reset-gpios = <&gpio_ext_pwr 9 GPIO_ACTIVE_HIGH>; + clocks = <&excan_ref_clk>; + interrupt-parent = <&gpio1>; + interrupts = <5 GPIO_ACTIVE_LOW>; @@ -20618,12 +20620,6 @@ index 0000000..280c3b7 + output-high; + line-name = "can2_120R_load"; + }; -+ can2_rst { -+ gpio-hog; -+ gpios = <8 GPIO_ACTIVE_HIGH>; -+ output-high; -+ line-name = "can2_rst"; -+ }; + /* CAN3 */ + can3_stby { + gpio-hog; @@ -20637,12 +20633,6 @@ index 0000000..280c3b7 + output-high; + line-name = "can3_120R_load"; + }; -+ can3_rst { -+ gpio-hog; -+ gpios = <9 GPIO_ACTIVE_HIGH>; -+ output-high; -+ line-name = "can3_rst"; -+ }; + }; + }; + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0108-can-mcp251x-add-reset-gpio-support.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0108-can-mcp251x-add-reset-gpio-support.patch new file mode 100644 index 0000000..646aa0c --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0108-can-mcp251x-add-reset-gpio-support.patch @@ -0,0 +1,72 @@ +From b69e3fdc91fbc88cc32eb6794872e1f058681b04 Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov +Date: Mon, 26 Mar 2018 13:51:49 +0300 +Subject: [PATCH] can: mcp251x: add reset gpio support + +Signed-off-by: Andrey Gusakov +--- + drivers/net/can/spi/mcp251x.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c +index f3f05fe..ac78ce3 100644 +--- a/drivers/net/can/spi/mcp251x.c ++++ b/drivers/net/can/spi/mcp251x.c +@@ -71,6 +71,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -270,6 +271,7 @@ struct mcp251x_priv { + struct regulator *power; + struct regulator *transceiver; + struct clk *clk; ++ struct gpio_desc *rst; + }; + + #define MCP251X_IS(_model) \ +@@ -1031,9 +1033,21 @@ static int mcp251x_can_probe(struct spi_device *spi) + struct mcp251x_platform_data *pdata = dev_get_platdata(&spi->dev); + struct net_device *net; + struct mcp251x_priv *priv; ++ struct gpio_desc *reset_gpio; + struct clk *clk; + int freq, ret; + ++ reset_gpio = devm_gpiod_get(&spi->dev, "reset", GPIOD_OUT_HIGH); ++ if (IS_ERR(reset_gpio)) { ++ if (PTR_ERR(reset_gpio) == -EPROBE_DEFER) ++ return -EPROBE_DEFER; ++ dev_err(&spi->dev, "cannot get reset-gpios %ld\n", ++ PTR_ERR(reset_gpio)); ++ reset_gpio = NULL; ++ } else { ++ gpiod_set_value_cansleep(reset_gpio, 1); ++ } ++ + clk = devm_clk_get(&spi->dev, NULL); + if (IS_ERR(clk)) { + if (pdata) +@@ -1074,6 +1088,7 @@ static int mcp251x_can_probe(struct spi_device *spi) + priv->model = spi_get_device_id(spi)->driver_data; + priv->net = net; + priv->clk = clk; ++ priv->rst = reset_gpio; + + spi_set_drvdata(spi, priv); + +@@ -1185,6 +1200,8 @@ static int mcp251x_can_remove(struct spi_device *spi) + + mcp251x_power_enable(priv->power, 0); + ++ gpiod_set_value_cansleep(priv->rst, 0); ++ + if (!IS_ERR(priv->clk)) + clk_disable_unprepare(priv->clk); + +-- +1.9.1 + 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 index 61a87e5..066f96b 100644 --- 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 @@ -85,6 +85,7 @@ SRC_URI_append = " \ file://0105-media-rcar-imr-IMR-driver-updates-for-raw-DL.patch \ file://0106-media-rcar-imr-Add-RSE-support.patch \ file://0107-V3H-device-tree-Add-VIP-devices-IRQs.patch \ + file://0108-can-mcp251x-add-reset-gpio-support.patch \ " SRC_URI_append_h3ulcb = " file://ulcb.cfg" -- cgit 1.2.3-korg From afe0749cc4b9e61b3643a0a16f639f50606c4e96 Mon Sep 17 00:00:00 2001 From: Andrey Gusakov Date: Mon, 26 Mar 2018 15:32:29 +0300 Subject: VB2: enable Kvaset USB/CAN --- meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/ulcb.cfg | 1 + 1 file changed, 1 insertion(+) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/ulcb.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/ulcb.cfg index 49f841f..5442f19 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/ulcb.cfg +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/ulcb.cfg @@ -1,5 +1,6 @@ CONFIG_CAN=y CONFIG_CAN_PEAK_USB=y +CONFIG_CAN_KVASER_USB=y CONFIG_CAN_BCM=y CONFIG_CAN_RAW=y CONFIG_CAN_DEV=y -- cgit 1.2.3-korg From 2cfbb1400230f380d60f27e549e390c0f0e00001 Mon Sep 17 00:00:00 2001 From: Andrey Gusakov Date: Tue, 27 Mar 2018 15:24:58 +0300 Subject: VB2: disable autosuspend for TUSB8041 hub --- ...-disable-autosuspend-for-SMSC-and-TI-hubs.patch | 58 ++++++++++++++++++++++ ...usb-hub-disable-autosuspend-for-SMSC-hubs.patch | 51 ------------------- .../linux/linux-renesas_4.9.bbappend | 2 +- 3 files changed, 59 insertions(+), 52 deletions(-) create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0072-usb-hub-disable-autosuspend-for-SMSC-and-TI-hubs.patch delete mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0072-usb-hub-disable-autosuspend-for-SMSC-hubs.patch (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0072-usb-hub-disable-autosuspend-for-SMSC-and-TI-hubs.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0072-usb-hub-disable-autosuspend-for-SMSC-and-TI-hubs.patch new file mode 100644 index 0000000..7adfb2e --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0072-usb-hub-disable-autosuspend-for-SMSC-and-TI-hubs.patch @@ -0,0 +1,58 @@ +From f05c07d846b5b815709cd741a85e922ddb72b958 Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Fri, 11 Aug 2017 17:30:40 +0300 +Subject: [PATCH] usb: hub: disable autosuspend for SMSC and TI hubs + +Disable autosuspend for SMSC hubs (USB5534B/USB2134B devices) and +TI hub (TUSB8041) +This is a workaround for RCar Gen3 XHCI on VB and VB2 + +Signed-off-by: Vladimir Barinov +Signed-off-by: Andrey Gusakov +--- + drivers/usb/core/hub.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c +index cbb1467..6f5575f 100644 +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -34,7 +34,10 @@ + #include "otg_whitelist.h" + + #define USB_VENDOR_GENESYS_LOGIC 0x05e3 ++#define USB_VENDOR_SMSC 0x0424 ++#define USB_VENDOR_TI 0x0451 + #define HUB_QUIRK_CHECK_PORT_AUTOSUSPEND 0x01 ++#define HUB_QUIRK_DISABLE_AUTOSUSPEND 0x02 + + /* Protect struct usb_device->state and ->children members + * Note: Both are also protected by ->dev.sem, except that ->state can +@@ -1845,6 +1848,9 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) + if (id->driver_info & HUB_QUIRK_CHECK_PORT_AUTOSUSPEND) + hub->quirk_check_port_auto_suspend = 1; + ++ if (id->driver_info & HUB_QUIRK_DISABLE_AUTOSUSPEND) ++ pm_runtime_set_autosuspend_delay(&hdev->dev, -1); ++ + if (hub_configure(hub, endpoint) >= 0) + return 0; + +@@ -5226,6 +5232,14 @@ static void hub_event(struct work_struct *work) + } + + static const struct usb_device_id hub_id_table[] = { ++ { .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_CLASS, ++ .idVendor = USB_VENDOR_SMSC, ++ .bInterfaceClass = USB_CLASS_HUB, ++ .driver_info = HUB_QUIRK_DISABLE_AUTOSUSPEND}, ++ { .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_CLASS, ++ .idVendor = USB_VENDOR_TI, ++ .bInterfaceClass = USB_CLASS_HUB, ++ .driver_info = HUB_QUIRK_DISABLE_AUTOSUSPEND}, + { .match_flags = USB_DEVICE_ID_MATCH_VENDOR + | USB_DEVICE_ID_MATCH_INT_CLASS, + .idVendor = USB_VENDOR_GENESYS_LOGIC, +-- +1.9.1 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0072-usb-hub-disable-autosuspend-for-SMSC-hubs.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0072-usb-hub-disable-autosuspend-for-SMSC-hubs.patch deleted file mode 100644 index 4989e05..0000000 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0072-usb-hub-disable-autosuspend-for-SMSC-hubs.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 8276db72581e4d1e3f89ccce84555c9fea145e16 Mon Sep 17 00:00:00 2001 -From: Vladimir Barinov -Date: Fri, 11 Aug 2017 17:30:40 +0300 -Subject: [PATCH] usb: hub: disable autosuspend for SMSC hubs - -Disable autosuspend for SMSC hubs (USB5534B/USB2134B devices) -This is a workaround for RCar Gen3 XHCI - -Signed-off-by: Vladimir Barinov ---- - drivers/usb/core/hub.c | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c -index cbb1467..2c4c006 100644 ---- a/drivers/usb/core/hub.c -+++ b/drivers/usb/core/hub.c -@@ -34,7 +34,9 @@ - #include "otg_whitelist.h" - - #define USB_VENDOR_GENESYS_LOGIC 0x05e3 -+#define USB_VENDOR_SMSC 0x0424 - #define HUB_QUIRK_CHECK_PORT_AUTOSUSPEND 0x01 -+#define HUB_QUIRK_DISABLE_AUTOSUSPEND 0x02 - - /* Protect struct usb_device->state and ->children members - * Note: Both are also protected by ->dev.sem, except that ->state can -@@ -1845,6 +1847,9 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) - if (id->driver_info & HUB_QUIRK_CHECK_PORT_AUTOSUSPEND) - hub->quirk_check_port_auto_suspend = 1; - -+ if (id->driver_info & HUB_QUIRK_DISABLE_AUTOSUSPEND) -+ pm_runtime_set_autosuspend_delay(&hdev->dev, -1); -+ - if (hub_configure(hub, endpoint) >= 0) - return 0; - -@@ -5226,6 +5231,10 @@ static void hub_event(struct work_struct *work) - } - - static const struct usb_device_id hub_id_table[] = { -+ { .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_CLASS, -+ .idVendor = USB_VENDOR_SMSC, -+ .bInterfaceClass = USB_CLASS_HUB, -+ .driver_info = HUB_QUIRK_DISABLE_AUTOSUSPEND}, - { .match_flags = USB_DEVICE_ID_MATCH_VENDOR - | USB_DEVICE_ID_MATCH_INT_CLASS, - .idVendor = USB_VENDOR_GENESYS_LOGIC, --- -1.9.1 - diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas_4.9.bbappend b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas_4.9.bbappend index 066f96b..9672e2b 100644 --- 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 @@ -63,7 +63,7 @@ SRC_URI_append = " \ file://0068-drm-adv7511-use-smbus-to-retrieve-edid.patch \ file://0070-clk-clk-5p49x-add-5P49V5925-chip.patch \ file://0071-ASoC-add-dummy-device-for-WL18xx-PCM-audio.patch \ - file://0072-usb-hub-disable-autosuspend-for-SMSC-hubs.patch \ + file://0072-usb-hub-disable-autosuspend-for-SMSC-and-TI-hubs.patch \ file://0073-MOST-dim2-add-device-tree-support.patch \ file://0074-MOST-dim2-add-R-Car3-related-initialization.patch \ file://0075-MOST-core-fix-memory-allocation-at-arm64.patch \ -- cgit 1.2.3-korg From 22ed863546773ae01a7e7b337a02d25f7e8fd7f7 Mon Sep 17 00:00:00 2001 From: Andrey Gusakov Date: Wed, 28 Mar 2018 19:30:44 +0300 Subject: VB2: enable ULCB sound --- .../0040-arm64-dts-renesas-add-ADAS-boards.patch | 56 ++++------------------ 1 file changed, 10 insertions(+), 46 deletions(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch index bd872ac..6e93fa6 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch @@ -1,4 +1,4 @@ -From fbc9403a97c602447751b49aa9d4d9cea56fef4c Mon Sep 17 00:00:00 2001 +From feb70aaac3b9760a732129c9dc6d7cbe9abc32b1 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Fri, 14 Jul 2017 15:05:42 +0300 Subject: [PATCH] arm64: dts: renesas: add ADAS boards @@ -39,7 +39,7 @@ Signed-off-by: Vladimir Barinov arch/arm64/boot/dts/renesas/legacy/Makefile | 8 + .../renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts | 1624 +++++++++++++++++++ .../renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts | 441 ++++++ - .../dts/renesas/legacy/r8a7795-h3ulcb-kf-v0.dts | 1638 +++++++++++++++++++ + .../dts/renesas/legacy/r8a7795-h3ulcb-kf-v0.dts | 1638 ++++++++++++++++++++ .../dts/renesas/legacy/r8a7795-h3ulcb-kf-v1.dts | 465 ++++++ .../dts/renesas/legacy/r8a7796-m3ulcb-kf-v0.dts | 1171 ++++++++++++++ .../dts/renesas/legacy/r8a7796-m3ulcb-kf-v1.dts | 465 ++++++ @@ -77,11 +77,11 @@ Signed-off-by: Vladimir Barinov .../boot/dts/renesas/r8a7797-es1-v3msk-view.dts | 17 + arch/arm64/boot/dts/renesas/r8a7797-es1-v3msk.dts | 17 + arch/arm64/boot/dts/renesas/r8a7797-es1.dtsi | 116 ++ - arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts | 520 ++++++ + arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts | 520 +++++++ .../boot/dts/renesas/r8a7797-v3msk-vbm-v2.dts | 81 + arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts | 507 ++++++ arch/arm64/boot/dts/renesas/r8a7797-v3msk-view.dts | 297 ++++ - arch/arm64/boot/dts/renesas/r8a7797-v3msk.dts | 345 ++++ + arch/arm64/boot/dts/renesas/r8a7797-v3msk.dts | 345 +++++ arch/arm64/boot/dts/renesas/r8a7797-v3mzf.dts | 462 ++++++ arch/arm64/boot/dts/renesas/r8a7798-condor.dts | 963 ++++++++++++ .../boot/dts/renesas/r8a7798-v3hsk-vbm-v2.dts | 72 + @@ -93,9 +93,9 @@ Signed-off-by: Vladimir Barinov arch/arm64/boot/dts/renesas/ulcb-kf.dtsi | 1456 +++++++++++++++++ arch/arm64/boot/dts/renesas/ulcb-vb-cn12.dtsi | 459 ++++++ arch/arm64/boot/dts/renesas/ulcb-vb.dtsi | 1610 +++++++++++++++++++ - arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi | 1650 ++++++++++++++++++++ + arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi | 1614 +++++++++++++++++++ arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi | 543 +++++++ - 60 files changed, 21129 insertions(+) + 60 files changed, 21093 insertions(+) create mode 100644 arch/arm64/boot/dts/renesas/legacy/Makefile create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts @@ -19446,10 +19446,10 @@ index 0000000..0185e46 +//#include "ulcb-vb-cn12.dtsi" diff --git a/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi b/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi new file mode 100644 -index 0000000..509c7f3 +index 0000000..fe2513e --- /dev/null +++ b/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi -@@ -0,0 +1,1650 @@ +@@ -0,0 +1,1614 @@ +/* + * Device Tree Source for the ULCB Videobox V2 board + * @@ -19546,28 +19546,6 @@ index 0000000..509c7f3 + regulator-always-on; + }; + -+ /delete-node/sound; -+ -+ rsnd_ak4613: sound@0 { -+ pinctrl-0 = <&sound_0_pins>; -+ pinctrl-names = "default"; -+ compatible = "simple-audio-card"; -+ -+ simple-audio-card,format = "left_j"; -+ simple-audio-card,name = "ak4613"; -+ -+ simple-audio-card,bitclock-master = <&sndcpu>; -+ simple-audio-card,frame-master = <&sndcpu>; -+ -+ sndcpu: simple-audio-card,cpu@1 { -+ sound-dai = <&rcar_sound>; -+ }; -+ -+ sndcodec: simple-audio-card,codec@1 { -+ sound-dai = <&ak4613>; -+ }; -+ }; -+ + lvds-encoder { + compatible = "thine,thc63lvdm83d"; + @@ -19678,13 +19656,6 @@ index 0000000..509c7f3 + function = "hscif4"; + }; + -+ /delete-node/sound; -+ -+ sound_0_pins: sound1 { -+ groups = "ssi01239_ctrl", "ssi0_data", "ssi1_data_a"; -+ function = "ssi"; -+ }; -+ + usb0_pins: usb0 { + groups = "usb0"; + function = "usb0"; @@ -21003,15 +20974,8 @@ index 0000000..509c7f3 + }; +}; + -+&rcar_sound { -+ pinctrl-0 = <&sound_clk_pins>; -+ -+ /* Multi DAI */ -+ #sound-dai-cells = <1>; -+}; -+ -+&ssi1 { -+ /delete-property/shared-pin; ++&rsnd_ak4613 { ++ simple-audio-card,name = "ak4613"; +}; + +&sdhi3 { -- cgit 1.2.3-korg From acd8c1a179076ed714b4b539199e2b81cbdc354a Mon Sep 17 00:00:00 2001 From: Andrey Gusakov Date: Fri, 30 Mar 2018 17:26:43 +0300 Subject: ULCB: fix onboard sound --- ...ar-fix-incorrect-behavior-with-PulseAudio.patch | 65 ++++++++++++++++++++++ .../linux/linux-renesas_4.9.bbappend | 1 + 2 files changed, 66 insertions(+) create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0109-ASoC-R-Car-fix-incorrect-behavior-with-PulseAudio.patch (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0109-ASoC-R-Car-fix-incorrect-behavior-with-PulseAudio.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0109-ASoC-R-Car-fix-incorrect-behavior-with-PulseAudio.patch new file mode 100644 index 0000000..89788bf --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0109-ASoC-R-Car-fix-incorrect-behavior-with-PulseAudio.patch @@ -0,0 +1,65 @@ +From 539d604c483df0a00033f207a2926b6048d99fbc Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov +Date: Fri, 30 Mar 2018 15:57:43 +0300 +Subject: [PATCH] ASoC: R-Car: fix incorrect behavior with PulseAudio + +io->hw_params is set for hw_constraint. And set to NULL in +rsnd_hw_params. But rule chacker can be called between +rsnd_hw_params and rsnd_soc_dai_trigger causing driver to +use io->hw_params instead of cached values. +Set io->hw_params = NULL in rsnd_soc_dai_trigger before actually +starting HW. + +Signed-off-by: Andrey Gusakov +--- + sound/soc/sh/rcar/core.c | 8 ++++++++ + sound/soc/sh/rcar/ssi.c | 6 +++--- + 2 files changed, 11 insertions(+), 3 deletions(-) + +diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c +index 7e85aec..982f3d0 100644 +--- a/sound/soc/sh/rcar/core.c ++++ b/sound/soc/sh/rcar/core.c +@@ -630,6 +630,14 @@ static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd, + int ret; + unsigned long flags; + ++ /* ++ * hw_refine finished. remove hw_param from rdai ++ * see ++ * __rsnd_soc_hw_rule_rate() ++ * __rsnd_soc_hw_rule_channels() ++ */ ++ io->hw_params = NULL; ++ + spin_lock_irqsave(&priv->lock, flags); + + switch (cmd) { +diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c +index fb5f7fd..8695647 100644 +--- a/sound/soc/sh/rcar/ssi.c ++++ b/sound/soc/sh/rcar/ssi.c +@@ -240,7 +240,6 @@ static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod, + struct rsnd_dai *rdai = rsnd_io_to_rdai(io); + struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); + struct rsnd_mod *ssi_parent_mod = rsnd_io_to_mod_ssip(io); +- int chan = rsnd_runtime_channel_for_ssi(io); + int idx, ret; + unsigned int main_rate; + unsigned int rate = rsnd_io_is_play(io) ? +@@ -265,9 +264,10 @@ static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod, + return 0; + } + +- main_rate = rsnd_ssi_clk_query(priv, rate, chan, &idx); ++ main_rate = rsnd_ssi_clk_query(priv, rate, ssi->chan, &idx); + if (!main_rate) { +- dev_err(dev, "unsupported clock rate\n"); ++ dev_err(dev, "unsupported clock rate: %dx%d\n", ++ rate, ssi->chan); + return -EIO; + } + +-- +1.9.1 + 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 index 9672e2b..f5a1445 100644 --- 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 @@ -86,6 +86,7 @@ SRC_URI_append = " \ file://0106-media-rcar-imr-Add-RSE-support.patch \ file://0107-V3H-device-tree-Add-VIP-devices-IRQs.patch \ file://0108-can-mcp251x-add-reset-gpio-support.patch \ + file://0109-ASoC-R-Car-fix-incorrect-behavior-with-PulseAudio.patch \ " SRC_URI_append_h3ulcb = " file://ulcb.cfg" -- cgit 1.2.3-korg From b0dc0b7992b85fc542ee5d634eec05efafd3f168 Mon Sep 17 00:00:00 2001 From: Andrey Gusakov Date: Fri, 30 Mar 2018 19:15:23 +0300 Subject: VB2: drop i2c2 clock to 100 KHz cs2000 support only 100 KHz clock. cs2000 is needed for onboard sound. ...and some minor cleanup --- .../0040-arm64-dts-renesas-add-ADAS-boards.patch | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch index 6e93fa6..88ed3ec 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch @@ -1,4 +1,4 @@ -From feb70aaac3b9760a732129c9dc6d7cbe9abc32b1 Mon Sep 17 00:00:00 2001 +From c3908942394fed76f3f8272e3b2a77a465dbaf15 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Fri, 14 Jul 2017 15:05:42 +0300 Subject: [PATCH] arm64: dts: renesas: add ADAS boards @@ -93,9 +93,9 @@ Signed-off-by: Vladimir Barinov arch/arm64/boot/dts/renesas/ulcb-kf.dtsi | 1456 +++++++++++++++++ arch/arm64/boot/dts/renesas/ulcb-vb-cn12.dtsi | 459 ++++++ arch/arm64/boot/dts/renesas/ulcb-vb.dtsi | 1610 +++++++++++++++++++ - arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi | 1614 +++++++++++++++++++ + arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi | 1605 +++++++++++++++++++ arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi | 543 +++++++ - 60 files changed, 21093 insertions(+) + 60 files changed, 21084 insertions(+) create mode 100644 arch/arm64/boot/dts/renesas/legacy/Makefile create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts @@ -19446,10 +19446,10 @@ index 0000000..0185e46 +//#include "ulcb-vb-cn12.dtsi" diff --git a/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi b/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi new file mode 100644 -index 0000000..fe2513e +index 0000000..6746723 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi -@@ -0,0 +1,1614 @@ +@@ -0,0 +1,1605 @@ +/* + * Device Tree Source for the ULCB Videobox V2 board + * @@ -19490,13 +19490,6 @@ index 0000000..fe2513e + }; + }; + -+ snd_clk: snd_clk { -+ compatible = "fixed-clock"; -+ #clock-cells = <0>; -+ clock-frequency = <24576000>; -+ clock-output-names = "scki"; -+ }; -+ + vcc_sdhi3: regulator-vcc-sdhi3 { + compatible = "regulator-fixed"; + @@ -19859,8 +19852,6 @@ index 0000000..fe2513e +}; + +&i2c2 { -+ clock-frequency = <400000>; -+ + i2cswitch2: pca9548@74 { + compatible = "nxp,pca9548"; + #address-cells = <1>; -- cgit 1.2.3-korg From dd06e952c5efab2914849b703a94f8b5e63bec86 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Wed, 4 Apr 2018 16:10:12 +0300 Subject: V3MZF: add generic kernel UIO for IMP --- meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3mzf.cfg | 1 + 1 file changed, 1 insertion(+) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3mzf.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3mzf.cfg index 1d888cd..cd41866 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3mzf.cfg +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3mzf.cfg @@ -19,6 +19,7 @@ CONFIG_SOC_CAMERA_TI9X4=y CONFIG_SOC_CAMERA_OV106XX=y CONFIG_VIDEO_RENESAS_IMR=y CONFIG_SERIAL_SH_SCI_DMA=y +CONFIG_UIO=y CONFIG_SPI_SLAVE=y CONFIG_SPI_SLAVE_TIME=y CONFIG_SPI_SLAVE_SYSTEM_CONTROL=y -- cgit 1.2.3-korg From c5f5893dd826d43b7e60e1c34147c9da48e1d0cb Mon Sep 17 00:00:00 2001 From: Valentine Barshak Date: Wed, 4 Apr 2018 02:04:43 +0300 Subject: recipes-kernel: linux-renesas: ulcb: Make AK4613 device name consistent This makes AK4613 sound device name consistent throughout all ULCB boards. This helps to avoid naming issues when pulseaudio fails to start because the device has different names on infotainment and starter boards. For example, "ak4613" on Kingfisher vs "rsnd-dai.0-ak4613-hifi" on Starter Kit. Pulseaudio is expecting "ak4613" name. Signed-off-by: Valentine Barshak --- ...enesas-ulcb-Make-AK4613-sound-device-name.patch | 59 ++++++++++++++++++++++ .../linux/linux-renesas_4.9.bbappend | 1 + 2 files changed, 60 insertions(+) create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0112-ARM64-dts-renesas-ulcb-Make-AK4613-sound-device-name.patch (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0112-ARM64-dts-renesas-ulcb-Make-AK4613-sound-device-name.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0112-ARM64-dts-renesas-ulcb-Make-AK4613-sound-device-name.patch new file mode 100644 index 0000000..8d7409a --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0112-ARM64-dts-renesas-ulcb-Make-AK4613-sound-device-name.patch @@ -0,0 +1,59 @@ +From e0807ef3f52f630dcfa694802273d63bbfd35f15 Mon Sep 17 00:00:00 2001 +From: Valentine Barshak +Date: Wed, 4 Apr 2018 18:48:27 +0300 +Subject: [PATCH] ARM64: dts: renesas: ulcb: Make AK4613 sound device name + consistent + +This makes AK4613 sound device name consistent throughout all +ULCB boards. This helps to avoid naming issues when pulseaudio +fails to start because the device has different names on +infotainment and starter boards. For example, "ak4613" +on Kingfisher vs "rsnd-dai.0-ak4613-hifi" on Starter Kit. +Pulseaudio is expecting "ak4613" name. + +Signed-off-by: Valentine Barshak +--- + arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb.dts | 1 + + arch/arm64/boot/dts/renesas/r8a7795-h3ulcb.dts | 1 + + arch/arm64/boot/dts/renesas/r8a7796-m3ulcb.dts | 1 + + 3 files changed, 3 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb.dts +index bffa775..124379d 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb.dts +@@ -178,6 +178,7 @@ + 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>; + +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb.dts b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb.dts +index 76da9f2..4a94a68 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb.dts +@@ -178,6 +178,7 @@ + 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>; + +diff --git a/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb.dts b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb.dts +index 7b58109..15c67ec 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb.dts +@@ -159,6 +159,7 @@ + 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>; + +-- +2.7.4 + 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 index f5a1445..7e86a78 100644 --- 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 @@ -87,6 +87,7 @@ SRC_URI_append = " \ file://0107-V3H-device-tree-Add-VIP-devices-IRQs.patch \ file://0108-can-mcp251x-add-reset-gpio-support.patch \ file://0109-ASoC-R-Car-fix-incorrect-behavior-with-PulseAudio.patch \ + file://0112-ARM64-dts-renesas-ulcb-Make-AK4613-sound-device-name.patch \ " SRC_URI_append_h3ulcb = " file://ulcb.cfg" -- cgit 1.2.3-korg From 3c34681dd3fe562d5d65d83229caa921afc67a1f Mon Sep 17 00:00:00 2001 From: Andrey Dolnikov Date: Wed, 11 Apr 2018 17:03:45 +0300 Subject: Add QSPI support and Hyperflash devicetree support. --- .../0110-Renesas-clk-Add-RPC-clock-source.patch | 263 ++++ .../0111-Renesas-r8a7798-Add-RPC-clock.patch | 46 + ...nesas-r8a7798-pinctrl-Add-RPC-pin-control.patch | 119 ++ .../0113-Renesas-RPC-Add-RPC-driver.patch | 1483 ++++++++++++++++++++ .../0114-R8A7798-dtsi-Add-RPC-node-to-dtsi.patch | 35 + .../0115-R8A7798-condor-dts-Add-qspi-flash.patch | 98 ++ .../0116-spi-nor-Add-s25fs512-flash-support.patch | 126 ++ .../0117-spi-nor-Add-flash-array-support.patch | 89 ++ .../0118-r8a7797-clk-Add-rpc-clock.patch | 45 + .../0119-r8a7797-pinctrl-Add-qspi-pins.patch | 118 ++ .../0120-r8a7797-dtsi-Add-rpc-node.patch | 35 + ...0121-r8a7797-eagle-dts-Add-spi-flash-node.patch | 96 ++ ...sk-r8a7797-v3mzf-dts-Add-spi-flash-s25fs5.patch | 172 +++ .../0123-V3HSK-dts-Add-qspi-node.patch | 101 ++ ...124-RPC-Hyperflash-Add-devicetree-support.patch | 219 +++ ...7-pinctrl-Add-pin-function-for-hyperflash.patch | 70 + ...8-pinctrl-Add-pin-function-for-hyperflash.patch | 69 + .../recipes-kernel/linux/linux-renesas/qspi.cfg | 3 + .../linux/linux-renesas_4.9.bbappend | 18 + 19 files changed, 3205 insertions(+) create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0110-Renesas-clk-Add-RPC-clock-source.patch create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0111-Renesas-r8a7798-Add-RPC-clock.patch create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0112-Renesas-r8a7798-pinctrl-Add-RPC-pin-control.patch create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0113-Renesas-RPC-Add-RPC-driver.patch create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0114-R8A7798-dtsi-Add-RPC-node-to-dtsi.patch create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0115-R8A7798-condor-dts-Add-qspi-flash.patch create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0116-spi-nor-Add-s25fs512-flash-support.patch create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0117-spi-nor-Add-flash-array-support.patch create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0118-r8a7797-clk-Add-rpc-clock.patch create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0119-r8a7797-pinctrl-Add-qspi-pins.patch create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0120-r8a7797-dtsi-Add-rpc-node.patch create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0121-r8a7797-eagle-dts-Add-spi-flash-node.patch create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0122-r8a7797-v3msk-r8a7797-v3mzf-dts-Add-spi-flash-s25fs5.patch create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0123-V3HSK-dts-Add-qspi-node.patch create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0124-RPC-Hyperflash-Add-devicetree-support.patch create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0125-r8a7797-pinctrl-Add-pin-function-for-hyperflash.patch create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0126-r8a7798-pinctrl-Add-pin-function-for-hyperflash.patch create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/qspi.cfg (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0110-Renesas-clk-Add-RPC-clock-source.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0110-Renesas-clk-Add-RPC-clock-source.patch new file mode 100644 index 0000000..37d08e9 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0110-Renesas-clk-Add-RPC-clock-source.patch @@ -0,0 +1,263 @@ +From b4acae6eda19307e0051763a532f522006a82d5c Mon Sep 17 00:00:00 2001 +From: Dmitry Shifrin +Date: Mon, 19 Mar 2018 10:37:04 +0300 +Subject: [PATCH 01/12] Renesas: clk: Add RPC clock source + +Add RPC clock source functionality + +Signed-off-by: Dmitry Shifrin +--- + drivers/clk/renesas/rcar-gen3-cpg.c | 200 ++++++++++++++++++++++++++++++++++++ + drivers/clk/renesas/rcar-gen3-cpg.h | 4 + + 2 files changed, 204 insertions(+) + +diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c +index 99acba2..969e1b2 100644 +--- a/drivers/clk/renesas/rcar-gen3-cpg.c ++++ b/drivers/clk/renesas/rcar-gen3-cpg.c +@@ -599,6 +599,7 @@ static const struct clk_div_table cpg_sd01_div_table[] = { + { 10, 36 }, { 11, 48 }, { 12, 10 }, { 0, 0 }, + }; + ++ + #define CPG_SD_STP_HCK BIT(9) + #define CPG_SD_STP_CK BIT(8) + +@@ -811,6 +812,202 @@ static struct clk * __init cpg_sd_clk_register(const struct cpg_core_clk *core, + return clk; + } + ++/**************** RPCSCK ***********************************/ ++ ++ ++ ++struct rpc_clock { ++ struct clk_hw hw; ++ void __iomem *reg; ++ const struct clk_div_table *div_table; ++ unsigned int div_num; ++ unsigned int div_min; ++ unsigned int div_max; ++}; ++ ++static const struct clk_div_table cpg_rpc_div_table[] = { ++ { 0x11, 20 }, { 0x13, 40 }, { 0x15, 60 }, { 0x17, 80 }, ++ { 0x19, 24 }, { 0x1B, 48 }, { 0x1D, 72 }, { 0x1F, 96 }, ++}; ++ ++#define to_rpc_clock(_hw) container_of(_hw, struct rpc_clock, hw) ++ ++#define CPG_RPC_ENA_MASK (BIT(9) | BIT(8)) ++#define CPG_RPC_SCALE_MASK (0x1F) ++ ++ ++static int cpg_rpc_clock_endisable(void __iomem *reg, bool enable) ++{ ++ u32 val; ++ ++ val = readl(reg); ++ ++ if (enable) ++ val &= ~CPG_RPC_ENA_MASK; ++ else ++ val |= CPG_RPC_ENA_MASK; ++ ++ writel(val, reg); ++ return 0; ++}; ++ ++static int cpg_rpc_clock_enable(struct clk_hw *hw) ++{ ++ struct rpc_clock *clock = to_rpc_clock(hw); ++ ++ cpg_rpc_clock_endisable(clock->reg, true); ++ ++ return 0; ++} ++ ++static void cpg_rpc_clock_disable(struct clk_hw *hw) ++{ ++ struct rpc_clock *clock = to_rpc_clock(hw); ++ ++ cpg_rpc_clock_endisable(clock->reg, false); ++} ++ ++static int cpg_rpc_clock_is_enabled(struct clk_hw *hw) ++{ ++ struct rpc_clock *clock = to_rpc_clock(hw); ++ ++ return !(readl(clock->reg) & CPG_RPC_ENA_MASK); ++} ++ ++static unsigned long cpg_rpc_clock_recalc_rate(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ struct rpc_clock *clock = to_rpc_clock(hw); ++ unsigned long rate = parent_rate; ++ u32 val, scale; ++ unsigned int i; ++ ++ val = readl(clock->reg); ++ ++ scale = val & CPG_RPC_SCALE_MASK; ++ for (i = 0; i < clock->div_num; i++) ++ if (scale == clock->div_table[i].val) ++ break; ++ ++ if (i >= clock->div_num) ++ return 0; ++ ++ return DIV_ROUND_CLOSEST(rate, clock->div_table[i].div); ++} ++ ++static unsigned int cpg_rpc_clock_calc_div(struct rpc_clock *clock, ++ unsigned long rate, ++ unsigned long parent_rate) ++{ ++ unsigned int div; ++ ++ if (!rate) ++ rate = 1; ++ ++ div = DIV_ROUND_CLOSEST(parent_rate, rate); ++ ++ return clamp_t(unsigned int, div, clock->div_min, clock->div_max); ++} ++ ++static long cpg_rpc_clock_round_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long *parent_rate) ++{ ++ struct rpc_clock *clock = to_rpc_clock(hw); ++ unsigned int div = cpg_rpc_clock_calc_div(clock, rate, *parent_rate); ++ ++ return DIV_ROUND_CLOSEST(*parent_rate, div); ++} ++ ++static int cpg_rpc_clock_set_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long parent_rate) ++{ ++ struct rpc_clock *clock = to_rpc_clock(hw); ++ unsigned int div = cpg_rpc_clock_calc_div(clock, rate, parent_rate); ++ u32 val; ++ unsigned int i, nearest_i, nearest_div; ++ ++ ++ for (i = 0; i < clock->div_num; i++) ++ if (div == clock->div_table[i].div) ++ break; ++ ++ if (i >= clock->div_num) { ++ /* find nearest */ ++ nearest_div = -1; ++ nearest_i = clock->div_num; ++ for (i = 0; i < clock->div_num; i++) { ++ if (clock->div_table[i].div >= div && ++ clock->div_table[i].div <= nearest_div) { ++ nearest_i = i; ++ nearest_div = clock->div_table[i].div; ++ } ++ } ++ ++ i = nearest_i; ++ } ++ ++ if (i >= clock->div_num) ++ return -EINVAL; ++ ++ val = readl(clock->reg); ++ val &= ~CPG_RPC_SCALE_MASK; ++ val |= clock->div_table[i].val; ++ writel(val, clock->reg); ++ ++ return 0; ++} ++ ++static const struct clk_ops cpg_rpc_clock_ops = { ++ .enable = cpg_rpc_clock_enable, ++ .disable = cpg_rpc_clock_disable, ++ .is_enabled = cpg_rpc_clock_is_enabled, ++ .recalc_rate = cpg_rpc_clock_recalc_rate, ++ .round_rate = cpg_rpc_clock_round_rate, ++ .set_rate = cpg_rpc_clock_set_rate, ++}; ++ ++static struct clk * __init cpg_rpc_clk_register(const struct cpg_core_clk *core, ++ void __iomem *base, ++ const char *parent_name) ++{ ++ struct clk_init_data init; ++ struct rpc_clock *clock; ++ struct clk *clk; ++ unsigned int i; ++ ++ clock = kzalloc(sizeof(*clock), GFP_KERNEL); ++ if (!clock) ++ return ERR_PTR(-ENOMEM); ++ ++ init.name = core->name; ++ init.ops = &cpg_rpc_clock_ops; ++ init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT; ++ init.parent_names = &parent_name; ++ init.num_parents = 1; ++ ++ clock->reg = base + core->offset; ++ clock->hw.init = &init; ++ clock->div_table = cpg_rpc_div_table; ++ clock->div_num = ARRAY_SIZE(cpg_rpc_div_table); ++ ++ clock->div_max = clock->div_table[0].div; ++ clock->div_min = clock->div_max; ++ for (i = 1; i < clock->div_num; i++) { ++ clock->div_max = max(clock->div_max, clock->div_table[i].div); ++ clock->div_min = min(clock->div_min, clock->div_table[i].div); ++ } ++ ++ clk = clk_register(NULL, &clock->hw); ++ if (IS_ERR(clk)) ++ kfree(clock); ++ ++ return clk; ++} ++ ++/***********************************************************/ ++ ++ ++ + + static const struct rcar_gen3_cpg_pll_config *cpg_pll_config __initdata; + static unsigned int cpg_clk_extalr __initdata; +@@ -943,6 +1140,9 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, + return cpg_zg_clk_register(core->name, __clk_get_name(parent), + base); + ++ case CLK_TYPE_GEN3_RPCSRC: ++ return cpg_rpc_clk_register(core, base, __clk_get_name(parent)); ++ + default: + return ERR_PTR(-EINVAL); + } +diff --git a/drivers/clk/renesas/rcar-gen3-cpg.h b/drivers/clk/renesas/rcar-gen3-cpg.h +index 694bedc..636ef54 100644 +--- a/drivers/clk/renesas/rcar-gen3-cpg.h ++++ b/drivers/clk/renesas/rcar-gen3-cpg.h +@@ -27,6 +27,7 @@ enum rcar_gen3_clk_types { + CLK_TYPE_GEN3_ZG, + CLK_TYPE_GEN3_RINT, + CLK_TYPE_GEN3_OSC, ++ CLK_TYPE_GEN3_RPCSRC, + }; + + #define DEF_GEN3_SD(_name, _id, _parent, _offset) \ +@@ -36,6 +37,9 @@ enum rcar_gen3_clk_types { + #define DEF_GEN3_SD0H(_name, _id, _parent, _offset) \ + DEF_BASE(_name, _id, CLK_TYPE_GEN3_SD0H, _parent, .offset = _offset) + ++#define DEF_GEN3_RPCSRC(_name, _id, _parent, _offset) \ ++ DEF_BASE(_name, _id, CLK_TYPE_GEN3_RPCSRC, _parent, .offset = _offset) ++ + struct rcar_gen3_cpg_pll_config { + unsigned int extal_div; + unsigned int pll1_mult; +-- +2.7.4 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0111-Renesas-r8a7798-Add-RPC-clock.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0111-Renesas-r8a7798-Add-RPC-clock.patch new file mode 100644 index 0000000..e0fb7d2 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0111-Renesas-r8a7798-Add-RPC-clock.patch @@ -0,0 +1,46 @@ +From 05ab83db0e0012674a0255fe37a51713a1601732 Mon Sep 17 00:00:00 2001 +From: Dmitry Shifrin +Date: Mon, 19 Mar 2018 10:42:50 +0300 +Subject: [PATCH 02/12] Renesas: r8a7798: Add RPC clock + +Signed-off-by: Dmitry Shifrin +--- + drivers/clk/renesas/r8a7798-cpg-mssr.c | 3 +++ + include/dt-bindings/clock/r8a7798-cpg-mssr.h | 1 + + 2 files changed, 4 insertions(+) + +diff --git a/drivers/clk/renesas/r8a7798-cpg-mssr.c b/drivers/clk/renesas/r8a7798-cpg-mssr.c +index e407916..2614147 100644 +--- a/drivers/clk/renesas/r8a7798-cpg-mssr.c ++++ b/drivers/clk/renesas/r8a7798-cpg-mssr.c +@@ -90,6 +90,8 @@ static const struct cpg_core_clk r8a7798_core_clks[] __initconst = { + + DEF_GEN3_SD("sd0", R8A7798_CLK_SD0, CLK_SDSRC, 0x0074), /* OK? */ + ++ DEF_GEN3_RPCSRC("rpcsrc", R8A7798_CLK_RPCSRC, CLK_PLL1, 0x0238), ++ + DEF_FIXED("cl", R8A7798_CLK_CL, CLK_PLL1_DIV2, 48, 1), + DEF_FIXED("cp", R8A7798_CLK_CP, CLK_EXTAL, 2, 1), + +@@ -194,6 +196,7 @@ static const struct mssr_mod_clk r8a7798_mod_clks[] __initconst = { + DEF_MOD("gpio1", 911, R8A7798_CLK_CP), + DEF_MOD("gpio0", 912, R8A7798_CLK_CP), + DEF_MOD("can-fd", 914, R8A7798_CLK_S3D2), ++ DEF_MOD("rpc", 917, R8A7798_CLK_RPCSRC), + /* FIXME missing MSSR for i2c5; should it be 919 as in H3/M3? */ + /* DEF_MOD("i2c4", 919, R8A7798_CLK_S3D2), */ + DEF_MOD("i2c4", 927, R8A7798_CLK_S0D6), +diff --git a/include/dt-bindings/clock/r8a7798-cpg-mssr.h b/include/dt-bindings/clock/r8a7798-cpg-mssr.h +index 3d85730..821383d3 100644 +--- a/include/dt-bindings/clock/r8a7798-cpg-mssr.h ++++ b/include/dt-bindings/clock/r8a7798-cpg-mssr.h +@@ -52,5 +52,6 @@ + #define R8A7798_CLK_CPEX 36 + #define R8A7798_CLK_R 37 + #define R8A7798_CLK_OSC 38 ++#define R8A7798_CLK_RPCSRC 39 + + #endif /* __DT_BINDINGS_CLOCK_R8A7798_CPG_MSSR_H__ */ +-- +2.7.4 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0112-Renesas-r8a7798-pinctrl-Add-RPC-pin-control.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0112-Renesas-r8a7798-pinctrl-Add-RPC-pin-control.patch new file mode 100644 index 0000000..5c91f56 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0112-Renesas-r8a7798-pinctrl-Add-RPC-pin-control.patch @@ -0,0 +1,119 @@ +From ba6a829c33809d780c40c3f60e97e8a9e2a99a92 Mon Sep 17 00:00:00 2001 +From: Dmitry Shifrin +Date: Mon, 19 Mar 2018 10:48:44 +0300 +Subject: [PATCH 03/12] Renesas: r8a7798: pinctrl: Add RPC pin control + +Signed-off-by: Dmitry Shifrin +--- + drivers/pinctrl/sh-pfc/pfc-r8a7798.c | 74 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 74 insertions(+) + +diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7798.c b/drivers/pinctrl/sh-pfc/pfc-r8a7798.c +index 39aba74..f20afd1 100644 +--- a/drivers/pinctrl/sh-pfc/pfc-r8a7798.c ++++ b/drivers/pinctrl/sh-pfc/pfc-r8a7798.c +@@ -1472,6 +1472,60 @@ static const unsigned int scif_clk_b_mux[] = { + SCIF_CLK_B_MARK, + }; + ++/* - QSPI ------------------------------------------------------------------- */ ++static const unsigned int qspi0_ctrl_pins[] = { ++ /* QSPI0_SPCLK QSPI0_SSL */ ++ RCAR_GP_PIN(5, 5), RCAR_GP_PIN(5, 0), ++}; ++static const unsigned int qspi0_ctrl_mux[] = { ++ QSPI0_SPCLK_MARK, QSPI0_SSL_MARK, ++}; ++ ++static const unsigned int qspi0_data2_pins[] = { ++ /* QSPI0_MOSI_IO0, QSPI0_MISO_IO1 */ ++ RCAR_GP_PIN(5, 1), RCAR_GP_PIN(5, 2), ++}; ++static const unsigned int qspi0_data2_mux[] = { ++ QSPI0_MOSI_IO0_MARK, QSPI0_MISO_IO1_MARK, ++}; ++ ++static const unsigned int qspi0_data4_pins[] = { ++ /* QSPI0_MOSI_IO0, QSPI0_MISO_IO1, QSPI0_IO2, QSPI0_IO3 */ ++ RCAR_GP_PIN(5, 1), RCAR_GP_PIN(5, 2), ++ RCAR_GP_PIN(5, 3), RCAR_GP_PIN(5, 4), ++}; ++static const unsigned int qspi0_data4_mux[] = { ++ QSPI0_MOSI_IO0_MARK, QSPI0_MISO_IO1_MARK, ++ QSPI0_IO2_MARK, QSPI0_IO3_MARK ++}; ++ ++static const unsigned int qspi1_ctrl_pins[] = { ++ /* QSPI1_SPCLK QSPI1_SSL */ ++ RCAR_GP_PIN(5, 6), RCAR_GP_PIN(5, 11), ++}; ++static const unsigned int qspi1_ctrl_mux[] = { ++ QSPI1_SPCLK_MARK, QSPI1_SSL_MARK, ++}; ++ ++static const unsigned int qspi1_data2_pins[] = { ++ /* QSPI1_MOSI_IO0, QSPI1_MISO_IO1 */ ++ RCAR_GP_PIN(5, 7), RCAR_GP_PIN(5, 8), ++}; ++static const unsigned int qspi1_data2_mux[] = { ++ QSPI1_MOSI_IO0_MARK, QSPI1_MISO_IO1_MARK, ++}; ++ ++static const unsigned int qspi1_data4_pins[] = { ++ /* QSPI1_MOSI_IO0, QSPI1_MISO_IO1, QSPI1_IO2, QSPI1_IO3 */ ++ RCAR_GP_PIN(5, 7), RCAR_GP_PIN(5, 8), ++ RCAR_GP_PIN(5, 9), RCAR_GP_PIN(5, 10), ++}; ++static const unsigned int qspi1_data4_mux[] = { ++ QSPI1_MOSI_IO0_MARK, QSPI1_MISO_IO1_MARK, ++ QSPI1_IO2_MARK, QSPI1_IO3_MARK ++}; ++ ++ + /* - I2C -------------------------------------------------------------------- */ + static const unsigned int i2c0_pins[] = { + /* SDA0, SCL0 */ +@@ -2419,6 +2473,12 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { + SH_PFC_PIN_GROUP(vin1_field), + SH_PFC_PIN_GROUP(vin1_clkenb), + SH_PFC_PIN_GROUP(vin1_clk), ++ SH_PFC_PIN_GROUP(qspi0_ctrl), ++ SH_PFC_PIN_GROUP(qspi0_data2), ++ SH_PFC_PIN_GROUP(qspi0_data4), ++ SH_PFC_PIN_GROUP(qspi1_ctrl), ++ SH_PFC_PIN_GROUP(qspi1_data2), ++ SH_PFC_PIN_GROUP(qspi1_data4), + }; + + static const char * const avb_groups[] = { +@@ -2683,6 +2743,18 @@ static const char * const vin1_groups[] = { + "vin1_clk", + }; + ++static const char * const qspi0_groups[] = { ++ "qspi0_ctrl", ++ "qspi0_data2", ++ "qspi0_data4", ++}; ++ ++static const char * const qspi1_groups[] = { ++ "qspi1_ctrl", ++ "qspi1_data2", ++ "qspi1_data4", ++}; ++ + static const struct sh_pfc_function pinmux_functions[] = { + SH_PFC_FUNCTION(avb), + SH_PFC_FUNCTION(gether), +@@ -2719,6 +2791,8 @@ static const struct sh_pfc_function pinmux_functions[] = { + SH_PFC_FUNCTION(tmu), + SH_PFC_FUNCTION(vin0), + SH_PFC_FUNCTION(vin1), ++ SH_PFC_FUNCTION(qspi0), ++ SH_PFC_FUNCTION(qspi1), + }; + + static const struct pinmux_cfg_reg pinmux_config_regs[] = { +-- +2.7.4 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0113-Renesas-RPC-Add-RPC-driver.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0113-Renesas-RPC-Add-RPC-driver.patch new file mode 100644 index 0000000..86b2d6c --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0113-Renesas-RPC-Add-RPC-driver.patch @@ -0,0 +1,1483 @@ +From 931484f9bd4eb1741588dc1574080fa4534ac5dc Mon Sep 17 00:00:00 2001 +From: Dmitry Shifrin +Date: Mon, 19 Mar 2018 11:08:16 +0300 +Subject: [PATCH 04/12] Renesas: RPC: Add RPC driver + +This is initial commit. Driver supports single and dual mode. +Dual mode means that there are two spi-nor flashes connected. +Supports qspi flashes. + +Signed-off-by: Dmitry Shifrin +--- + drivers/mtd/spi-nor/Kconfig | 8 + + drivers/mtd/spi-nor/Makefile | 1 + + drivers/mtd/spi-nor/renesas-rpc.c | 1429 +++++++++++++++++++++++++++++++++++++ + 3 files changed, 1438 insertions(+) + create mode 100644 drivers/mtd/spi-nor/renesas-rpc.c + +diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig +index 4a682ee..298dc1d 100644 +--- a/drivers/mtd/spi-nor/Kconfig ++++ b/drivers/mtd/spi-nor/Kconfig +@@ -7,6 +7,14 @@ menuconfig MTD_SPI_NOR + + if MTD_SPI_NOR + ++ ++config SPI_RENESAS_RPC ++ tristate "Renesas RPC controller" ++ depends on ARCH_R8A7795 || ARCH_R8A7796 || ARCH_R8A7797 || ARCH_R8A7798 || COMPILE_TEST ++ help ++ QSPI driver for Renesas SPI Multi I/O Bus controller. This controller ++ supports normal, dual and quad spi for one or two SPI NOR Flashes. ++ + config MTD_MT81xx_NOR + tristate "Mediatek MT81xx SPI NOR flash controller" + depends on HAS_IOMEM +diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile +index 121695e..e99d775 100644 +--- a/drivers/mtd/spi-nor/Makefile ++++ b/drivers/mtd/spi-nor/Makefile +@@ -5,3 +5,4 @@ obj-$(CONFIG_SPI_FSL_QUADSPI) += fsl-quadspi.o + obj-$(CONFIG_SPI_HISI_SFC) += hisi-sfc.o + obj-$(CONFIG_MTD_MT81xx_NOR) += mtk-quadspi.o + obj-$(CONFIG_SPI_NXP_SPIFI) += nxp-spifi.o ++obj-$(CONFIG_SPI_RENESAS_RPC) += renesas-rpc.o +diff --git a/drivers/mtd/spi-nor/renesas-rpc.c b/drivers/mtd/spi-nor/renesas-rpc.c +new file mode 100644 +index 0000000..1e93c98 +--- /dev/null ++++ b/drivers/mtd/spi-nor/renesas-rpc.c +@@ -0,0 +1,1429 @@ ++/* ++ * Renesas RPC driver ++ * ++ * Copyright (C) 2018, 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; version 2 of the License. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++ ++#define CMNCR 0x0000 ++#define SSLDR 0x0004 ++#define DRCR 0x000C ++#define DRCMR 0x0010 ++#define DREAR 0x0014 ++#define DROPR 0x0018 ++#define DRENR 0x001C ++#define SMCR 0x0020 ++#define SMCMR 0x0024 ++#define SMADR 0x0028 ++#define SMOPR 0x002C ++#define SMENR 0x0030 ++#define SMRDR0 0x0038 ++#define SMRDR1 0x003C ++#define SMWDR0 0x0040 ++#define SMWDR1 0x0044 ++#define CMNSR 0x0048 ++#define DRDMCR 0x0058 ++#define DRDRENR 0x005C ++#define SMDMCR 0x0060 ++#define SMDRENR 0x0064 ++#define PHYCNT 0x007C ++#define PHYOFFSET1 0x0080 ++#define PHYOFFSET2 0x0084 ++#define PHYINT 0x0088 ++#define DIV_REG 0x00A8 ++ ++/* CMNCR */ ++#define CMNCR_BSZ_MASK (0x03) ++#define CMNCR_BSZ_4x1 (0x0) ++#define CMNCR_BSZ_8x1 (0x1) ++#define CMNCR_BSZ_4x2 (0x1) ++#define CMNCR_MD (0x1 << 31) ++#define CMNCR_MOIIO3_MASK (0x3 << 22) ++#define CMNCR_MOIIO3_HIZ (0x3 << 22) ++#define CMNCR_MOIIO2_MASK (0x3 << 20) ++#define CMNCR_MOIIO2_HIZ (0x3 << 20) ++#define CMNCR_MOIIO1_MASK (0x3 << 18) ++#define CMNCR_MOIIO1_HIZ (0x3 << 18) ++#define CMNCR_MOIIO0_MASK (0x3 << 16) ++#define CMNCR_MOIIO0_HIZ (0x3 << 16) ++#define CMNCR_IO0FV_MASK (0x3 << 8) ++#define CMNCR_IO0FV_HIZ (0x3 << 8) ++ ++ ++/* DRCR */ ++#define DRCR_RBURST_MASK (0x1f << 16) ++#define DRCR_RBURST(v) (((v) & 0x1f) << 16) ++#define DRCR_SSLE (0x1) ++#define DRCR_RBE (0x1 << 8) ++#define DRCR_RCF (0x1 << 9) ++#define DRCR_RBURST_32 (0x1f << 16) ++ ++ ++/* SMENR */ ++#define SMENR_CDB_MASK (0x03 << 30) ++#define SMENR_CDB(v) (((v) & 0x03) << 30) ++#define SMENR_CDB_1B (0) ++#define SMENR_CDB_2B (0x1 << 30) ++#define SMENR_CDB_4B (0x2 << 30) ++#define SMENR_OCDB_MASK (0x03 << 28) ++#define SMENR_OCDB_1B (0) ++#define SMENR_OCDB_2B (0x1 << 28) ++#define SMENR_OCDB_4B (0x2 << 28) ++#define SMENR_ADB_MASK (0x03 << 24) ++#define SMENR_ADB(v) (((v) & 0x03) << 24) ++#define SMENR_ADB_1B (0) ++#define SMENR_ADB_2B (0x1 << 24) ++#define SMENR_ADB_4B (0x2 << 24) ++#define SMENR_OPDB_MASK (0x03 << 20) ++#define SMENR_OPDB_1B (0) ++#define SMENR_OPDB_2B (0x1 << 20) ++#define SMENR_OPDB_4B (0x2 << 20) ++#define SMENR_SPIDB_MASK (0x03 << 16) ++#define SMENR_SPIDB(v) (((v) & 0x03) << 16) ++#define SMENR_SPIDB_1B (0) ++#define SMENR_SPIDB_2B (0x1 << 16) ++#define SMENR_SPIDB_4B (0x2 << 16) ++#define SMENR_OPDE_MASK (0xf << 4) ++#define SMENR_OPDE_DISABLE (0) ++#define SMENR_OPDE3 (0x8 << 4) ++#define SMENR_OPDE32 (0xC << 4) ++#define SMENR_OPDE321 (0xE << 4) ++#define SMENR_OPDE3210 (0xF << 4) ++#define SMENR_SPIDE_MASK (0x0F) ++#define SMENR_SPIDE_DISABLE (0) ++#define SMENR_SPIDE_8B (0x08) ++#define SMENR_SPIDE_16B (0x0C) ++#define SMENR_SPIDE_32B (0x0F) ++#define SMENR_DME (1<<15) ++#define SMENR_CDE (1<<14) ++#define SMENR_OCDE (1<<12) ++#define SMENR_ADE_MASK (0xf << 8) ++#define SMENR_ADE_DISABLE (0) ++#define SMENR_ADE_23_16 (0x4 << 8) ++#define SMENR_ADE_23_8 (0x6 << 8) ++#define SMENR_ADE_23_0 (0x7 << 8) ++#define SMENR_ADE_31_0 (0xf << 8) ++ ++ ++/* SMCMR */ ++#define SMCMR_CMD(cmd) (((cmd) & 0xff) << 16) ++#define SMCMR_CMD_MASK (0xff << 16) ++#define SMCMR_OCMD(cmd) (((cmd) & 0xff)) ++#define SMCMR_OCMD_MASK (0xff) ++ ++ ++/* SMDRENR */ ++#define SMDRENR_HYPE_MASK (0x7 << 12) ++#define SMDRENR_HYPE_SPI_FLASH (0x0) ++#define SMDRENR_ADDRE (0x1 << 8) ++#define SMDRENR_OPDRE (0x1 << 4) ++#define SMDRENR_SPIDRE (0x1) ++ ++/* PHYCNT */ ++#define PHYCNT_CAL (0x1 << 31) ++#define PHYCNT_OCTA_MASK (0x3 << 22) ++#define PHYCNT_EXDS (0x1 << 21) ++#define PHYCNT_OCT (0x1 << 20) ++#define PHYCNT_DDRCAL (0x1 << 19) ++#define PHYCNT_HS (0x1 << 18) ++#define PHYCNT_STREAM_MASK (0x7 << 15) ++#define PHYCNT_STREAM(o) (((o) & 0x7) << 15) ++#define PHYCNT_WBUF2 (0x1 << 4) ++#define PHYCNT_WBUF (0x1 << 2) ++#define PHYCNT_PHYMEM_MASK (0x3) ++ ++/* SMCR */ ++#define SMCR_SSLKP (0x1 << 8) ++#define SMCR_SPIRE (0x1 << 2) ++#define SMCR_SPIWE (0x1 << 1) ++#define SMCR_SPIE (0x1) ++ ++/* CMNSR */ ++#define CMNSR_TEND (0x1 << 0) ++ ++/* SSLDR */ ++#define SSLDR_SPNDL(v) (((v) & 0x7) << 16) ++#define SSLDR_SLNDL(v) ((((v) | 0x4) & 0x7) << 8) ++#define SSLDR_SCKDL(v) ((v) & 0x7) ++ ++/* DREAR */ ++#define DREAR_EAV_MASK (0xff << 16) ++#define DREAR_EAV(v) (((v) & 0xff) << 16) ++#define DREAR_EAC_MASK (0x7) ++#define DREAR_24B (0) ++#define DREAR_25B (1) ++ ++/* DRENR */ ++#define DRENR_CDB_MASK (0x03 << 30) ++#define DRENR_CDB(v) (((v) & 0x3) << 30) ++#define DRENR_CDB_1B (0) ++#define DRENR_CDB_2B (0x1 << 30) ++#define DRENR_CDB_4B (0x2 << 30) ++#define DRENR_OCDB_MASK (0x03 << 28) ++#define DRENR_OCDB_1B (0) ++#define DRENR_OCDB_2B (0x1 << 28) ++#define DRENR_OCDB_4B (0x2 << 28) ++#define DRENR_ADB_MASK (0x03 << 24) ++#define DRENR_ADB(v) (((v) & 0x3) << 24) ++#define DRENR_ADB_1B (0) ++#define DRENR_ADB_2B (0x1 << 24) ++#define DRENR_ADB_4B (0x2 << 24) ++#define DRENR_OPDB_MASK (0x03 << 20) ++#define DRENR_OPDB_1B (0) ++#define DRENR_OPDB_2B (0x1 << 20) ++#define DRENR_OPDB_4B (0x2 << 20) ++#define DRENR_DRDB_MASK (0x03 << 16) ++#define DRENR_DRDB(v) (((v) & 0x3) << 16) ++#define DRENR_DRDB_1B (0) ++#define DRENR_DRDB_2B (0x1 << 16) ++#define DRENR_DRDB_4B (0x2 << 16) ++#define DRENR_OPDE_MASK (0xf << 4) ++#define DRENR_OPDE_DISABLE (0) ++#define DRENR_OPDE3 (0x8 << 4) ++#define DRENR_OPDE32 (0xC << 4) ++#define DRENR_OPDE321 (0xE << 4) ++#define DRENR_OPDE3210 (0xF << 4) ++#define DRENR_DME (1<<15) ++#define DRENR_CDE (1<<14) ++#define DRENR_OCDE (1<<12) ++#define DRENR_ADE_MASK (0xf << 8) ++#define DRENR_ADE_DISABLE (0) ++#define DRENR_ADE_23_0 (0x7 << 8) ++#define DRENR_ADE_31_0 (0xf << 8) ++ ++/* DRCMR */ ++#define DRCMR_CMD(cmd) (((cmd) & 0xff) << 16) ++#define DRCMR_CMD_MASK (0xff << 16) ++#define DRCMR_OCMD(cmd) (((cmd) & 0xff)) ++#define DRCMR_OCMD_MASK (0xff) ++ ++/* DRCMR */ ++#define DRDMCR_DMCYC(v) ((v) & 0x1f) ++#define DRDMCR_DMCYC_MASK (0x1f) ++ ++/* SMDMCR */ ++#define SMDMCR_DMCYC(v) ((v) & 0x0f) ++#define SMDMCR_DMCYC_MASK (0x0f) ++ ++/* PHYOFFSET1 */ ++#define PHYOFFSET1_DDRTMG (1 << 28) ++ ++/* DIVREG */ ++#define DIVREG_RATIO_MASK (0x03) ++#define DIVREG_RATIO(v) ((v) & 0x03) ++#define DIVREG_RATIO_MAX (0x2) ++ ++ ++#define DEFAULT_TO (100) ++#define WRITE_BUF_SIZE (0x100) ++#define WRITE_BUF_ADR_MASK (0xff) ++ ++#define REPEAT_MAX (20) ++#define REPEAT_TIME (10) ++ ++ ++struct rpc_spi { ++ struct platform_device *pdev; ++ void __iomem *base; ++ void __iomem *read_area; ++ void __iomem *write_area; ++ struct clk *clk; ++ unsigned int irq; ++ struct spi_nor spi_nor; ++ ++#define MTD_QSPI_1x 0 ++#define MTD_QSPI_2x 1 ++ ++ u32 mtdtype; ++}; ++ ++ ++ ++/* IP block use it's own clock divigion register */ ++#define OWN_CLOCK_DIVIDER BIT(0) ++ ++ ++ ++static void regs_dump(struct rpc_spi *rpc) ++{ ++ static u32 regs[] = { ++ CMNCR, SSLDR, DRCR, DRCMR, DREAR, ++ DROPR, DRENR, SMCR, SMCMR, SMADR, ++ SMOPR, SMENR, SMRDR0, SMRDR1, SMWDR0, ++ SMWDR1, CMNSR, DRDMCR, DRDRENR, SMDMCR, ++ SMDRENR, PHYCNT, PHYOFFSET1, PHYOFFSET2, ++ PHYINT ++ }; ++ ++ static const char *const names[] = { ++ "CMNCR", "SSLDR", "DRCR", "DRCMR", "DREAR", ++ "DROPR", "DRENR", "SMCR", "SMCMR", "SMADR", ++ "SMOPR", "SMENR", "SMRDR0", "SMRDR1", "SMWDR0", ++ "SMWDR1", "CMNSR", "DRDMCR", "DRDRENR", "SMDMCR", ++ "SMDRENR", "PHYCNT", "PHYOFFSET1", "PHYOFFSET2", ++ "PHYINT" ++ }; ++ ++ int i; ++ ++ dev_dbg(&rpc->pdev->dev, "RPC regs dump:\n"); ++ for (i = 0; i < ARRAY_SIZE(regs); i++) ++ dev_dbg(&rpc->pdev->dev, "%s = 0x%08x\n", names[i], ++ readl(rpc->base + regs[i])); ++} ++ ++ ++ ++ ++ ++static u32 rpc_read(struct rpc_spi *rpc, unsigned int reg) ++{ ++ u32 val; ++ ++ val = readl(rpc->base + reg); ++ return val; ++} ++ ++static void rpc_write(struct rpc_spi *rpc, unsigned int reg, u32 val) ++{ ++ writel(val, rpc->base + reg); ++} ++ ++ ++static int rpc_wait(struct rpc_spi *rpc, u32 to) ++{ ++ u32 val; ++ int i; ++ ++ for (i = 0; i < to; i++) { ++ val = rpc_read(rpc, CMNSR); ++ val &= CMNSR_TEND; ++ if (val) ++ break; ++ ++ udelay(100); ++ } ++ ++ if (i == to) { ++ dev_err(&rpc->pdev->dev, "timeout waiting for operation end %d\n", ++ rpc_read(rpc, CMNSR)); ++ return -ETIMEDOUT; ++ } ++ ++ return 0; ++} ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++static int rpc_setup_clk_ratio(struct rpc_spi *rpc, u32 max_clk_rate) ++{ ++ unsigned long rate = clk_get_rate(rpc->clk); ++ u32 ratio; ++ u32 val; ++ ++ ratio = DIV_ROUND_UP(rate, max_clk_rate * 2) >> 1; ++ if (ratio > DIVREG_RATIO_MAX) ++ ratio = DIVREG_RATIO_MAX; ++ ++ val = rpc_read(rpc, DIV_REG); ++ val &= DIVREG_RATIO_MASK; ++ val |= DIVREG_RATIO(ratio); ++ rpc_write(rpc, DIV_REG, val); ++ ++ return 0; ++} ++ ++static int rpc_endisable_write_buf(struct rpc_spi *rpc, bool en) ++{ ++ u32 val; ++ ++ val = rpc_read(rpc, PHYCNT); ++ ++ if (en) ++ val |= PHYCNT_WBUF | PHYCNT_WBUF2; ++ else ++ val &= ~(PHYCNT_WBUF | PHYCNT_WBUF2); ++ ++ rpc_write(rpc, PHYCNT, val); ++ ++ return 0; ++} ++ ++ ++static int rpc_begin(struct rpc_spi *rpc, ++ bool rx, bool tx, bool last) ++{ ++ u32 val = SMCR_SPIE; ++ ++ if (rx) ++ val |= SMCR_SPIRE; ++ ++ if (tx) ++ val |= SMCR_SPIWE; ++ ++ if (!last) ++ val |= SMCR_SSLKP; ++ ++ rpc_write(rpc, SMCR, val); ++ ++ return 0; ++} ++ ++ ++static int rpc_setup_reg_mode(struct rpc_spi *rpc) ++{ ++ u32 val; ++ ++ rpc_wait(rpc, DEFAULT_TO); ++ ++ rpc_endisable_write_buf(rpc, false); ++ ++ /* ...setup manual mode */ ++ val = rpc_read(rpc, CMNCR); ++ val |= CMNCR_MD; ++ rpc_write(rpc, CMNCR, val); ++ ++ /* disable ddr */ ++ val = rpc_read(rpc, SMDRENR); ++ val &= ~(SMDRENR_ADDRE | SMDRENR_OPDRE | SMDRENR_SPIDRE); ++ rpc_write(rpc, SMDRENR, val); ++ ++ /* enable 1bit command */ ++ val = rpc_read(rpc, SMENR); ++ val &= ~(SMENR_CDB_MASK | SMENR_OCDB_MASK | SMENR_DME ++ | SMENR_OCDE | SMENR_SPIDB_MASK ++ | SMENR_ADE_MASK | SMENR_ADB_MASK ++ | SMENR_OPDE_MASK | SMENR_SPIDE_MASK); ++ val |= SMENR_CDB_1B | SMENR_CDE | SMENR_SPIDE_32B; ++ rpc_write(rpc, SMENR, val); ++ ++ ++ return 0; ++} ++ ++static void rpc_flush_cache(struct rpc_spi *rpc) ++{ ++ u32 val; ++ ++ val = rpc_read(rpc, DRCR); ++ val |= DRCR_RCF; ++ ++ rpc_write(rpc, DRCR, val); ++} ++ ++ ++static int rpc_setup_ext_mode(struct rpc_spi *rpc) ++{ ++ u32 val; ++ u32 cmncr; ++ ++ rpc_wait(rpc, DEFAULT_TO); ++ ++ rpc_endisable_write_buf(rpc, false); ++ ++ /* ...setup ext mode */ ++ val = rpc_read(rpc, CMNCR); ++ cmncr = val; ++ val &= ~(CMNCR_MD); ++ rpc_write(rpc, CMNCR, val); ++ ++ /* ...enable burst and clear cache */ ++ val = rpc_read(rpc, DRCR); ++ val &= ~(DRCR_RBURST_MASK | DRCR_RBE | DRCR_SSLE); ++ val |= DRCR_RBURST(0x1f) | DRCR_RBE; ++ ++ if (cmncr & CMNCR_MD) ++ val |= DRCR_RCF; ++ ++ rpc_write(rpc, DRCR, val); ++ ++ return 0; ++} ++ ++ ++static int rpc_setup_data_size(struct rpc_spi *rpc, u32 size, bool copy) ++{ ++ u32 val; ++ ++ val = rpc_read(rpc, SMENR); ++ val &= ~(SMENR_SPIDE_MASK); ++ ++ if (rpc->mtdtype == MTD_QSPI_2x && !copy) ++ size >>= 1; ++ ++ switch (size) { ++ case 0: ++ break; ++ case 1: ++ val |= SMENR_SPIDE_8B; ++ break; ++ case 2: ++ val |= SMENR_SPIDE_16B; ++ break; ++ case 4: ++ val |= SMENR_SPIDE_32B; ++ break; ++ default: ++ dev_err(&rpc->pdev->dev, "Unsupported data width %d\n", size); ++ return -EINVAL; ++ } ++ rpc_write(rpc, SMENR, val); ++ ++ return 0; ++} ++ ++ ++static int rpc_setup_extmode_read_addr(struct rpc_spi *rpc, ++ int adr_width, loff_t adr) ++{ ++ u32 val; ++ u32 v; ++ ++ val = rpc_read(rpc, DREAR); ++ val &= ~(DREAR_EAV_MASK | DREAR_EAC_MASK); ++ ++ if (adr_width == 4) { ++ v = adr >> 25; ++ val |= DREAR_EAV(v) | DREAR_25B; ++ } ++ rpc_write(rpc, DREAR, val); ++ ++ val = rpc_read(rpc, DRENR); ++ val &= ~(DRENR_ADE_MASK); ++ if (adr_width == 4) ++ val |= DRENR_ADE_31_0; ++ else ++ val |= DRENR_ADE_23_0; ++ rpc_write(rpc, DRENR, val); ++ ++ return 0; ++} ++ ++ ++ ++#define NBITS_TO_VAL(v) ((v >> 1) & 3) ++static int rpc_setup_extmode_nbits(struct rpc_spi *rpc, int cnb, ++ int anb, int dnb) ++{ ++ u32 val; ++ ++ val = rpc_read(rpc, DRENR); ++ val &= ~(DRENR_CDB_MASK | DRENR_ADB_MASK | DRENR_DRDB_MASK); ++ val |= DRENR_CDB(NBITS_TO_VAL(cnb)) ++ | DRENR_ADB(NBITS_TO_VAL(anb)) ++ | DRENR_DRDB(NBITS_TO_VAL(dnb)); ++ rpc_write(rpc, DRENR, val); ++ ++ return 0; ++} ++ ++static int rpc_setup_writemode_nbits(struct rpc_spi *rpc, int cnb, ++ int anb, int dnb) ++{ ++ u32 val; ++ ++ val = rpc_read(rpc, SMENR); ++ val &= ~(SMENR_CDB_MASK | SMENR_ADB_MASK | SMENR_SPIDB_MASK); ++ val |= SMENR_CDB(NBITS_TO_VAL(cnb)) ++ | SMENR_ADB(NBITS_TO_VAL(anb)) ++ | SMENR_SPIDB(NBITS_TO_VAL(dnb)); ++ rpc_write(rpc, SMENR, val); ++ ++ return 0; ++} ++ ++static void rpc_setup_write_mode_command_and_adr(struct rpc_spi *rpc, ++ int adr_width, bool ena) ++{ ++ u32 val; ++ ++ val = rpc_read(rpc, SMENR); ++ val &= ~(SMENR_CDB_MASK | SMENR_CDE | SMENR_ADE_MASK); ++ ++ if (ena) { ++ /* enable 1bit command */ ++ val |= SMENR_CDB_1B | SMENR_CDE; ++ ++ if (adr_width == 4) ++ val |= SMENR_ADE_31_0; ++ else ++ val |= SMENR_ADE_23_0; ++ } ++ rpc_write(rpc, SMENR, val); ++} ++ ++static int rpc_setup_write_mode(struct rpc_spi *rpc) ++{ ++ u32 val; ++ ++ rpc_wait(rpc, DEFAULT_TO); ++ ++ rpc_endisable_write_buf(rpc, true); ++ ++ /* ...setup manual mode */ ++ val = rpc_read(rpc, CMNCR); ++ val |= CMNCR_MD; ++ rpc_write(rpc, CMNCR, val); ++ ++ /* disable ddr */ ++ val = rpc_read(rpc, SMDRENR); ++ val &= ~(SMDRENR_ADDRE | SMDRENR_OPDRE | SMDRENR_SPIDRE); ++ rpc_write(rpc, SMDRENR, val); ++ ++ val = rpc_read(rpc, SMENR); ++ val &= ~(SMENR_OCDB_MASK | SMENR_DME | SMENR_OCDE | SMENR_SPIDB_MASK ++ | SMENR_ADB_MASK | SMENR_OPDE_MASK | SMENR_SPIDE_MASK); ++ val |= SMENR_SPIDE_32B; ++ rpc_write(rpc, SMENR, val); ++ ++ return 0; ++} ++ ++static void rpc_read_manual_data(struct rpc_spi *rpc, u32 *pv0, u32 *pv1) ++{ ++ u32 val0, val1, rd0, rd1; ++ ++ val0 = rpc_read(rpc, SMRDR0); ++ val1 = rpc_read(rpc, SMRDR1); ++ ++ if (rpc->mtdtype == MTD_QSPI_2x) { ++ rd1 = (val0 & 0xff000000) | ((val0 << 8) & 0xff0000) | ++ ((val1 >> 16) & 0xff00) | ((val1 >> 8) & 0xff); ++ rd0 = ((val0 & 0xff0000) << 8) | ((val0 << 16) & 0xff0000) | ++ ((val1 >> 8) & 0xff00) | (val1 & 0xff); ++ } else ++ rd0 = val0; ++ ++ if (pv0) ++ *pv0 = rd0; ++ ++ if (pv1 && rpc->mtdtype == MTD_QSPI_2x) ++ *pv1 = rd1; ++} ++ ++ ++static int rpc_datalen2trancfersize(struct rpc_spi *rpc, int len, bool copy) ++{ ++ int sz = len; ++ ++ if (len >= 2) ++ sz = 2; ++ ++ if (len >= 4) ++ sz = 4; ++ ++ if (rpc->mtdtype == MTD_QSPI_2x ++ && len >= 8 && !copy) ++ sz = 8; ++ ++ return sz; ++} ++ ++static int __rpc_write_data2reg(struct rpc_spi *rpc, int off, ++ const u8 *buf, int sz) ++{ ++ const u32 *b32 = (const u32 *)buf; ++ const u16 *b16 = (const u16 *)buf; ++ ++ if (sz == 4) ++ rpc_write(rpc, off, *b32); ++ else if (sz == 2) ++ writew(*b16, rpc->base+off); ++ else if (sz == 1) ++ writeb(*buf, rpc->base+off); ++ else if (sz != 0) { ++ dev_err(&rpc->pdev->dev, "incorrect data size %d\n", sz); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++#define __SETVAL(x) ((((x) & 0xff) << 8) | ((x) & 0xff)) ++static int rpc_write_data2reg(struct rpc_spi *rpc, const u8 *buf, ++ int sz, bool copy) ++{ ++ int i, ret; ++ u32 v = 0; ++ ++ if (rpc->mtdtype == MTD_QSPI_2x) { ++ if (copy) { ++ for (i = 0; i < sz && i < 2; i++) ++ v |= (__SETVAL(buf[i]) << 16*i); ++ ++ ret = __rpc_write_data2reg(rpc, ++ sz == 4 ? SMWDR1 : SMWDR0, ++ (u8 *)&v, ++ sz == 4 ? sz : sz * 2); ++ if (ret) ++ return ret; ++ ++ v = 0; ++ for (; i < sz; i++) ++ v |= (__SETVAL(buf[i]) << 16*i); ++ ++ ++ ret = __rpc_write_data2reg(rpc, ++ sz == 4 ? SMWDR0 : SMWDR1, ++ (u8 *)&v, ++ sz == 4 ? sz : sz * 2); ++ if (ret) ++ return ret; ++ ++ return 0; ++ } ++ ++ sz >>= 1; ++ ret = __rpc_write_data2reg(rpc, ++ sz == 4 ? SMWDR1 : SMWDR0, ++ buf, ++ sz == 4 ? sz : sz * 2); ++ if (ret) ++ return ret; ++ buf += sz; ++ ++ return __rpc_write_data2reg(rpc, ++ sz == 4 ? SMWDR0 : SMWDR1, ++ buf, sz == 4 ? sz : sz * 2); ++ } ++ ++ return __rpc_write_data2reg(rpc, SMWDR0, buf, sz); ++} ++ ++static ssize_t rpc_write_unaligned(struct spi_nor *nor, loff_t to, size_t len, ++ const u_char *buf, size_t fullen) ++{ ++ int ret = len, dsize; ++ struct rpc_spi *rpc = nor->priv; ++ bool copy = false, last; ++ loff_t _to; ++ ++ rpc_endisable_write_buf(rpc, false); ++ ++ while (len > 0) { ++ _to = to; ++ if (rpc->mtdtype == MTD_QSPI_2x) ++ _to >>= 1; ++ rpc_write(rpc, SMADR, _to); ++ dsize = rpc_datalen2trancfersize(rpc, len, copy); ++ ++ if (rpc_setup_data_size(rpc, dsize, copy)) ++ return -EINVAL; ++ ++ rpc_write_data2reg(rpc, buf, dsize, copy); ++ ++ last = (len <= dsize && fullen <= ret); ++ rpc_begin(rpc, false, true, last); ++ if (rpc_wait(rpc, DEFAULT_TO)) ++ return -ETIMEDOUT; ++ ++ /* ...disable command */ ++ rpc_setup_write_mode_command_and_adr(rpc, ++ nor->addr_width, false); ++ ++ buf += dsize; ++ len -= dsize; ++ to += dsize; ++ } ++ ++ return ret; ++} ++ ++ ++ ++ ++static ssize_t rpc_write_flash(struct spi_nor *nor, loff_t to, size_t len, ++ const u_char *buf) ++{ ++ ssize_t res = len, full = len; ++ u32 val; ++ u8 rval[2]; ++ struct rpc_spi *rpc = nor->priv; ++ loff_t bo; ++ loff_t offset; ++ loff_t _to; ++ bool is_rounded = false; ++ ++ /* ...len should be rounded to 2 bytes */ ++ if (rpc->mtdtype == MTD_QSPI_2x && (len & 1)) { ++ is_rounded = true; ++ len &= ~(1); ++ } ++ ++ bo = to & (WRITE_BUF_ADR_MASK); ++ ++ rpc_flush_cache(rpc); ++ rpc_setup_write_mode(rpc); ++ rpc_setup_write_mode_command_and_adr(rpc, nor->addr_width, true); ++ rpc_setup_writemode_nbits(rpc, 1, 1, 1); ++ ++ /* ...setup command */ ++ val = rpc_read(rpc, SMCMR); ++ val &= ~(SMCMR_CMD_MASK); ++ val |= SMCMR_CMD(nor->program_opcode); ++ rpc_write(rpc, SMCMR, val); ++ ++ offset = (to & (~WRITE_BUF_ADR_MASK)); ++ ++ /* ...write unaligned first bytes */ ++ if (bo) { ++ rpc_write_unaligned(nor, to, WRITE_BUF_SIZE - bo, buf, full); ++ rpc_setup_write_mode(rpc); ++ ++ len -= WRITE_BUF_SIZE - bo; ++ buf += WRITE_BUF_SIZE - bo; ++ to += WRITE_BUF_SIZE - bo; ++ full -= WRITE_BUF_SIZE - bo; ++ } ++ ++ /* Unfortunatly RPC does not write properly in write buf mode ++ * without transferring command. ++ * May be it is better just remove this code ++ */ ++ if (len >= WRITE_BUF_SIZE && !bo) { ++ _to = to; ++ if (rpc->mtdtype == MTD_QSPI_2x) ++ _to >>= 1; ++ rpc_write(rpc, SMADR, _to); ++ memcpy_toio(rpc->write_area, buf, WRITE_BUF_SIZE); ++ buf += WRITE_BUF_SIZE; ++ len -= WRITE_BUF_SIZE; ++ to += WRITE_BUF_SIZE; ++ full -= WRITE_BUF_SIZE; ++ ++ rpc_begin(rpc, false, true, full <= 0); ++ if (rpc_wait(rpc, DEFAULT_TO)) ++ return -ETIMEDOUT; ++ ++ rpc_setup_write_mode_command_and_adr(rpc, ++ nor->addr_width, false); ++ } ++ ++ if (len) { ++ rpc_write_unaligned(nor, to, len, buf, full); ++ buf += len; ++ to += len; ++ full -= len; ++ len = 0; ++ } ++ ++ if (is_rounded) { ++ rval[0] = *buf; ++ rval[1] = 0xFF; ++ rpc_write_unaligned(nor, to, 2, rval, full); ++ } ++ ++ rpc_flush_cache(rpc); ++ ++ return res; ++} ++ ++static inline unsigned int rpc_rx_nbits(struct spi_nor *nor) ++{ ++ switch (nor->flash_read) { ++ case SPI_NOR_DUAL: ++ return 2; ++ case SPI_NOR_QUAD: ++ return 4; ++ default: ++ return 0; ++ } ++} ++ ++ ++#if 0 ++//manual read ++static ssize_t rpc_read_flash(struct spi_nor *nor, loff_t from, size_t len, ++ u_char *buf) ++{ ++ ssize_t ret = len; ++ struct rpc_spi *rpc = nor->priv; ++ int adr_width = nor->addr_width; ++ int opcode_nbits = 1;//SPI_NBITS_SINGLE; ++ int addr_nbits = spi_nor_get_read_addr_nbits(nor->read_opcode); ++ int data_nbits = rpc_rx_nbits(nor); ++ int dummy = nor->read_dummy - 1; ++ u32 val, val2; ++ u32 *buf32; ++ int sz = 4; ++ int i, j; ++ loff_t adr = from; ++ ++ rpc_wait(rpc, DEFAULT_TO); ++ if (rpc->mtdtype == MTD_QSPI_2x) ++ sz <<= 1; ++ ++ /* ...setup manual mode */ ++ val = rpc_read(rpc, CMNCR); ++ val |= CMNCR_MD; ++ rpc_write(rpc, CMNCR, val); ++ ++ /*...setup dummy */ ++ val = rpc_read(rpc, SMDMCR); ++ val &= ~(SMDMCR_DMCYC_MASK); ++ val |= SMDMCR_DMCYC(dummy); ++ rpc_write(rpc, SMDMCR, val); ++ ++ /* disable ddr */ ++ val = rpc_read(rpc, SMDRENR); ++ val &= ~(SMDRENR_ADDRE | SMDRENR_OPDRE | SMDRENR_SPIDRE); ++ rpc_write(rpc, SMDRENR, val); ++ ++ /* enable 1bit command */ ++ val = rpc_read(rpc, SMENR); ++ val &= ~(SMENR_CDB_MASK | SMENR_OCDB_MASK | SMENR_DME ++ | SMENR_OCDE | SMENR_SPIDB_MASK ++ | SMENR_ADE_MASK | SMENR_ADB_MASK ++ | SMENR_OPDE_MASK | SMENR_SPIDE_MASK); ++ val |= SMENR_CDB_1B | SMENR_ADB_4B | SMENR_SPIDB_4B ++ | SMENR_CDE | SMENR_ADE_31_0 | SMENR_DME | SMENR_SPIDE_32B; ++ rpc_write(rpc, SMENR, val); ++ ++ /* ...setup command */ ++ val = rpc_read(rpc, SMCMR); ++ val &= ~(SMCMR_CMD_MASK); ++ val |= SMCMR_CMD(nor->read_opcode); ++ rpc_write(rpc, SMCMR, val); ++ ++ buf32 = (u32 *)buf; ++ ++ while (len > 0) { ++ adr = from + ret - len; ++ ++ if (rpc->mtdtype == MTD_QSPI_2x) ++ adr >>= 1; ++ ++ rpc_write(rpc, SMADR, adr); ++ ++ rpc_begin(rpc, true, false, len <= sz); ++ if (rpc_wait(rpc, DEFAULT_TO)) ++ return -ETIMEDOUT; ++ ++ rpc_read_manual_data(rpc, &val, &val2); ++ ++ j = 0; ++ do { ++ if (len > 4) { ++ *buf32 = val; ++ buf32++; ++ len -= 4; ++ } else { ++ buf = (u8 *)buf32; ++ for (i = 0; i < len; i++) { ++ *buf = (val >> (8 * i)) & 0x000000ff; ++ buf++; ++ } ++ len = 0; ++ } ++ val = val2; ++ j++; ++ } while (j < 2 && rpc->mtdtype == MTD_QSPI_2x); ++ } ++ ++ return ret; ++} ++#else ++#define READ_ADR_MASK (BIT(26) - 1) ++static ssize_t rpc_read_flash(struct spi_nor *nor, loff_t from, size_t len, ++ u_char *buf) ++{ ++ u32 val; ++ struct rpc_spi *rpc = nor->priv; ++ int adr_width = nor->addr_width; ++ int opcode_nbits = 1; ++ int addr_nbits = spi_nor_get_read_addr_nbits(nor->read_opcode); ++ int data_nbits = rpc_rx_nbits(nor); ++ int dummy = nor->read_dummy - 1; ++ ssize_t ret = len; ++ ssize_t readlen; ++ loff_t _from; ++ ++ rpc_setup_ext_mode(rpc); ++ /* ...setup n bits */ ++ rpc_setup_extmode_nbits(rpc, opcode_nbits, addr_nbits, data_nbits); ++ ++ /* TODO: setup DDR */ ++ ++ /* ...setup command */ ++ val = rpc_read(rpc, DRCMR); ++ val &= ~(DRCMR_CMD_MASK); ++ val |= DRCMR_CMD(nor->read_opcode); ++ rpc_write(rpc, DRCMR, val); ++ ++ /* ...setup dummy cycles */ ++ val = rpc_read(rpc, DRDMCR); ++ val &= ~(DRDMCR_DMCYC_MASK); ++ val |= DRDMCR_DMCYC(dummy); ++ rpc_write(rpc, DRDMCR, val); ++ ++ /* ...setup read sequence */ ++ val = rpc_read(rpc, DRENR); ++ val |= DRENR_DME | DRENR_CDE; ++ rpc_write(rpc, DRENR, val); ++ ++ while (len > 0) { ++ /* ...setup address */ ++ rpc_setup_extmode_read_addr(rpc, adr_width, from); ++ /* ...use adr [25...0] */ ++ _from = from & READ_ADR_MASK; ++ ++ readlen = READ_ADR_MASK - _from + 1; ++ readlen = readlen > len ? len : readlen; ++ ++ memcpy_fromio(buf, rpc->read_area + _from, readlen); ++ buf += readlen; ++ from += readlen; ++ len -= readlen; ++ } ++ ++ return ret; ++} ++#endif ++ ++static int __rpc_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) ++{ ++ u32 val, val2; ++ u32 *buf32; ++ int i; ++ u32 mask = 0, type; ++ struct rpc_spi *rpc = nor->priv; ++ ++ type = rpc->mtdtype; ++ ++ rpc_setup_reg_mode(rpc); ++ val = rpc_read(rpc, SMCMR); ++ val &= ~(SMCMR_CMD_MASK); ++ val |= SMCMR_CMD(opcode); ++ rpc_write(rpc, SMCMR, val); ++ ++ rpc_begin(rpc, true, false, len <= 4); ++ if (rpc_wait(rpc, DEFAULT_TO)) ++ return -ETIMEDOUT; ++ ++ /* ...disable command */ ++ val = rpc_read(rpc, SMENR); ++ val &= ~(SMENR_CDE); ++ rpc_write(rpc, SMENR, val); ++ ++ buf32 = (u32 *)buf; ++ ++ while (len > 0) { ++ rpc_read_manual_data(rpc, &val, &val2); ++ ++ if (mask) { ++ dev_warn(&rpc->pdev->dev, ++ "Using mask workaround (0x%x)\n", mask); ++ val &= ~(mask); ++ val2 &= ~(mask); ++ } ++ ++ /* ... spi flashes should be the same */ ++ if (type == MTD_QSPI_2x && val != val2) { ++ /* clear cs */ ++ rpc_begin(rpc, true, false, true); ++ return -EAGAIN; ++ } ++ ++ if (len > 4) { ++ *buf32 = val; ++ buf32++; ++ len -= 4; ++ } else { ++ buf = (u8 *)buf32; ++ for (i = 0; i < len; i++) { ++ *buf = (val >> (8 * i)) & 0x000000ff; ++ buf++; ++ } ++ len = 0; ++ } ++ ++ if (!len) ++ break; ++ ++ mask = 0xff; ++ ++ rpc_begin(rpc, true, false, len <= 4); ++ if (rpc_wait(rpc, DEFAULT_TO)) ++ return -ETIMEDOUT; ++ ++ } ++ ++ return 0; ++} ++ ++ ++static int rpc_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) ++{ ++ int i, ret; ++ ++ /* A few read commands like read status can ++ * generate different answers. We repeat reading ++ * in that case ++ */ ++ for (i = 0; i < REPEAT_MAX; i++) { ++ ret = __rpc_read_reg(nor, opcode, buf, len); ++ if (!ret || ret != -EAGAIN) ++ break; ++ mdelay(REPEAT_TIME); ++ } ++ ++ return ret; ++} ++ ++ ++ ++static int rpc_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) ++{ ++ struct rpc_spi *rpc = nor->priv; ++ u32 val; ++ int dsize; ++ bool copy = true; ++ ++ rpc_setup_reg_mode(rpc); ++ ++ val = rpc_read(rpc, SMCMR); ++ val &= ~(SMCMR_CMD_MASK); ++ val |= SMCMR_CMD(opcode); ++ rpc_write(rpc, SMCMR, val); ++ ++ dsize = rpc_datalen2trancfersize(rpc, len, copy); ++ ++ if (rpc_setup_data_size(rpc, dsize, copy)) ++ return -EINVAL; ++ ++ if (rpc_write_data2reg(rpc, buf, dsize, copy)) ++ return -EINVAL; ++ buf += dsize; ++ len -= dsize; ++ rpc_begin(rpc, false, dsize > 0, len == 0); ++ ++ if (rpc_wait(rpc, DEFAULT_TO)) ++ return -ETIMEDOUT; ++ ++ /* ...disable command */ ++ val = rpc_read(rpc, SMENR); ++ val &= ~(SMENR_CDE); ++ rpc_write(rpc, SMENR, val); ++ ++ while (len > 0) { ++ dsize = rpc_datalen2trancfersize(rpc, len, copy); ++ if (rpc_setup_data_size(rpc, dsize, copy)) ++ return -EINVAL; ++ rpc_write_data2reg(rpc, buf, dsize, copy); ++ buf += dsize; ++ len -= dsize; ++ ++ rpc_begin(rpc, false, dsize, len == 0); ++ ++ if (rpc_wait(rpc, DEFAULT_TO)) ++ return -ETIMEDOUT; ++ ++ } ++ ++ return 0; ++} ++ ++ ++ ++/* hw init for spi-nor flashes */ ++static int rpc_hw_init_1x2x(struct rpc_spi *rpc) ++{ ++ u32 val; ++ ++ /* Exec calibration */ ++ val = rpc_read(rpc, PHYCNT); ++ val &= ~(PHYCNT_OCTA_MASK | PHYCNT_EXDS | PHYCNT_OCT ++ | PHYCNT_DDRCAL | PHYCNT_HS | PHYCNT_STREAM_MASK ++ | PHYCNT_WBUF2 | PHYCNT_WBUF | PHYCNT_PHYMEM_MASK); ++ val |= (PHYCNT_CAL) | PHYCNT_STREAM(6); ++ rpc_write(rpc, PHYCNT, val); ++ ++ /* disable rpc_* pins */ ++ val = rpc_read(rpc, PHYINT); ++ val &= ~((1<<24) | (7<<16)); ++ rpc_write(rpc, PHYINT, val); ++ ++ val = rpc_read(rpc, SMDRENR); ++ val &= ~(SMDRENR_HYPE_MASK); ++ val |= SMDRENR_HYPE_SPI_FLASH; ++ rpc_write(rpc, SMDRENR, val); ++ ++ val = rpc_read(rpc, CMNCR); ++ val &= ~(CMNCR_BSZ_MASK); ++ if (rpc->mtdtype != MTD_QSPI_1x) ++ val |= CMNCR_BSZ_4x2; ++ rpc_write(rpc, CMNCR, val); ++ ++ val = rpc_read(rpc, PHYOFFSET1); ++ val |= PHYOFFSET1_DDRTMG; ++ rpc_write(rpc, PHYOFFSET1, val); ++ ++ val = SSLDR_SPNDL(0) | SSLDR_SLNDL(4) | SSLDR_SCKDL(0); ++ rpc_write(rpc, SSLDR, val); ++ ++ return 0; ++} ++ ++ ++static int rpc_hw_init(struct rpc_spi *rpc) ++{ ++ switch (rpc->mtdtype) { ++ case MTD_QSPI_1x: ++ case MTD_QSPI_2x: ++ return rpc_hw_init_1x2x(rpc); ++ ++ default: ++ dev_err(&rpc->pdev->dev, "Unsupported connection mode\n"); ++ return -ENODEV; ++ } ++} ++ ++ ++static int rpc_erase_sector(struct spi_nor *nor, loff_t addr) ++{ ++ struct rpc_spi *rpc = nor->priv; ++ u8 buf[6]; ++ int i; ++ ++ if (rpc->mtdtype == MTD_QSPI_2x) ++ addr >>= 1; ++ ++ for (i = nor->addr_width - 1; i >= 0; i--) { ++ buf[i] = addr & 0xff; ++ addr >>= 8; ++ } ++ ++ return nor->write_reg(nor, nor->erase_opcode, buf, nor->addr_width); ++} ++ ++ ++ ++ ++static const struct of_device_id rpc_of_match[] = { ++ { .compatible = "renesas,qspi-rpc-r8a7798" }, ++ { .compatible = "renesas,qspi-rpc-r8a7797", .data = (void *)OWN_CLOCK_DIVIDER }, ++ { }, ++}; ++ ++MODULE_DEVICE_TABLE(of, rpc_of_match); ++ ++ ++ ++static int rpc_spi_probe(struct platform_device *pdev) ++{ ++ struct device_node *flash_np; ++ struct spi_nor *nor; ++ struct rpc_spi *rpc; ++ struct resource *res; ++ enum read_mode mode = SPI_NOR_NORMAL; ++ u32 max_clk_rate = 50000000; ++ u32 property; ++ int ret; ++ int own_clk; ++ ++ ++ flash_np = of_get_next_available_child(pdev->dev.of_node, NULL); ++ if (!flash_np) { ++ dev_err(&pdev->dev, "no SPI flash device to configure\n"); ++ return -ENODEV; ++ } ++ ++ if (!of_property_read_u32(flash_np, "spi-rx-bus-width", &property)) { ++ switch (property) { ++ case 1: ++ break; ++ case 2: ++ mode = SPI_NOR_DUAL; ++ break; ++ case 4: ++ mode = SPI_NOR_QUAD; ++ break; ++ default: ++ dev_err(&pdev->dev, "unsupported rx-bus-width\n"); ++ return -EINVAL; ++ } ++ } ++ ++ of_property_read_u32(flash_np, "spi-max-frequency", &max_clk_rate); ++ own_clk = of_device_get_match_data(&pdev->dev); ++ ++ rpc = devm_kzalloc(&pdev->dev, sizeof(*rpc), GFP_KERNEL); ++ if (!rpc) ++ return -ENOMEM; ++ ++ rpc->pdev = pdev; ++ ++ /* ... setup nor hooks */ ++ nor = &rpc->spi_nor; ++ nor->dev = &pdev->dev; ++ spi_nor_set_flash_node(nor, flash_np); ++ nor->read = rpc_read_flash; ++ nor->write = rpc_write_flash; ++ nor->read_reg = rpc_read_reg; ++ nor->write_reg = rpc_write_reg; ++ nor->priv = rpc; ++ rpc->mtdtype = MTD_QSPI_1x; ++ if (of_find_property(pdev->dev.of_node, "dual", NULL)) { ++ rpc->mtdtype = MTD_QSPI_2x; ++ spi_nor_set_array_size(nor, 2); ++ } ++ if (rpc->mtdtype == MTD_QSPI_2x) ++ nor->erase = rpc_erase_sector; ++ ++ /* ...get memory */ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ rpc->base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(rpc->base)) { ++ dev_err(&pdev->dev, "cannot get resources\n"); ++ ret = PTR_ERR(rpc->base); ++ goto error; ++ } ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ ++ rpc->read_area = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(rpc->base)) { ++ dev_err(&pdev->dev, "cannot get resources\n"); ++ ret = PTR_ERR(rpc->base); ++ goto error; ++ } ++ ++ /* ...get memory */ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 2); ++ rpc->write_area = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(rpc->base)) { ++ dev_err(&pdev->dev, "cannot get resources\n"); ++ ret = PTR_ERR(rpc->base); ++ goto error; ++ } ++ ++ /* ...get clk */ ++ rpc->clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(rpc->clk)) { ++ dev_err(&pdev->dev, "cannot get clock\n"); ++ ret = PTR_ERR(rpc->clk); ++ goto error; ++ } ++ ++ /* ...set max clk rate */ ++ if (!own_clk) { ++ ret = clk_set_rate(rpc->clk, max_clk_rate); ++ if (ret) { ++ dev_err(&pdev->dev, "cannot set clock rate\n"); ++ goto error; ++ } ++ } ++ ++ /* ... enable clk */ ++ ret = clk_prepare_enable(rpc->clk); ++ if (ret) { ++ dev_err(&pdev->dev, "cannot prepare clock\n"); ++ goto error; ++ } ++ ++ /* ...init device */ ++ ret = rpc_hw_init(rpc); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "rpc_hw_init error.\n"); ++ goto error_clk_disable; ++ } ++ ++ /* ...set clk ratio */ ++ if (own_clk) { ++ ret = rpc_setup_clk_ratio(rpc, max_clk_rate); ++ if (ret) { ++ dev_err(&pdev->dev, "cannot set clock ratio\n"); ++ goto error; ++ } ++ } ++ ++ platform_set_drvdata(pdev, rpc); ++ ++ ret = spi_nor_scan(nor, NULL, mode); ++ if (ret) { ++ dev_err(&pdev->dev, "spi_nor_scan error.\n"); ++ goto error_clk_disable; ++ } ++ ++ ret = mtd_device_register(&nor->mtd, NULL, 0); ++ if (ret) { ++ dev_err(&pdev->dev, "mtd_device_register error.\n"); ++ goto error_clk_disable; ++ } ++ ++ dev_info(&pdev->dev, "probed as %s\n", ++ rpc->mtdtype == MTD_QSPI_1x ? "single" : "dual"); ++ ++ return 0; ++ ++ ++error_clk_disable: ++ clk_disable_unprepare(rpc->clk); ++error: ++ return ret; ++} ++ ++ ++ ++ ++static int rpc_spi_remove(struct platform_device *pdev) ++{ ++ struct rpc_spi *rpc = platform_get_drvdata(pdev); ++ ++ /* HW shutdown */ ++ clk_disable_unprepare(rpc->clk); ++ mtd_device_unregister(&rpc->spi_nor.mtd); ++ return 0; ++} ++ ++ ++ ++ ++ ++/* platform driver interface */ ++static struct platform_driver rpc_platform_driver = { ++ .probe = rpc_spi_probe, ++ .remove = rpc_spi_remove, ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "rpc", ++ .of_match_table = of_match_ptr(rpc_of_match), ++ }, ++}; ++ ++module_platform_driver(rpc_platform_driver); ++ ++ ++MODULE_ALIAS("rpc"); ++MODULE_AUTHOR("Cogent Embedded Inc. "); ++MODULE_DESCRIPTION("Renesas RPC Driver"); ++MODULE_LICENSE("GPL"); +-- +2.7.4 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0114-R8A7798-dtsi-Add-RPC-node-to-dtsi.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0114-R8A7798-dtsi-Add-RPC-node-to-dtsi.patch new file mode 100644 index 0000000..7169baa --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0114-R8A7798-dtsi-Add-RPC-node-to-dtsi.patch @@ -0,0 +1,35 @@ +From 80ebc1949eb5d7db33c60faa8537029fcf6379ba Mon Sep 17 00:00:00 2001 +From: Dmitry Shifrin +Date: Mon, 19 Mar 2018 11:14:26 +0300 +Subject: [PATCH 05/12] R8A7798: dtsi: Add RPC node to dtsi + +Signed-off-by: Dmitry Shifrin +--- + arch/arm64/boot/dts/renesas/r8a7798.dtsi | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a7798.dtsi b/arch/arm64/boot/dts/renesas/r8a7798.dtsi +index e2b3404..fac60e6 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7798.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a7798.dtsi +@@ -1026,6 +1026,17 @@ + status = "disabled"; + }; + ++ qspi0: qspi@ee200000 { ++ compatible = "renesas,qspi-rpc-r8a7798"; ++ reg = <0 0xee200000 0 0x1f0>, ++ <0 0x08000000 0 0x04000000>, ++ <0 0xee208000 0 0x100>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 917>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ + msiof0: spi@e6e90000 { + #address-cells = <1>; + #size-cells = <0>; +-- +2.7.4 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0115-R8A7798-condor-dts-Add-qspi-flash.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0115-R8A7798-condor-dts-Add-qspi-flash.patch new file mode 100644 index 0000000..213421c --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0115-R8A7798-condor-dts-Add-qspi-flash.patch @@ -0,0 +1,98 @@ +From 45ac82977a015e6ec80a1fb119b26c5b5841b760 Mon Sep 17 00:00:00 2001 +From: Dmitry Shifrin +Date: Mon, 19 Mar 2018 11:19:54 +0300 +Subject: [PATCH 06/12] R8A7798-condor: dts: Add qspi flash + +Add s25fs512 flash support + +Signed-off-by: Dmitry Shifrin +--- + arch/arm64/boot/dts/renesas/r8a7798-condor.dts | 72 ++++++++++++++++++++++++++ + 1 file changed, 72 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a7798-condor.dts b/arch/arm64/boot/dts/renesas/r8a7798-condor.dts +index cdd9844..81f984f1 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7798-condor.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7798-condor.dts +@@ -240,6 +240,78 @@ + groups = "tpu_to0"; + function = "tpu"; + }; ++ ++ qspi0_pins: qspi0 { ++ groups = "qspi0_ctrl", "qspi0_data4"; ++ function = "qspi0"; ++ }; ++ ++ qspi1_pins: qspi1 { ++ groups = "qspi1_ctrl", "qspi1_data4"; ++ function = "qspi1"; ++ }; ++}; ++ ++&qspi0 { ++ pinctrl-0 = <&qspi0_pins &qspi1_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++ ++ flash@0 { ++ compatible = "spansion,s25fs512s", "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <50000000>; ++ spi-rx-bus-width = <4>; ++ ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ bootparam@0 { ++ reg = <0x00000000 0x040000>; ++ read-only; ++ }; ++ cr7@00040000 { ++ reg = <0x00040000 0x080000>; ++ read-only; ++ }; ++ cert_header_sa3@000C0000 { ++ reg = <0x000C0000 0x080000>; ++ read-only; ++ }; ++ bl2@00140000 { ++ reg = <0x00140000 0x040000>; ++ read-only; ++ }; ++ cert_header_sa6@00180000 { ++ reg = <0x00180000 0x040000>; ++ read-only; ++ }; ++ bl31@001C0000 { ++ reg = <0x001C0000 0x460000>; ++ read-only; ++ }; ++ uboot@00640000 { ++ reg = <0x00640000 0x0C0000>; ++ read-only; ++ }; ++ uboot-env@00700000 { ++ reg = <0x00700000 0x040000>; ++ read-only; ++ }; ++ dtb@00740000 { ++ reg = <0x00740000 0x080000>; ++ }; ++ kernel@007C0000 { ++ reg = <0x007C0000 0x1400000>; ++ }; ++ user@01BC0000 { ++ reg = <0x01BC0000 0x2440000>; ++ }; ++ }; ++ }; + }; + + &scif0 { +-- +2.7.4 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0116-spi-nor-Add-s25fs512-flash-support.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0116-spi-nor-Add-s25fs512-flash-support.patch new file mode 100644 index 0000000..7a3500b --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0116-spi-nor-Add-s25fs512-flash-support.patch @@ -0,0 +1,126 @@ +From 1b2a145d72c4202fc41b2af138b862a8be94b0f0 Mon Sep 17 00:00:00 2001 +From: Dmitry Shifrin +Date: Mon, 19 Mar 2018 11:29:21 +0300 +Subject: [PATCH 07/12] spi-nor: Add s25fs512 flash support + +Signed-off-by: Dmitry Shifrin +--- + drivers/mtd/spi-nor/spi-nor.c | 31 ++++++++++++++++++++++++++++--- + include/linux/mtd/spi-nor.h | 15 +++++++++++++++ + 2 files changed, 43 insertions(+), 3 deletions(-) + +diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c +index d0fc165..1855bbe 100644 +--- a/drivers/mtd/spi-nor/spi-nor.c ++++ b/drivers/mtd/spi-nor/spi-nor.c +@@ -75,6 +75,7 @@ struct flash_info { + * bit. Must be used with + * SPI_NOR_HAS_LOCK. + */ ++#define SPANSION_S512FS_QUIRK BIT(10) + }; + + #define JEDEC_MFR(info) ((info)->id[0]) +@@ -222,8 +223,18 @@ static inline int spi_nor_sr_ready(struct spi_nor *nor) + int sr = read_sr(nor); + if (sr < 0) + return sr; +- else +- return !(sr & SR_WIP); ++ ++ if (nor->flags & SNOR_F_USE_CLSR && sr & (SR_E_ERR | SR_P_ERR)) { ++ if (sr & SR_E_ERR) ++ dev_err(nor->dev, "Erase Error occurred\n"); ++ else ++ dev_err(nor->dev, "Programming Error occurred\n"); ++ ++ nor->write_reg(nor, SPINOR_OP_CLSR, NULL, 0); ++ return -EIO; ++ } ++ ++ return !(sr & SR_WIP); + } + + static inline int spi_nor_fsr_ready(struct spi_nor *nor) +@@ -901,7 +912,21 @@ static const struct flash_info spi_nor_ids[] = { + { "s25sl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, 0) }, + { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, +- { "s25fl512s", INFO(0x010220, 0x4d00, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, ++ { "s25fl512s", INFO6(0x010220, 0x4d0080, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, ++ ++ { ++ "s25fs512s", INFO6(0x010220, 0x4d0081, 256 * 1024, 256, ++ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SECT_4K | SPANSION_S512FS_QUIRK) ++ }, ++ { ++ "s25fs128s0", INFO6(0x012018, 0x4d0381, 256 * 1024, 64, ++ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SECT_4K | SPANSION_S512FS_QUIRK) ++ }, ++ { ++ "s25fs128s1", INFO6(0x012018, 0x4d0181, 64 * 1024, 256, ++ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SECT_4K | SPANSION_S512FS_QUIRK) ++ }, ++ + { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) }, + { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, + { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) }, +diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h +index c425c7b..99f7b2a 100644 +--- a/include/linux/mtd/spi-nor.h ++++ b/include/linux/mtd/spi-nor.h +@@ -60,8 +60,10 @@ + #define SPINOR_OP_READ4_FAST 0x0c /* Read data bytes (high frequency) */ + #define SPINOR_OP_READ4_1_1_2 0x3c /* Read data bytes (Dual SPI) */ + #define SPINOR_OP_READ4_1_1_4 0x6c /* Read data bytes (Quad SPI) */ ++#define SPINOR_OP_READ4_1_4_4 0xec /* Read data bytes (Quad I/O SPI) */ + #define SPINOR_OP_PP_4B 0x12 /* Page program (up to 256 bytes) */ + #define SPINOR_OP_SE_4B 0xdc /* Sector erase (usually 64KiB) */ ++#define SPINOR_OP_BE_4K_4B 0x21 /* Erase 4KiB block */ + + /* Used for SST flashes only. */ + #define SPINOR_OP_BP 0x02 /* Byte program */ +@@ -74,6 +76,7 @@ + + /* Used for Spansion flashes only. */ + #define SPINOR_OP_BRWR 0x17 /* Bank register write */ ++#define SPINOR_OP_CLSR 0x30 /* Clear status register 1 */ + + /* Used for Micron flashes only. */ + #define SPINOR_OP_RD_EVCR 0x65 /* Read EVCR register */ +@@ -88,6 +91,9 @@ + #define SR_BP2 BIT(4) /* Block protect 2 */ + #define SR_TB BIT(5) /* Top/Bottom protect */ + #define SR_SRWD BIT(7) /* SR write protect */ ++/* Spansion/Cypress specific status bits */ ++#define SR_E_ERR BIT(5) ++#define SR_P_ERR BIT(6) + + #define SR_QUAD_EN_MX BIT(6) /* Macronix Quad I/O */ + +@@ -119,6 +125,7 @@ enum spi_nor_ops { + enum spi_nor_option_flags { + SNOR_F_USE_FSR = BIT(0), + SNOR_F_HAS_SR_TB = BIT(1), ++ SNOR_F_USE_CLSR = BIT(5), + }; + + /** +@@ -197,6 +204,14 @@ static inline struct device_node *spi_nor_get_flash_node(struct spi_nor *nor) + return mtd_get_of_node(&nor->mtd); + } + ++static inline int spi_nor_get_read_addr_nbits(u8 opcode) ++{ ++ if (opcode == SPINOR_OP_READ4_1_4_4) ++ return 4; ++ return 1; ++} ++ ++ + /** + * spi_nor_scan() - scan the SPI NOR + * @nor: the spi_nor structure +-- +2.7.4 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0117-spi-nor-Add-flash-array-support.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0117-spi-nor-Add-flash-array-support.patch new file mode 100644 index 0000000..5003ae6 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0117-spi-nor-Add-flash-array-support.patch @@ -0,0 +1,89 @@ +From 0d10eb085d28a442b147e63383d1836cb3e62ae4 Mon Sep 17 00:00:00 2001 +From: Dmitry Shifrin +Date: Mon, 19 Mar 2018 11:32:58 +0300 +Subject: [PATCH 08/12] spi-nor: Add flash array support + +Signed-off-by: Dmitry Shifrin +--- + drivers/mtd/spi-nor/spi-nor.c | 20 ++++++++++++++++++-- + include/linux/mtd/spi-nor.h | 12 ++++++++++++ + 2 files changed, 30 insertions(+), 2 deletions(-) + +diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c +index 1855bbe..3ced558 100644 +--- a/drivers/mtd/spi-nor/spi-nor.c ++++ b/drivers/mtd/spi-nor/spi-nor.c +@@ -1338,6 +1338,9 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) + if (ret) + return ret; + ++ if (!nor->array_size) ++ nor->array_size = 1; ++ + if (name) + info = spi_nor_match_id(name); + /* Try to auto-detect if chip name wasn't specified or not found */ +@@ -1500,7 +1503,10 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) + /* Dedicated 4-byte command set */ + switch (nor->flash_read) { + case SPI_NOR_QUAD: +- nor->read_opcode = SPINOR_OP_READ4_1_1_4; ++ if (info->flags & SPANSION_S512FS_QUIRK) ++ nor->read_opcode = SPINOR_OP_READ4_1_4_4; ++ else ++ nor->read_opcode = SPINOR_OP_READ4_1_1_4; + break; + case SPI_NOR_DUAL: + nor->read_opcode = SPINOR_OP_READ4_1_1_2; +@@ -1528,7 +1534,17 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) + return -EINVAL; + } + +- nor->read_dummy = spi_nor_read_dummy_cycles(nor); ++ if (info->flags & SPANSION_S512FS_QUIRK) { ++ nor->read_dummy = 10; ++ nor->flags |= SNOR_F_USE_CLSR; ++ } else ++ nor->read_dummy = spi_nor_read_dummy_cycles(nor); ++ ++ /* recount parameters using array size */ ++ mtd->erasesize *= nor->array_size; ++ mtd->size *= nor->array_size; ++ nor->page_size *= nor->array_size; ++ mtd->writebufsize *= nor->array_size; + + dev_info(dev, "%s (%lld Kbytes)\n", info->name, + (long long)mtd->size >> 10); +diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h +index 99f7b2a..7216b09 100644 +--- a/include/linux/mtd/spi-nor.h ++++ b/include/linux/mtd/spi-nor.h +@@ -174,6 +174,7 @@ struct spi_nor { + bool sst_write_second; + u32 flags; + u8 cmd_buf[SPI_NOR_MAX_CMD_SIZE]; ++ u8 array_size; + + int (*prepare)(struct spi_nor *nor, enum spi_nor_ops ops); + void (*unprepare)(struct spi_nor *nor, enum spi_nor_ops ops); +@@ -204,6 +205,17 @@ static inline struct device_node *spi_nor_get_flash_node(struct spi_nor *nor) + return mtd_get_of_node(&nor->mtd); + } + ++static inline void spi_nor_set_array_size(struct spi_nor *nor, ++ u8 size) ++{ ++ nor->array_size = size; ++} ++ ++static inline u8 spi_nor_get_array_size(struct spi_nor *nor) ++{ ++ return nor->array_size; ++} ++ + static inline int spi_nor_get_read_addr_nbits(u8 opcode) + { + if (opcode == SPINOR_OP_READ4_1_4_4) +-- +2.7.4 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0118-r8a7797-clk-Add-rpc-clock.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0118-r8a7797-clk-Add-rpc-clock.patch new file mode 100644 index 0000000..7910790 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0118-r8a7797-clk-Add-rpc-clock.patch @@ -0,0 +1,45 @@ +From 730f3d906fa599bf76bb0b1fdf35b44a7cbdc2ed Mon Sep 17 00:00:00 2001 +From: Dmitry Shifrin +Date: Thu, 22 Mar 2018 14:57:46 +0300 +Subject: [PATCH 09/12] r8a7797: clk: Add rpc clock + +Signed-off-by: Dmitry Shifrin +--- + drivers/clk/renesas/r8a7797-cpg-mssr.c | 2 ++ + include/dt-bindings/clock/r8a7797-cpg-mssr.h | 1 + + 2 files changed, 3 insertions(+) + +diff --git a/drivers/clk/renesas/r8a7797-cpg-mssr.c b/drivers/clk/renesas/r8a7797-cpg-mssr.c +index a3eed41..9763f6c 100644 +--- a/drivers/clk/renesas/r8a7797-cpg-mssr.c ++++ b/drivers/clk/renesas/r8a7797-cpg-mssr.c +@@ -74,6 +74,7 @@ static const struct cpg_core_clk r8a7797_core_clks[] __initconst = { + 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_FIXED("rpcsrc", R8A7797_CLK_RPCSRC, CLK_PLL1_DIV2, 5, 1), + + DEF_GEN3_SD0H("sd0h", R8A7797_CLK_SD0H, CLK_PLL1_DIV4, 0x0074), + DEF_GEN3_SD0("sd0", R8A7797_CLK_SD0, CLK_PLL1_DIV4, 0x0074), +@@ -158,6 +159,7 @@ static const struct mssr_mod_clk r8a7797_mod_clks[] __initconst = { + DEF_MOD("i2c2", 929, R8A7797_CLK_S2D2), + DEF_MOD("i2c1", 930, R8A7797_CLK_S2D2), + DEF_MOD("i2c0", 931, R8A7797_CLK_S2D2), ++ DEF_MOD("rpc", 917, R8A7797_CLK_RPCSRC), + }; + + static const unsigned int r8a7797_crit_mod_clks[] __initconst = { +diff --git a/include/dt-bindings/clock/r8a7797-cpg-mssr.h b/include/dt-bindings/clock/r8a7797-cpg-mssr.h +index ae6b3af..c3bd0a7 100644 +--- a/include/dt-bindings/clock/r8a7797-cpg-mssr.h ++++ b/include/dt-bindings/clock/r8a7797-cpg-mssr.h +@@ -44,5 +44,6 @@ + #define R8A7797_CLK_CPEX 29 + #define R8A7797_CLK_R 30 + #define R8A7797_CLK_OSC 31 ++#define R8A7797_CLK_RPCSRC 32 + + #endif /* __DT_BINDINGS_CLOCK_R8A7797_CPG_MSSR_H__ */ +-- +2.7.4 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0119-r8a7797-pinctrl-Add-qspi-pins.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0119-r8a7797-pinctrl-Add-qspi-pins.patch new file mode 100644 index 0000000..a0b4330 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0119-r8a7797-pinctrl-Add-qspi-pins.patch @@ -0,0 +1,118 @@ +From 441ae85fe3fec270ea1284a669cdd348a8432d85 Mon Sep 17 00:00:00 2001 +From: Dmitry Shifrin +Date: Thu, 22 Mar 2018 15:00:02 +0300 +Subject: [PATCH 10/12] r8a7797: pinctrl: Add qspi pins + +Signed-off-by: Dmitry Shifrin +--- + drivers/pinctrl/sh-pfc/pfc-r8a7797.c | 73 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 73 insertions(+) + +diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7797.c b/drivers/pinctrl/sh-pfc/pfc-r8a7797.c +index 6b83f44..4f451c4 100644 +--- a/drivers/pinctrl/sh-pfc/pfc-r8a7797.c ++++ b/drivers/pinctrl/sh-pfc/pfc-r8a7797.c +@@ -1143,6 +1143,59 @@ static const unsigned int scif_clk_b_mux[] = { + SCIF_CLK_B_MARK, + }; + ++/* - QSPI ------------------------------------------------------------------- */ ++static const unsigned int qspi0_ctrl_pins[] = { ++ /* QSPI0_SPCLK QSPI0_SSL */ ++ RCAR_GP_PIN(5, 5), RCAR_GP_PIN(5, 0), ++}; ++static const unsigned int qspi0_ctrl_mux[] = { ++ QSPI0_SPCLK_MARK, QSPI0_SSL_MARK, ++}; ++ ++static const unsigned int qspi0_data2_pins[] = { ++ /* QSPI0_MOSI_IO0, QSPI0_MISO_IO1 */ ++ RCAR_GP_PIN(5, 1), RCAR_GP_PIN(5, 2), ++}; ++static const unsigned int qspi0_data2_mux[] = { ++ QSPI0_MOSI_IO0_MARK, QSPI0_MISO_IO1_MARK, ++}; ++ ++static const unsigned int qspi0_data4_pins[] = { ++ /* QSPI0_MOSI_IO0, QSPI0_MISO_IO1, QSPI0_IO2, QSPI0_IO3 */ ++ RCAR_GP_PIN(5, 1), RCAR_GP_PIN(5, 2), ++ RCAR_GP_PIN(5, 3), RCAR_GP_PIN(5, 4), ++}; ++static const unsigned int qspi0_data4_mux[] = { ++ QSPI0_MOSI_IO0_MARK, QSPI0_MISO_IO1_MARK, ++ QSPI0_IO2_MARK, QSPI0_IO3_MARK ++}; ++ ++static const unsigned int qspi1_ctrl_pins[] = { ++ /* QSPI1_SPCLK QSPI1_SSL */ ++ RCAR_GP_PIN(5, 6), RCAR_GP_PIN(5, 11), ++}; ++static const unsigned int qspi1_ctrl_mux[] = { ++ QSPI1_SPCLK_MARK, QSPI1_SSL_MARK, ++}; ++ ++static const unsigned int qspi1_data2_pins[] = { ++ /* QSPI1_MOSI_IO0, QSPI1_MISO_IO1 */ ++ RCAR_GP_PIN(5, 7), RCAR_GP_PIN(5, 8), ++}; ++static const unsigned int qspi1_data2_mux[] = { ++ QSPI1_MOSI_IO0_MARK, QSPI1_MISO_IO1_MARK, ++}; ++ ++static const unsigned int qspi1_data4_pins[] = { ++ /* QSPI1_MOSI_IO0, QSPI1_MISO_IO1, QSPI1_IO2, QSPI1_IO3 */ ++ RCAR_GP_PIN(5, 7), RCAR_GP_PIN(5, 8), ++ RCAR_GP_PIN(5, 9), RCAR_GP_PIN(5, 10), ++}; ++static const unsigned int qspi1_data4_mux[] = { ++ QSPI1_MOSI_IO0_MARK, QSPI1_MISO_IO1_MARK, ++ QSPI1_IO2_MARK, QSPI1_IO3_MARK ++}; ++ + /* - I2C -------------------------------------------------------------------- */ + static const unsigned int i2c0_pins[] = { + /* SDA0, SCL0 */ +@@ -1971,6 +2024,12 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { + SH_PFC_PIN_GROUP(vin1_field), + SH_PFC_PIN_GROUP(vin1_clkenb), + SH_PFC_PIN_GROUP(vin1_clk), ++ SH_PFC_PIN_GROUP(qspi0_ctrl), ++ SH_PFC_PIN_GROUP(qspi0_data2), ++ SH_PFC_PIN_GROUP(qspi0_data4), ++ SH_PFC_PIN_GROUP(qspi1_ctrl), ++ SH_PFC_PIN_GROUP(qspi1_data2), ++ SH_PFC_PIN_GROUP(qspi1_data4), + }; + + static const char * const avb0_groups[] = { +@@ -2201,6 +2260,18 @@ static const char * const vin1_groups[] = { + "vin1_clk", + }; + ++static const char * const qspi0_groups[] = { ++ "qspi0_ctrl", ++ "qspi0_data2", ++ "qspi0_data4", ++}; ++ ++static const char * const qspi1_groups[] = { ++ "qspi1_ctrl", ++ "qspi1_data2", ++ "qspi1_data4", ++}; ++ + #define POCCTRL0 0x380 + #define POCCTRL1 0x384 + #define PIN2POCCTRL0_SHIFT(a) ({ \ +@@ -2244,6 +2315,8 @@ static const struct sh_pfc_function pinmux_functions[] = { + SH_PFC_FUNCTION(tmu), + SH_PFC_FUNCTION(vin0), + SH_PFC_FUNCTION(vin1), ++ SH_PFC_FUNCTION(qspi0), ++ SH_PFC_FUNCTION(qspi1), + }; + + static const struct pinmux_cfg_reg pinmux_config_regs[] = { +-- +2.7.4 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0120-r8a7797-dtsi-Add-rpc-node.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0120-r8a7797-dtsi-Add-rpc-node.patch new file mode 100644 index 0000000..8d782ca --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0120-r8a7797-dtsi-Add-rpc-node.patch @@ -0,0 +1,35 @@ +From 847b14e65374563ec3ee1d06eec05b4004233e7d Mon Sep 17 00:00:00 2001 +From: Dmitry Shifrin +Date: Thu, 22 Mar 2018 15:27:49 +0300 +Subject: [PATCH 11/12] r8a7797: dtsi: Add rpc node + +Signed-off-by: Dmitry Shifrin +--- + arch/arm64/boot/dts/renesas/r8a7797.dtsi | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a7797.dtsi b/arch/arm64/boot/dts/renesas/r8a7797.dtsi +index a5552d6..2beca53 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7797.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a7797.dtsi +@@ -889,6 +889,17 @@ + status = "disabled"; + }; + ++ qspi0: qspi@ee200000 { ++ compatible = "renesas,qspi-rpc-r8a7797"; ++ reg = <0 0xee200000 0 0x1f0>, ++ <0 0x08000000 0 0x04000000>, ++ <0 0xee208000 0 0x100>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 917>; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ + msiof0: spi@e6e90000 { + #address-cells = <1>; + #size-cells = <0>; +-- +2.7.4 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0121-r8a7797-eagle-dts-Add-spi-flash-node.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0121-r8a7797-eagle-dts-Add-spi-flash-node.patch new file mode 100644 index 0000000..8dabedc --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0121-r8a7797-eagle-dts-Add-spi-flash-node.patch @@ -0,0 +1,96 @@ +From 0e884fcce89a6b15bd3971392b5641b48d1ad9ab Mon Sep 17 00:00:00 2001 +From: Dmitry Shifrin +Date: Thu, 22 Mar 2018 15:31:48 +0300 +Subject: [PATCH 12/12] r8a7797-eagle: dts: Add spi flash node + +Signed-off-by: Dmitry Shifrin +--- + arch/arm64/boot/dts/renesas/r8a7797-eagle.dts | 72 +++++++++++++++++++++++++++ + 1 file changed, 72 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a7797-eagle.dts b/arch/arm64/boot/dts/renesas/r8a7797-eagle.dts +index ce7a88e..c8150d9 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7797-eagle.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7797-eagle.dts +@@ -203,6 +203,78 @@ + groups = "du_rgb666", "du_sync", "du_clk_out_0", "du_disp"; + function = "du"; + }; ++ ++ qspi0_pins: qspi0 { ++ groups = "qspi0_ctrl", "qspi0_data4"; ++ function = "qspi0"; ++ }; ++ ++ qspi1_pins: qspi1 { ++ groups = "qspi1_ctrl", "qspi1_data4"; ++ function = "qspi1"; ++ }; ++}; ++ ++&qspi0 { ++ pinctrl-0 = <&qspi0_pins &qspi1_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++ ++ flash@0 { ++ compatible = "spansion,s25fs512s", "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <50000000>; ++ spi-rx-bus-width = <4>; ++ ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ bootparam@0 { ++ reg = <0x00000000 0x040000>; ++ read-only; ++ }; ++ cr7@00040000 { ++ reg = <0x00040000 0x080000>; ++ read-only; ++ }; ++ cert_header_sa3@000C0000 { ++ reg = <0x000C0000 0x080000>; ++ read-only; ++ }; ++ bl2@00140000 { ++ reg = <0x00140000 0x040000>; ++ read-only; ++ }; ++ cert_header_sa6@00180000 { ++ reg = <0x00180000 0x040000>; ++ read-only; ++ }; ++ bl31@001C0000 { ++ reg = <0x001C0000 0x460000>; ++ read-only; ++ }; ++ uboot@00640000 { ++ reg = <0x00640000 0x0C0000>; ++ read-only; ++ }; ++ uboot-env@00700000 { ++ reg = <0x00700000 0x040000>; ++ read-only; ++ }; ++ dtb@00740000 { ++ reg = <0x00740000 0x080000>; ++ }; ++ kernel@007C0000 { ++ reg = <0x007C0000 0x1400000>; ++ }; ++ user@01BC0000 { ++ reg = <0x01BC0000 0x2440000>; ++ }; ++ }; ++ }; + }; + + &scif0 { +-- +2.7.4 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0122-r8a7797-v3msk-r8a7797-v3mzf-dts-Add-spi-flash-s25fs5.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0122-r8a7797-v3msk-r8a7797-v3mzf-dts-Add-spi-flash-s25fs5.patch new file mode 100644 index 0000000..07a55d5 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0122-r8a7797-v3msk-r8a7797-v3mzf-dts-Add-spi-flash-s25fs5.patch @@ -0,0 +1,172 @@ +From 22f31ca58e24e9c8b92361e0d1f57a59d1fdbf64 Mon Sep 17 00:00:00 2001 +From: Dmitry Shifrin +Date: Fri, 23 Mar 2018 16:32:07 +0300 +Subject: [PATCH] r8a7797-v3msk,r8a7797-v3mzf: dts: Add spi flash s25fs512 + +Signed-off-by: Dmitry Shifrin +--- + arch/arm64/boot/dts/renesas/r8a7797-v3msk.dts | 68 +++++++++++++++++++++++++++ + arch/arm64/boot/dts/renesas/r8a7797-v3mzf.dts | 68 +++++++++++++++++++++++++++ + 2 files changed, 136 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a7797-v3msk.dts b/arch/arm64/boot/dts/renesas/r8a7797-v3msk.dts +index 33c6c0d..604475d 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7797-v3msk.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7797-v3msk.dts +@@ -213,6 +213,74 @@ + function = "mmc"; + power-source = <3300>; + }; ++ ++ qspi0_pins: qspi0 { ++ groups = "qspi0_ctrl", "qspi0_data4"; ++ function = "qspi0"; ++ }; ++ ++ qspi1_pins: qspi1 { ++ groups = "qspi1_ctrl", "qspi1_data4"; ++ function = "qspi1"; ++ }; ++}; ++ ++&qspi0 { ++ pinctrl-0 = <&qspi0_pins &qspi1_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++ ++ flash@0 { ++ compatible = "spansion,s25fs512s", "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <50000000>; ++ spi-rx-bus-width = <4>; ++ ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ bootparam@0 { ++ reg = <0x00000000 0x040000>; ++ read-only; ++ }; ++ cr7@00040000 { ++ reg = <0x00040000 0x080000>; ++ read-only; ++ }; ++ cert_header_sa3@000C0000 { ++ reg = <0x000C0000 0x080000>; ++ read-only; ++ }; ++ bl2@00140000 { ++ reg = <0x00140000 0x040000>; ++ read-only; ++ }; ++ cert_header_sa6@00180000 { ++ reg = <0x00180000 0x040000>; ++ read-only; ++ }; ++ bl31@001C0000 { ++ reg = <0x001C0000 0x460000>; ++ read-only; ++ }; ++ uboot@00640000 { ++ reg = <0x00640000 0x100000>; ++ read-only; ++ }; ++ dtb@00740000 { ++ reg = <0x00740000 0x080000>; ++ }; ++ kernel@007C0000 { ++ reg = <0x007C0000 0x1400000>; ++ }; ++ user@01BC0000 { ++ reg = <0x01BC0000 0x2440000>; ++ }; ++ }; ++ }; + }; + + &scif0 { +diff --git a/arch/arm64/boot/dts/renesas/r8a7797-v3mzf.dts b/arch/arm64/boot/dts/renesas/r8a7797-v3mzf.dts +index 71d7bad..4a64881 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7797-v3mzf.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7797-v3mzf.dts +@@ -401,6 +401,74 @@ + function = "mmc"; + power-source = <3300>; + }; ++ ++ qspi0_pins: qspi0 { ++ groups = "qspi0_ctrl", "qspi0_data4"; ++ function = "qspi0"; ++ }; ++ ++ qspi1_pins: qspi1 { ++ groups = "qspi1_ctrl", "qspi1_data4"; ++ function = "qspi1"; ++ }; ++}; ++ ++&qspi0 { ++ pinctrl-0 = <&qspi0_pins &qspi1_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++ ++ flash@0 { ++ compatible = "spansion,s25fs512s", "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <50000000>; ++ spi-rx-bus-width = <4>; ++ ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ bootparam@0 { ++ reg = <0x00000000 0x040000>; ++ read-only; ++ }; ++ cr7@00040000 { ++ reg = <0x00040000 0x080000>; ++ read-only; ++ }; ++ cert_header_sa3@000C0000 { ++ reg = <0x000C0000 0x080000>; ++ read-only; ++ }; ++ bl2@00140000 { ++ reg = <0x00140000 0x040000>; ++ read-only; ++ }; ++ cert_header_sa6@00180000 { ++ reg = <0x00180000 0x040000>; ++ read-only; ++ }; ++ bl31@001C0000 { ++ reg = <0x001C0000 0x460000>; ++ read-only; ++ }; ++ uboot@00640000 { ++ reg = <0x00640000 0x100000>; ++ read-only; ++ }; ++ dtb@00740000 { ++ reg = <0x00740000 0x080000>; ++ }; ++ kernel@007C0000 { ++ reg = <0x007C0000 0x1400000>; ++ }; ++ user@01BC0000 { ++ reg = <0x01BC0000 0x2440000>; ++ }; ++ }; ++ }; + }; + + &scif0 { +-- +2.7.4 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0123-V3HSK-dts-Add-qspi-node.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0123-V3HSK-dts-Add-qspi-node.patch new file mode 100644 index 0000000..4e39ed6 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0123-V3HSK-dts-Add-qspi-node.patch @@ -0,0 +1,101 @@ +From 2e5e9bce98281417fec62cb8af23c086c3d5b01a Mon Sep 17 00:00:00 2001 +From: Dmitry Shifrin +Date: Thu, 5 Apr 2018 17:23:14 +0300 +Subject: [PATCH] V3HSK: dts: Add qspi node + +Signed-off-by: Dmitry Shifrin +--- + arch/arm64/boot/dts/renesas/r8a7798-v3hsk.dts | 73 +++++++++++++++++++++++++++ + 1 file changed, 73 insertions(+) + +diff --git a/arch/arm64/boot/dts/renesas/r8a7798-v3hsk.dts b/arch/arm64/boot/dts/renesas/r8a7798-v3hsk.dts +index bf8abe6..d863a95 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7798-v3hsk.dts ++++ b/arch/arm64/boot/dts/renesas/r8a7798-v3hsk.dts +@@ -225,6 +225,17 @@ + groups = "tpu_to0"; + function = "tpu"; + }; ++ ++ ++ qspi0_pins: qspi0 { ++ groups = "qspi0_ctrl", "qspi0_data4"; ++ function = "qspi0"; ++ }; ++ ++ qspi1_pins: qspi1 { ++ groups = "qspi1_ctrl", "qspi1_data4"; ++ function = "qspi1"; ++ }; + }; + + &scif0 { +@@ -356,3 +367,65 @@ + max-speed = <1000>; + }; + }; ++ ++&qspi0 { ++ pinctrl-0 = <&qspi0_pins &qspi1_pins>; ++ pinctrl-names = "default"; ++ ++ status = "okay"; ++ ++ flash@0 { ++ compatible = "spansion,s25fs512s", "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <50000000>; ++ spi-rx-bus-width = <4>; ++ ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ bootparam@0 { ++ reg = <0x00000000 0x040000>; ++ read-only; ++ }; ++ cr7@00040000 { ++ reg = <0x00040000 0x080000>; ++ read-only; ++ }; ++ cert_header_sa3@000C0000 { ++ reg = <0x000C0000 0x080000>; ++ read-only; ++ }; ++ bl2@00140000 { ++ reg = <0x00140000 0x040000>; ++ read-only; ++ }; ++ cert_header_sa6@00180000 { ++ reg = <0x00180000 0x040000>; ++ read-only; ++ }; ++ bl31@001C0000 { ++ reg = <0x001C0000 0x460000>; ++ read-only; ++ }; ++ uboot@00640000 { ++ reg = <0x00640000 0x0C0000>; ++ read-only; ++ }; ++ uboot-env@00700000 { ++ reg = <0x00700000 0x040000>; ++ read-only; ++ }; ++ dtb@00740000 { ++ reg = <0x00740000 0x080000>; ++ }; ++ kernel@007C0000 { ++ reg = <0x007C0000 0x1400000>; ++ }; ++ user@01BC0000 { ++ reg = <0x01BC0000 0x2440000>; ++ }; ++ }; ++ }; ++}; +-- +2.7.4 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0124-RPC-Hyperflash-Add-devicetree-support.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0124-RPC-Hyperflash-Add-devicetree-support.patch new file mode 100644 index 0000000..f347d47 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0124-RPC-Hyperflash-Add-devicetree-support.patch @@ -0,0 +1,219 @@ +From 466608ee2217ce02df6df977a35c4afa6ee1e350 Mon Sep 17 00:00:00 2001 +From: Dmitry Shifrin +Date: Wed, 4 Apr 2018 12:29:47 +0300 +Subject: [PATCH 1/2] RPC: Hyperflash: Add devicetree support + +Signed-off-by: Dmitry Shifrin +--- + drivers/mtd/rpc_hyperflash.c | 142 +++++++++++++++++++++++-------------------- + 1 file changed, 77 insertions(+), 65 deletions(-) + +diff --git a/drivers/mtd/rpc_hyperflash.c b/drivers/mtd/rpc_hyperflash.c +index cf4d56e..c15e520 100644 +--- a/drivers/mtd/rpc_hyperflash.c ++++ b/drivers/mtd/rpc_hyperflash.c +@@ -15,8 +15,10 @@ + #include + #include + #include ++#include + #include + #include ++#include + + /* RPC */ + #define RPC_BASE 0xEE200000 +@@ -156,10 +158,9 @@ + + struct rpc_info { + struct rw_semaphore lock; ++ struct clk *clk; + void __iomem *rpc_base; + void __iomem *flash_base; +- struct resource *rpc_res; +- struct resource *flash_res; + u32 flash_id; + struct mtd_info mtd; + }; +@@ -243,8 +244,6 @@ enum rpc_hf_size { + 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); +@@ -861,8 +860,8 @@ static int rpc_hf_init_mtd(struct rpc_info *info) + 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_FLASH_SIZE) ++ size = RPC_FLASH_SIZE; + + if (size & (RPC_HF_ERASE_SIZE - 1)) { + retval = -EINVAL; +@@ -891,86 +890,99 @@ static int rpc_hf_init_mtd(struct rpc_info *info) + return retval; + } + +-static int rpc_flash_init(void) ++static int rpc_flash_probe(struct platform_device *pdev) + { +- struct rpc_info *info; ++ struct rpc_info *rpc; + struct resource *res; +- void __iomem *base; +- int retval = -ENODEV; +- +- if (!of_machine_is_compatible("renesas,r8a7795")) +- return -ENODEV; ++ int ret; + +- info = kzalloc(sizeof(*info), GFP_KERNEL); +- if (!info) ++ rpc = devm_kzalloc(&pdev->dev, sizeof(*rpc), GFP_KERNEL); ++ if (!rpc) + return -ENOMEM; + +- res = request_mem_region(RPC_BASE, RPC_SIZE, "RPC"); +- if (!res) +- goto out_info; ++ /* ...get memory */ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ rpc->rpc_base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(rpc->rpc_base)) { ++ dev_err(&pdev->dev, "cannot get resources\n"); ++ ret = PTR_ERR(rpc->rpc_base); ++ goto error; ++ } + +- info->rpc_res = res; +- base = ioremap(res->start, resource_size(res)); +- if (!base) +- goto out_rpc_res; ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ rpc->flash_base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(rpc->flash_base)) { ++ dev_err(&pdev->dev, "cannot get resources\n"); ++ ret = PTR_ERR(rpc->flash_base); ++ goto error; ++ } + +- info->rpc_base = base; +- res = request_mem_region(RPC_FLASH_BASE, RPC_FLASH_SIZE, "RPC-ext"); +- if (!res) +- goto out_rpc_base; ++ /* ...get clk */ ++ rpc->clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(rpc->clk)) { ++ dev_err(&pdev->dev, "cannot get clock\n"); ++ ret = PTR_ERR(rpc->clk); ++ goto error; ++ } + +- info->flash_res = res; +- base = ioremap(res->start, resource_size(res)); +- if (!base) +- goto out_flash_res; ++ /* ... enable clk */ ++ ret = clk_prepare_enable(rpc->clk); ++ if (ret) { ++ dev_err(&pdev->dev, "cannot prepare clock\n"); ++ goto error; ++ } ++ ++ platform_set_drvdata(pdev, rpc); + +- info->flash_base = base; +- retval = rpc_hf_init_mtd(info); +- if (retval) +- goto out_flash_base; ++ mtd_set_of_node(&rpc->mtd, pdev->dev.of_node); ++ ret = rpc_hf_init_mtd(rpc); ++ if (ret) { ++ dev_err(&pdev->dev, "mtd device register error.\n"); ++ goto error_clk_disable; ++ } + +- pr_info("HyperFlash Id: %x\n", info->flash_id); ++ dev_info(&pdev->dev, "HyperFlash Id: %x\n", rpc->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; ++ ++error_clk_disable: ++ clk_disable_unprepare(rpc->clk); ++error: ++ return ret; + } + +-static void rpc_flash_exit(void) ++static int rpc_flash_exit(struct platform_device *pdev) + { +- struct rpc_info *info = rpc_info; ++ struct rpc_info *rpc = platform_get_drvdata(pdev); ++ ++ /* HW shutdown */ ++ clk_disable_unprepare(rpc->clk); ++ mtd_device_unregister(&rpc->mtd); ++ return 0; ++} + +- if (!info) +- return; + +- rpc_info = NULL; ++static const struct of_device_id rpc_flash_of_match[] = { ++ { .compatible = "renesas,rpc-hyperflash-r8a7798" }, ++ { .compatible = "renesas,rpc-hyperflash-r8a7797" }, ++ { }, ++}; + +- mtd_device_unregister(&info->mtd); ++MODULE_DEVICE_TABLE(of, rpc_flash_of_match); + +- 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); +-} ++/* platform driver interface */ ++static struct platform_driver rpc_flash_platform_driver = { ++ .probe = rpc_flash_probe, ++ .remove = rpc_flash_exit, ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "rpc", ++ .of_match_table = of_match_ptr(rpc_flash_of_match), ++ }, ++}; + +-module_init(rpc_flash_init); +-module_exit(rpc_flash_exit); ++module_platform_driver(rpc_flash_platform_driver); + + 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/0125-r8a7797-pinctrl-Add-pin-function-for-hyperflash.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0125-r8a7797-pinctrl-Add-pin-function-for-hyperflash.patch new file mode 100644 index 0000000..08bee0d --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0125-r8a7797-pinctrl-Add-pin-function-for-hyperflash.patch @@ -0,0 +1,70 @@ +From 4b5dc172d87cc8291ddb7377d3252b6777cf8d4b Mon Sep 17 00:00:00 2001 +From: Dmitry Shifrin +Date: Wed, 4 Apr 2018 12:59:59 +0300 +Subject: [PATCH 2/2] r8a7797: pinctrl: Add pin function for hyperflash + +Signed-off-by: Dmitry Shifrin +--- + drivers/pinctrl/sh-pfc/pfc-r8a7797.c | 25 +++++++++++++++++++++++++ + 1 file changed, 25 insertions(+) + +diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7797.c b/drivers/pinctrl/sh-pfc/pfc-r8a7797.c +index 4f451c4..d989acd 100644 +--- a/drivers/pinctrl/sh-pfc/pfc-r8a7797.c ++++ b/drivers/pinctrl/sh-pfc/pfc-r8a7797.c +@@ -1196,6 +1196,25 @@ static const unsigned int qspi1_data4_mux[] = { + QSPI1_IO2_MARK, QSPI1_IO3_MARK + }; + ++static const unsigned int rpc_hyperflash_pins[] = { ++ RCAR_GP_PIN(5, 14), RCAR_GP_PIN(5, 12), ++ RCAR_GP_PIN(5, 11), RCAR_GP_PIN(5, 7), ++ RCAR_GP_PIN(5, 8), RCAR_GP_PIN(5, 9), ++ RCAR_GP_PIN(5, 10), RCAR_GP_PIN(5, 6), ++ RCAR_GP_PIN(5, 5), RCAR_GP_PIN(5, 4), ++ RCAR_GP_PIN(5, 3), RCAR_GP_PIN(5, 2), ++ RCAR_GP_PIN(5, 1), RCAR_GP_PIN(5, 0) ++}; ++static const unsigned int rpc_hyperflash_mux[] = { ++ RPC_INT_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 ++}; ++ + /* - I2C -------------------------------------------------------------------- */ + static const unsigned int i2c0_pins[] = { + /* SDA0, SCL0 */ +@@ -2030,6 +2049,7 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { + SH_PFC_PIN_GROUP(qspi1_ctrl), + SH_PFC_PIN_GROUP(qspi1_data2), + SH_PFC_PIN_GROUP(qspi1_data4), ++ SH_PFC_PIN_GROUP(rpc_hyperflash), + }; + + static const char * const avb0_groups[] = { +@@ -2272,6 +2292,10 @@ static const char * const qspi1_groups[] = { + "qspi1_data4", + }; + ++static const char * const rpc_hyperflash_groups[] = { ++ "rpc_hyperflash", ++}; ++ + #define POCCTRL0 0x380 + #define POCCTRL1 0x384 + #define PIN2POCCTRL0_SHIFT(a) ({ \ +@@ -2317,6 +2341,7 @@ static const struct sh_pfc_function pinmux_functions[] = { + SH_PFC_FUNCTION(vin1), + SH_PFC_FUNCTION(qspi0), + SH_PFC_FUNCTION(qspi1), ++ SH_PFC_FUNCTION(rpc_hyperflash), + }; + + static const struct pinmux_cfg_reg pinmux_config_regs[] = { +-- +2.7.4 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0126-r8a7798-pinctrl-Add-pin-function-for-hyperflash.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0126-r8a7798-pinctrl-Add-pin-function-for-hyperflash.patch new file mode 100644 index 0000000..0babaa4 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0126-r8a7798-pinctrl-Add-pin-function-for-hyperflash.patch @@ -0,0 +1,69 @@ +From 6633820967dcedde29b2e0507b7583c08901a12f Mon Sep 17 00:00:00 2001 +From: Dmitry Shifrin +Date: Thu, 5 Apr 2018 18:32:59 +0300 +Subject: [PATCH] r8a7798: pinctrl: Add pin function for hyperflash + +Signed-off-by: Dmitry Shifrin +--- + drivers/pinctrl/sh-pfc/pfc-r8a7798.c | 24 ++++++++++++++++++++++++ + 1 file changed, 24 insertions(+) + +diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7798.c b/drivers/pinctrl/sh-pfc/pfc-r8a7798.c +index f20afd1..f6f159e 100644 +--- a/drivers/pinctrl/sh-pfc/pfc-r8a7798.c ++++ b/drivers/pinctrl/sh-pfc/pfc-r8a7798.c +@@ -1525,6 +1525,24 @@ static const unsigned int qspi1_data4_mux[] = { + QSPI1_IO2_MARK, QSPI1_IO3_MARK + }; + ++static const unsigned int rpc_hyperflash_pins[] = { ++ RCAR_GP_PIN(5, 14), RCAR_GP_PIN(5, 12), ++ RCAR_GP_PIN(5, 11), RCAR_GP_PIN(5, 7), ++ RCAR_GP_PIN(5, 8), RCAR_GP_PIN(5, 9), ++ RCAR_GP_PIN(5, 10), RCAR_GP_PIN(5, 6), ++ RCAR_GP_PIN(5, 5), RCAR_GP_PIN(5, 4), ++ RCAR_GP_PIN(5, 3), RCAR_GP_PIN(5, 2), ++ RCAR_GP_PIN(5, 1), RCAR_GP_PIN(5, 0) ++}; ++static const unsigned int rpc_hyperflash_mux[] = { ++ RPC_INT_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 ++}; + + /* - I2C -------------------------------------------------------------------- */ + static const unsigned int i2c0_pins[] = { +@@ -2479,6 +2497,7 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { + SH_PFC_PIN_GROUP(qspi1_ctrl), + SH_PFC_PIN_GROUP(qspi1_data2), + SH_PFC_PIN_GROUP(qspi1_data4), ++ SH_PFC_PIN_GROUP(rpc_hyperflash), + }; + + static const char * const avb_groups[] = { +@@ -2755,6 +2774,10 @@ static const char * const qspi1_groups[] = { + "qspi1_data4", + }; + ++static const char * const rpc_hyperflash_groups[] = { ++ "rpc_hyperflash", ++}; ++ + static const struct sh_pfc_function pinmux_functions[] = { + SH_PFC_FUNCTION(avb), + SH_PFC_FUNCTION(gether), +@@ -2793,6 +2816,7 @@ static const struct sh_pfc_function pinmux_functions[] = { + SH_PFC_FUNCTION(vin1), + SH_PFC_FUNCTION(qspi0), + SH_PFC_FUNCTION(qspi1), ++ SH_PFC_FUNCTION(rpc_hyperflash), + }; + + static const struct pinmux_cfg_reg pinmux_config_regs[] = { +-- +2.7.4 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/qspi.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/qspi.cfg new file mode 100644 index 0000000..9a1c695 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/qspi.cfg @@ -0,0 +1,3 @@ +CONFIG_SPI_RENESAS_RPC=y +CONFIG_MTD_BLOCK=y +CONFIG_JFFS2_FS=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 index f5a1445..6beaec5 100644 --- 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 @@ -9,6 +9,7 @@ COMPATIBLE_MACHINE_v3hsk = "v3hsk" SRC_URI_append = " \ ${@bb.utils.contains('MACHINE_FEATURES', 'h3ulcb-had', ' file://hyperflash.cfg', '', d)} \ ${@base_conditional("SDHI_SEQ", "1", " file://sdhi_seq.cfg", "", d)} \ + file://qspi.cfg \ 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 \ @@ -87,6 +88,23 @@ SRC_URI_append = " \ file://0107-V3H-device-tree-Add-VIP-devices-IRQs.patch \ file://0108-can-mcp251x-add-reset-gpio-support.patch \ file://0109-ASoC-R-Car-fix-incorrect-behavior-with-PulseAudio.patch \ + file://0110-Renesas-clk-Add-RPC-clock-source.patch \ + file://0111-Renesas-r8a7798-Add-RPC-clock.patch \ + file://0112-Renesas-r8a7798-pinctrl-Add-RPC-pin-control.patch \ + file://0113-Renesas-RPC-Add-RPC-driver.patch \ + file://0114-R8A7798-dtsi-Add-RPC-node-to-dtsi.patch \ + file://0115-R8A7798-condor-dts-Add-qspi-flash.patch \ + file://0116-spi-nor-Add-s25fs512-flash-support.patch \ + file://0117-spi-nor-Add-flash-array-support.patch \ + file://0118-r8a7797-clk-Add-rpc-clock.patch \ + file://0119-r8a7797-pinctrl-Add-qspi-pins.patch \ + file://0120-r8a7797-dtsi-Add-rpc-node.patch \ + file://0121-r8a7797-eagle-dts-Add-spi-flash-node.patch \ + file://0122-r8a7797-v3msk-r8a7797-v3mzf-dts-Add-spi-flash-s25fs5.patch \ + file://0123-V3HSK-dts-Add-qspi-node.patch \ + file://0124-RPC-Hyperflash-Add-devicetree-support.patch \ + file://0125-r8a7797-pinctrl-Add-pin-function-for-hyperflash.patch \ + file://0126-r8a7798-pinctrl-Add-pin-function-for-hyperflash.patch \ " SRC_URI_append_h3ulcb = " file://ulcb.cfg" -- cgit 1.2.3-korg From 10aa7f1f74b054c2575e7584a02b3738a24d0c7a Mon Sep 17 00:00:00 2001 From: Andrey Dolnikov Date: Wed, 11 Apr 2018 17:06:13 +0300 Subject: Add IMR UIO support. V4L2 RCAR IMR driver is now a module. V4L2 driver is loaded by default. --- .../0127-IMR-UIO-Driver-initial-version.patch | 875 +++++++++++++++++++++ ...8-rcar_imr-v4l2-driver-Fix-module-support.patch | 321 ++++++++ .../recipes-kernel/linux/linux-renesas/condor.cfg | 1 - .../recipes-kernel/linux/linux-renesas/eagle.cfg | 1 - .../recipes-kernel/linux/linux-renesas/imr.cfg | 3 + .../linux/linux-renesas/salvator-x.cfg | 1 - .../recipes-kernel/linux/linux-renesas/ulcb.cfg | 1 - .../recipes-kernel/linux/linux-renesas/v3hsk.cfg | 1 - .../recipes-kernel/linux/linux-renesas/v3msk.cfg | 1 - .../recipes-kernel/linux/linux-renesas/v3mzf.cfg | 2 - .../linux/linux-renesas_4.9.bbappend | 9 + 11 files changed, 1208 insertions(+), 8 deletions(-) create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0127-IMR-UIO-Driver-initial-version.patch create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0128-rcar_imr-v4l2-driver-Fix-module-support.patch create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/imr.cfg (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0127-IMR-UIO-Driver-initial-version.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0127-IMR-UIO-Driver-initial-version.patch new file mode 100644 index 0000000..74d6c07 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0127-IMR-UIO-Driver-initial-version.patch @@ -0,0 +1,875 @@ +From 4a0e94fec7f69a717fc084fa168c2120998f076c Mon Sep 17 00:00:00 2001 +From: Toshiya Tamaki +Date: Thu, 1 Jun 2017 15:43:21 +0900 +Subject: [PATCH 1/2] IMR UIO Driver initial version + +Signed-off-by: Toshiya Tamaki +--- + .../devicetree/bindings/imr/renesas,imr.txt | 55 +++ + arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi | 24 +- + arch/arm64/boot/dts/renesas/r8a7795.dtsi | 24 +- + arch/arm64/boot/dts/renesas/r8a7796.dtsi | 16 + + arch/arm64/boot/dts/renesas/r8a7797.dtsi | 24 +- + arch/arm64/boot/dts/renesas/r8a7798.dtsi | 36 +- + drivers/clk/renesas/r8a7796-cpg-mssr.c | 2 + + drivers/uio/Kconfig | 8 + + drivers/uio/Makefile | 1 + + drivers/uio/uio_imr.c | 495 +++++++++++++++++++++ + 10 files changed, 631 insertions(+), 54 deletions(-) + create mode 100644 Documentation/devicetree/bindings/imr/renesas,imr.txt + create mode 100644 drivers/uio/uio_imr.c + +diff --git a/Documentation/devicetree/bindings/imr/renesas,imr.txt b/Documentation/devicetree/bindings/imr/renesas,imr.txt +new file mode 100644 +index 0000000..50ce539 +--- /dev/null ++++ b/Documentation/devicetree/bindings/imr/renesas,imr.txt +@@ -0,0 +1,55 @@ ++* Renesas Electronics IMR ++ ++This file provides information on what the device node for the IMR ++interface contains. ++ ++Required properties: ++- compatible: "renesas,imr-r8a7795" if the device is a part of R8A7795 SoC. ++ "renesas,imr-r8a7796" if the device is a part of R8A7796 SoC. ++ "renesas,imr-r8a7797" if the device is a part of R8A7797 SoC. ++ ++ When compatible with the generic version, nodes must list the ++ SoC-specific version corresponding to the platform first ++ followed by the generic version. ++ ++- reg: offset and length of (1) the register block and (2) the stream buffer. ++- interrupts: A list of interrupt-specifiers, one for each entry in ++ interrupt-names. ++ If interrupt-names is not present, an interrupt specifier ++ for a single muxed interrupt. ++- clocks: clock phandle and specifier pair. ++- power-domains: must contain a reference to the PM domain. ++ ++Example: ++ ++ imr0{ ++ compatible = "renesas,imr-r8a7797"; ++ reg = <0 0xfe860000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 823>; ++ power-domains = <&sysc R8A7797_PD_A3VC>; ++ }; ++ ++ imr1{ ++ compatible = "renesas,imr-r8a7797"; ++ reg = <0 0xfe870000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 822>; ++ power-domains = <&sysc R8A7797_PD_A3VC>; ++ }; ++ ++ imr2{ ++ compatible = "renesas,imr-r8a7797"; ++ reg = <0 0xfe880000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 821>; ++ power-domains = <&sysc R8A7797_PD_A3VC>; ++ }; ++ ++ imr3{ ++ compatible = "renesas,imr-r8a7797"; ++ reg = <0 0xfe890000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 820>; ++ power-domains = <&sysc R8A7797_PD_A3VC>; ++ }; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi b/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi +index 13516e9..745493c 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi +@@ -2899,33 +2899,33 @@ + power-domains = <&sysc R8A7795_PD_A3IR>; + }; + +- imrlx4_ch0: imr-lx4@fe860000 { +- compatible = "renesas,imr-lx4"; +- reg = <0 0xfe860000 0 0x2000>; ++ imrlx4_ch0: imr0@fe860000 { ++ compatible = "renesas,imr-lx4", "renesas,imr-r8a7795"; ++ reg = <0 0xfe860000 0 0x10000>; + interrupts = ; + 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>; ++ imrlx4_ch1: imr1@fe870000 { ++ compatible = "renesas,imr-lx4", "renesas,imr-r8a7795"; ++ reg = <0 0xfe870000 0 0x10000>; + interrupts = ; + 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>; ++ imrlx4_ch2: imr2@fe880000 { ++ compatible = "renesas,imr-lx4", "renesas,imr-r8a7795"; ++ reg = <0 0xfe880000 0 0x10000>; + interrupts = ; + 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>; ++ imrlx4_ch3: imr3@fe890000 { ++ compatible = "renesas,imr-lx4", "renesas,imr-r8a7795"; ++ reg = <0 0xfe890000 0 0x10000>; + interrupts = ; + 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 565beb9..96e182a 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi +@@ -2895,33 +2895,33 @@ + power-domains = <&sysc R8A7795_PD_A3IR>; + }; + +- imrlx4_ch0: imr-lx4@fe860000 { +- compatible = "renesas,imr-lx4"; +- reg = <0 0xfe860000 0 0x2000>; ++ imrlx4_ch0: imr0@fe860000 { ++ compatible = "renesas,imr-lx4", "renesas,imr-r8a7795"; ++ reg = <0 0xfe860000 0 0x10000>; + interrupts = ; + 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>; ++ imrlx4_ch1: imr1@fe870000 { ++ compatible = "renesas,imr-lx4", "renesas,imr-r8a7795"; ++ reg = <0 0xfe870000 0 0x10000>; + interrupts = ; + 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>; ++ imrlx4_ch2: imr2@fe880000 { ++ compatible = "renesas,imr-lx4", "renesas,imr-r8a7795"; ++ reg = <0 0xfe880000 0 0x10000>; + interrupts = ; + 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>; ++ imrlx4_ch3: imr3@fe890000 { ++ compatible = "renesas,imr-lx4", "renesas,imr-r8a7795"; ++ reg = <0 0xfe890000 0 0x10000>; + interrupts = ; + clocks = <&cpg CPG_MOD 820>; + power-domains = <&sysc R8A7795_PD_A3VC>; +diff --git a/arch/arm64/boot/dts/renesas/r8a7796.dtsi b/arch/arm64/boot/dts/renesas/r8a7796.dtsi +index bf37b8a..b747f0c 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7796.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a7796.dtsi +@@ -1174,6 +1174,22 @@ + status = "disabled"; + }; + ++ imrlx4_ch0: imr0@fe860000 { ++ compatible = "renesas,imr-lx4", "renesas,imr-r8a7796"; ++ reg = <0 0xfe860000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 823>; ++ power-domains = <&sysc R8A7796_PD_A3VC>; ++ }; ++ ++ imrlx4_ch1: imr1@fe870000 { ++ compatible = "renesas,imr-lx4", "renesas,imr-r8a7796"; ++ reg = <0 0xfe870000 0 0x10000>; ++ interrupts = ; ++ clocks = <&cpg CPG_MOD 822>; ++ power-domains = <&sysc R8A7796_PD_A3VC>; ++ }; ++ + can0: can@e6c30000 { + compatible = "renesas,can-r8a7796", + "renesas,rcar-gen3-can"; +diff --git a/arch/arm64/boot/dts/renesas/r8a7797.dtsi b/arch/arm64/boot/dts/renesas/r8a7797.dtsi +index 2beca53..c878467 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7797.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a7797.dtsi +@@ -1239,33 +1239,33 @@ + power-domains = <&sysc R8A7797_PD_A3IR>; + }; + +- imrlx4_ch0: imr-lx4@fe860000 { +- compatible = "renesas,imr-lx4"; +- reg = <0 0xfe860000 0 0x2000>; ++ imrlx4_ch0: imr0@fe860000 { ++ compatible = "renesas,imr-lx4", "renesas,imr-r8a7797"; ++ reg = <0 0xfe860000 0 0x10000>; + interrupts = ; + clocks = <&cpg CPG_MOD 823>; + power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; + }; + +- imrlx4_ch1: imr-lx4@fe870000 { +- compatible = "renesas,imr-lx4"; +- reg = <0 0xfe870000 0 0x2000>; ++ imrlx4_ch1: imr1@fe870000 { ++ compatible = "renesas,imr-lx4", "renesas,imr-r8a7797"; ++ reg = <0 0xfe870000 0 0x10000>; + interrupts = ; + clocks = <&cpg CPG_MOD 822>; + power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; + }; + +- imrlx4_ch2: imr-lx4@fe880000 { +- compatible = "renesas,imr-lx4"; +- reg = <0 0xfe880000 0 0x2000>; ++ imrlx4_ch2: imr2@fe880000 { ++ compatible = "renesas,imr-lx4", "renesas,imr-r8a7797"; ++ reg = <0 0xfe880000 0 0x10000>; + interrupts = ; + clocks = <&cpg CPG_MOD 821>; + power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; + }; + +- imrlx4_ch3: imr-lx4@fe890000 { +- compatible = "renesas,imr-lx4"; +- reg = <0 0xfe890000 0 0x2000>; ++ imrlx4_ch3: imr3@fe890000 { ++ compatible = "renesas,imr-lx4", "renesas,imr-r8a7797"; ++ reg = <0 0xfe890000 0 0x10000>; + interrupts = ; + clocks = <&cpg CPG_MOD 820>; + power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; +diff --git a/arch/arm64/boot/dts/renesas/r8a7798.dtsi b/arch/arm64/boot/dts/renesas/r8a7798.dtsi +index 48ce2af..7bfd0483 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7798.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a7798.dtsi +@@ -1588,50 +1588,50 @@ + power-domains = <&sysc R8A7798_PD_A3IR>; + }; + +- imrlx4_ch0: imr-lx4@fe860000 { +- compatible = "renesas,imr-lx4"; +- reg = <0 0xfe860000 0 0x2000>; ++ imrlx4_ch0: imr0@fe860000 { ++ compatible = "renesas,imr-lx4", "renesas,imr-r8a7798"; ++ reg = <0 0xfe860000 0 0x10000>; + interrupts = ; + clocks = <&cpg CPG_MOD 823>; + power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; + }; + +- imrlx4_ch1: imr-lx4@fe870000 { +- compatible = "renesas,imr-lx4"; +- reg = <0 0xfe870000 0 0x2000>; ++ imrlx4_ch1: imr1@fe870000 { ++ compatible = "renesas,imr-lx4", "renesas,imr-r8a7798"; ++ reg = <0 0xfe870000 0 0x10000>; + interrupts = ; + clocks = <&cpg CPG_MOD 822>; + power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; + }; + +- imrlx4_ch2: imr-lx4@fe880000 { +- compatible = "renesas,imr-lx4"; +- reg = <0 0xfe880000 0 0x2000>; ++ imrlx4_ch2: imr2@fe880000 { ++ compatible = "renesas,imr-lx4", "renesas,imr-r8a7798"; ++ reg = <0 0xfe880000 0 0x10000>; + interrupts = ; + clocks = <&cpg CPG_MOD 821>; + power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; + }; + +- imrlx4_ch3: imr-lx4@fe890000 { +- compatible = "renesas,imr-lx4"; +- reg = <0 0xfe890000 0 0x2000>; ++ imrlx4_ch3: imr3@fe890000 { ++ compatible = "renesas,imr-lx4", "renesas,imr-r8a7798"; ++ reg = <0 0xfe890000 0 0x10000>; + interrupts = ; + clocks = <&cpg CPG_MOD 820>; + power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; + }; + +- imrlx4_ch4: imr-lx4@fe8a0000 { +- compatible = "renesas,imr-lx4"; +- reg = <0 0xfe8a0000 0 0x2000>; ++ imrlx4_ch4: imr4@fe8a0000 { ++ compatible = "renesas,imr-lx4", "renesas,imr-r8a7798"; ++ reg = <0 0xfe8a0000 0 0x10000>; + interrupts = ; + clocks = <&cpg CPG_MOD 707>; + power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; + rse; + }; + +- imrlx4_ch5: imr-lx4@fe8b0000 { +- compatible = "renesas,imr-lx4"; +- reg = <0 0xfe8b0000 0 0x2000>; ++ imrlx4_ch5: imr5@fe8b0000 { ++ compatible = "renesas,imr-lx4", "renesas,imr-r8a7798"; ++ reg = <0 0xfe8b0000 0 0x10000>; + interrupts = ; + clocks = <&cpg CPG_MOD 706>; + power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; +diff --git a/drivers/clk/renesas/r8a7796-cpg-mssr.c b/drivers/clk/renesas/r8a7796-cpg-mssr.c +index e886d8a..e2ca77c 100644 +--- a/drivers/clk/renesas/r8a7796-cpg-mssr.c ++++ b/drivers/clk/renesas/r8a7796-cpg-mssr.c +@@ -204,6 +204,8 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = { + DEF_MOD("vin1", 810, R8A7796_CLK_S0D2), + DEF_MOD("vin0", 811, R8A7796_CLK_S0D2), + DEF_MOD("etheravb", 812, R8A7796_CLK_S0D6), ++ DEF_MOD("imr1", 822, R8A7796_CLK_S2D1), ++ DEF_MOD("imr0", 823, R8A7796_CLK_S2D1), + DEF_MOD("imp", 824, R8A7796_CLK_S1D1), + DEF_MOD("gpio7", 905, R8A7796_CLK_S3D4), + DEF_MOD("gpio6", 906, R8A7796_CLK_S3D4), +diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig +index 52c98ce..09d91ac 100644 +--- a/drivers/uio/Kconfig ++++ b/drivers/uio/Kconfig +@@ -155,4 +155,12 @@ config UIO_MF624 + + If you compile this as a module, it will be called uio_mf624. + ++config UIO_IMR ++ tristate "Renesas IMR support" ++ ++ help ++ Renesas IMR device driver. ++ This driver supports the following SoCs: ++ - R8A7795, R8A7796, R8A7797. ++ + endif +diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile +index 8560dad..3d29324 100644 +--- a/drivers/uio/Makefile ++++ b/drivers/uio/Makefile +@@ -9,3 +9,4 @@ obj-$(CONFIG_UIO_NETX) += uio_netx.o + obj-$(CONFIG_UIO_PRUSS) += uio_pruss.o + obj-$(CONFIG_UIO_MF624) += uio_mf624.o + obj-$(CONFIG_UIO_FSL_ELBC_GPCM) += uio_fsl_elbc_gpcm.o ++obj-$(CONFIG_UIO_IMR) += uio_imr.o +diff --git a/drivers/uio/uio_imr.c b/drivers/uio/uio_imr.c +new file mode 100644 +index 0000000..a64c65e +--- /dev/null ++++ b/drivers/uio/uio_imr.c +@@ -0,0 +1,495 @@ ++/*************************************************************************/ /* ++ IMR ++ ++ Copyright (C) 2015-2017 Renesas Electronics Corporation ++ ++ License Dual MIT/GPLv2 ++ ++ The contents of this file are subject to the MIT license as set out below. ++ ++ Permission is hereby granted, free of charge, to any person obtaining a copy ++ of this software and associated documentation files (the "Software"), to deal ++ in the Software without restriction, including without limitation the rights ++ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ copies of the Software, and to permit persons to whom the Software is ++ furnished to do so, subject to the following conditions: ++ ++ The above copyright notice and this permission notice shall be included in ++ all copies or substantial portions of the Software. ++ ++ Alternatively, the contents of this file may be used under the terms of ++ the GNU General Public License Version 2 ("GPL") in which case the provisions ++ of GPL are applicable instead of those above. ++ ++ If you wish to allow use of your version of this file only under the terms of ++ GPL, and not to allow others to use your version of this file under the terms ++ of the MIT license, indicate your decision by deleting the provisions above ++ and replace them with the notice and other provisions required by GPL as set ++ out in the file called "GPL-COPYING" included in this distribution. If you do ++ not delete the provisions above, a recipient may use your version of this file ++ under the terms of either the MIT license or GPL. ++ ++ This License is also included in this distribution in the file called ++ "MIT-COPYING". ++ ++ EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS ++ PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING ++ BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR ++ PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR ++ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER ++ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN ++ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ++ ++ ++ GPLv2: ++ If you wish to use this file under the terms of GPL, following terms are ++ effective. ++ ++ 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. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++*/ /*************************************************************************/ ++ ++/* PRQA S 292,2212,2214 EOF */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++/* IMR uio driver name */ ++#define DRIVER_NAME "uio_imr" ++ ++/* IMR register definition */ ++#define IMR_REG_IMR_ADDRESS (0x018U) ++#define IMR_REG_IMR_BIT_BASE (0x3U << 3) ++#define IMR_REG_IMR_BIT_INT (0x1U << 2) ++#define IMR_REG_IMR_BIT_IER (0x1U << 1) ++#define IMR_REG_IMR_BIT_TRA (0x1U << 0) ++ ++/** ++ * struct uio_platdata - the uio platform data structure ++ * @uioinfo: UIO device capabilities ++ * @lock lock flag for irq. ++ * @flags: flags for request_irq. ++ * @pdev: IMR platform device data. ++ * @base_reg: IMR base register address. ++ * @clk: clock data. ++ * ++ * the uio platform data structure. ++ */ ++struct uio_platdata { ++ struct uio_info *uioinfo; ++ spinlock_t lock; ++ unsigned long flags; ++ struct platform_device *pdev; ++ void __iomem *base_reg; ++ struct clk *clock; ++}; ++ ++static void write_register(struct uio_platdata *priv, ++ u32 reg_offs, u32 data); ++static int uio_imr_open(struct uio_info *info, ++ __attribute__((unused)) struct inode *inode); ++static int uio_imr_release(struct uio_info *info, ++ __attribute__((unused)) struct inode *inode); ++static irqreturn_t uio_imr_handler(__attribute__((unused)) int irq, ++ struct uio_info *dev_info); ++static int uio_imr_irqcontrol(struct uio_info *info, s32 irq_on); ++static int uio_imr_probe(struct platform_device *pdev); ++static int uio_imr_remove(struct platform_device *pdev); ++static int uio_runtime_imr_nop(__attribute__((unused)) struct device *dev); ++ ++/** ++ * write_register() - register setting ++ * @priv: uio platform data. ++ * @reg_offs: register offset. ++ * @data: register value. ++ * ++ * register setting. ++ * ++ * ++ * Return: none ++ */ ++static void write_register(struct uio_platdata *priv, ++ u32 reg_offs, u32 data) ++{ ++ iowrite32(data, (u8 *)priv->base_reg + reg_offs); /* PRQA S 488 */ ++} ++ ++/** ++ * uio_imr_open() - open imr module ++ * @info: UIO device capabilities. ++ * @inode: inode. ++ * ++ * Open imr module. ++ * ++ * ++ * Return: 0 normal end. ++ */ ++/* PRQA S 3206 2 */ ++static int uio_imr_open(struct uio_info *info, ++ __attribute__((unused)) struct inode *inode) ++{ ++ struct uio_platdata *pdata = info->priv; ++ /* PRQA S 3200 1 */ ++ pr_debug("uio_imr_open enter. name=%s\n", pdata->uioinfo->name); ++ ++ /* Wait until the Runtime PM code has woken up the device */ ++ (void)pm_runtime_get_sync(&pdata->pdev->dev); ++ ++ return 0; ++} ++ ++/** ++ * uio_imr_release() - close imr module ++ * @info: UIO device capabilities. ++ * @inode: inode. ++ * ++ * Close imr module. ++ * ++ * ++ * Return: 0 normal end. ++ */ ++/* PRQA S 3206 2 */ ++static int uio_imr_release(struct uio_info *info, ++ __attribute__((unused)) struct inode *inode) ++{ ++ struct uio_platdata *pdata = info->priv; ++ ++ pr_debug("uio_imr_release enter\n"); /* PRQA S 3200 */ ++ ++ /* Tell the Runtime PM code that the device has become idle */ ++ (void)pm_runtime_put_sync(&pdata->pdev->dev); ++ ++ return 0; ++} ++ ++/** ++ * uio_imr_handler() - IMR interrupt handler ++ * @irq: irq No. ++ * @dev_info: UIO device capabilities. ++ * ++ * IMR interrupt handler. ++ * ++ * ++ * Return: IRQ_HANDLED normal end. ++ */ ++/* PRQA S 3206 1*/ ++static irqreturn_t uio_imr_handler(__attribute__((unused))int irq, ++ struct uio_info *dev_info) ++{ ++ struct uio_platdata *pdata = dev_info->priv; ++ ++ ++ pr_debug("uio_imr_handler enter\n"); /* PRQA S 3200 */ ++ ++ /* Mask interrupt */ ++ write_register(pdata, IMR_REG_IMR_ADDRESS, ++ IMR_REG_IMR_BIT_BASE | (IMR_REG_IMR_BIT_INT | ++ IMR_REG_IMR_BIT_IER | IMR_REG_IMR_BIT_TRA)); ++ ++ return IRQ_HANDLED; ++} ++ ++/** ++ * uio_imr_irqcontrol() - IMR irq controller ++ * @info: UIO device capabilities. ++ * @irq_on: irq enable/disable. ++ * ++ * IMR irq controller. Enable and disable the interrupt. ++ * ++ * ++ * Return: 0 normal end. ++ */ ++static int uio_imr_irqcontrol(struct uio_info *info, s32 irq_on) ++{ ++ struct uio_platdata *pdata = info->priv; ++ u64 flag; ++ ++ pr_debug("uio_imr_irqcontrol enter\n"); /* PRQA S 3200 */ ++ ++ spin_lock_irqsave(&pdata->lock, flag); ++ if (irq_on != 0) { ++ if (test_and_clear_bit(0, &pdata->flags) != 0) ++ enable_irq((u32)info->irq); ++ } else { ++ if (test_and_set_bit(0, &pdata->flags) == 0) ++ disable_irq((u32)info->irq); ++ } ++ spin_unlock_irqrestore(&pdata->lock, flag); ++ ++ return 0; ++} ++ ++/* PRQA S 1053,1041,605 10 */ ++static const struct of_device_id rcar_imr_dt_ids[] = { ++ { .compatible = "renesas,imr-r8a7795", .data = 0 }, ++ { .compatible = "renesas,imr-r8a7796", .data = 0 }, ++ { .compatible = "renesas,imr-r8a7797", .data = 0 }, ++ { .compatible = "renesas,imr-r8a7798", .data = 0 }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, rcar_imr_dt_ids); /* PRQA S 605 */ ++ ++/** ++ * uio_imr_probe() - Initialize IMR module. ++ * @pdev: platform device data. ++ * ++ * Initialize IMR module. ++ * ++ * ++ * Return: 0 normal end. ++ * -EINVAL parameter error. ++ * -ENOMEM memory error. ++ * -ENODEV system error. ++ */ ++static int uio_imr_probe(struct platform_device *pdev) ++{ ++ struct uio_info *uioinfo_data = NULL; ++ struct uio_platdata *pdata; ++ struct uio_mem *uiomem; ++ int ret = 0; ++ unsigned int i; ++ struct resource *rsc; ++ unsigned int irq_l; ++ unsigned long remap_size; ++ ++ if (pdev == NULL) { ++ pr_err("missing pdev\n"); ++ ret = -EINVAL; ++ } else { ++ if (pdev->dev.of_node == NULL) { ++ dev_err(&pdev->dev, "missing pdev->dev.of_node\n"); ++ ret = -EINVAL; ++ } ++ } ++ ++ if (ret == 0) { ++ pr_debug("uio_imr_probe enter name = %s\n", /* PRQA S 3200 */ ++ pdev->dev.of_node->name); ++ ++ uioinfo_data = devm_kzalloc(&pdev->dev, ++ sizeof(*uioinfo_data), ++ GFP_KERNEL); ++ if (uioinfo_data == NULL) ++ ret = -ENOMEM; ++ } ++ ++ if (ret == 0) { ++ uioinfo_data->name = pdev->dev.of_node->name; ++ uioinfo_data->version = "0.1"; ++ ++ /* get irq number */ ++ irq_l = irq_of_parse_and_map(pdev->dev.of_node, 0); ++ if ((int)irq_l == -ENXIO) ++ uioinfo_data->irq = platform_get_irq(pdev, 0); ++ else ++ uioinfo_data->irq = (int)irq_l; ++ ++ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); ++ if (pdata == NULL) ++ ret = -ENOMEM; ++ } ++ ++ if (ret == 0) { ++ pdata->uioinfo = uioinfo_data; ++ spin_lock_init(&pdata->lock); /* PRQA S 3200 */ ++ pdata->flags = 0; ++ pdata->pdev = pdev; ++ ++ uiomem = &uioinfo_data->mem[0]; ++ ++ for (i = 0; i < pdev->num_resources; ++i) { ++ /* PRQA S 491 1 */ ++ struct resource *r = &pdev->resource[i]; ++ ++ if (r->flags == IORESOURCE_IRQ) { ++ uioinfo_data->irq = (long)r->start; ++ } else if (r->flags != IORESOURCE_MEM) { ++ ; ++ } else { ++ if (uiomem >= ++ &uioinfo_data->mem[MAX_UIO_MAPS]) { ++ dev_warn(&pdev->dev, ++ "device has more than " ++ __stringify(MAX_UIO_MAPS) ++ " I/O memory resources.\n"); ++ break; ++ } ++ ++ uiomem->memtype = UIO_MEM_PHYS; ++ uiomem->addr = r->start; ++ uiomem->size = (r->end - r->start) + 1; ++ ++uiomem; /* PRQA S 489 */ ++ } ++ } ++ ++ while (uiomem < &uioinfo_data->mem[MAX_UIO_MAPS]) { ++ uiomem->size = 0; ++ ++uiomem; /* PRQA S 489 */ ++ } ++ ++ uioinfo_data->handler = &uio_imr_handler; ++ uioinfo_data->irqcontrol = &uio_imr_irqcontrol; ++ uioinfo_data->open = &uio_imr_open; ++ uioinfo_data->release = &uio_imr_release; ++ uioinfo_data->priv = pdata; ++ ++ pm_runtime_enable(&pdev->dev); ++ ++ ret = uio_register_device(&pdev->dev, pdata->uioinfo); ++ if (ret != 0) { ++ pm_runtime_disable(&pdev->dev); ++ dev_err(&pdev->dev, "could not register uio device\n"); ++ ret = -ENODEV; ++ } ++ } ++ ++ if (ret == 0) { ++ platform_set_drvdata(pdev, pdata); ++ pdata->clock = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(pdata->clock)) { ++ pm_runtime_disable(&pdev->dev); ++ dev_err(&pdev->dev, "could not get clock\n"); ++ ret = -ENODEV; ++ } else { ++ /* clock enable */ ++ (void)clk_prepare_enable(pdata->clock); ++ } ++ } ++ ++ if (ret == 0) { ++ rsc = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (rsc == 0) { ++ pm_runtime_disable(&pdev->dev); ++ dev_err(&pdev->dev, "could not platform_get_resource\n"); ++ ret = -ENODEV; ++ } ++ } ++ ++ if (ret == 0) { ++ remap_size = (rsc->end - rsc->start) + 1; ++ if (!request_mem_region(rsc->start, ++ remap_size, ++ uioinfo_data->name)) { ++ dev_err(&pdev->dev, "could not request IO\n"); ++ pm_runtime_disable(&pdev->dev); ++ ret = -ENOMEM; ++ } ++ } ++ ++ if (ret == 0) { ++ /* IMR Register Adderss */ ++ pdata->base_reg = devm_ioremap_nocache(&pdev->dev, ++ rsc->start, ++ remap_size); ++ if (pdata->base_reg == NULL) { ++ release_mem_region(rsc->start, resource_size(rsc)); ++ dev_err(&pdev->dev, "could not remap IMR register\n"); ++ pm_runtime_disable(&pdev->dev); ++ ret = -ENOMEM; ++ } else { ++ /* PRQA S 3200 2 */ ++ pr_debug("IMR reg_base = %x size = %x\n", ++ (uint32_t)(rsc->start), (uint32_t)remap_size); ++ } ++ } ++ ++ return ret; ++} ++ ++/** ++ * uio_imr_remove() - release IMR module. ++ * @pdev: platform device data. ++ * ++ * release IMR module. ++ * ++ * ++ * Return: 0 normal end. ++ */ ++static int uio_imr_remove(struct platform_device *pdev) ++{ ++ struct resource *rsc; ++ struct uio_platdata *pdata = platform_get_drvdata(pdev); ++ ++ /* PRQA S 3200 1 */ ++ pr_debug("uio_imr_remove enter name = %s\n", pdata->uioinfo->name); ++ ++ clk_disable_unprepare(pdata->clock); ++ ++ uio_unregister_device(pdata->uioinfo); ++ ++ pm_runtime_disable(&pdev->dev); ++ ++ irq_dispose_mapping((u32)pdata->uioinfo->irq); ++ ++ pdata->uioinfo->handler = NULL; ++ pdata->uioinfo->irqcontrol = NULL; ++ ++ platform_set_drvdata(pdev, NULL); ++ ++ if (pdata->base_reg != NULL) ++ devm_iounmap(&pdev->dev, pdata->base_reg); ++ ++ rsc = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (rsc != 0) ++ release_mem_region(rsc->start, resource_size(rsc)); ++ ++ return 0; ++} ++ ++/** ++ * uio_runtime_imr_nop() - Runtime PM callback function. ++ * @dev: device data. ++ * ++ * Runtime PM callback function. ++ * ++ * ++ * Return: 0 normal end. ++ */ ++ /* PRQA S 3206 1 */ ++static int uio_runtime_imr_nop(__attribute__((unused)) struct device *dev) ++{ ++ pr_debug("uio_runtime_imr_nop enter\n"); /* PRQA S 3200 */ ++ return 0; ++} ++/* PRQA S 1053 4 */ ++static const struct dev_pm_ops uio_dev_pm_imr_ops = { ++ .runtime_suspend = &uio_runtime_imr_nop, ++ .runtime_resume = &uio_runtime_imr_nop, ++}; ++ ++static struct platform_driver uio_imr_platform_driver = { ++ .probe = &uio_imr_probe, ++ .remove = &uio_imr_remove, ++ .driver = { ++ .name = DRIVER_NAME, ++ .owner = THIS_MODULE, ++ .pm = &uio_dev_pm_imr_ops, ++ .of_match_table = of_match_ptr(rcar_imr_dt_ids), ++ }, ++}; ++ ++module_platform_driver(uio_imr_platform_driver); ++ ++ ++MODULE_AUTHOR("Renesas Electronics Corporation"); ++MODULE_DESCRIPTION("Userspace I/O driver for IMR"); ++MODULE_LICENSE("Dual MIT/GPL"); ++MODULE_ALIAS("platform:" DRIVER_NAME); +-- +2.7.4 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0128-rcar_imr-v4l2-driver-Fix-module-support.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0128-rcar_imr-v4l2-driver-Fix-module-support.patch new file mode 100644 index 0000000..f4ee6e2 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0128-rcar_imr-v4l2-driver-Fix-module-support.patch @@ -0,0 +1,321 @@ +From 772299b20e32fc3ff86de4a83845e8246d97bcbb Mon Sep 17 00:00:00 2001 +From: Andrey Dolnikov +Date: Mon, 9 Apr 2018 12:50:23 +0300 +Subject: [PATCH 2/2] rcar_imr v4l2 driver: Fix module support. + +--- + arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi | 8 +++++++ + arch/arm64/boot/dts/renesas/r8a7795.dtsi | 8 +++++++ + arch/arm64/boot/dts/renesas/r8a7796.dtsi | 6 ++++++ + arch/arm64/boot/dts/renesas/r8a7797.dtsi | 8 +++++++ + arch/arm64/boot/dts/renesas/r8a7798.dtsi | 10 +++++++++ + drivers/media/platform/rcar_imr.c | 32 +++++++++++++++++++++++++--- + 6 files changed, 69 insertions(+), 3 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi b/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi +index 745493c..f2769c2 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi +@@ -2899,12 +2899,17 @@ + power-domains = <&sysc R8A7795_PD_A3IR>; + }; + ++ imr_v4l2_alloc: imr_alloc { ++ dma-coherent; ++ }; ++ + imrlx4_ch0: imr0@fe860000 { + compatible = "renesas,imr-lx4", "renesas,imr-r8a7795"; + reg = <0 0xfe860000 0 0x10000>; + interrupts = ; + clocks = <&cpg CPG_MOD 823>; + power-domains = <&sysc R8A7795_PD_A3VC>; ++ alloc-dev = <&imr_v4l2_alloc>; + }; + + imrlx4_ch1: imr1@fe870000 { +@@ -2913,6 +2918,7 @@ + interrupts = ; + clocks = <&cpg CPG_MOD 822>; + power-domains = <&sysc R8A7795_PD_A3VC>; ++ alloc-dev = <&imr_v4l2_alloc>; + }; + + imrlx4_ch2: imr2@fe880000 { +@@ -2921,6 +2927,7 @@ + interrupts = ; + clocks = <&cpg CPG_MOD 821>; + power-domains = <&sysc R8A7795_PD_A3VC>; ++ alloc-dev = <&imr_v4l2_alloc>; + }; + + imrlx4_ch3: imr3@fe890000 { +@@ -2929,6 +2936,7 @@ + interrupts = ; + clocks = <&cpg CPG_MOD 820>; + power-domains = <&sysc R8A7795_PD_A3VC>; ++ alloc-dev = <&imr_v4l2_alloc>; + }; + }; + }; +diff --git a/arch/arm64/boot/dts/renesas/r8a7795.dtsi b/arch/arm64/boot/dts/renesas/r8a7795.dtsi +index 96e182a..366ee5f 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi +@@ -2895,12 +2895,17 @@ + power-domains = <&sysc R8A7795_PD_A3IR>; + }; + ++ imr_v4l2_alloc: imr_alloc { ++ dma-coherent; ++ }; ++ + imrlx4_ch0: imr0@fe860000 { + compatible = "renesas,imr-lx4", "renesas,imr-r8a7795"; + reg = <0 0xfe860000 0 0x10000>; + interrupts = ; + clocks = <&cpg CPG_MOD 823>; + power-domains = <&sysc R8A7795_PD_A3VC>; ++ alloc-dev = <&imr_v4l2_alloc>; + }; + + imrlx4_ch1: imr1@fe870000 { +@@ -2909,6 +2914,7 @@ + interrupts = ; + clocks = <&cpg CPG_MOD 822>; + power-domains = <&sysc R8A7795_PD_A3VC>; ++ alloc-dev = <&imr_v4l2_alloc>; + }; + + imrlx4_ch2: imr2@fe880000 { +@@ -2917,6 +2923,7 @@ + interrupts = ; + clocks = <&cpg CPG_MOD 821>; + power-domains = <&sysc R8A7795_PD_A3VC>; ++ alloc-dev = <&imr_v4l2_alloc>; + }; + + imrlx4_ch3: imr3@fe890000 { +@@ -2925,6 +2932,7 @@ + interrupts = ; + clocks = <&cpg CPG_MOD 820>; + power-domains = <&sysc R8A7795_PD_A3VC>; ++ alloc-dev = <&imr_v4l2_alloc>; + }; + }; + }; +diff --git a/arch/arm64/boot/dts/renesas/r8a7796.dtsi b/arch/arm64/boot/dts/renesas/r8a7796.dtsi +index b747f0c..442f027 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7796.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a7796.dtsi +@@ -1174,12 +1174,17 @@ + status = "disabled"; + }; + ++ imr_v4l2_alloc: imr_alloc { ++ dma-coherent; ++ }; ++ + imrlx4_ch0: imr0@fe860000 { + compatible = "renesas,imr-lx4", "renesas,imr-r8a7796"; + reg = <0 0xfe860000 0 0x10000>; + interrupts = ; + clocks = <&cpg CPG_MOD 823>; + power-domains = <&sysc R8A7796_PD_A3VC>; ++ alloc-dev = <&imr_v4l2_alloc>; + }; + + imrlx4_ch1: imr1@fe870000 { +@@ -1188,6 +1193,7 @@ + interrupts = ; + clocks = <&cpg CPG_MOD 822>; + power-domains = <&sysc R8A7796_PD_A3VC>; ++ alloc-dev = <&imr_v4l2_alloc>; + }; + + can0: can@e6c30000 { +diff --git a/arch/arm64/boot/dts/renesas/r8a7797.dtsi b/arch/arm64/boot/dts/renesas/r8a7797.dtsi +index c878467..16e73b4 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7797.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a7797.dtsi +@@ -1239,12 +1239,17 @@ + power-domains = <&sysc R8A7797_PD_A3IR>; + }; + ++ imr_v4l2_alloc: imr_alloc { ++ dma-coherent; ++ }; ++ + imrlx4_ch0: imr0@fe860000 { + compatible = "renesas,imr-lx4", "renesas,imr-r8a7797"; + reg = <0 0xfe860000 0 0x10000>; + interrupts = ; + clocks = <&cpg CPG_MOD 823>; + power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ alloc-dev = <&imr_v4l2_alloc>; + }; + + imrlx4_ch1: imr1@fe870000 { +@@ -1253,6 +1258,7 @@ + interrupts = ; + clocks = <&cpg CPG_MOD 822>; + power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ alloc-dev = <&imr_v4l2_alloc>; + }; + + imrlx4_ch2: imr2@fe880000 { +@@ -1261,6 +1267,7 @@ + interrupts = ; + clocks = <&cpg CPG_MOD 821>; + power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ alloc-dev = <&imr_v4l2_alloc>; + }; + + imrlx4_ch3: imr3@fe890000 { +@@ -1269,6 +1276,7 @@ + interrupts = ; + clocks = <&cpg CPG_MOD 820>; + power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ alloc-dev = <&imr_v4l2_alloc>; + }; + }; + }; +diff --git a/arch/arm64/boot/dts/renesas/r8a7798.dtsi b/arch/arm64/boot/dts/renesas/r8a7798.dtsi +index 7bfd0483..0742ec0 100644 +--- a/arch/arm64/boot/dts/renesas/r8a7798.dtsi ++++ b/arch/arm64/boot/dts/renesas/r8a7798.dtsi +@@ -1588,12 +1588,17 @@ + power-domains = <&sysc R8A7798_PD_A3IR>; + }; + ++ imr_v4l2_alloc: imr_alloc { ++ dma-coherent; ++ }; ++ + imrlx4_ch0: imr0@fe860000 { + compatible = "renesas,imr-lx4", "renesas,imr-r8a7798"; + reg = <0 0xfe860000 0 0x10000>; + interrupts = ; + clocks = <&cpg CPG_MOD 823>; + power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ alloc-dev = <&imr_v4l2_alloc>; + }; + + imrlx4_ch1: imr1@fe870000 { +@@ -1602,6 +1607,7 @@ + interrupts = ; + clocks = <&cpg CPG_MOD 822>; + power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ alloc-dev = <&imr_v4l2_alloc>; + }; + + imrlx4_ch2: imr2@fe880000 { +@@ -1610,6 +1616,7 @@ + interrupts = ; + clocks = <&cpg CPG_MOD 821>; + power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ alloc-dev = <&imr_v4l2_alloc>; + }; + + imrlx4_ch3: imr3@fe890000 { +@@ -1618,6 +1625,7 @@ + interrupts = ; + clocks = <&cpg CPG_MOD 820>; + power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ alloc-dev = <&imr_v4l2_alloc>; + }; + + imrlx4_ch4: imr4@fe8a0000 { +@@ -1626,6 +1634,7 @@ + interrupts = ; + clocks = <&cpg CPG_MOD 707>; + power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ alloc-dev = <&imr_v4l2_alloc>; + rse; + }; + +@@ -1635,6 +1644,7 @@ + interrupts = ; + clocks = <&cpg CPG_MOD 706>; + power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ alloc-dev = <&imr_v4l2_alloc>; + rse; + }; + +diff --git a/drivers/media/platform/rcar_imr.c b/drivers/media/platform/rcar_imr.c +index 7b16765..3558211 100644 +--- a/drivers/media/platform/rcar_imr.c ++++ b/drivers/media/platform/rcar_imr.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1917,6 +1918,8 @@ static int imr_probe(struct platform_device *pdev) + struct resource *res; + struct device_node *np = pdev->dev.of_node; + int ret; ++ phandle *prop; ++ struct device_node *node; + + imr = devm_kzalloc(&pdev->dev, sizeof(*imr), GFP_KERNEL); + if (!imr) +@@ -1989,10 +1992,15 @@ static int imr_probe(struct platform_device *pdev) + ret = PTR_ERR(adev); + goto m2m_init_rollback; + } ++ + adev->dma_mask = &adev->coherent_dma_mask; + adev->coherent_dma_mask = DMA_BIT_MASK(32); +- arch_setup_dma_ops(adev, 0, DMA_BIT_MASK(32) + 1, NULL, true); + imr->alloc_dev = adev; ++ prop = of_get_property(np, "alloc-dev", NULL); ++ if (prop) { ++ node = of_find_node_by_phandle(be32_to_cpup(prop)); ++ of_dma_configure(adev, node); ++ } + + strlcpy(imr->video_dev.name, dev_name(&pdev->dev), sizeof(imr->video_dev.name)); + imr->video_dev.fops = &imr_fops; +@@ -2032,7 +2040,6 @@ static int imr_remove(struct platform_device *pdev) + + //pm_runtime_disable(imr->v4l2_dev.dev); + video_unregister_device(&imr->video_dev); +- //device_destroy(imr->alloc_dev, MKDEV(0, 0)); + v4l2_m2m_release(imr->m2m_dev); + v4l2_device_unregister(&imr->v4l2_dev); + +@@ -2100,7 +2107,26 @@ static struct platform_driver imr_platform_driver = { + }, + }; + +-module_platform_driver(imr_platform_driver); ++static int __init imr_module_init(void) ++{ ++ return platform_driver_register(&imr_platform_driver); ++} ++ ++static int imr_device_destroy(struct device *dev, void *data) ++{ ++ device_destroy(imr_alloc_class, dev->devt); ++ return 0; ++} ++ ++static void __exit imr_module_exit(void) ++{ ++ class_for_each_device(imr_alloc_class, NULL, NULL, imr_device_destroy); ++ class_destroy(imr_alloc_class); ++ platform_driver_unregister(&imr_platform_driver); ++} ++ ++module_init(imr_module_init); ++module_exit(imr_module_exit); + + MODULE_ALIAS("imr"); + MODULE_AUTHOR("Cogent Embedded Inc. "); +-- +2.7.4 + diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/condor.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/condor.cfg index 7322e21..54ab6a7 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/condor.cfg +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/condor.cfg @@ -20,7 +20,6 @@ CONFIG_SOC_CAMERA_SCALE_CROP=y CONFIG_SOC_CAMERA_PLATFORM=y CONFIG_SOC_CAMERA_MAX9286=y CONFIG_SOC_CAMERA_OV106XX=y -CONFIG_VIDEO_RENESAS_IMR=y CONFIG_INPUT_TOUCHSCREEN=y CONFIG_INPUT_UINPUT=y CONFIG_TOUCHSCREEN_PROPERTIES=y 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 index ca8cee8..1e84e31 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/eagle.cfg +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/eagle.cfg @@ -20,7 +20,6 @@ CONFIG_SOC_CAMERA_SCALE_CROP=y CONFIG_SOC_CAMERA_PLATFORM=y CONFIG_SOC_CAMERA_MAX9286=y CONFIG_SOC_CAMERA_OV106XX=y -CONFIG_VIDEO_RENESAS_IMR=y CONFIG_INPUT_TOUCHSCREEN=y CONFIG_INPUT_UINPUT=y CONFIG_TOUCHSCREEN_PROPERTIES=y diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/imr.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/imr.cfg new file mode 100644 index 0000000..cc7f69e --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/imr.cfg @@ -0,0 +1,3 @@ +CONFIG_VIDEO_RENESAS_IMR=m +CONFIG_UIO=y +CONFIG_UIO_IMR=m 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 index 36c6103..4af8122 100644 --- 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 @@ -24,7 +24,6 @@ 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/ulcb.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/ulcb.cfg index 5442f19..2714452 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/ulcb.cfg +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/ulcb.cfg @@ -37,7 +37,6 @@ CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_PLATFORM=y CONFIG_USB_XHCI_RCAR=y CONFIG_USB_ACM=y -CONFIG_VIDEO_RENESAS_IMR=y CONFIG_VIRTIO_RCAR_PCIE=y CONFIG_BT=y CONFIG_BT_BNEP=m diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3hsk.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3hsk.cfg index 3713001..b842d14 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3hsk.cfg +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3hsk.cfg @@ -24,7 +24,6 @@ CONFIG_SOC_CAMERA_PLATFORM=y CONFIG_SOC_CAMERA_MAX9286=y CONFIG_SOC_CAMERA_TI9X4=y CONFIG_SOC_CAMERA_OV106XX=y -CONFIG_VIDEO_RENESAS_IMR=y CONFIG_INPUT_TOUCHSCREEN=y CONFIG_INPUT_UINPUT=y CONFIG_TOUCHSCREEN_PROPERTIES=y diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3msk.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3msk.cfg index a3c72d5..e349d80 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3msk.cfg +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3msk.cfg @@ -24,7 +24,6 @@ CONFIG_SOC_CAMERA_PLATFORM=y CONFIG_SOC_CAMERA_MAX9286=y CONFIG_SOC_CAMERA_TI9X4=y CONFIG_SOC_CAMERA_OV106XX=y -CONFIG_VIDEO_RENESAS_IMR=y CONFIG_INPUT_TOUCHSCREEN=y CONFIG_INPUT_UINPUT=y CONFIG_TOUCHSCREEN_PROPERTIES=y diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3mzf.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3mzf.cfg index cd41866..d1b8914 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3mzf.cfg +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3mzf.cfg @@ -17,9 +17,7 @@ CONFIG_SOC_CAMERA_SCALE_CROP=y CONFIG_SOC_CAMERA_PLATFORM=y CONFIG_SOC_CAMERA_TI9X4=y CONFIG_SOC_CAMERA_OV106XX=y -CONFIG_VIDEO_RENESAS_IMR=y CONFIG_SERIAL_SH_SCI_DMA=y -CONFIG_UIO=y CONFIG_SPI_SLAVE=y CONFIG_SPI_SLAVE_TIME=y CONFIG_SPI_SLAVE_SYSTEM_CONTROL=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 index 6beaec5..0233afa 100644 --- 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 @@ -10,6 +10,7 @@ SRC_URI_append = " \ ${@bb.utils.contains('MACHINE_FEATURES', 'h3ulcb-had', ' file://hyperflash.cfg', '', d)} \ ${@base_conditional("SDHI_SEQ", "1", " file://sdhi_seq.cfg", "", d)} \ file://qspi.cfg \ + file://imr.cfg \ 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 \ @@ -105,6 +106,8 @@ SRC_URI_append = " \ file://0124-RPC-Hyperflash-Add-devicetree-support.patch \ file://0125-r8a7797-pinctrl-Add-pin-function-for-hyperflash.patch \ file://0126-r8a7798-pinctrl-Add-pin-function-for-hyperflash.patch \ + file://0127-IMR-UIO-Driver-initial-version.patch \ + file://0128-rcar_imr-v4l2-driver-Fix-module-support.patch \ " SRC_URI_append_h3ulcb = " file://ulcb.cfg" @@ -178,6 +181,12 @@ KERNEL_DEVICETREE_append_v3hsk = " \ renesas/r8a7798-v3hsk-vbm-v2.dtb \ " +# Prefer V4L2 rcar_imr driver over UIO uio_imr +KERNEL_MODULE_AUTOLOAD += "rcar_imr" +KERNEL_MODULE_PROBECONF += "rcar_imr" +KERNEL_MODULE_PROBECONF += "uio_imr" +module_conf_uio_imr = 'blacklist uio_imr' + # V3H VIP devices KERNEL_MODULE_AUTOLOAD_r8a7798 += "uio_pdrv_genirq" KERNEL_MODULE_PROBECONF_r8a7798 += "uio_pdrv_genirq" -- cgit 1.2.3-korg From 620c0dd2ee137ea588326362c6c27dd175a7ed9d Mon Sep 17 00:00:00 2001 From: Andrey Dolnikov Date: Wed, 11 Apr 2018 17:15:57 +0300 Subject: linux-renesas: VSP1: Add cropping handling to VSP alpha-planes --- ...Add-cropping-handling-to-VSP-alpha-planes.patch | 44 ++++++++++++++++++++++ .../linux/linux-renesas_4.9.bbappend | 1 + 2 files changed, 45 insertions(+) create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0129-Add-cropping-handling-to-VSP-alpha-planes.patch (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0129-Add-cropping-handling-to-VSP-alpha-planes.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0129-Add-cropping-handling-to-VSP-alpha-planes.patch new file mode 100644 index 0000000..d55b196 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0129-Add-cropping-handling-to-VSP-alpha-planes.patch @@ -0,0 +1,44 @@ +From 4b26e8c561541c68c5755660eaad355d9a9afc86 Mon Sep 17 00:00:00 2001 +From: Konstantin Kozhevnikov +Date: Wed, 11 Apr 2018 05:11:21 -0700 +Subject: [PATCH] Add cropping handling to VSP alpha-planes + +--- + drivers/media/platform/vsp1/vsp1_dl.c | 2 +- + drivers/media/platform/vsp1/vsp1_rpf.c | 5 +++-- + 2 files changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/media/platform/vsp1/vsp1_dl.c b/drivers/media/platform/vsp1/vsp1_dl.c +index f9c6d09..d6314cd 100644 +--- a/drivers/media/platform/vsp1/vsp1_dl.c ++++ b/drivers/media/platform/vsp1/vsp1_dl.c +@@ -363,7 +363,7 @@ void vsp1_dl_set_addr_auto_fld(struct vsp1_dl_list *dl, struct vsp1_rwpf *rpf) + dl->src_dst_addr[v_bot_index].addr = v_bot_addr; + + /* ...set alpha-plane address as needed */ +- dl->src_dst_addr[alpha_index].addr = rpf->mem.alpha; ++ dl->src_dst_addr[alpha_index].addr = rpf->mem.alpha + crop->top * width + crop->left; + } + + static struct vsp1_dl_list *vsp1_dl_list_alloc(struct vsp1_dl_manager *dlm) +diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c +index 2cce294..1f70186 100644 +--- a/drivers/media/platform/vsp1/vsp1_rpf.c ++++ b/drivers/media/platform/vsp1/vsp1_rpf.c +@@ -292,10 +292,11 @@ static void rpf_configure(struct vsp1_entity *entity, + + // ...setup alpha-plane as required + if (rpf->mem.alpha) { +- vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_ADDR_AI, rpf->mem.alpha); ++ struct v4l2_rect *crop = vsp1_rwpf_get_crop(rpf, rpf->entity.config); ++ vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_ADDR_AI, rpf->mem.alpha + crop->top * rpf->alpha_pitch + crop->left); + vsp1_rpf_write(rpf, dl, VI6_RPF_ALPH_SEL, VI6_RPF_ALPH_SEL_ASEL_8B_PLANE); + vsp1_rpf_write(rpf, dl, VI6_RPF_SRCM_ASTRIDE, rpf->alpha_pitch); +- dev_dbg(vsp1->dev, "rpf#%d: setup alpha-plane: buffer=%pad, stride=%u\n", rpf->entity.index, &rpf->mem.alpha, rpf->alpha_pitch); ++ dev_dbg(vsp1->dev, "rpf#%d: setup alpha-plane: buffer=%pad, crop=%d,%d, stride=%u\n", rpf->entity.index, &rpf->mem.alpha, crop->left, crop->top, rpf->alpha_pitch); + goto out; + } + +-- +2.7.4 + 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 index 0233afa..b26c5d4 100644 --- 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 @@ -108,6 +108,7 @@ SRC_URI_append = " \ file://0126-r8a7798-pinctrl-Add-pin-function-for-hyperflash.patch \ file://0127-IMR-UIO-Driver-initial-version.patch \ file://0128-rcar_imr-v4l2-driver-Fix-module-support.patch \ + file://0129-Add-cropping-handling-to-VSP-alpha-planes.patch \ " SRC_URI_append_h3ulcb = " file://ulcb.cfg" -- cgit 1.2.3-korg From e1344265534511f331c8809f1d34e3b6f261dee9 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Wed, 11 Apr 2018 19:09:47 +0300 Subject: V3M: add ISP resources in dtsi --- ...as-r8a7797-Add-Renesas-R8A7797-SoC-suppor.patch | 26 ++++++++++++++++------ 1 file changed, 19 insertions(+), 7 deletions(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') 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 index 1f2b11c..63c109a 100644 --- 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 @@ -8,7 +8,7 @@ This adds Renesas R8A7797 SoC support Signed-off-by: Vladimir Barinov --- arch/arm64/Kconfig.platforms | 8 + - arch/arm64/boot/dts/renesas/r8a7797.dtsi | 1156 +++++++++++ + arch/arm64/boot/dts/renesas/r8a7797.dtsi | 1168 +++++++++++ drivers/clk/renesas/Kconfig | 1 + drivers/clk/renesas/Makefile | 1 + drivers/clk/renesas/r8a7797-cpg-mssr.c | 232 +++ @@ -47,7 +47,7 @@ Signed-off-by: Vladimir Barinov drivers/thermal/rcar_gen3_thermal.c | 29 + include/dt-bindings/clock/r8a7797-cpg-mssr.h | 48 + include/dt-bindings/power/r8a7797-sysc.h | 32 + - 40 files changed, 4489 insertions(+), 29 deletions(-) + 40 files changed, 4501 insertions(+), 29 deletions(-) create mode 100644 arch/arm64/boot/dts/renesas/r8a7797.dtsi create mode 100644 drivers/clk/renesas/r8a7797-cpg-mssr.c create mode 100644 drivers/pinctrl/sh-pfc/pfc-r8a7797.c @@ -76,10 +76,10 @@ index ebe0a37..9cebaad 100644 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..5319b1a +index 0000000..faefe8a --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7797.dtsi -@@ -0,0 +1,1156 @@ +@@ -0,0 +1,1168 @@ +/* + * Device Tree Source for the r8a7797 SoC + * @@ -115,6 +115,7 @@ index 0000000..5319b1a + vin2 = &vin2; + vin3 = &vin3; + tsc0 = &tsc1; ++ isp0 = &isp0; + }; + + psci { @@ -1234,6 +1235,17 @@ index 0000000..5319b1a + clocks = <&cpg CPG_MOD 820>; + power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; + }; ++ ++ isp0: isp@fec00000 { ++ compatible = "renesas,isp-r8a7797"; ++ reg = <0 0xfec00000 0 0x20000>, ++ <0 0xfed00000 0 0x4000>; ++ interrupts = , ++ ; ++ clocks = <&cpg CPG_MOD 817>; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; + }; +}; diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig @@ -1821,10 +1833,10 @@ index ecae864..d5fa06c 100644 lvdcr0 |= LVDCR0_LVRES; diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c -index 74c17d8..149c107 100644 +index 156fe5f..ea451cd 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) +@@ -836,6 +836,7 @@ static u32 rcar_i2c_func(struct i2c_adapter *adap) { .compatible = "renesas,i2c-r8a7795", .data = (void *)I2C_RCAR_GEN3 }, { .compatible = "renesas,i2c-r8a7796", .data = (void *)I2C_RCAR_GEN3 }, { .compatible = "renesas,i2c-r8a77965", .data = (void *)I2C_RCAR_GEN3 }, @@ -5171,7 +5183,7 @@ index 1b33c50..63f943d 100644 { .compatible = "renesas,sh73a0", .data = &soc_shmobile_ag5 }, #endif diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c -index 36e70db..a2606fe 100644 +index 2d3ac0b..1488964 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c @@ -216,7 +216,8 @@ static int msiof_rcar_is_gen3(struct device *dev) -- cgit 1.2.3-korg From 67e4a154c47123a974591dc2c2d7f4fea1887185 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Wed, 11 Apr 2018 19:10:10 +0300 Subject: V3H: add ISP resources in dtsi --- ...as-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch | 42 +++++++++++++++++----- 1 file changed, 33 insertions(+), 9 deletions(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch index 7d57c38..db09aab 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch @@ -9,7 +9,7 @@ Signed-off-by: Vladimir Barinov Signed-off-by: Mikhail Ulyanov --- arch/arm64/Kconfig.platforms | 8 + - arch/arm64/boot/dts/renesas/r8a7798.dtsi | 1700 +++++++++++++ + arch/arm64/boot/dts/renesas/r8a7798.dtsi | 1724 ++++++++++++++ drivers/clk/renesas/Kconfig | 1 + drivers/clk/renesas/Makefile | 1 + drivers/clk/renesas/r8a7798-cpg-mssr.c | 292 +++ @@ -47,7 +47,7 @@ Signed-off-by: Mikhail Ulyanov drivers/thermal/rcar_gen3_thermal.c | 10 + include/dt-bindings/clock/r8a7798-cpg-mssr.h | 56 + include/dt-bindings/power/r8a7798-sysc.h | 46 + - 39 files changed, 5618 insertions(+), 33 deletions(-) + 39 files changed, 5642 insertions(+), 33 deletions(-) create mode 100644 arch/arm64/boot/dts/renesas/r8a7798.dtsi create mode 100644 drivers/clk/renesas/r8a7798-cpg-mssr.c create mode 100644 drivers/pinctrl/sh-pfc/pfc-r8a7798.c @@ -76,10 +76,10 @@ index 9cebaad..3646b6e 100644 help diff --git a/arch/arm64/boot/dts/renesas/r8a7798.dtsi b/arch/arm64/boot/dts/renesas/r8a7798.dtsi new file mode 100644 -index 0000000..6412a24 +index 0000000..00bd4d6 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7798.dtsi -@@ -0,0 +1,1700 @@ +@@ -0,0 +1,1724 @@ +/* + * Device Tree Source for the r8a7798 SoC + * @@ -131,6 +131,8 @@ index 0000000..6412a24 + vin15 = &vin15; + tsc0 = &tsc1; + tsc1 = &tsc2; ++ isp0 = &isp0; ++ isp1 = &isp1; + }; + + psci { @@ -1778,6 +1780,28 @@ index 0000000..6412a24 + clocks = <&cpg CPG_MOD 1000>; + power-domains = <&sysc R8A7798_PD_A3VIP2>; + }; ++ ++ isp0: isp@fec00000 { ++ compatible = "renesas,isp-r8a7798"; ++ reg = <0 0xfec00000 0 0x20000>, ++ <0 0xfed00000 0 0x4000>; ++ interrupts = , ++ ; ++ clocks = <&cpg CPG_MOD 817>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; ++ ++ isp1: isp@fee00000 { ++ compatible = "renesas,isp-r8a7798"; ++ reg = <0 0xfee00000 0 0x20000>, ++ <0 0xfed20000 0 0x4000>; ++ interrupts = , ++ ; ++ clocks = <&cpg CPG_MOD 814>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ status = "disabled"; ++ }; + }; +}; diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig @@ -2253,10 +2277,10 @@ index 3916b63..22c7713 100644 rgrp->dptsr_planes); diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c -index 149c107..0ad583a 100644 +index ea451cd..6528f72 100644 --- a/drivers/i2c/busses/i2c-rcar.c +++ b/drivers/i2c/busses/i2c-rcar.c -@@ -808,6 +808,7 @@ static u32 rcar_i2c_func(struct i2c_adapter *adap) +@@ -837,6 +837,7 @@ static u32 rcar_i2c_func(struct i2c_adapter *adap) { .compatible = "renesas,i2c-r8a7796", .data = (void *)I2C_RCAR_GEN3 }, { .compatible = "renesas,i2c-r8a77965", .data = (void *)I2C_RCAR_GEN3 }, { .compatible = "renesas,i2c-r8a7797", .data = (void *)I2C_RCAR_GEN3 }, @@ -2279,7 +2303,7 @@ index 1ae9174..41e14fa 100644 }, }; diff --git a/drivers/media/platform/soc_camera/Kconfig b/drivers/media/platform/soc_camera/Kconfig -index 5539c5d..fc7d829 100644 +index d60909a..4ed8009 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 @@ -2292,7 +2316,7 @@ index 5539c5d..fc7d829 100644 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 2ef27e8..98f271f 100644 +index 53fc644..20ffba1 100644 --- a/drivers/media/platform/soc_camera/rcar_csi2.c +++ b/drivers/media/platform/soc_camera/rcar_csi2.c @@ -163,6 +163,11 @@ @@ -6317,7 +6341,7 @@ index 63f943d..b1fcae1 100644 { .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 a2606fe..13fd706 100644 +index 1488964..9ae47e5 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c @@ -217,7 +217,8 @@ static int msiof_rcar_is_gen3(struct device *dev) -- cgit 1.2.3-korg From 912c256c0b70b449fc819beb37a69411158d783b Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Wed, 11 Apr 2018 19:11:28 +0300 Subject: LVDS Sensors: add OX03A initial, IMX390, fix OV2775 This adds sensor OX03A, IMX390 Fix pll for OV2775 Fix refclk for all TI953 users Add ADV_DEBUG for soc_platform drivers --- .../linux-renesas/0030-Gen3-LVDS-cameras.patch | 11966 +++++++++++++++---- 1 file changed, 9364 insertions(+), 2602 deletions(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') 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 index fe71743..1623d12 100644 --- 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 @@ -6,45 +6,51 @@ Subject: [PATCH] Gen3: LVDS cameras This add Gen3 LVDS cameras support: - deserializers: MAX9286, DS90UB954/960/964 - cameras: ov10635, ov490+ov10640, ov495+OV2775, ar0132, ar0220, - ap0101+ar014x, ov2775 + ap0101+ar014x, ov2775, imx390, ox03a Signed-off-by: Vladimir Barinov --- drivers/media/i2c/soc_camera/Kconfig | 19 + drivers/media/i2c/soc_camera/Makefile | 3 + - drivers/media/i2c/soc_camera/ap0101_ar014x.c | 588 +++++++ + drivers/media/i2c/soc_camera/ap0101_ar014x.c | 588 ++++ drivers/media/i2c/soc_camera/ap0101_ar014x.h | 28 + - drivers/media/i2c/soc_camera/ar0132.c | 565 +++++++ - drivers/media/i2c/soc_camera/ar0132.h | 213 +++ - drivers/media/i2c/soc_camera/ar0220.c | 528 +++++++ - drivers/media/i2c/soc_camera/ar0220.h | 309 ++++ - drivers/media/i2c/soc_camera/max9286.c | 692 ++++++++ - drivers/media/i2c/soc_camera/max9286.h | 244 +++ - drivers/media/i2c/soc_camera/ov10635.c | 759 +++++++++ - drivers/media/i2c/soc_camera/ov10635.h | 1139 +++++++++++++ + drivers/media/i2c/soc_camera/ar0132.c | 565 ++++ + drivers/media/i2c/soc_camera/ar0132.h | 212 ++ + drivers/media/i2c/soc_camera/ar0220.c | 538 +++ + drivers/media/i2c/soc_camera/ar0220.h | 43 + + drivers/media/i2c/soc_camera/imx390.c | 533 +++ + drivers/media/i2c/soc_camera/imx390.h | 3817 ++++++++++++++++++++++ + drivers/media/i2c/soc_camera/max9286.c | 692 ++++ + drivers/media/i2c/soc_camera/max9286.h | 244 ++ + drivers/media/i2c/soc_camera/ov10635.c | 759 +++++ + drivers/media/i2c/soc_camera/ov10635.h | 1139 +++++++ drivers/media/i2c/soc_camera/ov10635_debug.h | 54 + - drivers/media/i2c/soc_camera/ov106xx.c | 139 ++ - drivers/media/i2c/soc_camera/ov2775.c | 527 +++++++ - drivers/media/i2c/soc_camera/ov2775.h | 1841 ++++++++++++++++++++++ - drivers/media/i2c/soc_camera/ov490_ov10640.c | 1133 +++++++++++++ - drivers/media/i2c/soc_camera/ov490_ov10640.h | 102 ++ - drivers/media/i2c/soc_camera/ov495_ov2775.c | 639 ++++++++ + drivers/media/i2c/soc_camera/ov106xx.c | 161 + + drivers/media/i2c/soc_camera/ov2775.c | 538 +++ + drivers/media/i2c/soc_camera/ov2775.h | 1841 +++++++++++ + drivers/media/i2c/soc_camera/ov490_ov10640.c | 1133 +++++++ + drivers/media/i2c/soc_camera/ov490_ov10640.h | 102 + + drivers/media/i2c/soc_camera/ov495_ov2775.c | 650 ++++ drivers/media/i2c/soc_camera/ov495_ov2775.h | 23 + - drivers/media/i2c/soc_camera/ti9x4.c | 518 ++++++ - drivers/media/i2c/soc_camera/ti9x4.h | 156 ++ - drivers/media/platform/soc_camera/rcar_csi2.c | 297 ++-- - drivers/media/platform/soc_camera/rcar_vin.c | 194 ++- - drivers/media/platform/soc_camera/soc_camera.c | 17 +- - drivers/media/platform/soc_camera/soc_mediabus.c | 16 + + drivers/media/i2c/soc_camera/ox03a.c | 526 +++ + drivers/media/i2c/soc_camera/ox03a.h | 1724 ++++++++++ + drivers/media/i2c/soc_camera/ti9x4.c | 518 +++ + drivers/media/i2c/soc_camera/ti9x4.h | 156 + + drivers/media/platform/soc_camera/rcar_csi2.c | 312 +- + drivers/media/platform/soc_camera/rcar_vin.c | 194 +- + drivers/media/platform/soc_camera/soc_camera.c | 47 +- + drivers/media/platform/soc_camera/soc_mediabus.c | 26 + include/media/drv-intf/soc_mediabus.h | 3 + - include/media/soc_camera.h | 1 + - 28 files changed, 10638 insertions(+), 109 deletions(-) + include/media/soc_camera.h | 5 + + 32 files changed, 17066 insertions(+), 127 deletions(-) create mode 100644 drivers/media/i2c/soc_camera/ap0101_ar014x.c create mode 100644 drivers/media/i2c/soc_camera/ap0101_ar014x.h create mode 100644 drivers/media/i2c/soc_camera/ar0132.c create mode 100644 drivers/media/i2c/soc_camera/ar0132.h create mode 100644 drivers/media/i2c/soc_camera/ar0220.c create mode 100644 drivers/media/i2c/soc_camera/ar0220.h + create mode 100644 drivers/media/i2c/soc_camera/imx390.c + create mode 100644 drivers/media/i2c/soc_camera/imx390.h create mode 100644 drivers/media/i2c/soc_camera/max9286.c create mode 100644 drivers/media/i2c/soc_camera/max9286.h create mode 100644 drivers/media/i2c/soc_camera/ov10635.c @@ -57,6 +63,8 @@ Signed-off-by: Vladimir Barinov 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/ox03a.c + create mode 100644 drivers/media/i2c/soc_camera/ox03a.h create mode 100644 drivers/media/i2c/soc_camera/ti9x4.c create mode 100644 drivers/media/i2c/soc_camera/ti9x4.h @@ -736,7 +744,7 @@ index 0000000..16599a1 +}; diff --git a/drivers/media/i2c/soc_camera/ar0132.c b/drivers/media/i2c/soc_camera/ar0132.c new file mode 100644 -index 0000000..e124e6a +index 0000000..c0ac733 --- /dev/null +++ b/drivers/media/i2c/soc_camera/ar0132.c @@ -0,0 +1,565 @@ @@ -770,7 +778,7 @@ index 0000000..e124e6a +#define AR0132_PID 0x3000 +#define AR0132_VERSION_REG 0x2400 + -+#define AR0132_MEDIA_BUS_FMT MEDIA_BUS_FMT_SBGGR12_1X12 ++#define AR0132_MEDIA_BUS_FMT MEDIA_BUS_FMT_SGRBG12_1X12 + +struct ar0132_priv { + struct v4l2_subdev sd; @@ -1307,10 +1315,10 @@ index 0000000..e124e6a +#endif diff --git a/drivers/media/i2c/soc_camera/ar0132.h b/drivers/media/i2c/soc_camera/ar0132.h new file mode 100644 -index 0000000..bafa193 +index 0000000..7dfc4e3 --- /dev/null +++ b/drivers/media/i2c/soc_camera/ar0132.h -@@ -0,0 +1,213 @@ +@@ -0,0 +1,212 @@ +/* + * ON Semiconductor AR0132 sensor camera wizard 1110x620@30/BGGR/BT601/12bit + * @@ -1327,16 +1335,15 @@ index 0000000..bafa193 + +#define AR0132_EMBEDDED_LINE + -+#define AR0132_MAX_WIDTH 1665 // (1110*3/2) ++#define AR0132_MAX_WIDTH 1104 +#define AR0132_MAX_HEIGHT 624 + +#define AR0132_DELAY 0xffff + +#define AR0132_MAX_ROI_DIM_X 1288 +#define AR0132_MAX_ROI_DIM_Y 968 -+#define AR0132_InfoLines 4 + -+#define AR0132_ROI_DIM_X 1110 // 1104 ++#define AR0132_ROI_DIM_X 1104 +#define AR0132_ROI_DIM_Y 620 // AR0132_MAX_HEIGHT + +#define AR0132_ROI_Y_START 0x00AE @@ -1370,11 +1377,11 @@ index 0000000..bafa193 + //256: Walking 1 test pattern (12 bit) +#ifdef AR0132_DISPLAY_PATTERN_FIXED +{0x3070, 0x0001}, ++#endif +{0x3072, 0x0123}, // R +{0x3074, 0x0456}, // G(GR row) +{0x3076, 0x0abc}, // B +{0x3078, 0x0def}, // G(GB row) -+#endif +#ifdef AR0132_DISPLAY_PATTERN_COLOR_BAR +{0x3070, 0x0002}, +#endif @@ -1526,10 +1533,10 @@ index 0000000..bafa193 +}; diff --git a/drivers/media/i2c/soc_camera/ar0220.c b/drivers/media/i2c/soc_camera/ar0220.c new file mode 100644 -index 0000000..ef2eb51 +index 0000000..eb20187 --- /dev/null +++ b/drivers/media/i2c/soc_camera/ar0220.c -@@ -0,0 +1,528 @@ +@@ -0,0 +1,538 @@ +/* + * ON Semiconductor AR0220 sensor camera driver + * @@ -1560,7 +1567,7 @@ index 0000000..ef2eb51 +#define AR0220_PID 0x3000 +#define AR0220_VERSION_REG 0x0C54 + -+#define AR0220_MEDIA_BUS_FMT MEDIA_BUS_FMT_SBGGR8_1X8 ++#define AR0220_MEDIA_BUS_FMT MEDIA_BUS_FMT_SGRBG14_1X14 + +struct ar0220_priv { + struct v4l2_subdev sd; @@ -1578,7 +1585,6 @@ index 0000000..ef2eb51 + int port; + int gpio_resetb; + int gpio_fsin; -+ +}; + +static inline struct ar0220_priv *to_ar0220(const struct i2c_client *client) @@ -1850,6 +1856,7 @@ index 0000000..ef2eb51 + u16 val = 0; + u16 pid = 0; + int ret = 0; ++ int tmp_addr; + + /* check and show model ID */ + reg16_read16(client, AR0220_PID, &pid); @@ -1860,6 +1867,16 @@ index 0000000..ef2eb51 + goto err; + } + ++ /* setup XCLK */ ++ tmp_addr = client->addr; ++ if (priv->ti9x4_addr) { ++ /* CLK_OUT=22.5792*160*M/N/CLKDIV -> CLK_OUT=27MHz: CLKDIV=2, M=15, N=251: 22.5792*160/8*15/251=26.987MHz=CLK_OUT */ ++ client->addr = priv->ti9x3_addr; /* Serializer I2C address */ ++ reg8_write(client, 0x06, 0x6f); /* Set CLKDIV and M */ ++ reg8_write(client, 0x07, 0xfb); /* Set N */ ++ } ++ client->addr = tmp_addr; ++ + /* Program wizard registers */ + ar0220_set_regs(client, ar0220_regs_wizard, ARRAY_SIZE(ar0220_regs_wizard)); + @@ -2060,7 +2077,7 @@ index 0000000..ef2eb51 +#endif diff --git a/drivers/media/i2c/soc_camera/ar0220.h b/drivers/media/i2c/soc_camera/ar0220.h new file mode 100644 -index 0000000..74bfdd2 +index 0000000..205c351 --- /dev/null +++ b/drivers/media/i2c/soc_camera/ar0220.h @@ -0,0 +1,43 @@ @@ -2078,7 +2095,7 @@ index 0000000..74bfdd2 +//#define AR0220_DISPLAY_PATTERN_FIXED +//#define AR0220_DISPLAY_PATTERN_COLOR_BAR + -+#define AR0220_MAX_WIDTH 3648 // (1820*2=3640) <- must be multiple of 16 - requred by R-CAR VIN ++#define AR0220_MAX_WIDTH 1820 +#define AR0220_MAX_HEIGHT 944 + +#define AR0220_DELAY 0xffff @@ -2107,16 +2124,16 @@ index 0000000..74bfdd2 +#endif +{AR0220_DELAY, 100}, // Wait 100ms +}; -diff --git a/drivers/media/i2c/soc_camera/max9286.c b/drivers/media/i2c/soc_camera/max9286.c +diff --git a/drivers/media/i2c/soc_camera/imx390.c b/drivers/media/i2c/soc_camera/imx390.c new file mode 100644 -index 0000000..c850196 +index 0000000..61f430d --- /dev/null -+++ b/drivers/media/i2c/soc_camera/max9286.c -@@ -0,0 +1,692 @@ ++++ b/drivers/media/i2c/soc_camera/imx390.c +@@ -0,0 +1,533 @@ +/* -+ * MAXIM max9286 GMSL driver ++ * OmniVision IMX390 sensor camera driver + * -+ * Copyright (C) 2015-2018 Cogent Embedded, Inc. ++ * Copyright (C) 2018 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 @@ -2125,384 +2142,213 @@ index 0000000..c850196 + */ + +#include ++#include +#include +#include -+#include -+#include +#include + ++#include +#include -+#include ++#include +#include -+#include + -+#include "max9286.h" ++#include "imx390.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 ++#define IMX390_I2C_ADDR 0x21 + -+struct max9286_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 him; -+ int hsync; -+ int vsync; -+ int timeout; -+ int poc_delay; -+ atomic_t use_count; -+ u32 csi2_outord; -+ struct i2c_client *client; -+ int max9271_addr_map[4]; -+ int ser_id; -+ struct gpio_desc *poc_gpio[4]; /* PoC power supply */ -+}; ++#define IMX390_PID 0x0330 ++#define IMX390_VER 0x0330 ++#define IMX390_VERSION_REG 0x1515 + -+static char fsync_mode_default[20] = "manual"; /* manual, automatic, semi-automatic, external */ ++#define IMX390_MEDIA_BUS_FMT MEDIA_BUS_FMT_SRGGB12_1X12 + -+static int conf_link; -+module_param(conf_link, int, 0644); -+MODULE_PARM_DESC(conf_link, " Force configuration link. Used only if robust firmware flashing required (f.e. recovery)"); ++struct imx390_priv { ++ struct v4l2_subdev sd; ++ struct v4l2_ctrl_handler hdl; ++ struct media_pad pad; ++ struct v4l2_rect rect; ++ int init_complete; ++ u8 id[6]; ++ int exposure; ++ int gain; ++ int autogain; ++ /* serializers */ ++ int ti9x4_addr; ++ int ti9x3_addr; ++ int port; ++ int gpio_resetb; ++ int gpio_fsin; ++}; + -+static int poc_trig; -+module_param(poc_trig, int, 0644); -+MODULE_PARM_DESC(poc_trig, " Use PoC triggering during reverse channel setup. Useful on systems with dedicated PoC and unstable ser-des lock"); ++static inline struct imx390_priv *to_imx390(const struct i2c_client *client) ++{ ++ return container_of(i2c_get_clientdata(client), struct imx390_priv, sd); ++} + -+static int him; -+module_param(him, int, 0644); -+MODULE_PARM_DESC(him, " Use High-Immunity mode (default: leagacy mode)"); ++static int imx390_set_regs(struct i2c_client *client, ++ const struct imx390_reg *regs, int nr_regs) ++{ ++ int i; + -+static int fsync_period; -+module_param(fsync_period, int, 0644); -+MODULE_PARM_DESC(fsync_period, " Frame sync period (default: 3.2MHz)"); ++ for (i = 0; i < nr_regs; i++) { ++ if (regs[i].reg == IMX390_DELAY) { ++ mdelay(regs[i].val); ++ continue; ++ } + -+static int hsync; -+module_param(hsync, int, 0644); -+MODULE_PARM_DESC(hsync, " HSYNC invertion (default: 0 - not inverted)"); ++ reg16_write(client, regs[i].reg, regs[i].val); ++ } + -+static int vsync = 1; -+module_param(vsync, int, 0644); -+MODULE_PARM_DESC(vsync, " VSYNC invertion (default: 1 - inverted)"); ++ return 0; ++} + -+static int gpio_resetb; -+module_param(gpio_resetb, int, 0644); -+MODULE_PARM_DESC(gpio_resetb, " Serializer GPIO reset (default: 0 - not used)"); ++static int imx390_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ return 0; ++} + -+static int active_low_resetb; -+module_param(active_low_resetb, int, 0644); -+MODULE_PARM_DESC(active_low_resetb, " Serializer GPIO reset level (default: 0 - active high)"); ++static int imx390_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 imx390_priv *priv = to_imx390(client); + -+static int poc_delay; -+module_param(poc_delay, int, 0644); -+MODULE_PARM_DESC(poc_delay, " Delay in ms after POC enable (default: 0 ms)"); ++ if (format->pad) ++ return -EINVAL; + -+static char* ser_name(int id) -+{ -+ switch (id) { -+ case MAX9271_ID: -+ return "MAX9271"; -+ case MAX96705_ID: -+ return "MAX96705"; -+ default: -+ return "unknown"; -+ } ++ mf->width = priv->rect.width; ++ mf->height = priv->rect.height; ++ mf->code = IMX390_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ return 0; +} + -+static void max9286_preinit(struct i2c_client *client, int addr) ++static int imx390_set_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) +{ -+ struct max9286_priv *priv = i2c_get_clientdata(client); ++ struct v4l2_mbus_framefmt *mf = &format->format; + -+ 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 */ -+ reg8_write(client, 0x1c, priv->him ? 0xf4 : 0x04); /* high-immunity or legacy mode */ ++ mf->code = IMX390_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ if (format->which == V4L2_SUBDEV_FORMAT_TRY) ++ cfg->try_fmt = *mf; ++ ++ return 0; +} + -+static void max9286_sensor_reset(struct i2c_client *client, int addr, int reset_on) ++static int imx390_enum_mbus_code(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_mbus_code_enum *code) +{ -+ struct max9286_priv *priv = i2c_get_clientdata(client); ++ if (code->pad || code->index > 0) ++ return -EINVAL; + -+ if (priv->gpio_resetb < 1 || priv->gpio_resetb > 5) -+ return; ++ code->code = IMX390_MEDIA_BUS_FMT; + -+ /* sensor reset/unreset */ -+ client->addr = addr; /* MAX9271-CAMx I2C */ -+ reg8_write(client, 0x0f, (0xfe & ~BIT(priv->gpio_resetb)) | /* set GPIOn value to reset/unreset */ -+ ((priv->active_low_resetb ? BIT(priv->gpio_resetb) : 0) ^ reset_on)); -+ reg8_write(client, 0x0e, 0x42 | BIT(priv->gpio_resetb)); /* set GPIOn direction output */ ++ return 0; +} + -+static void max9286_postinit(struct i2c_client *client, int addr) ++static int imx390_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) +{ -+ struct max9286_priv *priv = i2c_get_clientdata(client); -+ int idx; -+ -+ for (idx = 0; idx < priv->links; idx++) { -+ client->addr = priv->des_addr; /* MAX9286 I2C */ -+ reg8_write(client, 0x0a, 0x11 << idx); /* enable reverse/forward control for CAMx */ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct imx390_priv *priv = to_imx390(client); + -+ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C */ -+ max9286_sensor_reset(client, client->addr, 0); /* sensor unreset */ -+ } ++ memcpy(edid->edid, priv->id, 6); + -+ 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 */ ++ edid->edid[6] = 0xff; ++ edid->edid[7] = client->addr; ++ edid->edid[8] = IMX390_VERSION_REG >> 8; ++ edid->edid[9] = IMX390_VERSION_REG & 0xff; + -+ if (strcmp(priv->fsync_mode, "manual") == 0) { -+ 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 */ -+ } ++ return 0; +} + -+static int max9286_reverse_channel_setup(struct i2c_client *client, int idx) ++static int imx390_set_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) +{ -+ struct max9286_priv *priv = i2c_get_clientdata(client); -+ u8 val = 0; -+ int timeout = priv->timeout; -+ char timeout_str[10]; -+ int ret = 0; ++ struct v4l2_rect *rect = &sel->r; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct imx390_priv *priv = to_imx390(client); + -+ /* 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 */ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || ++ sel->target != V4L2_SEL_TGT_CROP) ++ return -EINVAL; + -+ 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 */ ++ rect->left = ALIGN(rect->left, 2); ++ rect->top = ALIGN(rect->top, 2); ++ rect->width = ALIGN(rect->width, 2); ++ rect->height = ALIGN(rect->height, 2); + -+ client->addr = 0x40; /* MAX9271-CAMx I2C */ -+ reg8_write(client, 0x04, 0x43); /* wake-up, enable reverse_control/conf_link */ -+ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ -+ reg8_write(client, 0x08, 0x01); /* reverse channel receiver high threshold enable */ -+ reg8_write(client, 0x97, priv->him ? 0xaf : 0x5f); /* enable reverse control channel programming (MAX96705-MAX96711 only) */ -+ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ if ((rect->left + rect->width > IMX390_MAX_WIDTH) || ++ (rect->top + rect->height > IMX390_MAX_HEIGHT)) ++ *rect = priv->rect; + -+ 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 */ ++ priv->rect.left = rect->left; ++ priv->rect.top = rect->top; ++ priv->rect.width = rect->width; ++ priv->rect.height = rect->height; + -+ client->addr = 0x40; /* MAX9271-CAMx I2C */ -+ reg8_read(client, 0x1e, &val); /* read max9271 ID */ -+ if (val == MAX9271_ID || val == MAX96705_ID || --timeout == 0) { -+ priv->ser_id = val; -+ break; -+ } ++ return 0; ++} + -+ /* Check if already initialized (after reboot/reset ?) */ -+ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C */ -+ reg8_read(client, 0x1e, &val); /* read max9271 ID */ -+ if (val == MAX9271_ID || val == MAX96705_ID) { -+ priv->ser_id = val; -+ reg8_write(client, 0x04, 0x43); /* enable reverse_control/conf_link */ -+ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ -+ ret = -EADDRINUSE; -+ break; -+ } -+ -+ if (timeout == priv->timeout / 2 && poc_trig) { -+ if (!IS_ERR(priv->poc_gpio[idx])) { -+ gpiod_direction_output(priv->poc_gpio[idx], 0); /* POC power off */ -+ mdelay(200); -+ gpiod_direction_output(priv->poc_gpio[idx], 1); /* POC power on */ -+ mdelay(priv->poc_delay); -+ } -+ } -+ } -+ -+ max9286_sensor_reset(client, client->addr, 1); /* sensor reset */ -+ -+ if (!timeout) { -+ ret = -ETIMEDOUT; -+ goto out; -+ } -+ -+ priv->links_mask |= BIT(idx); -+ priv->csi2_outord &= ~(0x3 << (idx * 2)); -+ priv->csi2_outord |= ((hweight8(priv->links_mask) - 1) << (idx * 2)); -+ -+out: -+ sprintf(timeout_str, "retries=%d", priv->timeout - timeout); -+ dev_info(&client->dev, "link%d %s %sat 0x%x %s %s\n", idx, ser_name(priv->ser_id), -+ ret == -EADDRINUSE ? "already " : "", priv->max9271_addr_map[idx], -+ ret == -ETIMEDOUT ? "not found: timeout GMSL link establish" : "", -+ priv->timeout - timeout? timeout_str : ""); -+ -+ return ret; -+} -+ -+static void max9286_initial_setup(struct i2c_client *client) -+{ -+ struct max9286_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); -+ } -+ -+ /* Start GMSL initialization with FSYNC disabled. This is required for some odd LVDS cameras */ -+ reg8_write(client, 0x01, 0xc0); /* ECU (aka MCU) based FrameSync using GPI-to-GPO */ -+ 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, 0x63, 0); /* disable overlap window */ -+ reg8_write(client, 0x64, 0); -+ reg8_write(client, 0x0c, 0x91 | (priv->vsync ? BIT(3) : 0) | (priv->hsync ? BIT(2) : 0)); /* enable HS/VS encoding, use D14/15 for HS/VS, invert HS/VS */ -+ reg8_write(client, 0x19, 0x0c); /* Drive HSTRAIL state for 120ns after the last payload bit */ -+} -+ -+static void max9286_gmsl_link_setup(struct i2c_client *client, int idx) ++static int imx390_get_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) +{ -+ struct max9286_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 */ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct imx390_priv *priv = to_imx390(client); + -+ if (priv->ser_id == MAX96705_ID) { -+ /* setup crossbar in DBL mode: reverse DVP bus */ -+ reg8_write(client, 0x20, 0x07); -+ reg8_write(client, 0x21, 0x06); -+ reg8_write(client, 0x22, 0x05); -+ reg8_write(client, 0x23, 0x04); -+ reg8_write(client, 0x24, 0x03); -+ reg8_write(client, 0x25, 0x02); -+ reg8_write(client, 0x26, 0x01); -+ reg8_write(client, 0x27, 0x00); ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) ++ return -EINVAL; + -+ reg8_write(client, 0x30, 0x17); -+ reg8_write(client, 0x31, 0x16); -+ reg8_write(client, 0x32, 0x15); -+ reg8_write(client, 0x33, 0x14); -+ reg8_write(client, 0x34, 0x13); -+ reg8_write(client, 0x35, 0x12); -+ reg8_write(client, 0x36, 0x11); -+ reg8_write(client, 0x37, 0x10); ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = IMX390_MAX_WIDTH; ++ sel->r.height = IMX390_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = IMX390_MAX_WIDTH; ++ sel->r.height = IMX390_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP: ++ sel->r = priv->rect; ++ return 0; ++ default: ++ return -EINVAL; + } -+ -+ client->addr = priv->des_addr; /* MAX9286-CAMx I2C */ -+ reg8_write(client, 0x34, 0x22 | MAXIM_I2C_I2C_SPEED); /* disable artificial ACK, I2C speed set */ -+ usleep_range(2000, 2500); /* wait 2ms */ -+ -+ /* I2C translator setup */ -+ client->addr = 0x40; /* MAX9271-CAMx I2C */ -+// reg8_write(client, 0x09, maxim_map[2][idx] << 1); /* SENSOR I2C translated - must be set by sensor driver */ -+// reg8_write(client, 0x0A, 0x30 << 1); /* SENSOR I2C native - must be set by sensor driver */ -+ reg8_write(client, 0x0B, BROADCAST << 1); /* broadcast I2C */ -+ reg8_write(client, 0x0C, priv->max9271_addr_map[idx] << 1); /* MAX9271-CAMx I2C new */ -+ /* I2C addresse change */ -+ reg8_write(client, 0x01, priv->des_addr << 1); /* MAX9286 I2C */ -+ reg8_write(client, 0x00, priv->max9271_addr_map[idx] << 1); /* MAX9271-CAM0 I2C new */ -+ usleep_range(2000, 2500); /* wait 2ms */ -+ /* put MAX9271 in configuration link state */ -+ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C new */ -+ reg8_write(client, 0x04, 0x43); /* enable reverse_control/conf_link */ -+ usleep_range(2000, 2500); /* wait 2ms */ -+#ifdef MAXIM_DUMP -+ client->addr = priv->des_addr; /* MAX9286-CAMx I2C */ -+ maxim_max927x_dump_regs(client); -+ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C new */ -+ maxim_max927x_dump_regs(client); -+#endif +} + -+static int max9286_initialize(struct i2c_client *client) ++static int imx390_g_mbus_config(struct v4l2_subdev *sd, ++ struct v4l2_mbus_config *cfg) +{ -+ struct max9286_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_preinit(client, priv->des_quirk_addr); -+ -+ max9286_preinit(client, priv->des_addr); -+ max9286_initial_setup(client); -+ -+ for (idx = 0; idx < priv->links; idx++) { -+ if (!IS_ERR(priv->poc_gpio[idx])) { -+ gpiod_direction_output(priv->poc_gpio[idx], 1); /* POC power on */ -+ mdelay(priv->poc_delay); -+ } -+ -+ ret = max9286_reverse_channel_setup(client, idx); -+ if (ret) -+ continue; -+ max9286_gmsl_link_setup(client, idx); -+ } -+ -+ max9286_postinit(client, priv->des_addr); -+ -+ client->addr = priv->des_addr; ++ 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 max9286_g_register(struct v4l2_subdev *sd, -+ struct v4l2_dbg_register *reg) ++static int imx390_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) +{ -+ struct max9286_priv *priv = v4l2_get_subdevdata(sd); -+ struct i2c_client *client = priv->client; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); + int ret; + u8 val = 0; + -+ ret = reg8_read(client, (u8)reg->reg, &val); ++ ret = reg16_read(client, (u16)reg->reg, &val); + if (ret < 0) + return ret; + @@ -2512,187 +2358,138 @@ index 0000000..c850196 + return 0; +} + -+static int max9286_s_register(struct v4l2_subdev *sd, -+ const struct v4l2_dbg_register *reg) ++static int imx390_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) +{ -+ struct max9286_priv *priv = v4l2_get_subdevdata(sd); -+ struct i2c_client *client = priv->client; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); + -+ return reg8_write(client, (u8)reg->reg, (u8)reg->val); ++ return reg16_write(client, (u16)reg->reg, (u8)reg->val); +} +#endif + -+static int max9286_s_power(struct v4l2_subdev *sd, int on) ++static struct v4l2_subdev_core_ops imx390_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = imx390_g_register, ++ .s_register = imx390_s_register, ++#endif ++}; ++ ++static int imx390_s_ctrl(struct v4l2_ctrl *ctrl) +{ -+ struct max9286_priv *priv = v4l2_get_subdevdata(sd); -+ struct i2c_client *client = priv->client; ++ struct v4l2_subdev *sd = to_sd(ctrl); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct imx390_priv *priv = to_imx390(client); ++ int ret = -EINVAL; + -+ 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 */ ++ if (!priv->init_complete) ++ return 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_BRIGHTNESS: ++ case V4L2_CID_CONTRAST: ++ case V4L2_CID_SATURATION: ++ case V4L2_CID_HUE: ++ case V4L2_CID_GAMMA: ++ case V4L2_CID_SHARPNESS: ++ case V4L2_CID_AUTOGAIN: ++ case V4L2_CID_GAIN: ++ case V4L2_CID_EXPOSURE: ++ case V4L2_CID_HFLIP: ++ case V4L2_CID_VFLIP: ++ break; + } + -+ return 0; ++ return ret; +} + -+static int max9286_registered_async(struct v4l2_subdev *sd) -+{ -+ struct max9286_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 */ ++static const struct v4l2_ctrl_ops imx390_ctrl_ops = { ++ .s_ctrl = imx390_s_ctrl, ++}; + -+ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx */ -+ reg8_write(client, 0x04, conf_link ? 0x43 : 0x83); /* enable serial_link */ -+ usleep_range(2000, 2500); /* wait 2ms after changing reverse_control */ ++static struct v4l2_subdev_video_ops imx390_video_ops = { ++ .s_stream = imx390_s_stream, ++ .g_mbus_config = imx390_g_mbus_config, ++}; + -+ 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 */ ++static const struct v4l2_subdev_pad_ops imx390_subdev_pad_ops = { ++ .get_edid = imx390_get_edid, ++ .enum_mbus_code = imx390_enum_mbus_code, ++ .get_selection = imx390_get_selection, ++ .set_selection = imx390_set_selection, ++ .get_fmt = imx390_get_fmt, ++ .set_fmt = imx390_set_fmt, ++}; + -+ client->addr = tmp_addr; ++static struct v4l2_subdev_ops imx390_subdev_ops = { ++ .core = &imx390_core_ops, ++ .video = &imx390_video_ops, ++ .pad = &imx390_subdev_pad_ops, ++}; + -+ return 0; ++static void imx390_otp_id_read(struct i2c_client *client) ++{ +} + -+static struct v4l2_subdev_core_ops max9286_subdev_core_ops = { -+#ifdef CONFIG_VIDEO_ADV_DEBUG -+ .g_register = max9286_g_register, -+ .s_register = max9286_s_register, -+#endif -+ .s_power = max9286_s_power, -+ .registered_async = max9286_registered_async, -+}; -+ -+static struct v4l2_subdev_ops max9286_subdev_ops = { -+ .core = &max9286_subdev_core_ops, -+}; -+ -+static int max9286_parse_dt(struct i2c_client *client) ++static ssize_t imx390_otp_id_show(struct device *dev, ++ struct device_attribute *attr, char *buf) +{ -+ struct max9286_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; -+ u8 val = 0; -+ char poc_name[10]; -+ -+ 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); -+ } ++ struct v4l2_subdev *sd = i2c_get_clientdata(to_i2c_client(dev)); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct imx390_priv *priv = to_imx390(client); + -+ mdelay(250); ++ 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]); ++} + -+ for (i = 0; i < 4; i++) { -+ sprintf(poc_name, "POC%d", i); -+ priv->poc_gpio[i] = devm_gpiod_get_optional(&client->dev, poc_name, 0); -+ } ++static DEVICE_ATTR(otp_id_imx390, S_IRUGO, imx390_otp_id_show, NULL); + -+ 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; -+ } ++static int imx390_initialize(struct i2c_client *client) ++{ ++ struct imx390_priv *priv = to_imx390(client); ++ u8 val = 0; ++ u16 pid; ++ int ret = 0; ++ int tmp_addr; + -+ 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); ++ /* check and show model ID */ ++ reg16_read(client, IMX390_PID, &val); ++ pid = val; ++ reg16_read(client, IMX390_VER, &val); ++ pid = (pid << 8) | val; + -+ 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 = 0; -+ else -+ priv->active_low_resetb = 1; ++ if (pid != IMX390_VERSION_REG) { ++ dev_dbg(&client->dev, "Product ID error %x\n", pid); ++ ret = -ENODEV; ++ goto err; + } + -+ 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; -+ if (of_property_read_u32(np, "maxim,him", &priv->him)) -+ priv->him = 0; -+ if (of_property_read_u32(np, "maxim,hsync", &priv->hsync)) -+ priv->hsync = 0; -+ if (of_property_read_u32(np, "maxim,vsync", &priv->vsync)) -+ priv->vsync = 1; -+ if (of_property_read_u32(np, "maxim,poc-delay", &priv->poc_delay)) -+ priv->poc_delay = 50; -+ -+ /* module params override dts */ -+ if (him) -+ priv->him = him; -+ if (fsync_period) { -+ priv->fsync_period = fsync_period; -+ priv->fsync_mode = fsync_mode_default; ++ /* setup XCLK */ ++ tmp_addr = client->addr; ++ if (priv->ti9x4_addr) { ++ /* CLK_OUT=22.5792*160*M/N/CLKDIV -> CLK_OUT=25MHz: CLKDIV=4, M=7, N=253: 22.5792*160/4*7/253=24.989MHz=CLK_OUT */ ++ client->addr = priv->ti9x3_addr; /* Serializer I2C address */ ++ reg8_write(client, 0x06, 0x47); /* Set CLKDIV and M */ ++ reg8_write(client, 0x07, 0xfd); /* Set N */ + } -+ if (hsync) -+ priv->hsync = hsync; -+ if (!vsync) -+ priv->vsync = vsync; -+ if (gpio_resetb) -+ priv->gpio_resetb = gpio_resetb; -+ if (active_low_resetb) -+ priv->active_low_resetb = active_low_resetb; -+ if (poc_delay) -+ priv->poc_delay = poc_delay; -+ -+ 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; -+ } ++ client->addr = tmp_addr; + -+ priv->sd_of_node[i] = endpoint; -+ } ++ /* Program wizard registers */ ++ imx390_set_regs(client, imx390_regs_wizard, ARRAY_SIZE(imx390_regs_wizard)); ++ /* Read OTP IDs */ ++ imx390_otp_id_read(client); + -+ return 0; ++ dev_info(&client->dev, "imx390 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, IMX390_MAX_WIDTH, IMX390_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++err: ++ return ret; +} + -+static void max9286_setup_remote_endpoint(struct i2c_client *client) ++static int imx390_parse_dt(struct device_node *np, struct imx390_priv *priv) +{ -+ struct max9286_priv *priv = i2c_get_clientdata(client); -+ struct device_node *np = client->dev.of_node; -+ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); + int i; -+ struct property *csi_rate_prop, *dvp_order_prop; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ int tmp_addr = 0; + + for (i = 0; ; i++) { + endpoint = of_graph_get_next_endpoint(np, endpoint); @@ -2705,116 +2502,177 @@ index 0000000..c850196 + 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); -+ } ++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti9x4") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti9x4_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ } + -+ dvp_order_prop = of_find_property(endpoint, "dvp-order", NULL); -+ if (dvp_order_prop) -+ of_update_property(rendpoint, dvp_order_prop); ++ if (!priv->ti9x4_addr) { ++ dev_err(&client->dev, "deserializer does not present\n"); ++ return -EINVAL; ++ } ++ ++ /* setup I2C translator address */ ++ tmp_addr = client->addr; ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x4_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, IMX390_I2C_ADDR << 1); /* Sensor native I2C address */ ++// reg8_write(client, 0x6e, 0xa9); /* GPIO0 - reset, GPIO1 - fsin */ + } ++ client->addr = tmp_addr; ++ ++ mdelay(10); ++ ++ return 0; +} + -+static int max9286_probe(struct i2c_client *client, -+ const struct i2c_device_id *did) ++static int imx390_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) +{ -+ struct max9286_priv *priv; -+ int err, i; ++ struct imx390_priv *priv; ++ int ret; + + 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; ++ v4l2_i2c_subdev_init(&priv->sd, client, &imx390_subdev_ops); ++ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; + -+ err = max9286_parse_dt(client); -+ if (err) -+ goto out; ++ priv->exposure = 0x100; ++ priv->gain = 0x100; ++ priv->autogain = 1; ++ v4l2_ctrl_handler_init(&priv->hdl, 4); ++ v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, ++ V4L2_CID_BRIGHTNESS, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, ++ V4L2_CID_CONTRAST, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, ++ V4L2_CID_SATURATION, 0, 7, 1, 2); ++ v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, ++ V4L2_CID_HUE, 0, 23, 1, 12); ++ v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, ++ V4L2_CID_GAMMA, -128, 128, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, ++ V4L2_CID_SHARPNESS, 0, 10, 1, 3); ++ v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, ++ V4L2_CID_AUTOGAIN, 0, 1, 1, priv->autogain); ++ v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, ++ V4L2_CID_GAIN, 0, 0xffff, 1, priv->gain); ++ v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, ++ V4L2_CID_EXPOSURE, 0, 0xffff, 1, priv->exposure); ++ v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 1); ++ v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ priv->sd.ctrl_handler = &priv->hdl; + -+ err = max9286_initialize(client); -+ if (err < 0) -+ goto out; ++ ret = priv->hdl.error; ++ if (ret) ++ goto cleanup; + -+ max9286_setup_remote_endpoint(client); ++ v4l2_ctrl_handler_setup(&priv->hdl); + -+ for (i = 0; i < 4; i++) { -+ v4l2_subdev_init(&priv->sd[i], &max9286_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]; ++ 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; + -+ 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); ++ ret = imx390_parse_dt(client->dev.of_node, priv); ++ if (ret) ++ goto cleanup; + -+ err = v4l2_async_register_subdev(&priv->sd[i]); -+ if (err < 0) -+ goto out; -+ } -+out: -+ return err; -+} ++ ret = imx390_initialize(client); ++ if (ret < 0) ++ goto cleanup; + -+static int max9286_remove(struct i2c_client *client) -+{ -+ struct max9286_priv *priv = i2c_get_clientdata(client); -+ int i; ++ priv->rect.left = 0; ++ priv->rect.top = 0; ++ priv->rect.width = IMX390_MAX_WIDTH; ++ priv->rect.height = IMX390_MAX_HEIGHT; + -+ for (i = 0; i < 4; i++) { -+ v4l2_async_unregister_subdev(&priv->sd[i]); -+ v4l2_device_unregister_subdev(&priv->sd[i]); -+ } ++ ret = v4l2_async_register_subdev(&priv->sd); ++ if (ret) ++ goto cleanup; + -+ return 0; ++ if (device_create_file(&client->dev, &dev_attr_otp_id_imx390) != 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_IMX390 ++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", ++ client->addr, client->adapter->name); ++#endif ++ return ret; +} + -+static const struct of_device_id max9286_dt_ids[] = { -+ { .compatible = "maxim,max9286" }, -+ {}, ++static int imx390_remove(struct i2c_client *client) ++{ ++ struct imx390_priv *priv = i2c_get_clientdata(client); ++ ++ device_remove_file(&client->dev, &dev_attr_otp_id_imx390); ++ 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_IMX390 ++static const struct i2c_device_id imx390_id[] = { ++ { "imx390", 0 }, ++ { } +}; -+MODULE_DEVICE_TABLE(of, max9286_dt_ids); ++MODULE_DEVICE_TABLE(i2c, imx390_id); + -+static const struct i2c_device_id max9286_id[] = { -+ { "max9286", 0 }, ++static const struct of_device_id imx390_of_ids[] = { ++ { .compatible = "sony,imx390", }, + { } +}; -+MODULE_DEVICE_TABLE(i2c, max9286_id); ++MODULE_DEVICE_TABLE(of, imx390_of_ids); + -+static struct i2c_driver max9286_i2c_driver = { ++static struct i2c_driver imx390_i2c_driver = { + .driver = { -+ .name = "max9286", -+ .of_match_table = of_match_ptr(max9286_dt_ids), ++ .name = "imx390", ++ .of_match_table = imx390_of_ids, + }, -+ .probe = max9286_probe, -+ .remove = max9286_remove, -+ .id_table = max9286_id, ++ .probe = imx390_probe, ++ .remove = imx390_remove, ++ .id_table = imx390_id, +}; + -+module_i2c_driver(max9286_i2c_driver); ++module_i2c_driver(imx390_i2c_driver); + -+MODULE_DESCRIPTION("GMSL driver for MAX9286"); ++MODULE_DESCRIPTION("SoC Camera driver for IMX390"); +MODULE_AUTHOR("Vladimir Barinov"); +MODULE_LICENSE("GPL"); -diff --git a/drivers/media/i2c/soc_camera/max9286.h b/drivers/media/i2c/soc_camera/max9286.h ++#endif +diff --git a/drivers/media/i2c/soc_camera/imx390.h b/drivers/media/i2c/soc_camera/imx390.h new file mode 100644 -index 0000000..6c2a9e0 +index 0000000..4217cd9 --- /dev/null -+++ b/drivers/media/i2c/soc_camera/max9286.h -@@ -0,0 +1,244 @@ ++++ b/drivers/media/i2c/soc_camera/imx390.h +@@ -0,0 +1,3817 @@ +/* -+ * MAXIM max9286-max9271 GMSL driver include file ++ * OmniVision IMX390 sensor camera wizard 1920x1080@30/BGGR/MIPI + * -+ * Copyright (C) 2015-2017 Cogent Embedded, Inc. ++ * Copyright (C) 2018 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 @@ -2822,1012 +2680,4768 @@ index 0000000..6c2a9e0 + * option) any later version. + */ + -+#ifndef _MAX9286_MAX9271_H -+#define _MAX9286_MAX9271_H ++//#define IMX390_DISPLAY_PATTERN_COLOR_BAR + -+//#define DEBUG -+#ifdef DEBUG -+//#define WRITE_VERIFY -+#define MAXIM_DUMP -+#undef dev_dbg -+#define dev_dbg dev_info ++#define IMX390_MAX_WIDTH 1920 ++#define IMX390_MAX_HEIGHT 1080 ++ ++#define IMX390_DELAY 0xffff ++#define IMX390_DT 0x2c /* MIPI Data Type RAW12 */ ++ ++struct imx390_reg { ++ u16 reg; ++ u8 val; ++}; ++ ++/* wizard: MIPI 1920x1080 RAW12 Linear 30fps 700Mbps */ ++static const struct imx390_reg imx390_regs_wizard[] = { ++{0x000C, 0xF2}, ++{0x000D, 0x02}, ++{0x000E, 0x00}, ++{0x0010, 0xF2}, ++{0x0011, 0x02}, ++{0x0012, 0x00}, ++{0x0018, 0x15}, ++{0x0019, 0x00}, ++{0x001A, 0x0C}, ++{0x001B, 0x00}, ++{0x0038, 0x00}, ++{0x003C, 0x00}, ++{0x003D, 0x00}, ++{0x003E, 0x00}, ++{0x0040, 0x00}, ++{0x0041, 0x00}, ++{0x0042, 0x00}, ++{0x0044, 0x00}, ++{0x0045, 0x00}, ++{0x0046, 0x00}, ++{0x0048, 0x00}, ++{0x0049, 0x00}, ++{0x004A, 0x00}, ++{0x004C, 0x00}, ++{0x004D, 0x00}, ++{0x004E, 0x00}, ++{0x0050, 0x00}, ++{0x0051, 0x00}, ++{0x0052, 0x00}, ++{0x0054, 0x00}, ++{0x0055, 0x00}, ++{0x0056, 0x00}, ++{0x0058, 0x00}, ++{0x0059, 0x00}, ++{0x005A, 0x00}, ++{0x005C, 0x00}, ++{0x005D, 0x00}, ++{0x005E, 0x00}, ++{0x0060, 0x00}, ++{0x0061, 0x00}, ++{0x0062, 0x00}, ++{0x0064, 0x00}, ++{0x0065, 0x00}, ++{0x0066, 0x00}, ++{0x0068, 0x00}, ++{0x0069, 0x00}, ++{0x006A, 0x00}, ++{0x0078, 0x00}, ++{0x007C, 0x00}, ++{0x007D, 0x00}, ++{0x0080, 0x00}, ++{0x0081, 0x00}, ++{0x00F4, 0x1C}, ++{0x00F5, 0xF8}, ++{0x00F6, 0x01}, ++{0x00F8, 0x03}, ++{0x00F9, 0x00}, ++{0x00FA, 0x00}, ++{0x00FB, 0x00}, ++{0x0114, 0x00}, ++{0x0115, 0x01}, ++{0x0118, 0x20}, ++{0x0119, 0x03}, ++{0x011A, 0x00}, ++{0x011B, 0x41}, ++{0x011C, 0x80}, ++{0x011D, 0x00}, ++{0x0120, 0x20}, ++{0x0121, 0x00}, ++{0x0122, 0x00}, ++{0x0123, 0x44}, ++{0x0124, 0x00}, ++{0x0125, 0x01}, ++{0x0128, 0xAC}, ++{0x0129, 0x0D}, ++{0x012A, 0x00}, ++{0x012B, 0xA4}, ++{0x012C, 0x00}, ++{0x012D, 0x01}, ++{0x0130, 0xC4}, ++{0x0131, 0x09}, ++{0x0132, 0x00}, ++{0x0133, 0xDA}, ++//{0x013A, ,3}, ++{0x013B, 0x01}, ++//{0x013C, ,3}, ++//{0x013D, ,3}, ++//{0x013E, ,3}, ++//{0x0140, ,3}, ++//{0x0141, ,3}, ++//{0x0142, ,3}, ++//{0x0144, ,3}, ++//{0x0145, ,3}, ++//{0x0146, ,3}, ++//{0x0148, ,3}, ++//{0x0149, ,3}, ++//{0x014A, ,3}, ++//{0x014C, ,3}, ++//{0x014D, ,3}, ++//{0x014E, ,3}, ++//{0x0150, ,3}, ++//{0x0151, ,3}, ++//{0x0152, ,3}, ++//{0x0154, ,3}, ++//{0x0155, ,3}, ++//{0x0156, ,3}, ++//{0x0158, ,3}, ++//{0x0159, ,3}, ++//{0x015A, ,3}, ++//{0x015C, ,3}, ++//{0x015D, ,3}, ++//{0x015E, ,3}, ++//{0x0160, ,3}, ++//{0x0161, ,3}, ++//{0x0162, ,3}, ++//{0x0164, ,3}, ++//{0x0165, ,3}, ++//{0x0166, ,3}, ++//{0x0168, ,3}, ++//{0x0169, ,3}, ++//{0x016A, ,3}, ++//{0x016C, ,3}, ++//{0x016D, ,3}, ++//{0x016E, ,3}, ++//{0x0170, ,3}, ++//{0x0171, ,3}, ++//{0x0172, ,3}, ++//{0x0174, ,3}, ++//{0x0175, ,3}, ++//{0x0176, ,3}, ++//{0x0178, ,3}, ++//{0x0179, ,3}, ++//{0x017A, ,3}, ++//{0x017C, ,3}, ++//{0x017D, ,3}, ++//{0x017E, ,3}, ++//{0x0180, ,3}, ++//{0x0181, ,3}, ++//{0x0182, ,3}, ++//{0x0184, ,3}, ++//{0x0185, ,3}, ++//{0x0186, ,3}, ++//{0x0188, ,3}, ++//{0x0189, ,3}, ++//{0x018A, ,3}, ++//{0x018C, ,3}, ++//{0x018D, ,3}, ++//{0x018E, ,3}, ++//{0x0190, ,3}, ++//{0x0191, ,3}, ++//{0x0192, ,3}, ++//{0x0194, ,3}, ++//{0x0195, ,3}, ++//{0x0196, ,3}, ++//{0x0198, ,3}, ++//{0x0199, ,3}, ++//{0x019A, ,3}, ++//{0x019B, ,3}, ++//{0x019C, ,3}, ++//{0x019D, ,3}, ++//{0x019E, ,3}, ++//{0x019F, ,3}, ++//{0x01A0, ,3}, ++//{0x01A1, ,3}, ++//{0x01A2, ,3}, ++//{0x01A3, ,3}, ++//{0x01A4, ,3}, ++//{0x01A5, ,3}, ++//{0x01A6, ,3}, ++//{0x01A7, ,3}, ++//{0x01A8, ,3}, ++//{0x01A9, ,3}, ++//{0x01AA, ,3}, ++//{0x01AB, ,3}, ++//{0x01AC, ,3}, ++//{0x01AD, ,3}, ++//{0x01AE, ,3}, ++//{0x01AF, ,3}, ++//{0x01B0, ,3}, ++//{0x01B1, ,3}, ++//{0x01B2, ,3}, ++//{0x01B3, ,3}, ++//{0x01B4, ,3}, ++//{0x01B5, ,3}, ++//{0x01B6, ,3}, ++//{0x01B7, ,3}, ++//{0x01B8, ,3}, ++//{0x01B9, ,3}, ++//{0x01BA, ,3}, ++//{0x01BB, ,3}, ++//{0x01BC, ,3}, ++//{0x01BD, ,3}, ++//{0x01BE, ,3}, ++//{0x01BF, ,3}, ++//{0x01C0, ,3}, ++//{0x01C1, ,3}, ++//{0x01C2, ,3}, ++//{0x01C3, ,3}, ++{0x01C4, 0x00}, ++{0x01C5, 0x00}, ++{0x01CC, 0x01}, ++{0x01D0, 0x09}, ++{0x01D4, 0x01}, ++{0x0232, 0x7E}, ++{0x0233, 0x00}, ++{0x0390, 0x00}, ++{0x0391, 0x00}, ++{0x0392, 0x00}, ++#ifdef IMX390_DISPLAY_PATTERN_COLOR_BAR ++{0x01DB, 0x32}, ++{0x03C0, 0x02}, ++#else ++{0x03C0, 0x00}, ++#endif ++{0x2000, 0x55}, ++{0x2001, 0x55}, ++{0x2002, 0x55}, ++{0x2003, 0x05}, ++{0x2004, 0x02}, ++{0x2008, 0x65}, ++{0x2009, 0x04}, ++{0x200A, 0x00}, ++{0x200C, 0x30}, ++{0x200D, 0x11}, ++{0x2010, 0x04}, ++{0x2014, 0x01}, ++{0x2018, 0x02}, ++{0x2019, 0x04}, ++{0x201A, 0x00}, ++{0x201C, 0x21}, ++{0x201D, 0x11}, ++{0x201E, 0x00}, ++{0x201F, 0x00}, ++{0x2020, 0xBC}, ++{0x2021, 0x00}, ++{0x2022, 0x7F}, ++{0x2023, 0x00}, ++{0x2024, 0xBA}, ++{0x2025, 0x00}, ++{0x2026, 0x81}, ++{0x2027, 0x00}, ++{0x2028, 0x7D}, ++{0x2029, 0x90}, ++{0x202A, 0x05}, ++{0x202C, 0xFC}, ++{0x202D, 0x02}, ++{0x202E, 0x25}, ++{0x202F, 0x03}, ++{0x2030, 0x05}, ++{0x2031, 0x02}, ++{0x2032, 0xCA}, ++{0x2033, 0x02}, ++{0x2034, 0xFC}, ++{0x2035, 0x02}, ++{0x2036, 0x25}, ++{0x2037, 0x03}, ++{0x2038, 0x25}, ++{0x2039, 0x97}, ++{0x203A, 0xEC}, ++{0x203B, 0x01}, ++{0x203C, 0xF5}, ++{0x203D, 0x8E}, ++{0x203E, 0x0C}, ++{0x203F, 0x2D}, ++{0x2040, 0x69}, ++{0x2041, 0x01}, ++{0x2042, 0x8E}, ++{0x2043, 0x01}, ++{0x2044, 0x0C}, ++{0x2045, 0x02}, ++{0x2046, 0x31}, ++{0x2047, 0x02}, ++{0x2048, 0x6A}, ++{0x2049, 0x01}, ++{0x204A, 0x8E}, ++{0x204B, 0x01}, ++{0x204C, 0x0D}, ++{0x204D, 0x02}, ++{0x204E, 0x31}, ++{0x204F, 0x02}, ++{0x2050, 0x7B}, ++{0x2051, 0x00}, ++{0x2052, 0x7D}, ++{0x2053, 0x00}, ++{0x2054, 0x95}, ++{0x2055, 0x00}, ++{0x2056, 0x97}, ++{0x2057, 0x00}, ++{0x2058, 0xAD}, ++{0x2059, 0x00}, ++{0x205A, 0xAF}, ++{0x205B, 0x00}, ++{0x205C, 0x92}, ++{0x205D, 0x00}, ++{0x205E, 0x94}, ++{0x205F, 0x00}, ++{0x2060, 0x8E}, ++{0x2061, 0x00}, ++{0x2062, 0x90}, ++{0x2063, 0x00}, ++{0x2064, 0xB1}, ++{0x2065, 0x00}, ++{0x2066, 0xB3}, ++{0x2067, 0x00}, ++{0x2068, 0x08}, ++{0x2069, 0x00}, ++{0x206A, 0x04}, ++{0x206B, 0x00}, ++{0x206C, 0x84}, ++{0x206D, 0x00}, ++{0x206E, 0x80}, ++{0x206F, 0x00}, ++{0x2070, 0x04}, ++{0x2071, 0x00}, ++{0x2072, 0x46}, ++{0x2073, 0x00}, ++{0x2074, 0xE9}, ++{0x2075, 0x01}, ++{0x2076, 0x74}, ++{0x2077, 0x02}, ++{0x2078, 0x80}, ++{0x2079, 0x00}, ++{0x207A, 0xC1}, ++{0x207B, 0x00}, ++{0x207C, 0xFF}, ++{0x207D, 0x03}, ++{0x207E, 0xFF}, ++{0x207F, 0x03}, ++{0x2080, 0x78}, ++{0x2081, 0x00}, ++{0x2082, 0x6A}, ++{0x2083, 0x01}, ++{0x2084, 0xE4}, ++{0x2085, 0x01}, ++{0x2086, 0x2B}, ++{0x2087, 0x03}, ++{0x2088, 0x00}, ++{0x2089, 0x00}, ++{0x208A, 0xFF}, ++{0x208B, 0x03}, ++{0x208C, 0xFF}, ++{0x208D, 0x03}, ++{0x208E, 0xFF}, ++{0x208F, 0x03}, ++{0x2090, 0x7D}, ++{0x2091, 0x00}, ++{0x2092, 0x62}, ++{0x2093, 0x01}, ++{0x2094, 0xE9}, ++{0x2095, 0x01}, ++{0x2096, 0x00}, ++{0x2097, 0x00}, ++{0x2098, 0x7C}, ++{0x2099, 0x00}, ++{0x209A, 0x21}, ++{0x209B, 0x03}, ++{0x209C, 0xE9}, ++{0x209D, 0x01}, ++{0x209E, 0x21}, ++{0x209F, 0x03}, ++{0x20A0, 0xFF}, ++{0x20A1, 0x03}, ++{0x20A2, 0xFF}, ++{0x20A3, 0x03}, ++{0x20A4, 0xFF}, ++{0x20A5, 0x03}, ++{0x20A6, 0xFF}, ++{0x20A7, 0x03}, ++{0x20A8, 0xFF}, ++{0x20A9, 0x03}, ++{0x20AA, 0xFF}, ++{0x20AB, 0x03}, ++{0x20AC, 0xFF}, ++{0x20AD, 0x03}, ++{0x20AE, 0xFF}, ++{0x20AF, 0x03}, ++{0x20B0, 0xFF}, ++{0x20B1, 0x03}, ++{0x20B2, 0xFF}, ++{0x20B3, 0x03}, ++{0x20B4, 0x87}, ++{0x20B5, 0xCC}, ++{0x20B6, 0x87}, ++{0x20B7, 0x08}, ++{0x20B8, 0xF4}, ++{0x20B9, 0xA5}, ++{0x20BA, 0x07}, ++{0x20BC, 0x1F}, ++{0x20BD, 0x01}, ++{0x20BE, 0xF6}, ++{0x20BF, 0x00}, ++{0x20C0, 0x90}, ++{0x20C1, 0x01}, ++{0x20C2, 0x67}, ++{0x20C3, 0x01}, ++{0x20C4, 0xFF}, ++{0x20C5, 0x03}, ++{0x20C6, 0xFF}, ++{0x20C7, 0x03}, ++{0x20C8, 0x33}, ++{0x20C9, 0x02}, ++{0x20CA, 0x0A}, ++{0x20CB, 0x02}, ++{0x20CC, 0x7F}, ++{0x20CD, 0x00}, ++{0x20CE, 0xD2}, ++{0x20CF, 0x00}, ++{0x20D0, 0x81}, ++{0x20D1, 0x00}, ++{0x20D2, 0x87}, ++{0x20D3, 0x00}, ++{0x20D4, 0x09}, ++{0x20D5, 0x00}, ++{0x20D8, 0x7F}, ++{0x20D9, 0x00}, ++{0x20DA, 0x62}, ++{0x20DB, 0x01}, ++{0x20DC, 0x7F}, ++{0x20DD, 0x00}, ++{0x20DE, 0x62}, ++{0x20DF, 0x01}, ++{0x20E0, 0x65}, ++{0x20E1, 0x00}, ++{0x20E2, 0x75}, ++{0x20E3, 0x00}, ++{0x20E4, 0xE0}, ++{0x20E5, 0x00}, ++{0x20E6, 0xF0}, ++{0x20E7, 0x00}, ++{0x20E8, 0x4C}, ++{0x20E9, 0x01}, ++{0x20EA, 0x5C}, ++{0x20EB, 0x01}, ++{0x20EC, 0xD1}, ++{0x20ED, 0x01}, ++{0x20EE, 0xE1}, ++{0x20EF, 0x01}, ++{0x20F0, 0x93}, ++{0x20F1, 0x02}, ++{0x20F2, 0xA3}, ++{0x20F3, 0x02}, ++{0x20F4, 0x0D}, ++{0x20F5, 0x03}, ++{0x20F6, 0x1D}, ++{0x20F7, 0x03}, ++{0x20F8, 0x57}, ++{0x20F9, 0x00}, ++{0x20FA, 0x7B}, ++{0x20FB, 0x00}, ++{0x20FC, 0xD2}, ++{0x20FD, 0x00}, ++{0x20FE, 0xF6}, ++{0x20FF, 0x00}, ++{0x2100, 0x3E}, ++{0x2101, 0x01}, ++{0x2102, 0x60}, ++{0x2103, 0x01}, ++{0x2104, 0xC3}, ++{0x2105, 0x01}, ++{0x2106, 0xE5}, ++{0x2107, 0x01}, ++{0x2108, 0x85}, ++{0x2109, 0x02}, ++{0x210A, 0xA9}, ++{0x210B, 0x02}, ++{0x210C, 0xFF}, ++{0x210D, 0x02}, ++{0x210E, 0x21}, ++{0x210F, 0x03}, ++{0x2110, 0xFF}, ++{0x2111, 0x03}, ++{0x2112, 0x00}, ++{0x2113, 0x00}, ++{0x2114, 0xFF}, ++{0x2115, 0x03}, ++{0x2116, 0xFF}, ++{0x2117, 0x03}, ++{0x2118, 0xFF}, ++{0x2119, 0x03}, ++{0x211A, 0xFF}, ++{0x211B, 0x03}, ++{0x211C, 0xFF}, ++{0x211D, 0x03}, ++{0x211E, 0xFF}, ++{0x211F, 0x03}, ++{0x2120, 0xFF}, ++{0x2121, 0x03}, ++{0x2122, 0xFF}, ++{0x2123, 0x03}, ++{0x2124, 0xFF}, ++{0x2125, 0x03}, ++{0x2126, 0xFF}, ++{0x2127, 0x03}, ++{0x2128, 0x7D}, ++{0x2129, 0x90}, ++{0x212A, 0xD5}, ++{0x212B, 0x07}, ++{0x212C, 0x64}, ++{0x212D, 0x01}, ++{0x2130, 0x5F}, ++{0x2131, 0x7D}, ++{0x2132, 0x05}, ++{0x2134, 0x78}, ++{0x2135, 0x00}, ++{0x2136, 0x76}, ++{0x2137, 0x00}, ++{0x2138, 0xF3}, ++{0x2139, 0x00}, ++{0x213A, 0xF1}, ++{0x213B, 0x00}, ++{0x213C, 0xA6}, ++{0x213D, 0x02}, ++{0x213E, 0xA4}, ++{0x213F, 0x02}, ++{0x2140, 0x7D}, ++{0x2141, 0x00}, ++{0x2142, 0x8D}, ++{0x2143, 0x00}, ++{0x2144, 0xA1}, ++{0x2145, 0x01}, ++{0x2146, 0xB1}, ++{0x2147, 0x01}, ++{0x2148, 0xAB}, ++{0x2149, 0x02}, ++{0x214A, 0xBB}, ++{0x214B, 0x02}, ++{0x214C, 0x17}, ++{0x214D, 0x5C}, ++{0x214E, 0x00}, ++{0x2150, 0x00}, ++{0x2151, 0x00}, ++{0x2152, 0xF8}, ++{0x2153, 0x00}, ++{0x2154, 0xBE}, ++{0x2155, 0x00}, ++{0x2156, 0x7D}, ++{0x2157, 0x00}, ++{0x2158, 0x25}, ++{0x2159, 0x00}, ++{0x215A, 0x7D}, ++{0x215B, 0x00}, ++{0x215C, 0x62}, ++{0x215D, 0x01}, ++{0x215E, 0xFF}, ++{0x215F, 0x03}, ++{0x2160, 0x26}, ++{0x2161, 0x00}, ++{0x2162, 0x7D}, ++{0x2163, 0x00}, ++{0x2164, 0x63}, ++{0x2165, 0x01}, ++{0x2166, 0xFF}, ++{0x2167, 0x03}, ++{0x2168, 0xCB}, ++{0x2169, 0x02}, ++{0x216A, 0xCF}, ++{0x216B, 0x02}, ++{0x216C, 0xFF}, ++{0x216D, 0x03}, ++{0x216E, 0xFF}, ++{0x216F, 0x03}, ++{0x2170, 0xFF}, ++{0x2171, 0x03}, ++{0x2172, 0xFF}, ++{0x2173, 0x03}, ++{0x2174, 0xFF}, ++{0x2175, 0x03}, ++{0x2176, 0xFF}, ++{0x2177, 0x03}, ++{0x2178, 0x7E}, ++{0x2179, 0x00}, ++{0x217A, 0xBD}, ++{0x217B, 0x00}, ++{0x217C, 0xEC}, ++{0x217D, 0x01}, ++{0x217E, 0x7B}, ++{0x217F, 0x02}, ++{0x2180, 0xD1}, ++{0x2181, 0x02}, ++{0x2182, 0x25}, ++{0x2183, 0x03}, ++{0x2184, 0x7F}, ++{0x2185, 0x00}, ++{0x2186, 0xBD}, ++{0x2187, 0x00}, ++{0x2188, 0xED}, ++{0x2189, 0x01}, ++{0x218A, 0x7B}, ++{0x218B, 0x02}, ++{0x218C, 0xD2}, ++{0x218D, 0x02}, ++{0x218E, 0x25}, ++{0x218F, 0x03}, ++{0x2190, 0xFF}, ++{0x2191, 0x03}, ++{0x2192, 0xFF}, ++{0x2193, 0x03}, ++{0x2194, 0xE9}, ++{0x2195, 0x01}, ++{0x2196, 0x21}, ++{0x2197, 0x03}, ++{0x2198, 0x17}, ++{0x2199, 0xFC}, ++{0x219A, 0x7F}, ++{0x219B, 0x01}, ++{0x219C, 0xFF}, ++{0x219D, 0x03}, ++{0x21A0, 0x1B}, ++{0x21A1, 0x1B}, ++{0x21A2, 0x1B}, ++{0x21A3, 0x1B}, ++{0x21A4, 0x2E}, ++{0x21A5, 0x80}, ++{0x21A6, 0x00}, ++{0x21A8, 0x04}, ++{0x21A9, 0x98}, ++{0x21AA, 0x60}, ++{0x21AB, 0x03}, ++{0x21AC, 0x7F}, ++{0x21AD, 0x80}, ++{0x21AE, 0x09}, ++{0x21B0, 0x1C}, ++{0x21B1, 0x00}, ++{0x21B2, 0xA0}, ++{0x21B3, 0x00}, ++{0x21B4, 0x0C}, ++{0x21B5, 0x00}, ++{0x21B6, 0x2D}, ++{0x21B7, 0x00}, ++{0x21B8, 0x20}, ++{0x21B9, 0x00}, ++{0x21BA, 0x02}, ++{0x21BB, 0x00}, ++{0x21BC, 0xCC}, ++{0x21BD, 0x00}, ++{0x21BE, 0x4A}, ++{0x21BF, 0x00}, ++{0x21C0, 0xD0}, ++{0x21C1, 0x00}, ++{0x21C2, 0x44}, ++{0x21C3, 0x00}, ++{0x21C4, 0x00}, ++{0x21C5, 0xE0}, ++{0x21C6, 0x00}, ++{0x21C8, 0x11}, ++{0x21C9, 0x00}, ++{0x21CA, 0x02}, ++{0x21CC, 0x08}, ++{0x21CD, 0xC0}, ++{0x21CE, 0x0C}, ++{0x21D0, 0x44}, ++{0x21D1, 0x00}, ++{0x21D2, 0x02}, ++{0x21D4, 0x02}, ++{0x21D5, 0x20}, ++{0x21D6, 0x2C}, ++{0x21D8, 0xFE}, ++{0x21D9, 0x9D}, ++{0x21DA, 0xDF}, ++{0x21DB, 0x03}, ++{0x21DC, 0x62}, ++{0x21DD, 0x01}, ++{0x21DE, 0x7F}, ++{0x21DF, 0x00}, ++{0x21E0, 0xB7}, ++{0x21E1, 0x01}, ++{0x21E2, 0xB5}, ++{0x21E3, 0x01}, ++{0x21E4, 0xC1}, ++{0x21E5, 0x02}, ++{0x21E6, 0xBF}, ++{0x21E7, 0x02}, ++{0x21E8, 0xB3}, ++{0x21E9, 0x0D}, ++{0x21EA, 0x00}, ++{0x21EB, 0x04}, ++#if 1 ++{0x21EC, 0x90}, ++{0x21ED, 0x07}, ++{0x21EE, 0x58}, ++{0x21EF, 0x04}, ++#else ++{0x21EC, 0x80}, ++{0x21ED, 0x07}, ++{0x21EE, 0x38}, ++{0x21EF, 0x04}, ++#endif ++{0x21F0, 0x54}, ++{0x21F1, 0x04}, ++{0x21F4, 0x02}, ++{0x21F5, 0x00}, ++{0x21F6, 0x00}, ++{0x21F8, 0x3C}, ++{0x21F9, 0x00}, ++{0x21FC, 0x28}, ++{0x21FD, 0x00}, ++{0x21FE, 0x3C}, ++{0x21FF, 0x00}, ++{0x2200, 0x00}, ++{0x2204, 0x4C}, ++{0x2205, 0x04}, ++{0x2206, 0x65}, ++{0x2207, 0x04}, ++{0x2208, 0x0A}, ++{0x2209, 0x00}, ++{0x220C, 0x47}, ++{0x220D, 0x00}, ++{0x220E, 0x1F}, ++{0x220F, 0x00}, ++{0x2210, 0x17}, ++{0x2211, 0x00}, ++{0x2212, 0x0F}, ++{0x2213, 0x00}, ++{0x2214, 0x17}, ++{0x2215, 0x00}, ++{0x2216, 0x47}, ++{0x2217, 0x00}, ++{0x2218, 0x0F}, ++{0x2219, 0x00}, ++{0x221A, 0x0F}, ++{0x221B, 0x00}, ++{0x221C, 0x03}, ++{0x2220, 0x20}, ++{0x2221, 0x20}, ++{0x2222, 0x22}, ++{0x2223, 0x02}, ++{0x2224, 0xA7}, ++{0x2225, 0xAA}, ++{0x2226, 0x80}, ++{0x2227, 0x08}, ++{0x2228, 0x01}, ++{0x22B2, 0x92}, ++{0x22B4, 0x20}, ++{0x22B5, 0x00}, ++{0x22B6, 0x20}, ++{0x22B7, 0x00}, ++{0x22B8, 0x20}, ++{0x22B9, 0x00}, ++{0x22BA, 0x20}, ++{0x22BB, 0x00}, ++{0x22BC, 0x20}, ++{0x22BD, 0x00}, ++{0x22BE, 0x20}, ++{0x22BF, 0x00}, ++{0x22C0, 0x20}, ++{0x22C1, 0x00}, ++{0x22C2, 0x20}, ++{0x22C3, 0x00}, ++{0x22C4, 0x20}, ++{0x22C5, 0x00}, ++{0x22C6, 0x20}, ++{0x22C7, 0x00}, ++{0x22C8, 0x20}, ++{0x22C9, 0x00}, ++{0x22CA, 0x20}, ++{0x22CB, 0x00}, ++{0x22CC, 0x20}, ++{0x22CD, 0x00}, ++{0x22CE, 0x20}, ++{0x22CF, 0x00}, ++{0x22DA, 0x00}, ++{0x2308, 0x01}, ++{0x2311, 0x09}, ++{0x2318, 0x40}, ++{0x2319, 0xCD}, ++{0x231A, 0x54}, ++{0x2324, 0x20}, ++{0x2325, 0x00}, ++{0x2328, 0x00}, ++{0x2354, 0x0C}, ++{0x23C0, 0x5D}, ++{0x244C, 0x00}, ++{0x244D, 0x02}, ++{0x244E, 0x54}, ++{0x244F, 0x02}, ++{0x24A0, 0x00}, ++{0x24DA, 0x6F}, ++{0x24DB, 0x00}, ++{0x24DC, 0x62}, ++{0x24DD, 0x01}, ++{0x24EA, 0x32}, ++{0x24EB, 0x00}, ++{0x24EC, 0xDC}, ++{0x24ED, 0x00}, ++{0x24FA, 0x32}, ++{0x24FB, 0x00}, ++{0x24FC, 0xDD}, ++{0x24FD, 0x00}, ++{0x254A, 0x15}, ++{0x254B, 0x01}, ++{0x255A, 0x15}, ++{0x255B, 0x01}, ++{0x2560, 0x01}, ++{0x2561, 0x00}, ++{0x2562, 0x2A}, ++{0x2563, 0x00}, ++{0x2564, 0xF8}, ++{0x2565, 0x00}, ++{0x2566, 0x15}, ++{0x2567, 0x01}, ++{0x2568, 0x0C}, ++{0x2569, 0x02}, ++{0x256A, 0x31}, ++{0x256B, 0x02}, ++{0x2578, 0x90}, ++{0x2579, 0x01}, ++{0x257A, 0x92}, ++{0x257B, 0x01}, ++{0x257C, 0xB8}, ++{0x257D, 0x02}, ++{0x257E, 0xBA}, ++{0x257F, 0x02}, ++{0x2584, 0x90}, ++{0x2585, 0x01}, ++{0x2586, 0x92}, ++{0x2587, 0x01}, ++{0x2588, 0xB8}, ++{0x2589, 0x02}, ++{0x258A, 0xBA}, ++{0x258B, 0x02}, ++{0x26B8, 0x10}, ++{0x26B9, 0x00}, ++{0x26BA, 0x33}, ++{0x26BB, 0x00}, ++{0x26BC, 0x89}, ++{0x26BD, 0x00}, ++{0x26BE, 0xB0}, ++{0x26BF, 0x00}, ++{0x26C4, 0x4E}, ++{0x26C5, 0x00}, ++{0x26C8, 0xC9}, ++{0x26C9, 0x00}, ++{0x26CC, 0x35}, ++{0x26CD, 0x01}, ++{0x26D0, 0xBA}, ++{0x26D1, 0x01}, ++{0x26D4, 0x7C}, ++{0x26D5, 0x02}, ++{0x26D8, 0xF6}, ++{0x26D9, 0x02}, ++{0x26DE, 0x51}, ++{0x26DF, 0x00}, ++{0x26E0, 0x7F}, ++{0x26E1, 0x00}, ++{0x26E2, 0xCC}, ++{0x26E3, 0x00}, ++{0x26E4, 0xF8}, ++{0x26E5, 0x00}, ++{0x26E6, 0x38}, ++{0x26E7, 0x01}, ++{0x26E8, 0x65}, ++{0x26E9, 0x01}, ++{0x26EA, 0xBD}, ++{0x26EB, 0x01}, ++{0x26EE, 0x7F}, ++{0x26EF, 0x02}, ++{0x26F0, 0xAB}, ++{0x26F1, 0x02}, ++{0x26F2, 0xF9}, ++{0x26F3, 0x02}, ++{0x2722, 0x59}, ++{0x2723, 0x02}, ++{0x2938, 0x55}, ++{0x2939, 0x00}, ++{0x293A, 0x17}, ++{0x293B, 0x00}, ++{0x293C, 0xD0}, ++{0x293D, 0x00}, ++{0x293E, 0x91}, ++{0x293F, 0x00}, ++{0x2940, 0x3C}, ++{0x2941, 0x01}, ++{0x2942, 0x0C}, ++{0x2943, 0x01}, ++{0x2944, 0xC1}, ++{0x2945, 0x01}, ++{0x2946, 0x76}, ++{0x2947, 0x01}, ++{0x2948, 0x83}, ++{0x2949, 0x02}, ++{0x294A, 0xFB}, ++{0x294B, 0x01}, ++{0x294C, 0xFD}, ++{0x294D, 0x02}, ++{0x294E, 0xBF}, ++{0x294F, 0x02}, ++{0x2A06, 0xFF}, ++{0x2A07, 0x03}, ++{0x2A20, 0x00}, ++{0x2A21, 0x00}, ++{0x2A22, 0x7D}, ++{0x2A23, 0x00}, ++{0x2B11, 0x19}, ++{0x2B13, 0x15}, ++{0x2B14, 0x14}, ++{0x2B15, 0x13}, ++{0x2B16, 0x12}, ++{0x2B17, 0x11}, ++{0x2B18, 0x10}, ++{0x2B19, 0x0F}, ++{0x2B1A, 0x0E}, ++{0x2B1B, 0x0D}, ++{0x2B1C, 0x0C}, ++{0x2B1D, 0x0B}, ++{0x2B1E, 0x0A}, ++{0x2B1F, 0x09}, ++{0x2B20, 0x08}, ++{0x2B21, 0x07}, ++{0x2B22, 0x06}, ++{0x2B23, 0x05}, ++{0x2B24, 0x04}, ++{0x2B25, 0x03}, ++{0x2B26, 0x03}, ++{0x2B38, 0x01}, ++{0x2B45, 0xE3}, ++{0x2B50, 0x01}, ++{0x2B51, 0x00}, ++//{0x2B62, ,3}, ++{0x2B6D, 0x47}, ++{0x2B70, 0x02}, ++{0x2B71, 0x02}, ++{0x2B72, 0x02}, ++{0x2B7F, 0x7F}, ++{0x2B80, 0x94}, ++{0x2B81, 0x06}, ++{0x2B87, 0x1B}, ++{0x2B88, 0x1B}, ++{0x2B89, 0x17}, ++{0x2B8A, 0x12}, ++{0x2B8B, 0x12}, ++{0x2B8D, 0x2B}, ++{0x2B8E, 0x2B}, ++{0x2B8F, 0x2B}, ++{0x2B90, 0x7F}, ++{0x2B91, 0x1F}, ++{0x2B94, 0x7F}, ++{0x2B95, 0x27}, ++{0x2B98, 0x7F}, ++{0x2B99, 0x57}, ++{0x2BA8, 0xBC}, ++{0x2BA9, 0x62}, ++{0x2BC1, 0x70}, ++{0x2BC5, 0x80}, ++{0x2BD5, 0x30}, ++{0x2BD6, 0xF0}, ++{0x2BD8, 0xDB}, ++{0x2BD9, 0xF6}, ++{0x2BDA, 0x63}, ++{0x2BDB, 0x0C}, ++{0x2BDC, 0x5C}, ++{0x2C98, 0xE1}, ++{0x2C99, 0x2E}, ++{0x2C9B, 0x86}, ++{0x2CA9, 0x80}, ++{0x2CAA, 0x01}, ++{0x2D39, 0x0E}, ++{0x2D54, 0x00}, ++{0x2D5B, 0x58}, ++{0x3000, 0x00}, ++{0x3001, 0x40}, ++{0x3002, 0x23}, ++{0x3003, 0xA1}, ++{0x3004, 0x00}, ++{0x3005, 0x20}, ++{0x3006, 0x94}, ++{0x3007, 0x00}, ++{0x3008, 0x06}, ++{0x3009, 0xB4}, ++{0x300A, 0x1F}, ++{0x300B, 0x28}, ++{0x300C, 0x00}, ++{0x300D, 0x18}, ++{0x300E, 0x90}, ++{0x300F, 0x97}, ++{0x3010, 0x00}, ++{0x3011, 0x40}, ++{0x3012, 0x21}, ++{0x3013, 0x21}, ++{0x3014, 0x00}, ++{0x3015, 0x20}, ++{0x3016, 0x94}, ++{0x3017, 0x00}, ++{0x3018, 0x00}, ++{0x3019, 0x09}, ++{0x301A, 0x46}, ++{0x301B, 0x28}, ++//{0x3053, ,3}, ++{0x3070, 0xC1}, ++{0x3071, 0x81}, ++{0x3072, 0x29}, ++{0x3073, 0x81}, ++//{0x3370, ,3}, ++//{0x3374, ,3}, ++//{0x3375, ,3}, ++//{0x3376, ,3}, ++//{0x3377, ,3}, ++#if 1 ++{0x3410, 0x90}, ++{0x3411, 0x07}, ++{0x3418, 0x48}, ++{0x3419, 0x04}, ++#else ++{0x3410, 0x80}, ++{0x3411, 0x07}, ++{0x3418, 0x38}, ++{0x3419, 0x04}, +#endif ++//{0x34C0, ,3}, ++//{0x34C1, ,3}, ++//{0x34C2, ,3}, ++//{0x34C3, ,3}, ++//{0x34C4, ,3}, ++//{0x34C5, ,3}, ++//{0x34C6, ,3}, ++//{0x34C7, ,3}, ++//{0x34C8, ,3}, ++//{0x34C9, ,3}, ++//{0x34CA, ,3}, ++//{0x34CB, ,3}, ++//{0x34CC, ,3}, ++//{0x34CD, ,3}, ++//{0x34CE, ,3}, ++//{0x34CF, ,3}, ++{0x3584, 0x00}, ++{0x3586, 0x00}, ++{0x3587, 0x01}, ++{0x3588, 0xE6}, ++{0x3589, 0x00}, ++{0x3590, 0x00}, ++{0x3591, 0x00}, ++{0x3594, 0x40}, ++{0x3598, 0x03}, ++{0x3599, 0x00}, ++{0x359A, 0x80}, ++{0x359B, 0x00}, ++{0x359C, 0x00}, ++{0x359D, 0x01}, ++{0x359E, 0x00}, ++{0x359F, 0x02}, ++{0x35A0, 0x00}, ++{0x35A1, 0x04}, ++{0x35A2, 0x20}, ++{0x35A3, 0x00}, ++{0x35A4, 0x40}, ++{0x35A5, 0x00}, ++{0x35A6, 0x80}, ++{0x35A7, 0x00}, ++{0x35A8, 0x00}, ++{0x35A9, 0x01}, ++{0x35AA, 0x3A}, ++{0x35AB, 0x00}, ++{0x35AC, 0x80}, ++{0x35AD, 0x00}, ++{0x35AE, 0x00}, ++{0x35AF, 0x01}, ++{0x35B0, 0x00}, ++{0x35B1, 0x02}, ++{0x35B2, 0x00}, ++{0x35B3, 0x04}, ++{0x35B4, 0x02}, ++{0x35B5, 0x00}, ++{0x35B6, 0x04}, ++{0x35B7, 0x00}, ++{0x35B8, 0x08}, ++{0x35B9, 0x00}, ++{0x35BA, 0x10}, ++{0x35BB, 0x00}, ++{0x35BC, 0x03}, ++{0x35BD, 0x00}, ++{0x35C8, 0x00}, ++{0x35C9, 0x01}, ++{0x35CA, 0x00}, ++{0x35CB, 0x04}, ++{0x35CC, 0x00}, ++{0x35CD, 0x10}, ++{0x35CE, 0x00}, ++{0x35CF, 0x40}, ++{0x35D0, 0x00}, ++{0x35D1, 0x0C}, ++{0x35D2, 0x00}, ++{0x35D3, 0x0C}, ++{0x35D4, 0x00}, ++{0x35D5, 0x0C}, ++{0x35D6, 0x00}, ++{0x35D7, 0x0C}, ++{0x35D8, 0x00}, ++{0x35D9, 0x00}, ++{0x35DA, 0x08}, ++{0x35DB, 0x00}, ++{0x35DC, 0xD8}, ++{0x35DD, 0x0E}, ++{0x35F0, 0x00}, ++{0x35F1, 0x10}, ++{0x35F2, 0x00}, ++{0x35F3, 0x10}, ++{0x35F4, 0x00}, ++{0x35F5, 0x10}, ++{0x35F6, 0x00}, ++{0x35F7, 0x03}, ++{0x35F8, 0x00}, ++{0x35F9, 0x01}, ++{0x35FA, 0x38}, ++{0x35FB, 0x00}, ++{0x35FC, 0xB3}, ++{0x35FD, 0x01}, ++{0x35FE, 0x00}, ++{0x35FF, 0x00}, ++{0x3600, 0x04}, ++{0x3601, 0x06}, ++{0x3604, 0x03}, ++{0x3605, 0x00}, ++{0x3608, 0x03}, ++{0x3609, 0x00}, ++{0x360C, 0x00}, ++{0x360D, 0x00}, ++{0x3610, 0x10}, ++{0x3611, 0x01}, ++{0x3612, 0x00}, ++{0x3613, 0x00}, ++{0x3614, 0x00}, ++{0x3615, 0x00}, ++{0x361C, 0x00}, ++{0x361D, 0x01}, ++{0x361E, 0x00}, ++{0x361F, 0x01}, ++{0x3620, 0x01}, ++{0x3621, 0x00}, ++{0x3622, 0xB0}, ++{0x3623, 0x04}, ++{0x3624, 0xDC}, ++{0x3625, 0x05}, ++{0x3626, 0x00}, ++{0x3627, 0x01}, ++{0x3628, 0xFF}, ++{0x3629, 0x0F}, ++{0x362A, 0x00}, ++{0x362B, 0x10}, ++{0x362C, 0x00}, ++{0x362D, 0x01}, ++//{0x3630, ,3}, ++//{0x3631, ,3}, ++//{0x3632, ,3}, ++//{0x3633, ,3}, ++//{0x3634, ,3}, ++//{0x3635, ,3}, ++//{0x3636, ,3}, ++//{0x3637, ,3}, ++//{0x3638, ,3}, ++//{0x3639, ,3}, ++//{0x363A, ,3}, ++//{0x363B, ,3}, ++//{0x363C, ,3}, ++//{0x363D, ,3}, ++//{0x363E, ,3}, ++//{0x363F, ,3}, ++{0x36C4, 0x99}, ++{0x36C5, 0x09}, ++{0x36C6, 0x18}, ++{0x36C7, 0x07}, ++{0x36C8, 0x65}, ++{0x36C9, 0x0E}, ++{0x36CC, 0x99}, ++{0x36CD, 0x01}, ++{0x36CE, 0x47}, ++{0x36CF, 0x00}, ++{0x36D0, 0x04}, ++{0x36D1, 0x00}, ++{0x36D4, 0x65}, ++{0x36D5, 0x0E}, ++{0x36D6, 0xA4}, ++{0x36D7, 0x0A}, ++{0x36D8, 0x65}, ++{0x36D9, 0x0E}, ++{0x36DC, 0x65}, ++{0x36DD, 0x0E}, ++{0x36DE, 0xA4}, ++{0x36DF, 0x0A}, ++{0x36E0, 0x65}, ++{0x36E1, 0x0E}, ++{0x36E4, 0x65}, ++{0x36E5, 0x0E}, ++{0x36E6, 0xA4}, ++{0x36E7, 0x0A}, ++{0x36E8, 0x65}, ++{0x36E9, 0x0E}, ++{0x36EE, 0x00}, ++{0x36EF, 0x00}, ++{0x36F0, 0x00}, ++{0x36F1, 0x80}, ++{0x36F8, 0x00}, ++{0x3702, 0x03}, ++{0x3703, 0x04}, ++{0x3704, 0x08}, ++{0x370E, 0x0E}, ++{0x3718, 0x62}, ++{0x3719, 0x4A}, ++{0x371A, 0x38}, ++{0x371B, 0x20}, ++{0x371C, 0x64}, ++{0x371D, 0x42}, ++{0x371E, 0x32}, ++{0x371F, 0x1B}, ++{0x3720, 0x98}, ++{0x3721, 0xA0}, ++{0x3722, 0xA8}, ++{0x3723, 0xB0}, ++{0x3748, 0xA5}, ++{0x3749, 0x9B}, ++{0x374A, 0x91}, ++{0x374B, 0x7D}, ++{0x37C0, 0x00}, ++{0x37C1, 0x00}, ++{0x37C2, 0x00}, ++{0x37C4, 0x00}, ++{0x37C5, 0x00}, ++{0x37C6, 0x00}, ++{0x37C8, 0x00}, ++{0x37C9, 0x00}, ++{0x37CA, 0x00}, ++{0x37CC, 0x00}, ++{0x37CD, 0x00}, ++{0x37CE, 0x00}, ++{0x37D0, 0x00}, ++{0x37D1, 0x00}, ++{0x37D2, 0x00}, ++{0x37D4, 0x00}, ++{0x37D5, 0x00}, ++{0x37D6, 0x00}, ++{0x37D8, 0x00}, ++{0x37D9, 0x00}, ++{0x37DA, 0x00}, ++{0x37DC, 0x00}, ++{0x37DD, 0x00}, ++{0x37DE, 0x00}, ++{0x37E0, 0x00}, ++{0x37E1, 0x00}, ++{0x37E2, 0x00}, ++{0x37E4, 0x00}, ++{0x37E5, 0x00}, ++{0x37E6, 0x00}, ++{0x37E8, 0x00}, ++{0x37E9, 0x00}, ++{0x37EA, 0x00}, ++{0x37EC, 0x00}, ++{0x37ED, 0x00}, ++{0x37EE, 0x00}, ++{0x37F0, 0x00}, ++{0x37F4, 0x00}, ++{0x37F5, 0x1E}, ++{0x37F6, 0x34}, ++{0x37F7, 0x00}, ++{0x37F8, 0xFF}, ++{0x37F9, 0xFF}, ++{0x37FA, 0x03}, ++{0x37FC, 0x00}, ++{0x37FD, 0x00}, ++{0x37FE, 0x04}, ++{0x3800, 0xFF}, ++{0x3801, 0xFF}, ++{0x3802, 0x03}, ++{0x3804, 0x00}, ++{0x3805, 0x00}, ++{0x3806, 0x04}, ++{0x3808, 0x00}, ++{0x3809, 0x00}, ++{0x380A, 0x00}, ++{0x380C, 0x00}, ++{0x380D, 0x00}, ++{0x380E, 0x00}, ++{0x3810, 0x00}, ++{0x3811, 0x00}, ++{0x3812, 0x00}, ++{0x3814, 0x00}, ++{0x3815, 0x00}, ++{0x3816, 0x00}, ++{0x3818, 0x00}, ++{0x3819, 0x00}, ++{0x381A, 0x00}, ++{0x381C, 0x00}, ++{0x381D, 0x00}, ++{0x381E, 0x00}, ++{0x3820, 0x00}, ++{0x3821, 0x00}, ++{0x3822, 0x00}, ++{0x3824, 0x00}, ++{0x3825, 0x00}, ++{0x3826, 0x00}, ++{0x3828, 0x00}, ++{0x3829, 0x00}, ++{0x382A, 0x00}, ++{0x382C, 0x00}, ++{0x382D, 0x00}, ++{0x382E, 0x00}, ++{0x3830, 0x00}, ++{0x3831, 0x00}, ++{0x3832, 0x00}, ++{0x3834, 0x00}, ++{0x3835, 0x00}, ++{0x3836, 0x00}, ++{0x3838, 0x22}, ++{0x3839, 0x00}, ++{0x383A, 0x25}, ++{0x383B, 0x00}, ++{0x383C, 0x1A}, ++{0x383D, 0x00}, ++{0x383E, 0x26}, ++{0x383F, 0x00}, ++{0x3840, 0x07}, ++{0x3841, 0x00}, ++{0x3842, 0x06}, ++{0x3843, 0x00}, ++{0x3844, 0x03}, ++{0x3845, 0x00}, ++{0x3846, 0x02}, ++{0x3847, 0x00}, ++{0x3848, 0xFB}, ++{0x3849, 0xFF}, ++{0x384A, 0xFF}, ++{0x384B, 0xFF}, ++{0x384C, 0xF3}, ++{0x384D, 0xFF}, ++{0x384E, 0xF2}, ++{0x384F, 0xFF}, ++{0x3850, 0xFF}, ++{0x3851, 0x0F}, ++{0x3852, 0x00}, ++{0x3853, 0x10}, ++{0x3854, 0xFF}, ++{0x3855, 0x0F}, ++{0x3856, 0x00}, ++{0x3857, 0x10}, ++{0x3858, 0xFF}, ++{0x3859, 0x0F}, ++{0x385A, 0x00}, ++{0x385B, 0x10}, ++{0x385C, 0x02}, ++{0x385D, 0x00}, ++{0x385E, 0x06}, ++{0x385F, 0x00}, ++{0x3860, 0x06}, ++{0x3861, 0x00}, ++{0x3862, 0x08}, ++{0x3863, 0x00}, ++{0x3864, 0x02}, ++{0x3865, 0x00}, ++{0x38A0, 0x01}, ++{0x38A1, 0x01}, ++{0x38A2, 0x00}, ++{0x38A3, 0x01}, ++{0x38A4, 0x07}, ++{0x38A5, 0x00}, ++{0x38A6, 0x04}, ++{0x38A7, 0x05}, ++{0x38A8, 0x00}, ++{0x38A9, 0x00}, ++{0x38AC, 0x00}, ++{0x38AD, 0x00}, ++{0x38AE, 0x01}, ++{0x38B0, 0x02}, ++{0x38B2, 0x22}, ++{0x38B3, 0x00}, ++{0x38B4, 0x17}, ++{0x38B5, 0x00}, ++{0x38B6, 0x11}, ++{0x38B7, 0x00}, ++{0x38B8, 0x0E}, ++{0x38B9, 0x00}, ++{0x38BA, 0x2A}, ++{0x38BB, 0x00}, ++{0x38BC, 0x1C}, ++{0x38BD, 0x00}, ++{0x38BE, 0x14}, ++{0x38BF, 0x00}, ++{0x38C0, 0x10}, ++{0x38C1, 0x00}, ++{0x38C2, 0x31}, ++{0x38C3, 0x00}, ++{0x38C4, 0x21}, ++{0x38C5, 0x00}, ++{0x38C6, 0x18}, ++{0x38C7, 0x00}, ++{0x38C8, 0x12}, ++{0x38C9, 0x00}, ++{0x38CA, 0x3C}, ++{0x38CB, 0x00}, ++{0x38CC, 0x29}, ++{0x38CD, 0x00}, ++{0x38CE, 0x1D}, ++{0x38CF, 0x00}, ++{0x38D0, 0x15}, ++{0x38D1, 0x00}, ++{0x38D2, 0x4E}, ++{0x38D3, 0x00}, ++{0x38D4, 0x35}, ++{0x38D5, 0x00}, ++{0x38D6, 0x26}, ++{0x38D7, 0x00}, ++{0x38D8, 0x1A}, ++{0x38D9, 0x00}, ++{0x38DA, 0x69}, ++{0x38DB, 0x00}, ++{0x38DC, 0x48}, ++{0x38DD, 0x00}, ++{0x38DE, 0x33}, ++{0x38DF, 0x00}, ++{0x38E0, 0x22}, ++{0x38E1, 0x00}, ++{0x38E2, 0x93}, ++{0x38E3, 0x00}, ++{0x38E4, 0x64}, ++{0x38E5, 0x00}, ++{0x38E6, 0x48}, ++{0x38E7, 0x00}, ++{0x38E8, 0x30}, ++{0x38E9, 0x00}, ++{0x38EA, 0xD3}, ++{0x38EB, 0x00}, ++{0x38EC, 0x90}, ++{0x38ED, 0x00}, ++{0x38EE, 0x69}, ++{0x38EF, 0x00}, ++{0x38F0, 0x49}, ++{0x38F1, 0x00}, ++{0x38F2, 0x39}, ++{0x38F3, 0x01}, ++{0x38F4, 0xD5}, ++{0x38F5, 0x00}, ++{0x38F6, 0x9F}, ++{0x38F7, 0x00}, ++{0x38F8, 0x75}, ++{0x38F9, 0x00}, ++{0x38FA, 0x00}, ++{0x38FB, 0x01}, ++{0x38FC, 0x00}, ++{0x38FD, 0x01}, ++{0x38FE, 0x00}, ++{0x38FF, 0x01}, ++{0x3900, 0x00}, ++{0x3901, 0x01}, ++{0x3902, 0x60}, ++{0x3903, 0x00}, ++{0x3904, 0x25}, ++{0x3905, 0x00}, ++{0x3906, 0x18}, ++{0x3907, 0x00}, ++{0x3908, 0x10}, ++{0x3909, 0x00}, ++{0x390A, 0xFF}, ++{0x390B, 0x00}, ++{0x390C, 0xD5}, ++{0x390D, 0x00}, ++{0x390E, 0xAA}, ++{0x390F, 0x00}, ++{0x3910, 0x85}, ++{0x3911, 0x00}, ++{0x3912, 0xFF}, ++{0x3913, 0x00}, ++{0x3914, 0xD5}, ++{0x3915, 0x00}, ++{0x3916, 0xAA}, ++{0x3917, 0x00}, ++{0x3918, 0x85}, ++{0x3919, 0x00}, ++{0x391A, 0xFF}, ++{0x391B, 0x00}, ++{0x391C, 0xD5}, ++{0x391D, 0x00}, ++{0x391E, 0xAA}, ++{0x391F, 0x00}, ++{0x3920, 0x85}, ++{0x3921, 0x00}, ++{0x3922, 0x40}, ++{0x3923, 0x00}, ++{0x3924, 0x40}, ++{0x3925, 0x00}, ++{0x3926, 0x40}, ++{0x3927, 0x00}, ++{0x3928, 0x40}, ++{0x3929, 0x00}, ++{0x392A, 0x80}, ++{0x392B, 0x00}, ++{0x392C, 0x80}, ++{0x392D, 0x00}, ++{0x392E, 0x80}, ++{0x392F, 0x00}, ++{0x3930, 0x80}, ++{0x3931, 0x00}, ++{0x3932, 0x4C}, ++{0x3933, 0x4C}, ++{0x3934, 0x4C}, ++{0x3940, 0x01}, ++{0x3941, 0x01}, ++{0x3942, 0x00}, ++{0x3943, 0x01}, ++{0x3944, 0x07}, ++{0x3945, 0x00}, ++{0x3946, 0x04}, ++{0x3947, 0x05}, ++{0x3948, 0x00}, ++{0x3949, 0x00}, ++{0x394C, 0x00}, ++{0x394D, 0x00}, ++{0x394E, 0x01}, ++{0x3950, 0x03}, ++{0x3952, 0x14}, ++{0x3953, 0x00}, ++{0x3954, 0x0F}, ++{0x3955, 0x00}, ++{0x3956, 0x0E}, ++{0x3957, 0x00}, ++{0x3958, 0x0E}, ++{0x3959, 0x00}, ++{0x395A, 0x19}, ++{0x395B, 0x00}, ++{0x395C, 0x11}, ++{0x395D, 0x00}, ++{0x395E, 0x0F}, ++{0x395F, 0x00}, ++{0x3960, 0x0E}, ++{0x3961, 0x00}, ++{0x3962, 0x1C}, ++{0x3963, 0x00}, ++{0x3964, 0x13}, ++{0x3965, 0x00}, ++{0x3966, 0x0F}, ++{0x3967, 0x00}, ++{0x3968, 0x0E}, ++{0x3969, 0x00}, ++{0x396A, 0x23}, ++{0x396B, 0x00}, ++{0x396C, 0x15}, ++{0x396D, 0x00}, ++{0x396E, 0x11}, ++{0x396F, 0x00}, ++{0x3970, 0x0E}, ++{0x3971, 0x00}, ++{0x3972, 0x2E}, ++{0x3973, 0x00}, ++{0x3974, 0x1A}, ++{0x3975, 0x00}, ++{0x3976, 0x14}, ++{0x3977, 0x00}, ++{0x3978, 0x0F}, ++{0x3979, 0x00}, ++{0x397A, 0x3E}, ++{0x397B, 0x00}, ++{0x397C, 0x23}, ++{0x397D, 0x00}, ++{0x397E, 0x1A}, ++{0x397F, 0x00}, ++{0x3980, 0x12}, ++{0x3981, 0x00}, ++{0x3982, 0x56}, ++{0x3983, 0x00}, ++{0x3984, 0x31}, ++{0x3985, 0x00}, ++{0x3986, 0x25}, ++{0x3987, 0x00}, ++{0x3988, 0x1A}, ++{0x3989, 0x00}, ++{0x398A, 0x7B}, ++{0x398B, 0x00}, ++{0x398C, 0x49}, ++{0x398D, 0x00}, ++{0x398E, 0x39}, ++{0x398F, 0x00}, ++{0x3990, 0x2C}, ++{0x3991, 0x00}, ++{0x3992, 0xB4}, ++{0x3993, 0x00}, ++{0x3994, 0x75}, ++{0x3995, 0x00}, ++{0x3996, 0x61}, ++{0x3997, 0x00}, ++{0x3998, 0x53}, ++{0x3999, 0x00}, ++{0x399A, 0x00}, ++{0x399B, 0x01}, ++{0x399C, 0x00}, ++{0x399D, 0x01}, ++{0x399E, 0x00}, ++{0x399F, 0x01}, ++{0x39A0, 0x00}, ++{0x39A1, 0x01}, ++{0x39A2, 0x60}, ++{0x39A3, 0x00}, ++{0x39A4, 0x20}, ++{0x39A5, 0x00}, ++{0x39A6, 0x15}, ++{0x39A7, 0x00}, ++{0x39A8, 0x10}, ++{0x39A9, 0x00}, ++{0x39AA, 0xFF}, ++{0x39AB, 0x00}, ++{0x39AC, 0xD5}, ++{0x39AD, 0x00}, ++{0x39AE, 0xAA}, ++{0x39AF, 0x00}, ++{0x39B0, 0x85}, ++{0x39B1, 0x00}, ++{0x39B2, 0xFF}, ++{0x39B3, 0x00}, ++{0x39B4, 0xD5}, ++{0x39B5, 0x00}, ++{0x39B6, 0xAA}, ++{0x39B7, 0x00}, ++{0x39B8, 0x85}, ++{0x39B9, 0x00}, ++{0x39BA, 0xFF}, ++{0x39BB, 0x00}, ++{0x39BC, 0xD5}, ++{0x39BD, 0x00}, ++{0x39BE, 0xAA}, ++{0x39BF, 0x00}, ++{0x39C0, 0x85}, ++{0x39C1, 0x00}, ++{0x39C2, 0x40}, ++{0x39C3, 0x00}, ++{0x39C4, 0x40}, ++{0x39C5, 0x00}, ++{0x39C6, 0x40}, ++{0x39C7, 0x00}, ++{0x39C8, 0x40}, ++{0x39C9, 0x00}, ++{0x39CA, 0x80}, ++{0x39CB, 0x00}, ++{0x39CC, 0x80}, ++{0x39CD, 0x00}, ++{0x39CE, 0x80}, ++{0x39CF, 0x00}, ++{0x39D0, 0x80}, ++{0x39D1, 0x00}, ++{0x39D2, 0x4C}, ++{0x39D3, 0x4C}, ++{0x39D4, 0x4C}, ++{0x39E0, 0x01}, ++{0x39E1, 0x00}, ++{0x39E4, 0x40}, ++{0x39E5, 0x01}, ++{0x39E6, 0x01}, ++{0x39E8, 0x00}, ++{0x39E9, 0x01}, ++{0x39EA, 0x00}, ++{0x39EB, 0x00}, ++{0x39EC, 0x01}, ++{0x39ED, 0x00}, ++{0x39EE, 0x01}, ++{0x39F0, 0x03}, ++{0x39F1, 0x04}, ++{0x39F2, 0x0E}, ++{0x39F4, 0x1C}, ++{0x39F5, 0x00}, ++{0x39F6, 0x13}, ++{0x39F7, 0x00}, ++{0x39F8, 0x0D}, ++{0x39F9, 0x00}, ++{0x39FA, 0x07}, ++{0x39FB, 0x00}, ++{0x39FC, 0x38}, ++{0x39FD, 0x00}, ++{0x39FE, 0x1C}, ++{0x39FF, 0x00}, ++{0x3A00, 0x11}, ++{0x3A01, 0x00}, ++{0x3A02, 0x08}, ++{0x3A03, 0x00}, ++{0x3A04, 0x4A}, ++{0x3A05, 0x00}, ++{0x3A06, 0x23}, ++{0x3A07, 0x00}, ++{0x3A08, 0x15}, ++{0x3A09, 0x00}, ++{0x3A0A, 0x09}, ++{0x3A0B, 0x00}, ++{0x3A0C, 0x65}, ++{0x3A0D, 0x00}, ++{0x3A0E, 0x2D}, ++{0x3A0F, 0x00}, ++{0x3A10, 0x1A}, ++{0x3A11, 0x00}, ++{0x3A12, 0x0B}, ++{0x3A13, 0x00}, ++{0x3A14, 0x8D}, ++{0x3A15, 0x00}, ++{0x3A16, 0x3D}, ++{0x3A17, 0x00}, ++{0x3A18, 0x23}, ++{0x3A19, 0x00}, ++{0x3A1A, 0x0E}, ++{0x3A1B, 0x00}, ++{0x3A1C, 0xC5}, ++{0x3A1D, 0x00}, ++{0x3A1E, 0x55}, ++{0x3A1F, 0x00}, ++{0x3A20, 0x30}, ++{0x3A21, 0x00}, ++{0x3A22, 0x13}, ++{0x3A23, 0x00}, ++{0x3A24, 0x16}, ++{0x3A25, 0x01}, ++{0x3A26, 0x76}, ++{0x3A27, 0x00}, ++{0x3A28, 0x42}, ++{0x3A29, 0x00}, ++{0x3A2A, 0x1A}, ++{0x3A2B, 0x00}, ++{0x3A2C, 0x88}, ++{0x3A2D, 0x01}, ++{0x3A2E, 0xA7}, ++{0x3A2F, 0x00}, ++{0x3A30, 0x5D}, ++{0x3A31, 0x00}, ++{0x3A32, 0x24}, ++{0x3A33, 0x00}, ++{0x3A34, 0x2A}, ++{0x3A35, 0x02}, ++{0x3A36, 0xEB}, ++{0x3A37, 0x00}, ++{0x3A38, 0x83}, ++{0x3A39, 0x00}, ++{0x3A3A, 0x32}, ++{0x3A3B, 0x00}, ++{0x3A3C, 0x00}, ++{0x3A3D, 0x01}, ++{0x3A3E, 0x00}, ++{0x3A3F, 0x01}, ++{0x3A40, 0x00}, ++{0x3A41, 0x01}, ++{0x3A42, 0x00}, ++{0x3A43, 0x01}, ++{0x3A44, 0x70}, ++{0x3A45, 0x00}, ++{0x3A46, 0x25}, ++{0x3A47, 0x00}, ++{0x3A48, 0x18}, ++{0x3A49, 0x00}, ++{0x3A4A, 0x10}, ++{0x3A4B, 0x00}, ++{0x3A4C, 0xFF}, ++{0x3A4D, 0x00}, ++{0x3A4E, 0xD5}, ++{0x3A4F, 0x00}, ++{0x3A50, 0xAA}, ++{0x3A51, 0x00}, ++{0x3A52, 0x85}, ++{0x3A53, 0x00}, ++{0x3A54, 0xFF}, ++{0x3A55, 0x00}, ++{0x3A56, 0xD5}, ++{0x3A57, 0x00}, ++{0x3A58, 0xAA}, ++{0x3A59, 0x00}, ++{0x3A5A, 0x85}, ++{0x3A5B, 0x00}, ++{0x3A5C, 0xFF}, ++{0x3A5D, 0x00}, ++{0x3A5E, 0xD5}, ++{0x3A5F, 0x00}, ++{0x3A60, 0xAA}, ++{0x3A61, 0x00}, ++{0x3A62, 0x85}, ++{0x3A63, 0x00}, ++{0x3A64, 0x1C}, ++{0x3A65, 0x00}, ++{0x3A66, 0x13}, ++{0x3A67, 0x00}, ++{0x3A68, 0x0D}, ++{0x3A69, 0x00}, ++{0x3A6A, 0x07}, ++{0x3A6B, 0x00}, ++{0x3A6C, 0x0D}, ++{0x3A6D, 0x00}, ++{0x3A6E, 0x0B}, ++{0x3A6F, 0x00}, ++{0x3A70, 0x06}, ++{0x3A71, 0x00}, ++{0x3A72, 0x05}, ++{0x3A73, 0x00}, ++{0x3A74, 0x19}, ++{0x3A75, 0x00}, ++{0x3A76, 0x14}, ++{0x3A77, 0x00}, ++{0x3A78, 0x0F}, ++{0x3A79, 0x00}, ++{0x3A7A, 0x0A}, ++{0x3A7B, 0x00}, ++{0x3A7C, 0x80}, ++{0x3A7D, 0x00}, ++{0x3A7E, 0x80}, ++{0x3A7F, 0x00}, ++{0x3A80, 0x80}, ++{0x3A81, 0x00}, ++{0x3A82, 0x80}, ++{0x3A83, 0x00}, ++{0x3A84, 0x08}, ++{0x3A85, 0x00}, ++{0x3A86, 0x05}, ++{0x3A87, 0x00}, ++{0x3A88, 0x04}, ++{0x3A89, 0x00}, ++{0x3A8A, 0x03}, ++{0x3A8B, 0x00}, ++{0x3A8C, 0xCD}, ++{0x3A8D, 0x00}, ++{0x3A8E, 0xAA}, ++{0x3A8F, 0x00}, ++{0x3A90, 0x8C}, ++{0x3A91, 0x00}, ++{0x3A92, 0x64}, ++{0x3A93, 0x00}, ++{0x3A94, 0xCD}, ++{0x3A95, 0x00}, ++{0x3A96, 0xAA}, ++{0x3A97, 0x00}, ++{0x3A98, 0x8C}, ++{0x3A99, 0x00}, ++{0x3A9A, 0x64}, ++{0x3A9B, 0x00}, ++{0x3A9C, 0x08}, ++{0x3A9D, 0x10}, ++{0x3A9E, 0x4C}, ++{0x3A9F, 0x4C}, ++{0x3AA0, 0x4C}, ++{0x3AA1, 0x04}, ++{0x3AA2, 0x05}, ++{0x3AC0, 0x01}, ++{0x3AC4, 0x81}, ++{0x3AC5, 0x00}, ++{0x3AC6, 0x00}, ++{0x3AC7, 0x00}, ++{0x3AC8, 0x00}, ++{0x3AC9, 0x00}, ++{0x3ACA, 0x00}, ++{0x3ACB, 0x00}, ++{0x3ACC, 0x02}, ++{0x3ACD, 0x00}, ++{0x3ACE, 0x81}, ++{0x3ACF, 0x00}, ++{0x3AD0, 0x00}, ++{0x3AD1, 0x00}, ++{0x3AD2, 0xFD}, ++{0x3AD3, 0x03}, ++{0x3AD4, 0x02}, ++{0x3AD5, 0x00}, ++{0x3AD6, 0x00}, ++{0x3AD7, 0x00}, ++{0x3AD8, 0x81}, ++{0x3AD9, 0x00}, ++{0x3ADA, 0xFD}, ++{0x3ADB, 0x03}, ++{0x3ADC, 0xFF}, ++{0x3ADD, 0x03}, ++{0x3ADE, 0x01}, ++{0x3ADF, 0x00}, ++{0x3AE0, 0x01}, ++{0x3AE1, 0x00}, ++{0x3AE2, 0x7E}, ++{0x3AE3, 0x00}, ++{0x3AF4, 0x00}, ++{0x3AF6, 0x40}, ++{0x3AF7, 0x1E}, ++{0x3AF8, 0x01}, ++{0x3AFA, 0x63}, ++{0x3AFB, 0x09}, ++{0x3AFC, 0x11}, ++{0x3AFD, 0x09}, ++{0x3AFE, 0x00}, ++{0x3AFF, 0x00}, ++{0x3B00, 0x00}, ++{0x3B01, 0x00}, ++{0x3B02, 0x84}, ++{0x3B03, 0x06}, ++{0x3B04, 0x30}, ++{0x3B05, 0x06}, ++{0x3B06, 0x00}, ++{0x3B07, 0x00}, ++{0x3B08, 0x00}, ++{0x3B09, 0x00}, ++{0x3B0A, 0x00}, ++{0x3B0B, 0x00}, ++{0x3B0C, 0x00}, ++{0x3B0D, 0x00}, ++{0x3B0E, 0x00}, ++{0x3B0F, 0x00}, ++{0x3B10, 0x00}, ++{0x3B11, 0x00}, ++{0x3B12, 0x00}, ++{0x3B13, 0x00}, ++{0x3B14, 0x00}, ++{0x3B15, 0x00}, ++{0x3B16, 0x00}, ++{0x3B17, 0x00}, ++{0x3B18, 0x00}, ++{0x3B19, 0x00}, ++{0x3B1A, 0x00}, ++{0x3B1B, 0x00}, ++{0x3B1C, 0x00}, ++{0x3B1D, 0x00}, ++{0x3B1E, 0x00}, ++{0x3B1F, 0x00}, ++{0x3B20, 0x00}, ++{0x3B21, 0x00}, ++{0x3B22, 0x00}, ++{0x3B23, 0x00}, ++{0x3B24, 0x00}, ++{0x3B25, 0x00}, ++{0x3B26, 0x00}, ++{0x3B27, 0x00}, ++{0x3B28, 0x00}, ++{0x3B29, 0x00}, ++{0x3B2A, 0x00}, ++{0x3B2C, 0x00}, ++{0x3B2E, 0x00}, ++{0x3B30, 0x00}, ++{0x3B32, 0x0C}, ++{0x4000, 0xD1}, ++{0x4001, 0xC0}, ++{0x4002, 0xC0}, ++{0x4003, 0xB8}, ++{0x4004, 0xC0}, ++{0x4005, 0xB8}, ++{0x4006, 0xB9}, ++{0x4007, 0xB7}, ++{0x4008, 0xB0}, ++{0x4009, 0xAB}, ++{0x400A, 0xAC}, ++{0x400B, 0xAB}, ++{0x400C, 0xA8}, ++{0x400D, 0xA6}, ++{0x400E, 0xA6}, ++{0x400F, 0xA5}, ++{0x4010, 0xA2}, ++{0x4011, 0xA0}, ++{0x4012, 0xA0}, ++{0x4013, 0x9F}, ++{0x4014, 0xA4}, ++{0x4015, 0xA2}, ++{0x4016, 0xA2}, ++{0x4017, 0x9C}, ++{0x4018, 0xA8}, ++{0x4019, 0xA6}, ++{0x401A, 0xA8}, ++{0x401B, 0xAA}, ++{0x401C, 0xB0}, ++{0x401D, 0xAE}, ++{0x401E, 0xAE}, ++{0x401F, 0xAE}, ++{0x4020, 0xBA}, ++{0x4021, 0xAE}, ++{0x4022, 0xAF}, ++{0x4023, 0xAE}, ++{0x4024, 0xC6}, ++{0x4025, 0xBD}, ++{0x4026, 0xBD}, ++{0x4027, 0xBA}, ++{0x4028, 0xB0}, ++{0x4029, 0xA9}, ++{0x402A, 0xAA}, ++{0x402B, 0xA8}, ++{0x402C, 0x9F}, ++{0x402D, 0x9C}, ++{0x402E, 0x9C}, ++{0x402F, 0x9B}, ++{0x4030, 0x93}, ++{0x4031, 0x91}, ++{0x4032, 0x92}, ++{0x4033, 0x91}, ++{0x4034, 0x8D}, ++{0x4035, 0x8C}, ++{0x4036, 0x8C}, ++{0x4037, 0x8C}, ++{0x4038, 0x8F}, ++{0x4039, 0x8E}, ++{0x403A, 0x8E}, ++{0x403B, 0x8E}, ++{0x403C, 0x98}, ++{0x403D, 0x96}, ++{0x403E, 0x96}, ++{0x403F, 0x95}, ++{0x4040, 0xA4}, ++{0x4041, 0xA0}, ++{0x4042, 0xA0}, ++{0x4043, 0x9E}, ++{0x4044, 0xB3}, ++{0x4045, 0xAE}, ++{0x4046, 0xAF}, ++{0x4047, 0xAB}, ++{0x4048, 0xC2}, ++{0x4049, 0xB7}, ++{0x404A, 0xB8}, ++{0x404B, 0xB5}, ++{0x404C, 0xAB}, ++{0x404D, 0xA4}, ++{0x404E, 0xA5}, ++{0x404F, 0xA3}, ++{0x4050, 0x99}, ++{0x4051, 0x96}, ++{0x4052, 0x96}, ++{0x4053, 0x96}, ++{0x4054, 0x8B}, ++{0x4055, 0x8A}, ++{0x4056, 0x8A}, ++{0x4057, 0x8A}, ++{0x4058, 0x82}, ++{0x4059, 0x81}, ++{0x405A, 0x81}, ++{0x405B, 0x81}, ++{0x405C, 0x85}, ++{0x405D, 0x86}, ++{0x405E, 0x85}, ++{0x405F, 0x85}, ++{0x4060, 0x90}, ++{0x4061, 0x90}, ++{0x4062, 0x8F}, ++{0x4063, 0x8F}, ++{0x4064, 0x9D}, ++{0x4065, 0x9B}, ++{0x4066, 0x9B}, ++{0x4067, 0x9A}, ++{0x4068, 0xAF}, ++{0x4069, 0xAA}, ++{0x406A, 0xAC}, ++{0x406B, 0xAA}, ++{0x406C, 0xC2}, ++{0x406D, 0xB7}, ++{0x406E, 0xB8}, ++{0x406F, 0xB5}, ++{0x4070, 0xAB}, ++{0x4071, 0xA4}, ++{0x4072, 0xA4}, ++{0x4073, 0xA3}, ++{0x4074, 0x99}, ++{0x4075, 0x96}, ++{0x4076, 0x96}, ++{0x4077, 0x96}, ++{0x4078, 0x8B}, ++{0x4079, 0x8A}, ++{0x407A, 0x8A}, ++{0x407B, 0x8A}, ++{0x407C, 0x82}, ++{0x407D, 0x82}, ++{0x407E, 0x82}, ++{0x407F, 0x82}, ++{0x4080, 0x85}, ++{0x4081, 0x86}, ++{0x4082, 0x86}, ++{0x4083, 0x86}, ++{0x4084, 0x90}, ++{0x4085, 0x90}, ++{0x4086, 0x8F}, ++{0x4087, 0x8F}, ++{0x4088, 0x9D}, ++{0x4089, 0x9B}, ++{0x408A, 0x9B}, ++{0x408B, 0x99}, ++{0x408C, 0xAE}, ++{0x408D, 0xAA}, ++{0x408E, 0xAA}, ++{0x408F, 0xA7}, ++{0x4090, 0xC7}, ++{0x4091, 0xBA}, ++{0x4092, 0xBC}, ++{0x4093, 0xB9}, ++{0x4094, 0xB1}, ++{0x4095, 0xA8}, ++{0x4096, 0xA8}, ++{0x4097, 0xA7}, ++{0x4098, 0x9F}, ++{0x4099, 0x9B}, ++{0x409A, 0x9B}, ++{0x409B, 0x9B}, ++{0x409C, 0x93}, ++{0x409D, 0x91}, ++{0x409E, 0x91}, ++{0x409F, 0x91}, ++{0x40A0, 0x8D}, ++{0x40A1, 0x8C}, ++{0x40A2, 0x8C}, ++{0x40A3, 0x8C}, ++{0x40A4, 0x8E}, ++{0x40A5, 0x8E}, ++{0x40A6, 0x8D}, ++{0x40A7, 0x8D}, ++{0x40A8, 0x96}, ++{0x40A9, 0x95}, ++{0x40AA, 0x95}, ++{0x40AB, 0x94}, ++{0x40AC, 0xA2}, ++{0x40AD, 0x9F}, ++{0x40AE, 0x9F}, ++{0x40AF, 0x9D}, ++{0x40B0, 0xB1}, ++{0x40B1, 0xAC}, ++{0x40B2, 0xAB}, ++{0x40B3, 0xAA}, ++{0x40B4, 0xD3}, ++{0x40B5, 0xBC}, ++{0x40B6, 0xBD}, ++{0x40B7, 0xBC}, ++{0x40B8, 0xC1}, ++{0x40B9, 0xB7}, ++{0x40BA, 0xB7}, ++{0x40BB, 0xB5}, ++{0x40BC, 0xB0}, ++{0x40BD, 0xAA}, ++{0x40BE, 0xAA}, ++{0x40BF, 0xAA}, ++{0x40C0, 0xA8}, ++{0x40C1, 0xA4}, ++{0x40C2, 0xA4}, ++{0x40C3, 0xA4}, ++{0x40C4, 0xA2}, ++{0x40C5, 0x9F}, ++{0x40C6, 0x9F}, ++{0x40C7, 0x9F}, ++{0x40C8, 0xA3}, ++{0x40C9, 0xA0}, ++{0x40CA, 0xA0}, ++{0x40CB, 0xA0}, ++{0x40CC, 0xA6}, ++{0x40CD, 0xA3}, ++{0x40CE, 0xA3}, ++{0x40CF, 0xA2}, ++{0x40D0, 0xAF}, ++{0x40D1, 0xAB}, ++{0x40D2, 0xAA}, ++{0x40D3, 0xA8}, ++{0x40D4, 0xBA}, ++{0x40D5, 0xAE}, ++{0x40D6, 0xAE}, ++{0x40D7, 0xAB}, ++{0x4100, 0xBD}, ++{0x4101, 0xBA}, ++{0x4102, 0xBD}, ++{0x4103, 0xB7}, ++{0x4104, 0xB7}, ++{0x4105, 0xB7}, ++{0x4106, 0xB8}, ++{0x4107, 0xB5}, ++{0x4108, 0xAB}, ++{0x4109, 0xAA}, ++{0x410A, 0xAC}, ++{0x410B, 0xAB}, ++{0x410C, 0xA4}, ++{0x410D, 0xA5}, ++{0x410E, 0xA5}, ++{0x410F, 0xA4}, ++{0x4110, 0x9F}, ++{0x4111, 0xA0}, ++{0x4112, 0xA0}, ++{0x4113, 0x9F}, ++{0x4114, 0xA0}, ++{0x4115, 0xA0}, ++{0x4116, 0xA0}, ++{0x4117, 0x9F}, ++{0x4118, 0xA1}, ++{0x4119, 0xA1}, ++{0x411A, 0xA1}, ++{0x411B, 0xA0}, ++{0x411C, 0xA7}, ++{0x411D, 0xA6}, ++{0x411E, 0xA6}, ++{0x411F, 0xA6}, ++{0x4120, 0xA7}, ++{0x4121, 0xA6}, ++{0x4122, 0xA6}, ++{0x4123, 0xA3}, ++{0x4124, 0xB9}, ++{0x4125, 0xB9}, ++{0x4126, 0xBA}, ++{0x4127, 0xB8}, ++{0x4128, 0xA6}, ++{0x4129, 0xA7}, ++{0x412A, 0xA7}, ++{0x412B, 0xA6}, ++{0x412C, 0x9B}, ++{0x412D, 0x9B}, ++{0x412E, 0x9B}, ++{0x412F, 0x9B}, ++{0x4130, 0x91}, ++{0x4131, 0x92}, ++{0x4132, 0x92}, ++{0x4133, 0x91}, ++{0x4134, 0x8C}, ++{0x4135, 0x8C}, ++{0x4136, 0x8C}, ++{0x4137, 0x8C}, ++{0x4138, 0x8D}, ++{0x4139, 0x8D}, ++{0x413A, 0x8D}, ++{0x413B, 0x8D}, ++{0x413C, 0x93}, ++{0x413D, 0x93}, ++{0x413E, 0x93}, ++{0x413F, 0x92}, ++{0x4140, 0x9A}, ++{0x4141, 0x9A}, ++{0x4142, 0x9A}, ++{0x4143, 0x99}, ++{0x4144, 0xA7}, ++{0x4145, 0xA5}, ++{0x4146, 0xA6}, ++{0x4147, 0xA6}, ++{0x4148, 0xB8}, ++{0x4149, 0xB4}, ++{0x414A, 0xB4}, ++{0x414B, 0xB3}, ++{0x414C, 0xA3}, ++{0x414D, 0xA2}, ++{0x414E, 0xA3}, ++{0x414F, 0xA2}, ++{0x4150, 0x96}, ++{0x4151, 0x96}, ++{0x4152, 0x96}, ++{0x4153, 0x96}, ++{0x4154, 0x8A}, ++{0x4155, 0x8A}, ++{0x4156, 0x8A}, ++{0x4157, 0x8A}, ++{0x4158, 0x82}, ++{0x4159, 0x82}, ++{0x415A, 0x82}, ++{0x415B, 0x82}, ++{0x415C, 0x84}, ++{0x415D, 0x85}, ++{0x415E, 0x84}, ++{0x415F, 0x84}, ++{0x4160, 0x8D}, ++{0x4161, 0x8D}, ++{0x4162, 0x8D}, ++{0x4163, 0x8D}, ++{0x4164, 0x96}, ++{0x4165, 0x96}, ++{0x4166, 0x96}, ++{0x4167, 0x95}, ++{0x4168, 0xA5}, ++{0x4169, 0xA2}, ++{0x416A, 0xA3}, ++{0x416B, 0xA2}, ++{0x416C, 0xB7}, ++{0x416D, 0xB3}, ++{0x416E, 0xB5}, ++{0x416F, 0xB4}, ++{0x4170, 0xA4}, ++{0x4171, 0xA2}, ++{0x4172, 0xA3}, ++{0x4173, 0xA2}, ++{0x4174, 0x97}, ++{0x4175, 0x96}, ++{0x4176, 0x96}, ++{0x4177, 0x96}, ++{0x4178, 0x8B}, ++{0x4179, 0x8A}, ++{0x417A, 0x8A}, ++{0x417B, 0x8A}, ++{0x417C, 0x81}, ++{0x417D, 0x81}, ++{0x417E, 0x81}, ++{0x417F, 0x81}, ++{0x4180, 0x84}, ++{0x4181, 0x84}, ++{0x4182, 0x84}, ++{0x4183, 0x84}, ++{0x4184, 0x8C}, ++{0x4185, 0x8D}, ++{0x4186, 0x8D}, ++{0x4187, 0x8D}, ++{0x4188, 0x95}, ++{0x4189, 0x96}, ++{0x418A, 0x96}, ++{0x418B, 0x95}, ++{0x418C, 0xA1}, ++{0x418D, 0xA1}, ++{0x418E, 0xA1}, ++{0x418F, 0xA0}, ++{0x4190, 0xBC}, ++{0x4191, 0xB8}, ++{0x4192, 0xB8}, ++{0x4193, 0xB9}, ++{0x4194, 0xA8}, ++{0x4195, 0xA5}, ++{0x4196, 0xA6}, ++{0x4197, 0xA5}, ++{0x4198, 0x9C}, ++{0x4199, 0x9A}, ++{0x419A, 0x9A}, ++{0x419B, 0x9A}, ++{0x419C, 0x91}, ++{0x419D, 0x91}, ++{0x419E, 0x91}, ++{0x419F, 0x91}, ++{0x41A0, 0x8B}, ++{0x41A1, 0x8B}, ++{0x41A2, 0x8B}, ++{0x41A3, 0x8B}, ++{0x41A4, 0x8C}, ++{0x41A5, 0x8C}, ++{0x41A6, 0x8C}, ++{0x41A7, 0x8C}, ++{0x41A8, 0x91}, ++{0x41A9, 0x92}, ++{0x41AA, 0x91}, ++{0x41AB, 0x91}, ++{0x41AC, 0x98}, ++{0x41AD, 0x99}, ++{0x41AE, 0x99}, ++{0x41AF, 0x98}, ++{0x41B0, 0xA3}, ++{0x41B1, 0xA3}, ++{0x41B2, 0xA3}, ++{0x41B3, 0xA2}, ++{0x41B4, 0xC1}, ++{0x41B5, 0xB8}, ++{0x41B6, 0xB9}, ++{0x41B7, 0xBA}, ++{0x41B8, 0xB8}, ++{0x41B9, 0xB4}, ++{0x41BA, 0xB4}, ++{0x41BB, 0xB4}, ++{0x41BC, 0xAA}, ++{0x41BD, 0xA7}, ++{0x41BE, 0xA7}, ++{0x41BF, 0xA8}, ++{0x41C0, 0xA4}, ++{0x41C1, 0xA2}, ++{0x41C2, 0xA2}, ++{0x41C3, 0xA3}, ++{0x41C4, 0x9E}, ++{0x41C5, 0x9D}, ++{0x41C6, 0x9D}, ++{0x41C7, 0x9D}, ++{0x41C8, 0x9E}, ++{0x41C9, 0x9D}, ++{0x41CA, 0x9D}, ++{0x41CB, 0x9D}, ++{0x41CC, 0x9E}, ++{0x41CD, 0x9E}, ++{0x41CE, 0x9E}, ++{0x41CF, 0x9E}, ++{0x41D0, 0xA3}, ++{0x41D1, 0xA3}, ++{0x41D2, 0xA2}, ++{0x41D3, 0xA1}, ++{0x41D4, 0xA7}, ++{0x41D5, 0xA7}, ++{0x41D6, 0xA7}, ++{0x41D7, 0xA3}, ++{0x4200, 0xCE}, ++{0x4201, 0xC0}, ++{0x4202, 0xC1}, ++{0x4203, 0xB9}, ++{0x4204, 0xC3}, ++{0x4205, 0xB9}, ++{0x4206, 0xBC}, ++{0x4207, 0xBD}, ++{0x4208, 0xB3}, ++{0x4209, 0xAE}, ++{0x420A, 0xAF}, ++{0x420B, 0xAE}, ++{0x420C, 0xAA}, ++{0x420D, 0xA8}, ++{0x420E, 0xA8}, ++{0x420F, 0xA6}, ++{0x4210, 0xA4}, ++{0x4211, 0xA2}, ++{0x4212, 0xA2}, ++{0x4213, 0xA0}, ++{0x4214, 0xA4}, ++{0x4215, 0xA3}, ++{0x4216, 0xA2}, ++{0x4217, 0xA0}, ++{0x4218, 0xA7}, ++{0x4219, 0xA5}, ++{0x421A, 0xA3}, ++{0x421B, 0xA1}, ++{0x421C, 0xB0}, ++{0x421D, 0xA8}, ++{0x421E, 0xA8}, ++{0x421F, 0xA6}, ++{0x4220, 0xB4}, ++{0x4221, 0xAA}, ++{0x4222, 0xA5}, ++{0x4223, 0xA3}, ++{0x4224, 0xC7}, ++{0x4225, 0xBC}, ++{0x4226, 0xBE}, ++{0x4227, 0xBC}, ++{0x4228, 0xB0}, ++{0x4229, 0xA9}, ++{0x422A, 0xA9}, ++{0x422B, 0xA8}, ++{0x422C, 0xA0}, ++{0x422D, 0x9D}, ++{0x422E, 0x9D}, ++{0x422F, 0x9C}, ++{0x4230, 0x94}, ++{0x4231, 0x93}, ++{0x4232, 0x93}, ++{0x4233, 0x92}, ++{0x4234, 0x8E}, ++{0x4235, 0x8D}, ++{0x4236, 0x8D}, ++{0x4237, 0x8C}, ++{0x4238, 0x8F}, ++{0x4239, 0x8E}, ++{0x423A, 0x8E}, ++{0x423B, 0x8D}, ++{0x423C, 0x96}, ++{0x423D, 0x94}, ++{0x423E, 0x94}, ++{0x423F, 0x92}, ++{0x4240, 0xA1}, ++{0x4241, 0x9C}, ++{0x4242, 0x9C}, ++{0x4243, 0x99}, ++{0x4244, 0xB0}, ++{0x4245, 0xA8}, ++{0x4246, 0xAB}, ++{0x4247, 0xA7}, ++{0x4248, 0xC3}, ++{0x4249, 0xB7}, ++{0x424A, 0xB7}, ++{0x424B, 0xBC}, ++{0x424C, 0xAB}, ++{0x424D, 0xA4}, ++{0x424E, 0xA5}, ++{0x424F, 0xA5}, ++{0x4250, 0x9A}, ++{0x4251, 0x97}, ++{0x4252, 0x97}, ++{0x4253, 0x98}, ++{0x4254, 0x8C}, ++{0x4255, 0x8B}, ++{0x4256, 0x8B}, ++{0x4257, 0x8B}, ++{0x4258, 0x82}, ++{0x4259, 0x82}, ++{0x425A, 0x82}, ++{0x425B, 0x82}, ++{0x425C, 0x85}, ++{0x425D, 0x85}, ++{0x425E, 0x85}, ++{0x425F, 0x84}, ++{0x4260, 0x8F}, ++{0x4261, 0x8E}, ++{0x4262, 0x8E}, ++{0x4263, 0x8D}, ++{0x4264, 0x9B}, ++{0x4265, 0x98}, ++{0x4266, 0x98}, ++{0x4267, 0x95}, ++{0x4268, 0xAE}, ++{0x4269, 0xA5}, ++{0x426A, 0xA7}, ++{0x426B, 0xA2}, ++{0x426C, 0xC2}, ++{0x426D, 0xB7}, ++{0x426E, 0xB8}, ++{0x426F, 0xB9}, ++{0x4270, 0xAA}, ++{0x4271, 0xA4}, ++{0x4272, 0xA4}, ++{0x4273, 0xA5}, ++{0x4274, 0x99}, ++{0x4275, 0x96}, ++{0x4276, 0x97}, ++{0x4277, 0x98}, ++{0x4278, 0x8B}, ++{0x4279, 0x8A}, ++{0x427A, 0x8A}, ++{0x427B, 0x8B}, ++{0x427C, 0x81}, ++{0x427D, 0x81}, ++{0x427E, 0x81}, ++{0x427F, 0x82}, ++{0x4280, 0x84}, ++{0x4281, 0x84}, ++{0x4282, 0x84}, ++{0x4283, 0x84}, ++{0x4284, 0x8E}, ++{0x4285, 0x8E}, ++{0x4286, 0x8D}, ++{0x4287, 0x8C}, ++{0x4288, 0x9A}, ++{0x4289, 0x97}, ++{0x428A, 0x97}, ++{0x428B, 0x95}, ++{0x428C, 0xAA}, ++{0x428D, 0xA3}, ++{0x428E, 0xA3}, ++{0x428F, 0xA2}, ++{0x4290, 0xC7}, ++{0x4291, 0xBA}, ++{0x4292, 0xC0}, ++{0x4293, 0xC3}, ++{0x4294, 0xB0}, ++{0x4295, 0xA7}, ++{0x4296, 0xA7}, ++{0x4297, 0xA9}, ++{0x4298, 0x9F}, ++{0x4299, 0x9B}, ++{0x429A, 0x9B}, ++{0x429B, 0x9D}, ++{0x429C, 0x93}, ++{0x429D, 0x91}, ++{0x429E, 0x91}, ++{0x429F, 0x92}, ++{0x42A0, 0x8C}, ++{0x42A1, 0x8B}, ++{0x42A2, 0x8B}, ++{0x42A3, 0x8C}, ++{0x42A4, 0x8D}, ++{0x42A5, 0x8C}, ++{0x42A6, 0x8C}, ++{0x42A7, 0x8C}, ++{0x42A8, 0x94}, ++{0x42A9, 0x93}, ++{0x42AA, 0x92}, ++{0x42AB, 0x91}, ++{0x42AC, 0x9E}, ++{0x42AD, 0x9B}, ++{0x42AE, 0x9B}, ++{0x42AF, 0x98}, ++{0x42B0, 0xAC}, ++{0x42B1, 0xA6}, ++{0x42B2, 0xA6}, ++{0x42B3, 0xA2}, ++{0x42B4, 0xCE}, ++{0x42B5, 0xBA}, ++{0x42B6, 0xBC}, ++{0x42B7, 0xB7}, ++{0x42B8, 0xC5}, ++{0x42B9, 0xB5}, ++{0x42BA, 0xBA}, ++{0x42BB, 0xC0}, ++{0x42BC, 0xB1}, ++{0x42BD, 0xA8}, ++{0x42BE, 0xAE}, ++{0x42BF, 0xAF}, ++{0x42C0, 0xA7}, ++{0x42C1, 0xA3}, ++{0x42C2, 0xA3}, ++{0x42C3, 0xA5}, ++{0x42C4, 0xA0}, ++{0x42C5, 0x9D}, ++{0x42C6, 0x9D}, ++{0x42C7, 0x9F}, ++{0x42C8, 0xA0}, ++{0x42C9, 0x9E}, ++{0x42CA, 0x9E}, ++{0x42CB, 0x9F}, ++{0x42CC, 0xA2}, ++{0x42CD, 0xA0}, ++{0x42CE, 0xA0}, ++{0x42CF, 0xA0}, ++{0x42D0, 0xA8}, ++{0x42D1, 0xA5}, ++{0x42D2, 0xA5}, ++{0x42D3, 0xA2}, ++{0x42D4, 0xB3}, ++{0x42D5, 0xAA}, ++{0x42D6, 0xAB}, ++{0x42D7, 0xA3}, ++{0x42D8, 0x00}, ++{0x42D9, 0x00}, ++{0x4300, 0xA2}, ++{0x4301, 0xAE}, ++{0x4302, 0xAD}, ++{0x4303, 0xB5}, ++{0x4304, 0x95}, ++{0x4305, 0x9A}, ++{0x4306, 0x98}, ++{0x4307, 0x9B}, ++{0x4308, 0x8D}, ++{0x4309, 0x90}, ++{0x430A, 0x8F}, ++{0x430B, 0x91}, ++{0x430C, 0x86}, ++{0x430D, 0x88}, ++{0x430E, 0x87}, ++{0x430F, 0x89}, ++{0x4310, 0x86}, ++{0x4311, 0x87}, ++{0x4312, 0x86}, ++{0x4313, 0x88}, ++{0x4314, 0x89}, ++{0x4315, 0x88}, ++{0x4316, 0x88}, ++{0x4317, 0x8E}, ++{0x4318, 0x90}, ++{0x4319, 0x8F}, ++{0x431A, 0x8C}, ++{0x431B, 0x8C}, ++{0x431C, 0x9C}, ++{0x431D, 0x99}, ++{0x431E, 0x98}, ++{0x431F, 0x99}, ++{0x4320, 0xAB}, ++{0x4321, 0xB0}, ++{0x4322, 0xAD}, ++{0x4323, 0xAF}, ++{0x4324, 0x9B}, ++{0x4325, 0x9F}, ++{0x4326, 0x9E}, ++{0x4327, 0xA1}, ++{0x4328, 0x8E}, ++{0x4329, 0x91}, ++{0x432A, 0x90}, ++{0x432B, 0x93}, ++{0x432C, 0x86}, ++{0x432D, 0x88}, ++{0x432E, 0x87}, ++{0x432F, 0x89}, ++{0x4330, 0x82}, ++{0x4331, 0x84}, ++{0x4332, 0x83}, ++{0x4333, 0x84}, ++{0x4334, 0x82}, ++{0x4335, 0x82}, ++{0x4336, 0x82}, ++{0x4337, 0x83}, ++{0x4338, 0x85}, ++{0x4339, 0x84}, ++{0x433A, 0x84}, ++{0x433B, 0x85}, ++{0x433C, 0x8A}, ++{0x433D, 0x89}, ++{0x433E, 0x88}, ++{0x433F, 0x89}, ++{0x4340, 0x93}, ++{0x4341, 0x91}, ++{0x4342, 0x91}, ++{0x4343, 0x93}, ++{0x4344, 0xA0}, ++{0x4345, 0x9E}, ++{0x4346, 0x9D}, ++{0x4347, 0xA1}, ++{0x4348, 0x95}, ++{0x4349, 0x9B}, ++{0x434A, 0x9A}, ++{0x434B, 0x9C}, ++{0x434C, 0x8A}, ++{0x434D, 0x8D}, ++{0x434E, 0x8C}, ++{0x434F, 0x8D}, ++{0x4350, 0x83}, ++{0x4351, 0x85}, ++{0x4352, 0x84}, ++{0x4353, 0x85}, ++{0x4354, 0x80}, ++{0x4355, 0x81}, ++{0x4356, 0x81}, ++{0x4357, 0x81}, ++{0x4358, 0x80}, ++{0x4359, 0x80}, ++{0x435A, 0x80}, ++{0x435B, 0x80}, ++{0x435C, 0x82}, ++{0x435D, 0x81}, ++{0x435E, 0x81}, ++{0x435F, 0x81}, ++{0x4360, 0x85}, ++{0x4361, 0x84}, ++{0x4362, 0x84}, ++{0x4363, 0x85}, ++{0x4364, 0x8D}, ++{0x4365, 0x8B}, ++{0x4366, 0x8B}, ++{0x4367, 0x8D}, ++{0x4368, 0x98}, ++{0x4369, 0x98}, ++{0x436A, 0x95}, ++{0x436B, 0x98}, ++{0x436C, 0x95}, ++{0x436D, 0x9A}, ++{0x436E, 0x99}, ++{0x436F, 0x9A}, ++{0x4370, 0x8A}, ++{0x4371, 0x8D}, ++{0x4372, 0x8C}, ++{0x4373, 0x8C}, ++{0x4374, 0x83}, ++{0x4375, 0x85}, ++{0x4376, 0x84}, ++{0x4377, 0x84}, ++{0x4378, 0x80}, ++{0x4379, 0x80}, ++{0x437A, 0x80}, ++{0x437B, 0x80}, ++{0x437C, 0x7F}, ++{0x437D, 0x7F}, ++{0x437E, 0x7F}, ++{0x437F, 0x7F}, ++{0x4380, 0x81}, ++{0x4381, 0x80}, ++{0x4382, 0x80}, ++{0x4383, 0x81}, ++{0x4384, 0x84}, ++{0x4385, 0x83}, ++{0x4386, 0x83}, ++{0x4387, 0x84}, ++{0x4388, 0x8B}, ++{0x4389, 0x8A}, ++{0x438A, 0x8A}, ++{0x438B, 0x8C}, ++{0x438C, 0x97}, ++{0x438D, 0x96}, ++{0x438E, 0x96}, ++{0x438F, 0x99}, ++{0x4390, 0x99}, ++{0x4391, 0x9F}, ++{0x4392, 0x9E}, ++{0x4393, 0x9D}, ++{0x4394, 0x8D}, ++{0x4395, 0x90}, ++{0x4396, 0x90}, ++{0x4397, 0x8F}, ++{0x4398, 0x85}, ++{0x4399, 0x87}, ++{0x439A, 0x87}, ++{0x439B, 0x86}, ++{0x439C, 0x81}, ++{0x439D, 0x83}, ++{0x439E, 0x82}, ++{0x439F, 0x82}, ++{0x43A0, 0x80}, ++{0x43A1, 0x81}, ++{0x43A2, 0x81}, ++{0x43A3, 0x81}, ++{0x43A4, 0x82}, ++{0x43A5, 0x82}, ++{0x43A6, 0x82}, ++{0x43A7, 0x82}, ++{0x43A8, 0x86}, ++{0x43A9, 0x85}, ++{0x43AA, 0x85}, ++{0x43AB, 0x87}, ++{0x43AC, 0x8D}, ++{0x43AD, 0x8D}, ++{0x43AE, 0x8D}, ++{0x43AF, 0x90}, ++{0x43B0, 0x9A}, ++{0x43B1, 0x9A}, ++{0x43B2, 0x9B}, ++{0x43B3, 0x9D}, ++{0x43B4, 0xA0}, ++{0x43B5, 0xAD}, ++{0x43B6, 0xAC}, ++{0x43B7, 0xAA}, ++{0x43B8, 0x93}, ++{0x43B9, 0x97}, ++{0x43BA, 0x97}, ++{0x43BB, 0x96}, ++{0x43BC, 0x8B}, ++{0x43BD, 0x8E}, ++{0x43BE, 0x8E}, ++{0x43BF, 0x8C}, ++{0x43C0, 0x83}, ++{0x43C1, 0x85}, ++{0x43C2, 0x85}, ++{0x43C3, 0x84}, ++{0x43C4, 0x82}, ++{0x43C5, 0x84}, ++{0x43C6, 0x83}, ++{0x43C7, 0x83}, ++{0x43C8, 0x83}, ++{0x43C9, 0x84}, ++{0x43CA, 0x84}, ++{0x43CB, 0x85}, ++{0x43CC, 0x8A}, ++{0x43CD, 0x8A}, ++{0x43CE, 0x8A}, ++{0x43CF, 0x8C}, ++{0x43D0, 0x92}, ++{0x43D1, 0x93}, ++{0x43D2, 0x93}, ++{0x43D3, 0x96}, ++{0x43D4, 0x9F}, ++{0x43D5, 0xA6}, ++{0x43D6, 0xA5}, ++{0x43D7, 0xAA}, ++{0x4400, 0xA1}, ++{0x4401, 0xAB}, ++{0x4402, 0xA7}, ++{0x4403, 0xB0}, ++{0x4404, 0x91}, ++{0x4405, 0x96}, ++{0x4406, 0x94}, ++{0x4407, 0x99}, ++{0x4408, 0x8A}, ++{0x4409, 0x8E}, ++{0x440A, 0x8C}, ++{0x440B, 0x8F}, ++{0x440C, 0x85}, ++{0x440D, 0x86}, ++{0x440E, 0x86}, ++{0x440F, 0x88}, ++{0x4410, 0x85}, ++{0x4411, 0x86}, ++{0x4412, 0x85}, ++{0x4413, 0x87}, ++{0x4414, 0x88}, ++{0x4415, 0x87}, ++{0x4416, 0x87}, ++{0x4417, 0x89}, ++{0x4418, 0x91}, ++{0x4419, 0x8F}, ++{0x441A, 0x8F}, ++{0x441B, 0x90}, ++{0x441C, 0x9C}, ++{0x441D, 0x9B}, ++{0x441E, 0x9A}, ++{0x441F, 0x9A}, ++{0x4420, 0xB3}, ++{0x4421, 0xB1}, ++{0x4422, 0xB0}, ++{0x4423, 0xB2}, ++{0x4424, 0x96}, ++{0x4425, 0x9C}, ++{0x4426, 0x9A}, ++{0x4427, 0x9E}, ++{0x4428, 0x8B}, ++{0x4429, 0x8F}, ++{0x442A, 0x8E}, ++{0x442B, 0x91}, ++{0x442C, 0x84}, ++{0x442D, 0x87}, ++{0x442E, 0x86}, ++{0x442F, 0x88}, ++{0x4430, 0x82}, ++{0x4431, 0x83}, ++{0x4432, 0x82}, ++{0x4433, 0x84}, ++{0x4434, 0x82}, ++{0x4435, 0x82}, ++{0x4436, 0x82}, ++{0x4437, 0x83}, ++{0x4438, 0x84}, ++{0x4439, 0x84}, ++{0x443A, 0x84}, ++{0x443B, 0x84}, ++{0x443C, 0x8B}, ++{0x443D, 0x89}, ++{0x443E, 0x89}, ++{0x443F, 0x89}, ++{0x4440, 0x95}, ++{0x4441, 0x93}, ++{0x4442, 0x93}, ++{0x4443, 0x93}, ++{0x4444, 0xA2}, ++{0x4445, 0xA2}, ++{0x4446, 0xA1}, ++{0x4447, 0xA0}, ++{0x4448, 0x8F}, ++{0x4449, 0x97}, ++{0x444A, 0x97}, ++{0x444B, 0x98}, ++{0x444C, 0x87}, ++{0x444D, 0x8B}, ++{0x444E, 0x8A}, ++{0x444F, 0x8B}, ++{0x4450, 0x81}, ++{0x4451, 0x83}, ++{0x4452, 0x83}, ++{0x4453, 0x84}, ++{0x4454, 0x7F}, ++{0x4455, 0x80}, ++{0x4456, 0x80}, ++{0x4457, 0x81}, ++{0x4458, 0x80}, ++{0x4459, 0x80}, ++{0x445A, 0x80}, ++{0x445B, 0x80}, ++{0x445C, 0x82}, ++{0x445D, 0x81}, ++{0x445E, 0x81}, ++{0x445F, 0x81}, ++{0x4460, 0x87}, ++{0x4461, 0x85}, ++{0x4462, 0x85}, ++{0x4463, 0x86}, ++{0x4464, 0x90}, ++{0x4465, 0x8E}, ++{0x4466, 0x8E}, ++{0x4467, 0x8E}, ++{0x4468, 0x9B}, ++{0x4469, 0x9C}, ++{0x446A, 0x9A}, ++{0x446B, 0x9A}, ++{0x446C, 0x91}, ++{0x446D, 0x97}, ++{0x446E, 0x95}, ++{0x446F, 0x95}, ++{0x4470, 0x87}, ++{0x4471, 0x8A}, ++{0x4472, 0x8A}, ++{0x4473, 0x89}, ++{0x4474, 0x81}, ++{0x4475, 0x83}, ++{0x4476, 0x83}, ++{0x4477, 0x83}, ++{0x4478, 0x7F}, ++{0x4479, 0x80}, ++{0x447A, 0x80}, ++{0x447B, 0x80}, ++{0x447C, 0x80}, ++{0x447D, 0x80}, ++{0x447E, 0x80}, ++{0x447F, 0x7F}, ++{0x4480, 0x81}, ++{0x4481, 0x81}, ++{0x4482, 0x81}, ++{0x4483, 0x81}, ++{0x4484, 0x85}, ++{0x4485, 0x85}, ++{0x4486, 0x85}, ++{0x4487, 0x85}, ++{0x4488, 0x8E}, ++{0x4489, 0x8D}, ++{0x448A, 0x8D}, ++{0x448B, 0x8E}, ++{0x448C, 0x9D}, ++{0x448D, 0x9C}, ++{0x448E, 0x9C}, ++{0x448F, 0x9C}, ++{0x4490, 0x94}, ++{0x4491, 0x9B}, ++{0x4492, 0x9A}, ++{0x4493, 0x97}, ++{0x4494, 0x8A}, ++{0x4495, 0x8E}, ++{0x4496, 0x8E}, ++{0x4497, 0x8C}, ++{0x4498, 0x84}, ++{0x4499, 0x86}, ++{0x449A, 0x86}, ++{0x449B, 0x84}, ++{0x449C, 0x81}, ++{0x449D, 0x83}, ++{0x449E, 0x83}, ++{0x449F, 0x81}, ++{0x44A0, 0x81}, ++{0x44A1, 0x82}, ++{0x44A2, 0x82}, ++{0x44A3, 0x81}, ++{0x44A4, 0x83}, ++{0x44A5, 0x83}, ++{0x44A6, 0x83}, ++{0x44A7, 0x83}, ++{0x44A8, 0x88}, ++{0x44A9, 0x88}, ++{0x44AA, 0x88}, ++{0x44AB, 0x88}, ++{0x44AC, 0x91}, ++{0x44AD, 0x91}, ++{0x44AE, 0x91}, ++{0x44AF, 0x92}, ++{0x44B0, 0xA0}, ++{0x44B1, 0xA0}, ++{0x44B2, 0xA0}, ++{0x44B3, 0xA0}, ++{0x44B4, 0x9E}, ++{0x44B5, 0xA9}, ++{0x44B6, 0xA8}, ++{0x44B7, 0xA3}, ++{0x44B8, 0x90}, ++{0x44B9, 0x95}, ++{0x44BA, 0x95}, ++{0x44BB, 0x92}, ++{0x44BC, 0x8A}, ++{0x44BD, 0x8E}, ++{0x44BE, 0x8E}, ++{0x44BF, 0x8B}, ++{0x44C0, 0x84}, ++{0x44C1, 0x86}, ++{0x44C2, 0x86}, ++{0x44C3, 0x84}, ++{0x44C4, 0x84}, ++{0x44C5, 0x85}, ++{0x44C6, 0x85}, ++{0x44C7, 0x84}, ++{0x44C8, 0x86}, ++{0x44C9, 0x87}, ++{0x44CA, 0x87}, ++{0x44CB, 0x86}, ++{0x44CC, 0x8D}, ++{0x44CD, 0x8E}, ++{0x44CE, 0x8E}, ++{0x44CF, 0x8D}, ++{0x44D0, 0x98}, ++{0x44D1, 0x98}, ++{0x44D2, 0x99}, ++{0x44D3, 0x9A}, ++{0x44D4, 0xA9}, ++{0x44D5, 0xAA}, ++{0x44D6, 0xAA}, ++{0x44D7, 0xAD}, ++{0x4500, 0x9F}, ++{0x4501, 0xA8}, ++{0x4502, 0xA5}, ++{0x4503, 0xAF}, ++{0x4504, 0x8F}, ++{0x4505, 0x96}, ++{0x4506, 0x92}, ++{0x4507, 0x94}, ++{0x4508, 0x89}, ++{0x4509, 0x8D}, ++{0x450A, 0x8A}, ++{0x450B, 0x8E}, ++{0x450C, 0x84}, ++{0x450D, 0x85}, ++{0x450E, 0x84}, ++{0x450F, 0x87}, ++{0x4510, 0x84}, ++{0x4511, 0x85}, ++{0x4512, 0x84}, ++{0x4513, 0x86}, ++{0x4514, 0x87}, ++{0x4515, 0x86}, ++{0x4516, 0x86}, ++{0x4517, 0x88}, ++{0x4518, 0x8F}, ++{0x4519, 0x8D}, ++{0x451A, 0x8D}, ++{0x451B, 0x8F}, ++{0x451C, 0x9A}, ++{0x451D, 0x9A}, ++{0x451E, 0x98}, ++{0x451F, 0x9A}, ++{0x4520, 0xAF}, ++{0x4521, 0xAF}, ++{0x4522, 0xB2}, ++{0x4523, 0xB1}, ++{0x4524, 0x95}, ++{0x4525, 0x9B}, ++{0x4526, 0x97}, ++{0x4527, 0x9C}, ++{0x4528, 0x8A}, ++{0x4529, 0x8E}, ++{0x452A, 0x8D}, ++{0x452B, 0x90}, ++{0x452C, 0x84}, ++{0x452D, 0x86}, ++{0x452E, 0x85}, ++{0x452F, 0x87}, ++{0x4530, 0x81}, ++{0x4531, 0x82}, ++{0x4532, 0x82}, ++{0x4533, 0x83}, ++{0x4534, 0x81}, ++{0x4535, 0x81}, ++{0x4536, 0x81}, ++{0x4537, 0x82}, ++{0x4538, 0x84}, ++{0x4539, 0x83}, ++{0x453A, 0x83}, ++{0x453B, 0x84}, ++{0x453C, 0x8A}, ++{0x453D, 0x88}, ++{0x453E, 0x88}, ++{0x453F, 0x89}, ++{0x4540, 0x94}, ++{0x4541, 0x92}, ++{0x4542, 0x91}, ++{0x4543, 0x92}, ++{0x4544, 0xA1}, ++{0x4545, 0xA0}, ++{0x4546, 0x9C}, ++{0x4547, 0x9D}, ++{0x4548, 0x8F}, ++{0x4549, 0x96}, ++{0x454A, 0x95}, ++{0x454B, 0x92}, ++{0x454C, 0x87}, ++{0x454D, 0x8A}, ++{0x454E, 0x89}, ++{0x454F, 0x8A}, ++{0x4550, 0x81}, ++{0x4551, 0x83}, ++{0x4552, 0x82}, ++{0x4553, 0x83}, ++{0x4554, 0x7F}, ++{0x4555, 0x80}, ++{0x4556, 0x80}, ++{0x4557, 0x81}, ++{0x4558, 0x7F}, ++{0x4559, 0x80}, ++{0x455A, 0x7F}, ++{0x455B, 0x80}, ++{0x455C, 0x81}, ++{0x455D, 0x81}, ++{0x455E, 0x81}, ++{0x455F, 0x81}, ++{0x4560, 0x86}, ++{0x4561, 0x85}, ++{0x4562, 0x85}, ++{0x4563, 0x85}, ++{0x4564, 0x8F}, ++{0x4565, 0x8D}, ++{0x4566, 0x8D}, ++{0x4567, 0x8D}, ++{0x4568, 0x99}, ++{0x4569, 0x9A}, ++{0x456A, 0x97}, ++{0x456B, 0x99}, ++{0x456C, 0x90}, ++{0x456D, 0x95}, ++{0x456E, 0x93}, ++{0x456F, 0x92}, ++{0x4570, 0x87}, ++{0x4571, 0x8A}, ++{0x4572, 0x88}, ++{0x4573, 0x87}, ++{0x4574, 0x81}, ++{0x4575, 0x83}, ++{0x4576, 0x82}, ++{0x4577, 0x82}, ++{0x4578, 0x7F}, ++{0x4579, 0x80}, ++{0x457A, 0x80}, ++{0x457B, 0x80}, ++{0x457C, 0x80}, ++{0x457D, 0x80}, ++{0x457E, 0x80}, ++{0x457F, 0x80}, ++{0x4580, 0x81}, ++{0x4581, 0x81}, ++{0x4582, 0x81}, ++{0x4583, 0x81}, ++{0x4584, 0x85}, ++{0x4585, 0x85}, ++{0x4586, 0x84}, ++{0x4587, 0x85}, ++{0x4588, 0x8E}, ++{0x4589, 0x8D}, ++{0x458A, 0x8C}, ++{0x458B, 0x8D}, ++{0x458C, 0x9B}, ++{0x458D, 0x9B}, ++{0x458E, 0x9A}, ++{0x458F, 0x98}, ++{0x4590, 0x94}, ++{0x4591, 0x9A}, ++{0x4592, 0x94}, ++{0x4593, 0x90}, ++{0x4594, 0x8A}, ++{0x4595, 0x8D}, ++{0x4596, 0x8C}, ++{0x4597, 0x89}, ++{0x4598, 0x84}, ++{0x4599, 0x86}, ++{0x459A, 0x85}, ++{0x459B, 0x83}, ++{0x459C, 0x82}, ++{0x459D, 0x83}, ++{0x459E, 0x82}, ++{0x459F, 0x80}, ++{0x45A0, 0x81}, ++{0x45A1, 0x82}, ++{0x45A2, 0x81}, ++{0x45A3, 0x80}, ++{0x45A4, 0x83}, ++{0x45A5, 0x83}, ++{0x45A6, 0x83}, ++{0x45A7, 0x83}, ++{0x45A8, 0x88}, ++{0x45A9, 0x87}, ++{0x45AA, 0x87}, ++{0x45AB, 0x88}, ++{0x45AC, 0x91}, ++{0x45AD, 0x90}, ++{0x45AE, 0x90}, ++{0x45AF, 0x91}, ++{0x45B0, 0x9F}, ++{0x45B1, 0x9F}, ++{0x45B2, 0x9E}, ++{0x45B3, 0x9F}, ++{0x45B4, 0x9F}, ++{0x45B5, 0xA8}, ++{0x45B6, 0xA6}, ++{0x45B7, 0xA7}, ++{0x45B8, 0x8D}, ++{0x45B9, 0x95}, ++{0x45BA, 0x90}, ++{0x45BB, 0x8A}, ++{0x45BC, 0x89}, ++{0x45BD, 0x8D}, ++{0x45BE, 0x88}, ++{0x45BF, 0x86}, ++{0x45C0, 0x84}, ++{0x45C1, 0x86}, ++{0x45C2, 0x85}, ++{0x45C3, 0x82}, ++{0x45C4, 0x84}, ++{0x45C5, 0x85}, ++{0x45C6, 0x85}, ++{0x45C7, 0x83}, ++{0x45C8, 0x86}, ++{0x45C9, 0x86}, ++{0x45CA, 0x86}, ++{0x45CB, 0x85}, ++{0x45CC, 0x8E}, ++{0x45CD, 0x8D}, ++{0x45CE, 0x8D}, ++{0x45CF, 0x8C}, ++{0x45D0, 0x99}, ++{0x45D1, 0x98}, ++{0x45D2, 0x98}, ++{0x45D3, 0x98}, ++{0x45D4, 0xA6}, ++{0x45D5, 0xA9}, ++{0x45D6, 0xA7}, ++{0x45D7, 0xAC}, ++{0x7000, 0xAB}, ++{0x7001, 0xBA}, ++{0x7002, 0x40}, ++{0x7003, 0x02}, ++{0x7004, 0x00}, ++{0x7005, 0x00}, ++{0x7006, 0x00}, ++{0x7007, 0x00}, ++{0x7008, 0x00}, ++{0x7009, 0x00}, ++{0x700A, 0x00}, ++{0x700B, 0x00}, ++{0x700C, 0x00}, ++{0x700D, 0x00}, ++{0x700E, 0x00}, ++{0x700F, 0x00}, ++{0x7010, 0x55}, ++{0x7011, 0x88}, ++{0x7012, 0x40}, ++{0x7013, 0x01}, ++{0x7014, 0x72}, ++{0x7015, 0xF1}, ++{0x7016, 0x02}, ++{0x7017, 0xF8}, ++{0x7018, 0x00}, ++{0x7019, 0x00}, ++{0x701A, 0x00}, ++{0x701B, 0x00}, ++{0x701C, 0x00}, ++{0x701D, 0x00}, ++{0x701E, 0x00}, ++{0x701F, 0x00}, ++{0x7020, 0x00}, ++{0x7021, 0x00}, ++{0x7022, 0x00}, ++{0x7023, 0x00}, ++{0x7024, 0x00}, ++{0x7025, 0x00}, ++{0x7026, 0x00}, ++{0x7027, 0x00}, ++{0x7028, 0x00}, ++{0x7029, 0x00}, ++{0x702A, 0x00}, ++{0x702B, 0x00}, ++{0x702C, 0x00}, ++{0x702D, 0x00}, ++{0x702E, 0x00}, ++{0x702F, 0x00}, ++{0x7030, 0x00}, ++{0x7031, 0x00}, ++{0x7032, 0x00}, ++{0x7033, 0x00}, ++{0x7034, 0x00}, ++{0x7035, 0x00}, ++{0x7036, 0x00}, ++{0x7037, 0x00}, ++{0x7038, 0x00}, ++{0x7039, 0x00}, ++{0x703A, 0x00}, ++{0x703B, 0x00}, ++{0x703C, 0x00}, ++{0x703D, 0x00}, ++{0x703E, 0x00}, ++{0x703F, 0x00}, ++{0x7040, 0x00}, ++{0x7041, 0x00}, ++{0x7042, 0x00}, ++{0x7043, 0x00}, ++{0x7044, 0x00}, ++{0x7045, 0x00}, ++{0x7046, 0x00}, ++{0x7047, 0x00}, ++{0x7048, 0x00}, ++{0x7049, 0x00}, ++{0x704A, 0x00}, ++{0x704B, 0x00}, ++{0x704C, 0x00}, ++{0x704D, 0x00}, ++{0x704E, 0x00}, ++{0x704F, 0x00}, ++{0x7050, 0x00}, ++{0x7051, 0x00}, ++{0x7052, 0x00}, ++{0x7053, 0x00}, ++{0x7054, 0x00}, ++{0x7055, 0x00}, ++{0x7056, 0x00}, ++{0x7057, 0x00}, ++{0x7058, 0x00}, ++{0x7059, 0x00}, ++{0x705A, 0x00}, ++{0x705B, 0x00}, ++{0x705C, 0x00}, ++{0x705D, 0x00}, ++{0x705E, 0x00}, ++{0x705F, 0x00}, ++{0x7060, 0x00}, ++{0x7061, 0x00}, ++{0x7062, 0x00}, ++{0x7063, 0x00}, ++{0x7064, 0x00}, ++{0x7065, 0x00}, ++{0x7066, 0x00}, ++{0x7067, 0x00}, ++{0x7068, 0x00}, ++{0x7069, 0x00}, ++{0x706A, 0x00}, ++{0x706B, 0x00}, ++{0x706C, 0x00}, ++{0x706D, 0x00}, ++{0x706E, 0x00}, ++{0x706F, 0x00}, ++{0x7070, 0x00}, ++{0x7071, 0x00}, ++{0x7072, 0x00}, ++{0x7073, 0x00}, ++{0x7074, 0x00}, ++{0x7075, 0x00}, ++{0x7076, 0x00}, ++{0x7077, 0x00}, ++{0x7078, 0x00}, ++{0x7079, 0x00}, ++{0x707A, 0x00}, ++{0x707B, 0x00}, ++{0x707C, 0x00}, ++{0x707D, 0x00}, ++{0x707E, 0x00}, ++{0x707F, 0x00}, ++{0x7080, 0x00}, ++{0x7081, 0x00}, ++{0x7082, 0x00}, ++{0x7083, 0x00}, ++{0x7084, 0x00}, ++{0x7085, 0x00}, ++{0x7086, 0x00}, ++{0x7087, 0x00}, ++{0x7088, 0x00}, ++{0x7089, 0x00}, ++{0x708A, 0x00}, ++{0x708B, 0x00}, ++{0x708C, 0x00}, ++{0x708D, 0x00}, ++{0x708E, 0x00}, ++{0x708F, 0x00}, ++{0x7090, 0x00}, ++{0x7091, 0xF0}, ++{0x7092, 0x02}, ++{0x7093, 0xF8}, ++{0x7094, 0x8D}, ++{0x7095, 0xF6}, ++{0x7096, 0xFA}, ++{0x7097, 0xFF}, ++{0x7098, 0xF0}, ++{0x7099, 0xB5}, ++{0x709A, 0x04}, ++{0x709B, 0x46}, ++{0x709C, 0x8F}, ++{0x709D, 0xB0}, ++{0x709E, 0x5F}, ++{0x709F, 0x48}, ++{0x70A0, 0x0C}, ++{0x70A1, 0x90}, ++{0x70A2, 0x5F}, ++{0x70A3, 0x48}, ++{0x70A4, 0x06}, ++{0x70A5, 0x90}, ++{0x70A6, 0x20}, ++{0x70A7, 0x46}, ++{0x70A8, 0x34}, ++{0x70A9, 0x30}, ++{0x70AA, 0x0B}, ++{0x70AB, 0x90}, ++{0x70AC, 0x5B}, ++{0x70AD, 0x48}, ++{0x70AE, 0x5A}, ++{0x70AF, 0x49}, ++{0x70B0, 0x26}, ++{0x70B1, 0x46}, ++{0x70B2, 0x66}, ++{0x70B3, 0x30}, ++{0x70B4, 0x3A}, ++{0x70B5, 0x31}, ++{0x70B6, 0x3C}, ++{0x70B7, 0x36}, ++{0x70B8, 0x05}, ++{0x70B9, 0x90}, ++{0x70BA, 0x0A}, ++{0x70BB, 0x30}, ++{0x70BC, 0x04}, ++{0x70BD, 0x90}, ++{0x70BE, 0x59}, ++{0x70BF, 0x48}, ++{0x70C0, 0x55}, ++{0x70C1, 0x4A}, ++{0x70C2, 0x40}, ++{0x70C3, 0x6E}, ++{0x70C4, 0xC0}, ++{0x70C5, 0x07}, ++{0x70C6, 0x7D}, ++{0x70C7, 0xD1}, ++{0x70C8, 0x17}, ++{0x70C9, 0x88}, ++{0x70CA, 0x0A}, ++{0x70CB, 0x5E}, ++{0x70CC, 0x0D}, ++{0x70CD, 0x92}, ++{0x70CE, 0x53}, ++{0x70CF, 0x49}, ++{0x70D0, 0x55}, ++{0x70D1, 0x48}, ++{0x70D2, 0x94}, ++{0x70D3, 0x31}, ++{0x70D4, 0x89}, ++{0x70D5, 0x6B}, ++{0x70D6, 0x80}, ++{0x70D7, 0x68}, ++{0x70D8, 0x09}, ++{0x70D9, 0x02}, ++{0x70DA, 0x00}, ++{0x70DB, 0x03}, ++{0x70DC, 0x09}, ++{0x70DD, 0x0E}, ++{0x70DE, 0x00}, ++{0x70DF, 0x0B}, ++{0x70E0, 0x49}, ++{0x70E1, 0x1C}, ++{0x70E2, 0x48}, ++{0x70E3, 0x43}, ++{0x70E4, 0x4D}, ++{0x70E5, 0x49}, ++{0x70E6, 0x6C}, ++{0x70E7, 0x39}, ++{0x70E8, 0x8A}, ++{0x70E9, 0x6A}, ++{0x70EA, 0x07}, ++{0x70EB, 0x92}, ++{0x70EC, 0xCA}, ++{0x70ED, 0x6A}, ++{0x70EE, 0x00}, ++{0x70EF, 0x21}, ++{0x70F0, 0xC9}, ++{0x70F1, 0x43}, ++{0x70F2, 0x03}, ++{0x70F3, 0x92}, ++{0x70F4, 0x00}, ++{0x70F5, 0x22}, ++{0x70F6, 0x00}, ++{0x70F7, 0x91}, ++{0x70F8, 0x01}, ++{0x70F9, 0x92}, ++{0x70FA, 0x39}, ++{0x70FB, 0x46}, ++{0x70FC, 0x8F}, ++{0x70FD, 0xF6}, ++{0x70FE, 0xCE}, ++{0x70FF, 0xFB}, ++{0x7100, 0x01}, ++{0x7101, 0x22}, ++{0x7102, 0x00}, ++{0x7103, 0x23}, ++{0x7104, 0x8C}, ++{0x7105, 0xF6}, ++{0x7106, 0x02}, ++{0x7107, 0xFA}, ++{0x7108, 0x00}, ++{0x7109, 0x21}, ++{0x710A, 0x05}, ++{0x710B, 0x46}, ++{0x710C, 0x01}, ++{0x710D, 0x91}, ++{0x710E, 0x00}, ++{0x710F, 0x90}, ++{0x7110, 0x39}, ++{0x7111, 0x46}, ++{0x7112, 0x07}, ++{0x7113, 0x98}, ++{0x7114, 0x8F}, ++{0x7115, 0xF6}, ++{0x7116, 0xC2}, ++{0x7117, 0xFB}, ++{0x7118, 0x0D}, ++{0x7119, 0x9A}, ++{0x711A, 0xD3}, ++{0x711B, 0x17}, ++{0x711C, 0x80}, ++{0x711D, 0x18}, ++{0x711E, 0x59}, ++{0x711F, 0x41}, ++{0x7120, 0x01}, ++{0x7121, 0x22}, ++{0x7122, 0x00}, ++{0x7123, 0x23}, ++{0x7124, 0x8C}, ++{0x7125, 0xF6}, ++{0x7126, 0xCD}, ++{0x7127, 0xF9}, ++{0x7128, 0x07}, ++{0x7129, 0x90}, ++{0x712A, 0x00}, ++{0x712B, 0x20}, ++{0x712C, 0x01}, ++{0x712D, 0x90}, ++{0x712E, 0x00}, ++{0x712F, 0x95}, ++{0x7130, 0x39}, ++{0x7131, 0x46}, ++{0x7132, 0x03}, ++{0x7133, 0x98}, ++{0x7134, 0x8F}, ++{0x7135, 0xF6}, ++{0x7136, 0xB2}, ++{0x7137, 0xFB}, ++{0x7138, 0x01}, ++{0x7139, 0x22}, ++{0x713A, 0x00}, ++{0x713B, 0x23}, ++{0x713C, 0x8C}, ++{0x713D, 0xF6}, ++{0x713E, 0xE6}, ++{0x713F, 0xF9}, ++{0x7140, 0x02}, ++{0x7141, 0x46}, ++{0x7142, 0x07}, ++{0x7143, 0x98}, ++{0x7144, 0x00}, ++{0x7145, 0x23}, ++{0x7146, 0x81}, ++{0x7147, 0x0B}, ++{0x7148, 0x80}, ++{0x7149, 0x04}, ++{0x714A, 0x7A}, ++{0x714B, 0xF6}, ++{0x714C, 0x54}, ++{0x714D, 0xF8}, ++{0x714E, 0x37}, ++{0x714F, 0x4A}, ++{0x7150, 0x00}, ++{0x7151, 0x23}, ++{0x7152, 0x00}, ++{0x7153, 0x92}, ++{0x7154, 0x01}, ++{0x7155, 0x93}, ++{0x7156, 0x01}, ++{0x7157, 0x22}, ++{0x7158, 0x8C}, ++{0x7159, 0xF6}, ++{0x715A, 0xD8}, ++{0x715B, 0xF9}, ++{0x715C, 0x05}, ++{0x715D, 0x46}, ++{0x715E, 0x60}, ++{0x715F, 0x68}, ++{0x7160, 0x00}, ++{0x7161, 0x23}, ++{0x7162, 0x01}, ++{0x7163, 0x0C}, ++{0x7164, 0x00}, ++{0x7165, 0x04}, ++{0x7166, 0xE2}, ++{0x7167, 0x68}, ++{0x7168, 0x7A}, ++{0x7169, 0xF6}, ++{0x716A, 0x45}, ++{0x716B, 0xF8}, ++{0x716C, 0x00}, ++{0x716D, 0x22}, ++{0x716E, 0xD2}, ++{0x716F, 0x43}, ++{0x7170, 0x00}, ++{0x7171, 0x23}, ++{0x7172, 0x00}, ++{0x7173, 0x92}, ++{0x7174, 0x01}, ++{0x7175, 0x93}, ++{0x7176, 0x1A}, ++{0x7177, 0x46}, ++{0x7178, 0x8C}, ++{0x7179, 0xF6}, ++{0x717A, 0xC8}, ++{0x717B, 0xF9}, ++{0x717C, 0x29}, ++{0x717D, 0x46}, ++{0x717E, 0x8F}, ++{0x717F, 0xF6}, ++{0x7180, 0x8D}, ++{0x7181, 0xFB}, ++{0x7182, 0x8A}, ++{0x7183, 0x03}, ++{0x7184, 0x80}, ++{0x7185, 0x0C}, ++{0x7186, 0x10}, ++{0x7187, 0x43}, ++{0x7188, 0x00}, ++{0x7189, 0x22}, ++{0x718A, 0xD2}, ++{0x718B, 0x43}, ++{0x718C, 0x00}, ++{0x718D, 0x23}, ++{0x718E, 0x00}, ++{0x718F, 0x92}, ++{0x7190, 0x89}, ++{0x7191, 0x0C}, ++{0x7192, 0x01}, ++{0x7193, 0x93}, ++{0x7194, 0x1A}, ++{0x7195, 0x46}, ++{0x7196, 0x8C}, ++{0x7197, 0xF6}, ++{0x7198, 0xB9}, ++{0x7199, 0xF9}, ++{0x719A, 0x00}, ++{0x719B, 0x24}, ++{0x719C, 0x03}, ++{0x719D, 0x90}, ++{0x719E, 0x0C}, ++{0x719F, 0x98}, ++{0x71A0, 0x61}, ++{0x71A1, 0x00}, ++{0x71A2, 0x45}, ++{0x71A3, 0x5A}, ++{0x71A4, 0x06}, ++{0x71A5, 0x98}, ++{0x71A6, 0x22}, ++{0x71A7, 0x4A}, ++{0x71A8, 0x40}, ++{0x71A9, 0x5A}, ++{0x71AA, 0x00}, ++{0x71AB, 0x21}, ++{0x71AC, 0x8C}, ++{0x71AD, 0xF6}, ++{0x71AE, 0xBE}, ++{0x71AF, 0xF9}, ++{0x71B0, 0x07}, ++{0x71B1, 0x46}, ++{0x71B2, 0x28}, ++{0x71B3, 0x46}, ++{0x71B4, 0x03}, ++{0x71B5, 0x99}, ++{0x71B6, 0x8F}, ++{0x71B7, 0xF6}, ++{0x71B8, 0x71}, ++{0x71B9, 0xFB}, ++{0x71BA, 0x3A}, ++{0x71BB, 0x46}, ++{0x71BC, 0x00}, ++{0x71BD, 0x23}, ++{0x71BE, 0x79}, ++{0x71BF, 0xF6}, ++{0x71C0, 0xCA}, ++{0x71C1, 0xFF}, ++{0x71C2, 0x00}, ++{0x71C3, 0xE0}, ++{0x71C4, 0x0F}, ++{0x71C5, 0xE0}, ++{0x71C6, 0x8A}, ++{0x71C7, 0x02}, ++{0x71C8, 0x80}, ++{0x71C9, 0x0D}, ++{0x71CA, 0x10}, ++{0x71CB, 0x43}, ++{0x71CC, 0x19}, ++{0x71CD, 0x4A}, ++{0x71CE, 0x00}, ++{0x71CF, 0x23}, ++{0x71D0, 0x00}, ++{0x71D1, 0x92}, ++{0x71D2, 0x89}, ++{0x71D3, 0x0D}, ++{0x71D4, 0x01}, ++{0x71D5, 0x93}, ++{0x71D6, 0x40}, ++{0x71D7, 0x22}, ++{0x71D8, 0x8C}, ++{0x71D9, 0xF6}, ++{0x71DA, 0x98}, ++{0x71DB, 0xF9}, ++{0x71DC, 0xA1}, ++{0x71DD, 0x00}, ++{0x71DE, 0x64}, ++{0x71DF, 0x1C}, ++{0x71E0, 0x70}, ++{0x71E1, 0x50}, ++{0x71E2, 0x04}, ++{0x71E3, 0x2C}, ++{0x71E4, 0xDB}, ++{0x71E5, 0xD3}, ++{0x71E6, 0x14}, ++{0x71E7, 0x4D}, ++{0x71E8, 0x00}, ++{0x71E9, 0x24}, ++{0x71EA, 0x0B}, ++{0x71EB, 0x98}, ++{0x71EC, 0x67}, ++{0x71ED, 0x00}, ++{0x71EE, 0xC0}, ++{0x71EF, 0x5B}, ++{0x71F0, 0x2A}, ++{0x71F1, 0x46}, ++{0x71F2, 0x40}, ++{0x71F3, 0x21}, ++{0x71F4, 0x8C}, ++{0x71F5, 0xF6}, ++{0x71F6, 0x9A}, ++{0x71F7, 0xF9}, ++{0x71F8, 0x05}, ++{0x71F9, 0x99}, ++{0x71FA, 0x0E}, ++{0x71FB, 0x4A}, ++{0x71FC, 0xC8}, ++{0x71FD, 0x53}, ++{0x71FE, 0xA7}, ++{0x71FF, 0x00}, ++{0x7200, 0xF0}, ++{0x7201, 0x59}, ++{0x7202, 0x40}, ++{0x7203, 0x21}, ++{0x7204, 0x8C}, ++{0x7205, 0xF6}, ++{0x7206, 0x7B}, ++{0x7207, 0xF9}, ++{0x7208, 0x04}, ++{0x7209, 0x99}, ++{0x720A, 0x64}, ++{0x720B, 0x1C}, ++{0x720C, 0xC8}, ++{0x720D, 0x51}, ++{0x720E, 0x04}, ++{0x720F, 0x2C}, ++{0x7210, 0xEB}, ++{0x7211, 0xD3}, ++{0x7212, 0x0F}, ++{0x7213, 0xB0}, ++{0x7214, 0xF0}, ++{0x7215, 0xBD}, ++{0x7216, 0x00}, ++{0x7217, 0x00}, ++{0x7218, 0x76}, ++{0x7219, 0x69}, ++{0x721A, 0x18}, ++{0x721B, 0x00}, ++{0x721C, 0xEC}, ++{0x721D, 0x58}, ++{0x721E, 0x18}, ++{0x721F, 0x00}, ++{0x7220, 0x38}, ++{0x7221, 0x36}, ++{0x7222, 0x18}, ++{0x7223, 0x00}, ++{0x7224, 0x00}, ++{0x7225, 0x35}, ++{0x7226, 0x18}, ++{0x7227, 0x00}, ++{0x7228, 0x00}, ++{0x7229, 0x20}, ++{0x722A, 0x18}, ++{0x722B, 0x00}, ++{0x722C, 0xFF}, ++{0x722D, 0xFF}, ++{0x722E, 0xFF}, ++{0x722F, 0x3F}, ++{0x7230, 0xFF}, ++{0x7231, 0x07}, ++{0x7232, 0x00}, ++{0x7233, 0x00}, ++{0x7234, 0xFF}, ++{0x7235, 0xFF}, ++{0x7236, 0x07}, ++{0x7237, 0x00}, ++{0x7238, 0xFF}, ++{0x7239, 0x1F}, ++{0x723A, 0x00}, ++{0x723B, 0x00}, ++{0x723C, 0x01}, ++{0x723D, 0xF6}, ++{0x723E, 0x45}, ++{0x723F, 0x12}, ++{0x0000, 0x00}, ++}; +diff --git a/drivers/media/i2c/soc_camera/max9286.c b/drivers/media/i2c/soc_camera/max9286.c +new file mode 100644 +index 0000000..c850196 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/max9286.c +@@ -0,0 +1,692 @@ ++/* ++ * MAXIM max9286 GMSL driver ++ * ++ * Copyright (C) 2015-2018 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 REG8_NUM_RETRIES 1 /* number of read/write retries */ -+#define REG16_NUM_RETRIES 10 /* number of read/write retries */ -+#define MAX9271_ID 0x9 -+#define MAX96705_ID 0x41 -+#define MAX9286_ID 0x40 -+#define BROADCAST 0x6f ++#include ++#include ++#include ++#include ++#include ++#include + -+static inline int reg8_read(struct i2c_client *client, u8 reg, u8 *val) -+{ -+ int ret, retries; ++#include ++#include ++#include ++#include + -+ for (retries = REG8_NUM_RETRIES; retries; retries--) { -+ ret = i2c_smbus_read_byte_data(client, reg); -+ if (!(ret < 0)) -+ break; -+ } ++#include "max9286.h" + -+ if (ret < 0) { -+ dev_dbg(&client->dev, -+ "read fail: chip 0x%x register 0x%x: %d\n", -+ client->addr, reg, ret); -+ } else { -+ *val = ret; -+ } ++#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 + -+ return ret < 0 ? ret : 0; -+} ++struct max9286_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 him; ++ int hsync; ++ int vsync; ++ int timeout; ++ int poc_delay; ++ atomic_t use_count; ++ u32 csi2_outord; ++ struct i2c_client *client; ++ int max9271_addr_map[4]; ++ int ser_id; ++ struct gpio_desc *poc_gpio[4]; /* PoC power supply */ ++}; + -+static inline int reg8_write(struct i2c_client *client, u8 reg, u8 val) -+{ -+ int ret, retries; ++static char fsync_mode_default[20] = "manual"; /* manual, automatic, semi-automatic, external */ + -+ for (retries = REG8_NUM_RETRIES; retries; retries--) { -+ ret = i2c_smbus_write_byte_data(client, reg, val); -+ if (!(ret < 0)) -+ break; -+ } ++static int conf_link; ++module_param(conf_link, int, 0644); ++MODULE_PARM_DESC(conf_link, " Force configuration link. Used only if robust firmware flashing required (f.e. recovery)"); + -+ 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 -+ } ++static int poc_trig; ++module_param(poc_trig, int, 0644); ++MODULE_PARM_DESC(poc_trig, " Use PoC triggering during reverse channel setup. Useful on systems with dedicated PoC and unstable ser-des lock"); + -+ return ret < 0 ? ret : 0; -+} ++static int him; ++module_param(him, int, 0644); ++MODULE_PARM_DESC(him, " Use High-Immunity mode (default: leagacy mode)"); + -+static inline int reg16_read(struct i2c_client *client, u16 reg, u8 *val) -+{ -+ int ret, retries; -+ u8 buf[2] = {reg >> 8, reg & 0xff}; ++static int fsync_period; ++module_param(fsync_period, int, 0644); ++MODULE_PARM_DESC(fsync_period, " Frame sync period (default: 3.2MHz)"); + -+ 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; -+ } -+ } ++static int hsync; ++module_param(hsync, int, 0644); ++MODULE_PARM_DESC(hsync, " HSYNC invertion (default: 0 - not inverted)"); + -+ 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]; -+ } ++static int vsync = 1; ++module_param(vsync, int, 0644); ++MODULE_PARM_DESC(vsync, " VSYNC invertion (default: 1 - inverted)"); + -+ return ret < 0 ? ret : 0; -+} ++static int gpio_resetb; ++module_param(gpio_resetb, int, 0644); ++MODULE_PARM_DESC(gpio_resetb, " Serializer GPIO reset (default: 0 - not used)"); + -+static inline int reg16_write(struct i2c_client *client, u16 reg, u8 val) -+{ -+ int ret, retries; -+ u8 buf[3] = {reg >> 8, reg & 0xff, val}; ++static int active_low_resetb; ++module_param(active_low_resetb, int, 0644); ++MODULE_PARM_DESC(active_low_resetb, " Serializer GPIO reset level (default: 0 - active high)"); + -+ for (retries = REG16_NUM_RETRIES; retries; retries--) { -+ ret = i2c_master_send(client, buf, 3); -+ if (ret == 3) -+ break; -+ } ++static int poc_delay; ++module_param(poc_delay, int, 0644); ++MODULE_PARM_DESC(poc_delay, " Delay in ms after POC enable (default: 0 ms)"); + -+ 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 ++static char* ser_name(int id) ++{ ++ switch (id) { ++ case MAX9271_ID: ++ return "MAX9271"; ++ case MAX96705_ID: ++ return "MAX96705"; ++ default: ++ return "unknown"; + } -+ -+ return ret < 0 ? ret : 0; +} + -+ -+static inline int reg16_read16(struct i2c_client *client, u16 reg, u16 *val) ++static void max9286_preinit(struct i2c_client *client, int addr) +{ -+ int ret, retries; -+ u8 buf[2] = {reg >> 8, reg & 0xff}; ++ struct max9286_priv *priv = i2c_get_clientdata(client); + -+ for (retries = REG8_NUM_RETRIES; retries; retries--) { -+ ret = i2c_master_send(client, buf, 2); -+ if (ret == 2) { -+ ret = i2c_master_recv(client, buf, 2); -+ if (ret == 2) -+ break; -+ } -+ } ++ 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 */ ++ reg8_write(client, 0x1c, priv->him ? 0xf4 : 0x04); /* high-immunity or legacy mode */ ++} + -+ if (ret < 0) { -+ dev_err(&client->dev, -+ "read fail: chip 0x%x register 0x%x: %d\n", -+ client->addr, reg, ret); -+ } else { -+ *val = ((u16)buf[0] << 8) | buf[1]; -+ } ++static void max9286_sensor_reset(struct i2c_client *client, int addr, int reset_on) ++{ ++ struct max9286_priv *priv = i2c_get_clientdata(client); + -+ return ret < 0 ? ret : 0; ++ if (priv->gpio_resetb < 1 || priv->gpio_resetb > 5) ++ return; ++ ++ /* sensor reset/unreset */ ++ client->addr = addr; /* MAX9271-CAMx I2C */ ++ reg8_write(client, 0x0f, (0xfe & ~BIT(priv->gpio_resetb)) | /* set GPIOn value to reset/unreset */ ++ ((priv->active_low_resetb ? BIT(priv->gpio_resetb) : 0) ^ reset_on)); ++ reg8_write(client, 0x0e, 0x42 | BIT(priv->gpio_resetb)); /* set GPIOn direction output */ +} + -+static inline int reg16_write16(struct i2c_client *client, u16 reg, u16 val) ++static void max9286_postinit(struct i2c_client *client, int addr) +{ -+ int ret, retries; -+ u8 buf[4] = {reg >> 8, reg & 0xff, val >> 8, val & 0xff}; ++ struct max9286_priv *priv = i2c_get_clientdata(client); ++ int idx; + -+ for (retries = REG8_NUM_RETRIES; retries; retries--) { -+ ret = i2c_master_send(client, buf, 4); -+ if (ret == 4) -+ break; -+ } ++ for (idx = 0; idx < priv->links; idx++) { ++ client->addr = priv->des_addr; /* MAX9286 I2C */ ++ reg8_write(client, 0x0a, 0x11 << idx); /* enable reverse/forward control for CAMx */ + -+ if (ret < 0) { -+ dev_err(&client->dev, -+ "write fail: chip 0x%x register 0x%x: %d\n", -+ client->addr, reg, ret); ++ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C */ ++ max9286_sensor_reset(client, client->addr, 0); /* sensor unreset */ + } + -+ return ret < 0 ? ret : 0; -+} ++ 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 */ + ++ if (strcmp(priv->fsync_mode, "manual") == 0) { ++ 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 */ ++ } ++} + -+#ifdef MAXIM_DUMP -+static void maxim_ovsensor_dump_regs(struct i2c_client *client) ++static int max9286_reverse_channel_setup(struct i2c_client *client, int idx) +{ -+ int ret, i; ++ struct max9286_priv *priv = i2c_get_clientdata(client); + u8 val = 0; -+ u16 regs[] = {0x300a, 0x300b, 0x300c}; -+ -+ dev_dbg(&client->dev, "dump regs 0x%x\n", client->addr); ++ int timeout = priv->timeout; ++ char timeout_str[10]; ++ int ret = 0; + -+ 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); -+ } -+} ++ /* 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 */ + -+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, -+ }; ++ 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 */ + -+ dev_dbg(&client->dev, "dump regs 0x%x\n", client->addr); ++ client->addr = 0x40; /* MAX9271-CAMx I2C */ ++ reg8_write(client, 0x04, 0x43); /* wake-up, enable reverse_control/conf_link */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ reg8_write(client, 0x08, 0x01); /* reverse channel receiver high threshold enable */ ++ reg8_write(client, 0x97, priv->him ? 0xaf : 0x5f); /* enable reverse control channel programming (MAX96705-MAX96711 only) */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ + -+ 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); -+ } -+} ++ 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 */ + -+static void maxim_max927x_dump_regs(struct i2c_client *client) -+{ -+ int ret; -+ u8 reg; ++ client->addr = 0x40; /* MAX9271-CAMx I2C */ ++ reg8_read(client, 0x1e, &val); /* read max9271 ID */ ++ if (val == MAX9271_ID || val == MAX96705_ID || --timeout == 0) { ++ priv->ser_id = val; ++ break; ++ } + -+ dev_dbg(&client->dev, "dump regs 0x%x\n", client->addr); ++ /* Check if already initialized (after reboot/reset ?) */ ++ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C */ ++ reg8_read(client, 0x1e, &val); /* read max9271 ID */ ++ if (val == MAX9271_ID || val == MAX96705_ID) { ++ priv->ser_id = val; ++ 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; ++ } + -+ 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"); ++ if (timeout == priv->timeout / 2 && poc_trig) { ++ if (!IS_ERR(priv->poc_gpio[idx])) { ++ gpiod_direction_output(priv->poc_gpio[idx], 0); /* POC power off */ ++ mdelay(200); ++ gpiod_direction_output(priv->poc_gpio[idx], 1); /* POC power on */ ++ mdelay(priv->poc_delay); ++ } ++ } + } -+} -+#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..8c06e59 ---- /dev/null -+++ b/drivers/media/i2c/soc_camera/ov10635.c -@@ -0,0 +1,759 @@ -+/* -+ * 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 -+#include -+#include -+#include -+#include ++ max9286_sensor_reset(client, client->addr, 1); /* sensor reset */ + -+#include -+#include -+#include -+#include ++ if (!timeout) { ++ ret = -ETIMEDOUT; ++ goto out; ++ } + -+#include "max9286.h" -+#include "ov10635.h" ++ priv->links_mask |= BIT(idx); ++ priv->csi2_outord &= ~(0x3 << (idx * 2)); ++ priv->csi2_outord |= ((hweight8(priv->links_mask) - 1) << (idx * 2)); + -+#define OV10635_I2C_ADDR 0x30 ++out: ++ sprintf(timeout_str, "retries=%d", priv->timeout - timeout); ++ dev_info(&client->dev, "link%d %s %sat 0x%x %s %s\n", idx, ser_name(priv->ser_id), ++ ret == -EADDRINUSE ? "already " : "", priv->max9271_addr_map[idx], ++ ret == -ETIMEDOUT ? "not found: timeout GMSL link establish" : "", ++ priv->timeout - timeout? timeout_str : ""); + -+#define OV10635_PID 0x300a -+#define OV10635_VER 0x300b -+#define OV10635_VERSION_REG 0xa635 -+#define OV10635_VERSION(pid, ver) (((pid) << 8) | ((ver) & 0xff)) ++ return ret; ++} + -+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) ++static void max9286_initial_setup(struct i2c_client *client) +{ -+ return container_of(i2c_get_clientdata(client), struct ov10635_priv, sd); -+} ++ struct max9286_priv *priv = i2c_get_clientdata(client); + -+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) -+{ -+ return &container_of(ctrl->handler, struct ov10635_priv, hdl)->sd; -+} ++ /* 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); ++ } + -+static void ov10635_s_port(struct i2c_client *client, int fwd_en) -+{ -+ struct ov10635_priv *priv = to_ov10635(client); -+ int tmp_addr; ++ /* Start GMSL initialization with FSYNC disabled. This is required for some odd LVDS cameras */ ++ reg8_write(client, 0x01, 0xc0); /* ECU (aka MCU) based FrameSync using GPI-to-GPO */ ++ 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); + -+ 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(5000, 5500); /* wait 5ms */ -+ client->addr = tmp_addr; -+ }; ++ reg8_write(client, 0x63, 0); /* disable overlap window */ ++ reg8_write(client, 0x64, 0); ++ reg8_write(client, 0x0c, 0x91 | (priv->vsync ? BIT(3) : 0) | (priv->hsync ? BIT(2) : 0)); /* enable HS/VS encoding, use D14/15 for HS/VS, invert HS/VS */ ++ reg8_write(client, 0x19, 0x0c); /* Drive HSTRAIL state for 120ns after the last payload bit */ +} + -+static int ov10635_set_regs(struct i2c_client *client, -+ const struct ov10635_reg *regs, int nr_regs) ++static void max9286_gmsl_link_setup(struct i2c_client *client, int idx) +{ -+ int i; ++ struct max9286_priv *priv = i2c_get_clientdata(client); + -+ 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); -+ } ++ /* 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 */ ++ ++ if (priv->ser_id == MAX96705_ID) { ++ /* setup crossbar in DBL mode: reverse DVP bus */ ++ reg8_write(client, 0x20, 0x07); ++ reg8_write(client, 0x21, 0x06); ++ reg8_write(client, 0x22, 0x05); ++ reg8_write(client, 0x23, 0x04); ++ reg8_write(client, 0x24, 0x03); ++ reg8_write(client, 0x25, 0x02); ++ reg8_write(client, 0x26, 0x01); ++ reg8_write(client, 0x27, 0x00); ++ ++ reg8_write(client, 0x30, 0x17); ++ reg8_write(client, 0x31, 0x16); ++ reg8_write(client, 0x32, 0x15); ++ reg8_write(client, 0x33, 0x14); ++ reg8_write(client, 0x34, 0x13); ++ reg8_write(client, 0x35, 0x12); ++ reg8_write(client, 0x36, 0x11); ++ reg8_write(client, 0x37, 0x10); + } + -+ return 0; -+} ++ 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 */ + -+static int ov10635_s_stream(struct v4l2_subdev *sd, int enable) -+{ -+ return 0; ++ /* I2C translator setup */ ++ client->addr = 0x40; /* MAX9271-CAMx I2C */ ++// reg8_write(client, 0x09, maxim_map[2][idx] << 1); /* SENSOR I2C translated - must be set by sensor driver */ ++// reg8_write(client, 0x0A, 0x30 << 1); /* SENSOR I2C native - must be set by sensor driver */ ++ reg8_write(client, 0x0B, BROADCAST << 1); /* broadcast I2C */ ++ reg8_write(client, 0x0C, priv->max9271_addr_map[idx] << 1); /* MAX9271-CAMx I2C new */ ++ /* I2C addresse change */ ++ reg8_write(client, 0x01, priv->des_addr << 1); /* MAX9286 I2C */ ++ reg8_write(client, 0x00, priv->max9271_addr_map[idx] << 1); /* MAX9271-CAM0 I2C new */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ /* put MAX9271 in configuration link state */ ++ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C new */ ++ reg8_write(client, 0x04, 0x43); /* enable reverse_control/conf_link */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++#ifdef MAXIM_DUMP ++ client->addr = priv->des_addr; /* MAX9286-CAMx I2C */ ++ maxim_max927x_dump_regs(client); ++ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C new */ ++ maxim_max927x_dump_regs(client); ++#endif +} + -+static int ov10635_set_window(struct v4l2_subdev *sd, int subsampling) ++static int max9286_initialize(struct i2c_client *client) +{ -+ 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); ++ struct max9286_priv *priv = i2c_get_clientdata(client); ++ int idx, ret; + -+ /* 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); ++ 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"); + -+ /* 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 (priv->des_quirk_addr) ++ max9286_preinit(client, priv->des_quirk_addr); + -+#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); ++ max9286_preinit(client, priv->des_addr); ++ max9286_initial_setup(client); + -+ return 0; -+}; ++ for (idx = 0; idx < priv->links; idx++) { ++ if (!IS_ERR(priv->poc_gpio[idx])) { ++ gpiod_direction_output(priv->poc_gpio[idx], 1); /* POC power on */ ++ mdelay(priv->poc_delay); ++ } + -+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); ++ ret = max9286_reverse_channel_setup(client, idx); ++ if (ret) ++ continue; ++ max9286_gmsl_link_setup(client, idx); ++ } + -+ if (format->pad) -+ return -EINVAL; ++ max9286_postinit(client, priv->des_addr); + -+ 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; ++ client->addr = priv->des_addr; + + return 0; +} + -+static int ov10635_set_fmt(struct v4l2_subdev *sd, -+ struct v4l2_subdev_pad_config *cfg, -+ struct v4l2_subdev_format *format) ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int max9286_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) +{ -+ struct v4l2_mbus_framefmt *mf = &format->format; ++ struct max9286_priv *priv = v4l2_get_subdevdata(sd); ++ struct i2c_client *client = priv->client; ++ int ret; ++ u8 val = 0; + -+ mf->code = MEDIA_BUS_FMT_YUYV8_2X8; -+ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; -+ mf->field = V4L2_FIELD_NONE; ++ ret = reg8_read(client, (u8)reg->reg, &val); ++ if (ret < 0) ++ return ret; + -+ if (format->which == V4L2_SUBDEV_FORMAT_TRY) -+ cfg->try_fmt = *mf; ++ reg->val = val; ++ reg->size = sizeof(u8); + + 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) ++static int max9286_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) +{ -+ if (code->pad || code->index > 0) -+ return -EINVAL; -+ -+ code->code = MEDIA_BUS_FMT_YUYV8_2X8; ++ struct max9286_priv *priv = v4l2_get_subdevdata(sd); ++ struct i2c_client *client = priv->client; + -+ return 0; ++ return reg8_write(client, (u8)reg->reg, (u8)reg->val); +} ++#endif + -+static int ov10635_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++static int max9286_s_power(struct v4l2_subdev *sd, int on) +{ -+ struct i2c_client *client = v4l2_get_subdevdata(sd); -+ struct ov10635_priv *priv = to_ov10635(client); ++ struct max9286_priv *priv = v4l2_get_subdevdata(sd); ++ struct i2c_client *client = priv->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; ++ 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 ov10635_set_selection(struct v4l2_subdev *sd, -+ struct v4l2_subdev_pad_config *cfg, -+ struct v4l2_subdev_selection *sel) ++static int max9286_registered_async(struct v4l2_subdev *sd) +{ -+ 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; ++ struct max9286_priv *priv = v4l2_get_subdevdata(sd); ++ struct i2c_client *client = priv->client; ++ int idx, tmp_addr; + -+ rect->left = ALIGN(rect->left, 2); -+ rect->top = ALIGN(rect->top, 2); -+ rect->width = ALIGN(rect->width, 2); -+ rect->height = ALIGN(rect->height, 2); ++ /* switch to GMSL serial_link for streaming video */ ++ tmp_addr = client->addr; ++ idx = sd->grp_id; + -+ if ((rect->left + rect->width > OV10635_MAX_WIDTH) || -+ (rect->top + rect->height > OV10635_MAX_HEIGHT)) -+ *rect = priv->rect; ++ client->addr = priv->des_addr; /* MAX9286 I2C */ ++ reg8_write(client, 0x0a, 0x11 << idx); /* enable reverse/forward control for CAMx */ + -+ if (rect->width == OV10635_MAX_WIDTH / 2 && -+ rect->height == OV10635_MAX_HEIGHT / 2) -+ subsampling = 1; ++ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx */ ++ reg8_write(client, 0x04, conf_link ? 0x43 : 0x83); /* enable serial_link */ ++ usleep_range(2000, 2500); /* wait 2ms after changing reverse_control */ + -+ priv->rect.left = rect->left; -+ priv->rect.top = rect->top; -+ priv->rect.width = rect->width; -+ priv->rect.height = rect->height; ++ 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 */ + -+ /* change window only for subsampling, crop is done by VIN */ -+ if (subsampling != priv->subsampling) { -+ ov10635_set_window(sd, subsampling); -+ priv->subsampling = subsampling; -+ } ++ client->addr = tmp_addr; + + 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; ++static struct v4l2_subdev_core_ops max9286_subdev_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = max9286_g_register, ++ .s_register = max9286_s_register, ++#endif ++ .s_power = max9286_s_power, ++ .registered_async = max9286_registered_async, ++}; + -+ 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 struct v4l2_subdev_ops max9286_subdev_ops = { ++ .core = &max9286_subdev_core_ops, ++}; + -+static int ov10635_g_mbus_config(struct v4l2_subdev *sd, -+ struct v4l2_mbus_config *cfg) ++static int max9286_parse_dt(struct i2c_client *client) +{ -+ cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | -+ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; -+ cfg->type = V4L2_MBUS_CSI2; ++ struct max9286_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; ++ u8 val = 0; ++ char poc_name[10]; + -+ return 0; -+} ++ if (of_property_read_u32(np, "maxim,links", &priv->links)) ++ priv->links = 4; + -+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 (of_property_read_u32(np, "maxim,lanes", &priv->lanes)) ++ priv->lanes = 4; + -+ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) -+ return -EINVAL; ++ 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); ++ } + -+ memset(cp, 0, sizeof(struct v4l2_captureparm)); -+ cp->capability = V4L2_CAP_TIMEPERFRAME; -+ cp->timeperframe.numerator = 1; -+ cp->timeperframe.denominator = priv->fps_denominator; ++ mdelay(250); + -+ return 0; -+} ++ for (i = 0; i < 4; i++) { ++ sprintf(poc_name, "POC%d", i); ++ priv->poc_gpio[i] = devm_gpiod_get_optional(&client->dev, poc_name, 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; ++ 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 (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) -+ return -EINVAL; -+ if (cp->extendedmode != 0) -+ return -EINVAL; ++ 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 (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; -+ } ++ 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 = 0; ++ else ++ priv->active_low_resetb = 1; ++ } + -+ priv->fps_denominator = cp->timeperframe.denominator; ++ 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; ++ if (of_property_read_u32(np, "maxim,him", &priv->him)) ++ priv->him = 0; ++ if (of_property_read_u32(np, "maxim,hsync", &priv->hsync)) ++ priv->hsync = 0; ++ if (of_property_read_u32(np, "maxim,vsync", &priv->vsync)) ++ priv->vsync = 1; ++ if (of_property_read_u32(np, "maxim,poc-delay", &priv->poc_delay)) ++ priv->poc_delay = 50; ++ ++ /* module params override dts */ ++ if (him) ++ priv->him = him; ++ if (fsync_period) { ++ priv->fsync_period = fsync_period; ++ priv->fsync_mode = fsync_mode_default; + } ++ if (hsync) ++ priv->hsync = hsync; ++ if (!vsync) ++ priv->vsync = vsync; ++ if (gpio_resetb) ++ priv->gpio_resetb = gpio_resetb; ++ if (active_low_resetb) ++ priv->active_low_resetb = active_low_resetb; ++ if (poc_delay) ++ priv->poc_delay = poc_delay; + -+out: -+ return ret; -+} ++ for (i = 0; i < priv->links; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; + -+#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; ++ of_node_put(endpoint); + -+ ret = reg16_read(client, (u16)reg->reg, &val); -+ if (ret < 0) -+ return ret; ++ if (of_property_read_u32(endpoint, "max9271-addr", &priv->max9271_addr_map[i])) { ++ dev_err(&client->dev, "max9271-addr not set\n"); ++ return -EINVAL; ++ } + -+ reg->val = val; -+ reg->size = sizeof(u16); ++ priv->sd_of_node[i] = endpoint; ++ } + + return 0; +} + -+static int ov10635_s_register(struct v4l2_subdev *sd, -+ const struct v4l2_dbg_register *reg) ++static void max9286_setup_remote_endpoint(struct i2c_client *client) +{ -+ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct max9286_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; + -+ return reg16_write(client, (u16)reg->reg, (u8)reg->val); -+} -+#endif ++ for (i = 0; ; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; + -+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 -+}; ++ of_node_put(endpoint); + -+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; ++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); ++ if (!rendpoint) ++ continue; + -+ if (!priv->init_complete) -+ return 0; ++ 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); ++ } + -+ switch (ctrl->id) { -+ case V4L2_CID_BRIGHTNESS: -+ /* AEC/AGC target */ -+ ret = reg16_write(client, 0xc46a, ctrl->val); -+ break; -+ case V4L2_CID_CONTRAST: -+ udelay(100); -+ ret = ov10635_set_regs(client, &ov10635_regs_contrast[ctrl->val][0], 18); -+ break; -+ case V4L2_CID_SATURATION: -+ ret = reg16_write(client, 0xc316, ctrl->val); -+ break; -+ case V4L2_CID_HUE: -+ /* CMX ? */ -+ ret = 0; -+ break; -+ case V4L2_CID_GAMMA: -+ ret = reg16_write(client, 0xc4be, ctrl->val >> 8); -+ ret |= reg16_write(client, 0xc4bf, ctrl->val & 0xff); -+ break; -+ case V4L2_CID_AUTOGAIN: -+ /* automatic gain/exposure */ -+ ret = reg16_write(client, 0x56d0, !ctrl->val); -+ break; -+ case V4L2_CID_GAIN: -+ /* manual gain */ -+ ret = reg16_write(client, 0x3504, 0); -+ ret |= reg16_write(client, 0x56d1, ctrl->val >> 8); -+ ret |= reg16_write(client, 0x56d2, ctrl->val & 0xff); -+ ret |= reg16_write(client, 0x3504, 1); /* validate gain */ -+ break; -+ case V4L2_CID_EXPOSURE: -+ /* manual exposure */ -+ ret = reg16_write(client, 0x3504, 0); -+ ret |= reg16_write(client, 0x56d5, ctrl->val >> 8); -+ ret |= reg16_write(client, 0x56d6, ctrl->val & 0xff); -+ ret |= reg16_write(client, 0x3504, 1); /* validate exposure */ -+ break; -+ case V4L2_CID_HFLIP: -+ ret = reg16_read(client, 0x381d, &val); -+ if (ret < 0) -+ goto out; -+ if (ctrl->val) -+ val |= 0x3; -+ else -+ val &= ~0x3; -+ ret = reg16_write(client, 0x381d, val); -+ break; -+ case V4L2_CID_VFLIP: -+ ret = reg16_read(client, 0x381c, &val); -+ if (ctrl->val) -+ val |= 0xc0; -+ else -+ val &= ~0xc0; -+ ret = reg16_write(client, 0x381c, val); -+ break; -+ case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: -+ ret = 0; -+ break; ++ dvp_order_prop = of_find_property(endpoint, "dvp-order", NULL); ++ if (dvp_order_prop) ++ of_update_property(rendpoint, dvp_order_prop); + } -+ -+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) ++static int max9286_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) +{ -+ 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 */ ++ struct max9286_priv *priv; ++ int err, i; + -+ for (i = 0; i < 6; i++) -+ reg16_read(client, 0x3d00 + i, &priv->id[i]); -+} ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; + -+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); ++ i2c_set_clientdata(client, priv); ++ priv->des_addr = client->addr; ++ priv->client = client; ++ atomic_set(&priv->use_count, 0); ++ priv->csi2_outord = 0xff; + -+ 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]); -+} ++ err = max9286_parse_dt(client); ++ if (err) ++ goto out; + -+static DEVICE_ATTR(otp_id_ov10635, S_IRUGO, ov10635_otp_id_show, NULL); ++ err = max9286_initialize(client); ++ if (err < 0) ++ goto out; + -+static int ov10635_initialize(struct i2c_client *client) -+{ -+ struct ov10635_priv *priv = to_ov10635(client); -+ u8 pid = 0, ver = 0; -+ int ret = 0; ++ max9286_setup_remote_endpoint(client); + -+ ov10635_s_port(client, 1); ++ for (i = 0; i < 4; i++) { ++ v4l2_subdev_init(&priv->sd[i], &max9286_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]; + -+ /* check and show product ID and manufacturer ID */ -+ reg16_read(client, OV10635_PID, &pid); -+ reg16_read(client, OV10635_VER, &ver); ++ 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); + -+ if (OV10635_VERSION(pid, ver) != OV10635_VERSION_REG) { -+ dev_dbg(&client->dev, "Product ID error %x:%x\n", pid, ver); -+ ret = -ENODEV; -+ goto out; ++ err = v4l2_async_register_subdev(&priv->sd[i]); ++ if (err < 0) ++ 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; ++ return err; +} + -+static int ov10635_parse_dt(struct device_node *np, struct ov10635_priv *priv) ++static int max9286_remove(struct i2c_client *client) +{ -+ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); ++ struct max9286_priv *priv = i2c_get_clientdata(client); + 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; ++ for (i = 0; i < 4; i++) { ++ v4l2_async_unregister_subdev(&priv->sd[i]); ++ v4l2_device_unregister_subdev(&priv->sd[i]); ++ } + -+ of_node_put(endpoint); ++ return 0; ++} + -+ of_property_read_u32(endpoint, "dvp-order", &priv->dvp_order); ++static const struct of_device_id max9286_dt_ids[] = { ++ { .compatible = "maxim,max9286" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, max9286_dt_ids); + -+ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); -+ if (!rendpoint) -+ continue; ++static const struct i2c_device_id max9286_id[] = { ++ { "max9286", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, max9286_id); + -+ 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; ++static struct i2c_driver max9286_i2c_driver = { ++ .driver = { ++ .name = "max9286", ++ .of_match_table = of_match_ptr(max9286_dt_ids), ++ }, ++ .probe = max9286_probe, ++ .remove = max9286_remove, ++ .id_table = max9286_id, ++}; + -+ 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; -+ } ++module_i2c_driver(max9286_i2c_driver); + -+ if (!priv->max9286_addr && !priv->ti964_addr && !priv->ti954_addr) { -+ dev_err(&client->dev, "deserializer does not present for OV10635\n"); -+ return -EINVAL; -+ } ++MODULE_DESCRIPTION("GMSL driver for MAX9286"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/i2c/soc_camera/max9286.h b/drivers/media/i2c/soc_camera/max9286.h +new file mode 100644 +index 0000000..6c2a9e0 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/max9286.h +@@ -0,0 +1,244 @@ ++/* ++ * MAXIM max9286-max9271 GMSL driver include file ++ * ++ * Copyright (C) 2015-2017 Cogent Embedded, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ */ + -+ ov10635_s_port(client, 1); ++#ifndef _MAX9286_MAX9271_H ++#define _MAX9286_MAX9271_H + -+ /* setup I2C translator address */ -+ tmp_addr = client->addr; -+ if (priv->max9286_addr) { -+ client->addr = priv->max9271_addr; /* Serializer I2C address */ ++//#define DEBUG ++#ifdef DEBUG ++//#define WRITE_VERIFY ++#define MAXIM_DUMP ++#undef dev_dbg ++#define dev_dbg dev_info ++#endif + -+ 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 */ -+ }; ++#define REG8_NUM_RETRIES 1 /* number of read/write retries */ ++#define REG16_NUM_RETRIES 10 /* number of read/write retries */ ++#define MAX9271_ID 0x9 ++#define MAX96705_ID 0x41 ++#define MAX9286_ID 0x40 ++#define BROADCAST 0x6f + -+ if (priv->ti964_addr) { -+ client->addr = priv->ti964_addr; /* Deserializer I2C address */ ++static inline int reg8_read(struct i2c_client *client, u8 reg, u8 *val) ++{ ++ int ret, retries; + -+ 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 */ ++ for (retries = REG8_NUM_RETRIES; retries; retries--) { ++ ret = i2c_smbus_read_byte_data(client, reg); ++ if (!(ret < 0)) ++ break; ++ } + -+ reg8_write(client, 0x6e, 0xa9); /* GPIO0 - resetb, GPIO1 - fsin */ ++ if (ret < 0) { ++ dev_dbg(&client->dev, ++ "read fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } else { ++ *val = ret; + } + -+ if (priv->ti954_addr) { -+ client->addr = priv->ti954_addr; /* Deserializer I2C address */ ++ return ret < 0 ? ret : 0; ++} + -+ 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 */ ++static inline int reg8_write(struct i2c_client *client, u8 reg, u8 val) ++{ ++ int ret, retries; + -+ reg8_write(client, 0x6e, 0xa9); /* GPIO0 - resetb, GPIO1 - fsin */ ++ for (retries = REG8_NUM_RETRIES; retries; retries--) { ++ ret = i2c_smbus_write_byte_data(client, reg, val); ++ if (!(ret < 0)) ++ break; + } -+ client->addr = tmp_addr; + -+ udelay(100); ++ 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 0; ++ return ret < 0 ? ret : 0; +} + -+static int ov10635_probe(struct i2c_client *client, -+ const struct i2c_device_id *did) ++static inline int reg16_read(struct i2c_client *client, u16 reg, u8 *val) +{ -+ struct ov10635_priv *priv; -+ struct v4l2_ctrl *ctrl; -+ int ret; ++ int ret, retries; ++ u8 buf[2] = {reg >> 8, reg & 0xff}; + -+ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; ++ 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; ++ } ++ } + -+ 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; ++ 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]; ++ } + -+ v4l2_ctrl_handler_init(&priv->hdl, 4); -+ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, -+ V4L2_CID_BRIGHTNESS, 0, 0xff, 1, 0x30); -+ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, -+ V4L2_CID_CONTRAST, 0, 4, 1, 2); -+ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, -+ V4L2_CID_SATURATION, 0, 0xff, 1, 0xff); -+ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, -+ V4L2_CID_HUE, 0, 255, 1, 0); -+ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, -+ V4L2_CID_GAMMA, 0, 0xffff, 1, 0x233); -+ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, -+ V4L2_CID_AUTOGAIN, 0, 1, 1, 1); -+ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, -+ V4L2_CID_GAIN, 0, 0x3ff, 1, 0x10); -+ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, -+ V4L2_CID_EXPOSURE, 0, 0xffff, 1, 0x80); -+ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, -+ V4L2_CID_HFLIP, 0, 1, 1, 0); -+ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, -+ V4L2_CID_VFLIP, 0, 1, 1, 0); -+ ctrl = v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, -+ V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 9); -+ if (ctrl) -+ ctrl->flags &= ~V4L2_CTRL_FLAG_READ_ONLY; -+ priv->sd.ctrl_handler = &priv->hdl; ++ return ret < 0 ? ret : 0; ++} + -+ ret = priv->hdl.error; -+ if (ret) -+ goto cleanup; ++static inline int reg16_write(struct i2c_client *client, u16 reg, u8 val) ++{ ++ int ret, retries; ++ u8 buf[3] = {reg >> 8, reg & 0xff, val}; + -+ v4l2_ctrl_handler_setup(&priv->hdl); ++ for (retries = REG16_NUM_RETRIES; retries; retries--) { ++ ret = i2c_master_send(client, buf, 3); ++ if (ret == 3) ++ break; ++ } + -+ 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; ++ 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 ++ } + -+ ret = ov10635_parse_dt(client->dev.of_node, priv); -+ if (ret) -+ goto cleanup; ++ return ret < 0 ? ret : 0; ++} + -+ ret = ov10635_initialize(client); -+ if (ret < 0) -+ goto cleanup; + -+ ret = v4l2_async_register_subdev(&priv->sd); -+ if (ret) -+ goto cleanup; ++static inline int reg16_read16(struct i2c_client *client, u16 reg, u16 *val) ++{ ++ int ret, retries; ++ u8 buf[2] = {reg >> 8, reg & 0xff}; + -+ 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; ++ for (retries = REG8_NUM_RETRIES; retries; retries--) { ++ ret = i2c_master_send(client, buf, 2); ++ if (ret == 2) { ++ ret = i2c_master_recv(client, buf, 2); ++ if (ret == 2) ++ break; ++ } + } + -+ priv->init_complete = 1; -+ -+ return 0; ++ if (ret < 0) { ++ dev_err(&client->dev, ++ "read fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } else { ++ *val = ((u16)buf[0] << 8) | buf[1]; ++ } + -+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; ++ return ret < 0 ? ret : 0; +} + -+static int ov10635_remove(struct i2c_client *client) ++static inline int reg16_write16(struct i2c_client *client, u16 reg, u16 val) +{ -+ struct ov10635_priv *priv = i2c_get_clientdata(client); ++ int ret, retries; ++ u8 buf[4] = {reg >> 8, reg & 0xff, val >> 8, val & 0xff}; + -+ 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); ++ for (retries = REG8_NUM_RETRIES; retries; retries--) { ++ ret = i2c_master_send(client, buf, 4); ++ if (ret == 4) ++ break; ++ } + -+ return 0; ++ if (ret < 0) { ++ dev_err(&client->dev, ++ "write fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } ++ ++ return ret < 0 ? ret : 0; +} + -+#ifdef 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); ++#ifdef MAXIM_DUMP ++static void maxim_ovsensor_dump_regs(struct i2c_client *client) ++{ ++ int ret, i; ++ u8 val = 0; ++ u16 regs[] = {0x300a, 0x300b, 0x300c}; + -+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, -+}; ++ dev_dbg(&client->dev, "dump regs 0x%x\n", client->addr); + -+module_i2c_driver(ov10635_i2c_driver); ++ 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); ++ } ++} + -+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 ++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..a0e510d +index 0000000..8c06e59 --- /dev/null -+++ b/drivers/media/i2c/soc_camera/ov10635.h -@@ -0,0 +1,1139 @@ ++++ b/drivers/media/i2c/soc_camera/ov10635.c +@@ -0,0 +1,759 @@ +/* -+ * OmniVision ov10635 sensor camera wizard 1280x800@30/UYVY/BT601/8bit ++ * OmniVision ov10635 sensor camera driver + * + * Copyright (C) 2015-2017 Cogent Embedded, Inc. + * @@ -3837,35 +7451,800 @@ index 0000000..a0e510d + * option) any later version. + */ + -+//#define OV10635_DISPLAY_PATTERN ++#include ++#include ++#include ++#include ++#include + -+#define OV10635_SENSOR_WIDTH 1312 -+#define OV10635_SENSOR_HEIGHT 814 ++#include ++#include ++#include ++#include + -+#define OV10635_MAX_WIDTH 1280 -+#define OV10635_MAX_HEIGHT 800 ++#include "max9286.h" ++#include "ov10635.h" + -+//#define OV10635_PCLK_96MHZ -+#define OV10635_PCLK_88MHZ ++#define OV10635_I2C_ADDR 0x30 + -+#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 ++#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 */ ++ usleep_range(5000, 5500); /* wait 5ms */ ++ 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); + -+struct ov10635_reg { -+ u16 reg; -+ u8 val; ++ return 0; +}; + -+static const struct ov10635_reg ov10635_regs_wizard[] = { ++static int ov10635_get_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10635_priv *priv = to_ov10635(client); ++ ++ if (format->pad) ++ return -EINVAL; ++ ++ mf->width = priv->rect.width; ++ mf->height = priv->rect.height; ++ mf->code = MEDIA_BUS_FMT_YUYV8_2X8; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static int ov10635_set_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ ++ mf->code = MEDIA_BUS_FMT_YUYV8_2X8; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ if (format->which == V4L2_SUBDEV_FORMAT_TRY) ++ cfg->try_fmt = *mf; ++ ++ return 0; ++} ++ ++static int ov10635_enum_mbus_code(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ if (code->pad || code->index > 0) ++ return -EINVAL; ++ ++ code->code = MEDIA_BUS_FMT_YUYV8_2X8; ++ ++ return 0; ++} ++ ++static int ov10635_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10635_priv *priv = to_ov10635(client); ++ ++ memcpy(edid->edid, priv->id, 6); ++ ++ edid->edid[6] = 0xff; ++ edid->edid[7] = client->addr; ++ edid->edid[8] = OV10635_VERSION_REG >> 8; ++ edid->edid[9] = OV10635_VERSION_REG & 0xff; ++ ++ return 0; ++} ++ ++static int ov10635_set_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct v4l2_rect *rect = &sel->r; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10635_priv *priv = to_ov10635(client); ++ int subsampling = 0; ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || ++ sel->target != V4L2_SEL_TGT_CROP) ++ return -EINVAL; ++ ++ rect->left = ALIGN(rect->left, 2); ++ rect->top = ALIGN(rect->top, 2); ++ rect->width = ALIGN(rect->width, 2); ++ rect->height = ALIGN(rect->height, 2); ++ ++ if ((rect->left + rect->width > OV10635_MAX_WIDTH) || ++ (rect->top + rect->height > OV10635_MAX_HEIGHT)) ++ *rect = priv->rect; ++ ++ if (rect->width == OV10635_MAX_WIDTH / 2 && ++ rect->height == OV10635_MAX_HEIGHT / 2) ++ subsampling = 1; ++ ++ priv->rect.left = rect->left; ++ priv->rect.top = rect->top; ++ priv->rect.width = rect->width; ++ priv->rect.height = rect->height; ++ ++ /* change window only for subsampling, crop is done by VIN */ ++ if (subsampling != priv->subsampling) { ++ ov10635_set_window(sd, subsampling); ++ priv->subsampling = subsampling; ++ } ++ ++ return 0; ++} ++ ++static int ov10635_get_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10635_priv *priv = to_ov10635(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) ++ return -EINVAL; ++ ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = OV10635_MAX_WIDTH; ++ sel->r.height = OV10635_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = OV10635_MAX_WIDTH; ++ sel->r.height = OV10635_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP: ++ sel->r = priv->rect; ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int ov10635_g_mbus_config(struct v4l2_subdev *sd, ++ struct v4l2_mbus_config *cfg) ++{ ++ cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | ++ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; ++ cfg->type = V4L2_MBUS_CSI2; ++ ++ return 0; ++} ++ ++static int ov10635_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10635_priv *priv = to_ov10635(client); ++ struct v4l2_captureparm *cp = &parms->parm.capture; ++ ++ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ ++ memset(cp, 0, sizeof(struct v4l2_captureparm)); ++ cp->capability = V4L2_CAP_TIMEPERFRAME; ++ cp->timeperframe.numerator = 1; ++ cp->timeperframe.denominator = priv->fps_denominator; ++ ++ return 0; ++} ++ ++static int ov10635_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10635_priv *priv = to_ov10635(client); ++ struct v4l2_captureparm *cp = &parms->parm.capture; ++ int ret = 0; ++ ++ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ if (cp->extendedmode != 0) ++ return -EINVAL; ++ ++ if (priv->fps_denominator != cp->timeperframe.denominator) { ++ switch (cp->timeperframe.denominator) { ++ case 5: ++ ret = ov10635_set_regs(client, ov10635_regs_5fps, ++ ARRAY_SIZE(ov10635_regs_5fps)); ++ break; ++ case 10: ++ ret = ov10635_set_regs(client, ov10635_regs_10fps, ++ ARRAY_SIZE(ov10635_regs_10fps)); ++ break; ++ case 15: ++ ret = ov10635_set_regs(client, ov10635_regs_15fps, ++ ARRAY_SIZE(ov10635_regs_15fps)); ++ break; ++ case 30: ++ ret = ov10635_set_regs(client, ov10635_regs_30fps, ++ ARRAY_SIZE(ov10635_regs_30fps)); ++ break; ++ default: ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ priv->fps_denominator = cp->timeperframe.denominator; ++ } ++ ++out: ++ return ret; ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int ov10635_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ int ret; ++ u8 val = 0; ++ ++ ret = reg16_read(client, (u16)reg->reg, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u16); ++ ++ return 0; ++} ++ ++static int ov10635_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ return reg16_write(client, (u16)reg->reg, (u8)reg->val); ++} ++#endif ++ ++static struct v4l2_subdev_core_ops ov10635_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = ov10635_g_register, ++ .s_register = ov10635_s_register, ++#endif ++}; ++ ++static int ov10635_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct v4l2_subdev *sd = to_sd(ctrl); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10635_priv *priv = to_ov10635(client); ++ int ret = -EINVAL; ++ u8 val = 0; ++ ++ if (!priv->init_complete) ++ return 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_BRIGHTNESS: ++ /* AEC/AGC target */ ++ ret = reg16_write(client, 0xc46a, ctrl->val); ++ break; ++ case V4L2_CID_CONTRAST: ++ udelay(100); ++ ret = ov10635_set_regs(client, &ov10635_regs_contrast[ctrl->val][0], 18); ++ break; ++ case V4L2_CID_SATURATION: ++ ret = reg16_write(client, 0xc316, ctrl->val); ++ break; ++ case V4L2_CID_HUE: ++ /* CMX ? */ ++ ret = 0; ++ break; ++ case V4L2_CID_GAMMA: ++ ret = reg16_write(client, 0xc4be, ctrl->val >> 8); ++ ret |= reg16_write(client, 0xc4bf, ctrl->val & 0xff); ++ break; ++ case V4L2_CID_AUTOGAIN: ++ /* automatic gain/exposure */ ++ ret = reg16_write(client, 0x56d0, !ctrl->val); ++ break; ++ case V4L2_CID_GAIN: ++ /* manual gain */ ++ ret = reg16_write(client, 0x3504, 0); ++ ret |= reg16_write(client, 0x56d1, ctrl->val >> 8); ++ ret |= reg16_write(client, 0x56d2, ctrl->val & 0xff); ++ ret |= reg16_write(client, 0x3504, 1); /* validate gain */ ++ break; ++ case V4L2_CID_EXPOSURE: ++ /* manual exposure */ ++ ret = reg16_write(client, 0x3504, 0); ++ ret |= reg16_write(client, 0x56d5, ctrl->val >> 8); ++ ret |= reg16_write(client, 0x56d6, ctrl->val & 0xff); ++ ret |= reg16_write(client, 0x3504, 1); /* validate exposure */ ++ break; ++ case V4L2_CID_HFLIP: ++ ret = reg16_read(client, 0x381d, &val); ++ if (ret < 0) ++ goto out; ++ if (ctrl->val) ++ val |= 0x3; ++ else ++ val &= ~0x3; ++ ret = reg16_write(client, 0x381d, val); ++ break; ++ case V4L2_CID_VFLIP: ++ ret = reg16_read(client, 0x381c, &val); ++ if (ctrl->val) ++ val |= 0xc0; ++ else ++ val &= ~0xc0; ++ ret = reg16_write(client, 0x381c, val); ++ break; ++ case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: ++ ret = 0; ++ break; ++ } ++ ++out: ++ return ret; ++} ++ ++static const struct v4l2_ctrl_ops ov10635_ctrl_ops = { ++ .s_ctrl = ov10635_s_ctrl, ++}; ++ ++static struct v4l2_subdev_video_ops ov10635_video_ops = { ++ .s_stream = ov10635_s_stream, ++ .g_mbus_config = ov10635_g_mbus_config, ++ .g_parm = ov10635_g_parm, ++ .s_parm = ov10635_s_parm, ++}; ++ ++static const struct v4l2_subdev_pad_ops ov10635_subdev_pad_ops = { ++ .get_edid = ov10635_get_edid, ++ .enum_mbus_code = ov10635_enum_mbus_code, ++ .get_selection = ov10635_get_selection, ++ .set_selection = ov10635_set_selection, ++ .get_fmt = ov10635_get_fmt, ++ .set_fmt = ov10635_set_fmt, ++}; ++ ++static struct v4l2_subdev_ops ov10635_subdev_ops = { ++ .core = &ov10635_core_ops, ++ .video = &ov10635_video_ops, ++ .pad = &ov10635_subdev_pad_ops, ++}; ++ ++static void ov10635_otp_id_read(struct i2c_client *client) ++{ ++ struct ov10635_priv *priv = to_ov10635(client); ++ int i; ++ ++ /* read camera id from OTP memory */ ++ reg16_write(client, 0x3d10, 1); ++ ++ usleep_range(15000, 16000); /* wait 15ms */ ++ ++ for (i = 0; i < 6; i++) ++ reg16_read(client, 0x3d00 + i, &priv->id[i]); ++} ++ ++static ssize_t ov10635_otp_id_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(to_i2c_client(dev)); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10635_priv *priv = to_ov10635(client); ++ ++ return snprintf(buf, 32, "%02x:%02x:%02x:%02x:%02x:%02x\n", ++ priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++} ++ ++static DEVICE_ATTR(otp_id_ov10635, S_IRUGO, ov10635_otp_id_show, NULL); ++ ++static int ov10635_initialize(struct i2c_client *client) ++{ ++ struct ov10635_priv *priv = to_ov10635(client); ++ u8 pid = 0, ver = 0; ++ int ret = 0; ++ ++ ov10635_s_port(client, 1); ++ ++ /* check and show product ID and manufacturer ID */ ++ reg16_read(client, OV10635_PID, &pid); ++ reg16_read(client, OV10635_VER, &ver); ++ ++ if (OV10635_VERSION(pid, ver) != OV10635_VERSION_REG) { ++ dev_dbg(&client->dev, "Product ID error %x:%x\n", pid, ver); ++ ret = -ENODEV; ++ goto out; ++ } ++ ++ /* s/w reset sensor */ ++ reg16_write(client, 0x103, 0x1); ++ udelay(100); ++ /* Program wizard registers */ ++ ov10635_set_regs(client, ov10635_regs_wizard, ARRAY_SIZE(ov10635_regs_wizard)); ++ /* Set DVP bit swap */ ++ reg16_write(client, 0x4709, priv->dvp_order << 4); ++ /* Read OTP IDs */ ++ ov10635_otp_id_read(client); ++ ++ dev_info(&client->dev, "ov10635 Product ID %x Manufacturer ID %x OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, ver, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++out: ++ ov10635_s_port(client, 0); ++ ++ return ret; ++} ++ ++static int ov10635_parse_dt(struct device_node *np, struct ov10635_priv *priv) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); ++ int i; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ int tmp_addr = 0; ++ ++ for (i = 0; ; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; ++ ++ of_node_put(endpoint); ++ ++ of_property_read_u32(endpoint, "dvp-order", &priv->dvp_order); ++ ++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); ++ if (!rendpoint) ++ continue; ++ ++ if (!of_property_read_u32(rendpoint, "max9271-addr", &priv->max9271_addr) && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->max9286_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ ++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti964-ti9x3") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti964_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ ++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti954-ti9x3") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti954_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ } ++ ++ if (!priv->max9286_addr && !priv->ti964_addr && !priv->ti954_addr) { ++ dev_err(&client->dev, "deserializer does not present for OV10635\n"); ++ return -EINVAL; ++ } ++ ++ ov10635_s_port(client, 1); ++ ++ /* setup I2C translator address */ ++ tmp_addr = client->addr; ++ if (priv->max9286_addr) { ++ client->addr = priv->max9271_addr; /* Serializer I2C address */ ++ ++ reg8_write(client, 0x09, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x0A, OV10635_I2C_ADDR << 1); /* Sensor native I2C address */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ }; ++ ++ if (priv->ti964_addr) { ++ client->addr = priv->ti964_addr; /* Deserializer I2C address */ ++ ++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x5d, OV10635_I2C_ADDR << 1); /* Sensor native I2C address */ ++ ++ reg8_write(client, 0x6e, 0xa9); /* GPIO0 - resetb, GPIO1 - fsin */ ++ } ++ ++ if (priv->ti954_addr) { ++ client->addr = priv->ti954_addr; /* Deserializer I2C address */ ++ ++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x5d, OV10635_I2C_ADDR << 1); /* Sensor native I2C address */ ++ ++ reg8_write(client, 0x6e, 0xa9); /* GPIO0 - resetb, GPIO1 - fsin */ ++ } ++ client->addr = tmp_addr; ++ ++ udelay(100); ++ ++ return 0; ++} ++ ++static int ov10635_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct ov10635_priv *priv; ++ struct v4l2_ctrl *ctrl; ++ int ret; ++ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ v4l2_i2c_subdev_init(&priv->sd, client, &ov10635_subdev_ops); ++ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; ++ priv->rect.left = 0; ++ priv->rect.top = 0; ++ priv->rect.width = OV10635_MAX_WIDTH; ++ priv->rect.height = OV10635_MAX_HEIGHT; ++ priv->fps_denominator = 30; ++ ++ v4l2_ctrl_handler_init(&priv->hdl, 4); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_BRIGHTNESS, 0, 0xff, 1, 0x30); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_CONTRAST, 0, 4, 1, 2); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_SATURATION, 0, 0xff, 1, 0xff); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_HUE, 0, 255, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_GAMMA, 0, 0xffff, 1, 0x233); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_AUTOGAIN, 0, 1, 1, 1); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_GAIN, 0, 0x3ff, 1, 0x10); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_EXPOSURE, 0, 0xffff, 1, 0x80); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ ctrl = v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 9); ++ if (ctrl) ++ ctrl->flags &= ~V4L2_CTRL_FLAG_READ_ONLY; ++ priv->sd.ctrl_handler = &priv->hdl; ++ ++ ret = priv->hdl.error; ++ if (ret) ++ goto cleanup; ++ ++ v4l2_ctrl_handler_setup(&priv->hdl); ++ ++ priv->pad.flags = MEDIA_PAD_FL_SOURCE; ++ priv->sd.entity.flags |= MEDIA_ENT_F_CAM_SENSOR; ++ ret = media_entity_pads_init(&priv->sd.entity, 1, &priv->pad); ++ if (ret < 0) ++ goto cleanup; ++ ++ ret = ov10635_parse_dt(client->dev.of_node, priv); ++ if (ret) ++ goto cleanup; ++ ++ ret = ov10635_initialize(client); ++ if (ret < 0) ++ goto cleanup; ++ ++ ret = v4l2_async_register_subdev(&priv->sd); ++ if (ret) ++ goto cleanup; ++ ++ if (device_create_file(&client->dev, &dev_attr_otp_id_ov10635) != 0) { ++ dev_err(&client->dev, "sysfs otp_id entry creation failed\n"); ++ goto cleanup; ++ } ++ ++ priv->init_complete = 1; ++ ++ return 0; ++ ++cleanup: ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++#ifdef CONFIG_SOC_CAMERA_OV10635 ++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", ++ client->addr, client->adapter->name); ++#endif ++ return ret; ++} ++ ++static int ov10635_remove(struct i2c_client *client) ++{ ++ struct ov10635_priv *priv = i2c_get_clientdata(client); ++ ++ device_remove_file(&client->dev, &dev_attr_otp_id_ov10635); ++ v4l2_async_unregister_subdev(&priv->sd); ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_SOC_CAMERA_OV10635 ++static const struct i2c_device_id ov10635_id[] = { ++ { "ov10635", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, ov10635_id); ++ ++static const struct of_device_id ov10635_of_ids[] = { ++ { .compatible = "ovti,ov10635", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ov10635_of_ids); ++ ++static struct i2c_driver ov10635_i2c_driver = { ++ .driver = { ++ .name = "ov10635", ++ .of_match_table = ov10635_of_ids, ++ }, ++ .probe = ov10635_probe, ++ .remove = ov10635_remove, ++ .id_table = ov10635_id, ++}; ++ ++module_i2c_driver(ov10635_i2c_driver); ++ ++MODULE_DESCRIPTION("SoC Camera driver for OV10635"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); ++#endif +diff --git a/drivers/media/i2c/soc_camera/ov10635.h b/drivers/media/i2c/soc_camera/ov10635.h +new file mode 100644 +index 0000000..a0e510d +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov10635.h +@@ -0,0 +1,1139 @@ ++/* ++ * OmniVision ov10635 sensor camera wizard 1280x800@30/UYVY/BT601/8bit ++ * ++ * Copyright (C) 2015-2017 Cogent Embedded, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ */ ++ ++//#define OV10635_DISPLAY_PATTERN ++ ++#define OV10635_SENSOR_WIDTH 1312 ++#define OV10635_SENSOR_HEIGHT 814 ++ ++#define OV10635_MAX_WIDTH 1280 ++#define OV10635_MAX_HEIGHT 800 ++ ++//#define OV10635_PCLK_96MHZ ++#define OV10635_PCLK_88MHZ ++ ++#if defined(OV10635_PCLK_96MHZ) ++/* VTS=PCLK/FPS/HTS/2 (=96MHz/30/1600/2) */ ++ #define OV10635_HTS 1600 ++ #define OV10635_VTS 1000 /* fps=30 */ ++#elif defined(OV10635_PCLK_88MHZ) ++/* VTS=PCLK/FPS/HTS/2 (=88MHz/1572/30/2) */ ++ #define OV10635_HTS 1572 ++ #define OV10635_VTS 933 /* fps=29.9998 */ ++#else ++ #error PCLK not defined ++#endif ++ ++struct ov10635_reg { ++ u16 reg; ++ u8 val; ++}; ++ ++static const struct ov10635_reg ov10635_regs_wizard[] = { +//{0x0103, 0x01}, +{0x300C, 0x61}, +{0x300C, 0x61}, @@ -5027,10 +9406,10 @@ index 0000000..4c3515a +#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..fa775ae +index 0000000..08786ab --- /dev/null +++ b/drivers/media/i2c/soc_camera/ov106xx.c -@@ -0,0 +1,139 @@ +@@ -0,0 +1,161 @@ +/* + * OmniVision ov10635/ov490-ov10640/ov495-ov2775 sensor camera driver + * @@ -5049,6 +9428,8 @@ index 0000000..fa775ae +#include "ar0220.c" +#include "ap0101_ar014x.c" +#include "ov2775.c" ++#include "imx390.c" ++#include "ox03a.c" + +static enum { + ID_OV10635, @@ -5058,6 +9439,8 @@ index 0000000..fa775ae + ID_AR0220, + ID_AP0101_AR014X, + ID_OV2775, ++ ID_IMX390, ++ ID_OX03A, +} chip_id; + +static int ov106xx_probe(struct i2c_client *client, @@ -5108,6 +9491,18 @@ index 0000000..fa775ae + goto out; + } + ++ ret = imx390_probe(client, did); ++ if (!ret) { ++ chip_id = ID_IMX390; ++ goto out; ++ } ++ ++ ret = ox03a_probe(client, did); ++ if (!ret) { ++ chip_id = ID_OX03A; ++ goto out; ++ } ++ + v4l_err(client, "failed to probe @ 0x%02x (%s)\n", + client->addr, client->adapter->name); +out: @@ -5138,6 +9533,12 @@ index 0000000..fa775ae + case ID_OV2775: + ov2775_remove(client); + break; ++ case ID_IMX390: ++ imx390_remove(client); ++ break; ++ case ID_OX03A: ++ ox03a_remove(client); ++ break; + }; + + return 0; @@ -5172,10 +9573,10 @@ index 0000000..fa775ae +MODULE_LICENSE("GPL"); diff --git a/drivers/media/i2c/soc_camera/ov2775.c b/drivers/media/i2c/soc_camera/ov2775.c new file mode 100644 -index 0000000..dac6d60 +index 0000000..f57fc71 --- /dev/null +++ b/drivers/media/i2c/soc_camera/ov2775.c -@@ -0,0 +1,527 @@ +@@ -0,0 +1,538 @@ +/* + * OmniVision OV2775 sensor camera driver + * @@ -5206,7 +9607,7 @@ index 0000000..dac6d60 +#define OV2775_VER 0x300b +#define OV2775_VERSION_REG 0x2770 + -+#define OV2775_MEDIA_BUS_FMT MEDIA_BUS_FMT_SBGGR8_1X8 ++#define OV2775_MEDIA_BUS_FMT MEDIA_BUS_FMT_SBGGR12_1X12 + +struct ov2775_priv { + struct v4l2_subdev sd; @@ -5496,6 +9897,7 @@ index 0000000..dac6d60 + u8 val = 0; + u16 pid; + int ret = 0; ++ int tmp_addr; + + /* check and show model ID */ + reg16_read(client, OV2775_PID, &val); @@ -5509,6 +9911,16 @@ index 0000000..dac6d60 + goto err; + } + ++ /* setup XCLK */ ++ tmp_addr = client->addr; ++ if (priv->ti9x4_addr) { ++ /* CLK_OUT=22.5792*160*M/N/CLKDIV -> CLK_OUT=25MHz: CLKDIV=4, M=7, N=253: 22.5792*160/4*7/253=24.989MHz=CLK_OUT */ ++ client->addr = priv->ti9x3_addr; /* Serializer I2C address */ ++ reg8_write(client, 0x06, 0x47); /* Set CLKDIV and M */ ++ reg8_write(client, 0x07, 0xfd); /* Set N */ ++ } ++ client->addr = tmp_addr; ++ + /* Program wizard registers */ + ov2775_set_regs(client, ov2775_regs_wizard, ARRAY_SIZE(ov2775_regs_wizard)); + /* Read OTP IDs */ @@ -5705,12 +10117,12 @@ index 0000000..dac6d60 +#endif diff --git a/drivers/media/i2c/soc_camera/ov2775.h b/drivers/media/i2c/soc_camera/ov2775.h new file mode 100644 -index 0000000..1cdfb50 +index 0000000..7e1ee31 --- /dev/null +++ b/drivers/media/i2c/soc_camera/ov2775.h @@ -0,0 +1,1841 @@ +/* -+ * OmniVision OV2775 sensor camera wizard 1928x1088@30/RGGB/MIPI ++ * OmniVision OV2775 sensor camera wizard 1920x1080@30/BGGR/MIPI + * + * Copyright (C) 2018 Cogent Embedded, Inc. + * @@ -5720,29 +10132,29 @@ index 0000000..1cdfb50 + * option) any later version. + */ + -+//#define OV2775_DISPLAY_PATTERN_COLOR_BAR ++#define OV2775_DISPLAY_PATTERN_COLOR_BAR + -+#define OV2775_MAX_WIDTH 2880 // (1928*1.5=2892) <- must be multiple of 16 - requred by R-CAR VIN -+#define OV2775_MAX_HEIGHT 1088 ++#define OV2775_MAX_WIDTH 1920 ++#define OV2775_MAX_HEIGHT 1080 + +#define OV2775_DELAY 0xffff -+#define OV2775_DT 0x2c // MIPI Data Type ++#define OV2775_DT 0x2c /* MIPI Data Type RAW12 */ + +struct ov2775_reg { + u16 reg; + u8 val; +}; + -+/* wizard: MIPI 1928x1088 RAW12 Linear 30fps 960Mbps */ ++/* wizard: MIPI 1920x1080 RAW12 Linear 30fps 600Mbps XCLK=25MHz */ +static const struct ov2775_reg ov2775_regs_wizard[] = { +{0x3013, 0x01}, // s/w reset +{OV2775_DELAY, 10}, // Wait 10ms -+{0x3000, 0x02}, -+{0x3001, 0x28}, -+{0x3002, 0x03}, ++{0x3000, 0x03}, ++{0x3001, 0x18}, ++{0x3002, 0x01}, +{0x3003, 0x01}, -+{0x3004, 0x02}, -+{0x3005, 0x26}, ++{0x3004, 0x03}, ++{0x3005, 0x1c}, +{0x3006, 0x00}, +{0x3007, 0x07}, +{0x3008, 0x01}, @@ -5752,7 +10164,7 @@ index 0000000..1cdfb50 +{0x300f, 0x00}, +{0x3012, 0x00}, +{0x3013, 0x00}, -+{0x3014, 0xc4}, ++{0x3014, 0x44}, +{0x3015, 0x00}, +{0x3017, 0x00}, +{0x3018, 0x00}, @@ -6039,7 +10451,7 @@ index 0000000..1cdfb50 +{0x320d, 0x1e}, +{0x320e, 0x30}, +{0x320f, 0x2d}, -+{0x3210, OV2775_DT}, ++{0x3210, 0x2c}, +{0x3211, 0x2b}, +{0x3212, 0x2a}, +{0x3213, 0x24}, @@ -6069,7 +10481,7 @@ index 0000000..1cdfb50 +{0x3251, 0x00}, +{0x3252, 0x20}, +#ifdef OV2775_DISPLAY_PATTERN_COLOR_BAR -+{0x3253, 0x80}, ++{0x3253, 0xC0}, +#else +{0x3253, 0x00}, +#endif @@ -7533,9 +11945,9 @@ index 0000000..1cdfb50 +{0x30a9, 0x04}, +{0x30aa, 0x00}, +{0x30ab, 0x04}, -+{0x30ac, 0x07}, ++{0x30ac, 0x07}, /* OV2775_MAX_WIDTH */ +{0x30ad, 0x88}, -+{0x30ae, 0x04}, ++{0x30ae, 0x04}, /* OV2775_MAX_HEIGHT */ +{0x30af, 0x40}, +{0x30b0, 0x0d}, +{0x30b1, 0xde}, @@ -7550,16 +11962,1263 @@ index 0000000..1cdfb50 +{0x3250, 0xf7}, +{0x3012, 0x01}, +}; -diff --git a/drivers/media/i2c/soc_camera/ov490_ov10640.c b/drivers/media/i2c/soc_camera/ov490_ov10640.c +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..812f367 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov490_ov10640.c +@@ -0,0 +1,1133 @@ ++/* ++ * OmniVision ov490-ov10640 sensor camera driver ++ * ++ * Copyright (C) 2016-2018 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 ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "max9286.h" ++#include "ov490_ov10640.h" ++ ++#define OV490_I2C_ADDR 0x24 ++ ++#define OV490_PID 0x300a ++#define OV490_VER 0x300b ++#define OV490_VERSION_REG 0x0490 ++#define OV490_VERSION(pid, ver) (((pid) << 8) | ((ver) & 0xff)) ++ ++#define OV490_ISP_HSIZE_LOW 0x60 ++#define OV490_ISP_HSIZE_HIGH 0x61 ++#define OV490_ISP_VSIZE_LOW 0x62 ++#define OV490_ISP_VSIZE_HIGH 0x63 ++ ++struct ov490_priv { ++ struct v4l2_subdev sd; ++ struct v4l2_ctrl_handler hdl; ++ struct media_pad pad; ++ struct v4l2_rect rect; ++ int max_width; ++ int max_height; ++ char is_fixed_sensor; ++ int init_complete; ++ u8 id[6]; ++ int exposure; ++ int gain; ++ int autogain; ++ int red; ++ int green_r; ++ int green_b; ++ int blue; ++ int awb; ++ int dvp_order; ++ /* serializers */ ++ int max9286_addr; ++ int max9271_addr; ++ int ti9x4_addr; ++ int ti9x3_addr; ++ int port; ++ int gpio_resetb; ++ int active_low_resetb; ++ int gpio_fsin; ++}; ++ ++static int conf_link; ++module_param(conf_link, int, 0644); ++MODULE_PARM_DESC(conf_link, " Force configuration link. Used only if robust firmware flashing required (f.e. recovery)"); ++ ++static int dvp_order; ++module_param(dvp_order, int, 0644); ++MODULE_PARM_DESC(dvp_order, " DVP bus bits order"); ++ ++static int max_width; ++module_param(max_width, int, 0644); ++MODULE_PARM_DESC(max_width, " Fixed sensor width"); ++ ++static int max_height; ++module_param(max_height, int, 0644); ++MODULE_PARM_DESC(max_height, " Fixed sensor height"); ++ ++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(5000, 5500); /* wait 5ms */ ++ client->addr = tmp_addr; ++ }; ++} ++ ++static void ov490_reset(struct i2c_client *client) ++{ ++ struct ov490_priv *priv = to_ov490(client); ++ int tmp_addr; ++ ++ if (priv->max9286_addr) { ++ if (priv->gpio_resetb < 1 || priv->gpio_resetb > 5) ++ return; ++ ++ tmp_addr = client->addr; ++ /* get out from sensor reset */ ++ client->addr = priv->max9271_addr; /* MAX9271 I2C address */ ++ reg8_write(client, 0x0f, (0xfe & ~BIT(priv->gpio_resetb)) | ++ (priv->active_low_resetb ? 0 : BIT(priv->gpio_resetb))); /* set GPIOn value to reset */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x0f, (0xfe & ~BIT(priv->gpio_resetb)) | ++ (priv->active_low_resetb ? BIT(priv->gpio_resetb) : 0)); /* set GPIOn value to un-reset */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ client->addr = tmp_addr; ++ } ++ ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x4_addr; /* TI9x4 I2C address */ ++ ++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x6e, 0x8a); /* set GPIO1 value to reset */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x6e, 0x9a); /* set GPIO1 value to un-reset */ ++ } ++} ++ ++static int ov490_set_regs(struct i2c_client *client, ++ const struct ov490_reg *regs, int nr_regs) ++{ ++ int i; ++ ++ for (i = 0; i < nr_regs; i++) { ++ if (reg16_write(client, regs[i].reg, regs[i].val)) { ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, regs[i].reg, regs[i].val); ++ } ++ } ++ ++ return 0; ++} ++ ++static u8 ov490_ov10640_read(struct i2c_client *client, u16 addr) ++{ ++ u8 reg_val = 0; ++ ++ reg16_write(client, 0xFFFD, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x5000, 0x01); /* read operation */ ++ reg16_write(client, 0x5001, addr >> 8); ++ reg16_write(client, 0x5002, addr & 0xff); ++ reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x00C0, 0xc1); ++ reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(1000, 1500); /* wait 1 ms */ ++ reg16_read(client, 0x5000, ®_val); ++ ++ return reg_val; ++} ++ ++static void ov490_ov10640_write(struct i2c_client *client, u16 addr, u8 val) ++{ ++ reg16_write(client, 0xFFFD, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x5000, 0x00); /* write operation */ ++ reg16_write(client, 0x5001, addr >> 8); ++ reg16_write(client, 0x5002, addr & 0xff); ++ reg16_write(client, 0x5003, val); ++ reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x00C0, 0xc1); ++} ++ ++static int ov490_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ return 0; ++} ++ ++static int ov490_get_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov490_priv *priv = to_ov490(client); ++ ++ if (format->pad) ++ return -EINVAL; ++ ++ mf->width = priv->rect.width; ++ mf->height = priv->rect.height; ++ mf->code = MEDIA_BUS_FMT_YUYV8_2X8; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static int ov490_set_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ ++ mf->code = MEDIA_BUS_FMT_YUYV8_2X8; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ if (format->which == V4L2_SUBDEV_FORMAT_TRY) ++ cfg->try_fmt = *mf; ++ ++ return 0; ++} ++ ++static int ov490_enum_mbus_code(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ if (code->pad || code->index > 0) ++ return -EINVAL; ++ ++ code->code = MEDIA_BUS_FMT_YUYV8_2X8; ++ ++ return 0; ++} ++ ++static int ov490_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov490_priv *priv = to_ov490(client); ++ ++ memcpy(edid->edid, priv->id, 6); ++ ++ edid->edid[6] = 0xff; ++ edid->edid[7] = client->addr; ++ edid->edid[8] = OV490_VERSION_REG >> 8; ++ edid->edid[9] = OV490_VERSION_REG & 0xff; ++ ++ return 0; ++} ++ ++static int ov490_set_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct v4l2_rect *rect = &sel->r; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov490_priv *priv = to_ov490(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || ++ sel->target != V4L2_SEL_TGT_CROP) ++ return -EINVAL; ++ ++ rect->left = ALIGN(rect->left, 2); ++ rect->top = ALIGN(rect->top, 2); ++ rect->width = ALIGN(rect->width, 2); ++ rect->height = ALIGN(rect->height, 2); ++ ++ if ((rect->left + rect->width > priv->max_width) || ++ (rect->top + rect->height > priv->max_height)) ++ *rect = priv->rect; ++ ++ priv->rect.left = rect->left; ++ priv->rect.top = rect->top; ++ priv->rect.width = rect->width; ++ priv->rect.height = rect->height; ++ ++ return 0; ++} ++ ++static int ov490_get_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov490_priv *priv = to_ov490(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) ++ return -EINVAL; ++ ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = priv->max_width; ++ sel->r.height = priv->max_height; ++ return 0; ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = priv->max_width; ++ sel->r.height = priv->max_height; ++ return 0; ++ case V4L2_SEL_TGT_CROP: ++ sel->r = priv->rect; ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int ov490_g_mbus_config(struct v4l2_subdev *sd, ++ struct v4l2_mbus_config *cfg) ++{ ++ cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | ++ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; ++ cfg->type = V4L2_MBUS_CSI2; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int ov490_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ int ret; ++ u8 val = 0; ++ ++ ret = reg16_read(client, (u16)reg->reg, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u16); ++ ++ return 0; ++} ++ ++static int ov490_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ int ret; ++ ++ ret = reg16_write(client, (u16)reg->reg, (u8)reg->val); ++ if ((u8)reg->reg == 0xFFFD) ++ usleep_range(100, 150); /* wait 100 us */ ++ if ((u8)reg->reg == 0xFFFE) ++ usleep_range(100, 150); /* wait 100 us */ ++ return ret; ++} ++#endif ++ ++static struct v4l2_subdev_core_ops ov490_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = ov490_g_register, ++ .s_register = ov490_s_register, ++#endif ++}; ++ ++static int ov490_s_gamma(int a, int ref) ++{ ++ if ((a + ref) > 0xff) ++ return 0xff; ++ ++ if ((a + ref) < 0) ++ return 0; ++ ++ return a + ref; ++} ++ ++static int ov490_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct v4l2_subdev *sd = to_sd(ctrl); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov490_priv *priv = to_ov490(client); ++ int ret = -EINVAL; ++ ++ if (!priv->init_complete) ++ return 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_BRIGHTNESS: ++ /* SDE (rough) brightness */ ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x00); ++ ret |= reg16_write(client, 0x5001, ctrl->val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xf1); ++ break; ++ case V4L2_CID_CONTRAST: ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, ctrl->val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xfd); ++ break; ++ case V4L2_CID_SATURATION: ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, ctrl->val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xf3); ++ break; ++ case V4L2_CID_HUE: ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, ctrl->val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xf5); ++ break; ++ case V4L2_CID_GAMMA: ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, ov490_s_gamma(ctrl->val, 0x12)); ++ ret |= reg16_write(client, 0x5001, ov490_s_gamma(ctrl->val, 0x20)); ++ ret |= reg16_write(client, 0x5002, ov490_s_gamma(ctrl->val, 0x3b)); ++ ret |= reg16_write(client, 0x5003, ov490_s_gamma(ctrl->val, 0x5d)); ++ ret |= reg16_write(client, 0x5004, ov490_s_gamma(ctrl->val, 0x6a)); ++ ret |= reg16_write(client, 0x5005, ov490_s_gamma(ctrl->val, 0x76)); ++ ret |= reg16_write(client, 0x5006, ov490_s_gamma(ctrl->val, 0x81)); ++ ret |= reg16_write(client, 0x5007, ov490_s_gamma(ctrl->val, 0x8b)); ++ ret |= reg16_write(client, 0x5008, ov490_s_gamma(ctrl->val, 0x96)); ++ ret |= reg16_write(client, 0x5009, ov490_s_gamma(ctrl->val, 0x9e)); ++ ret |= reg16_write(client, 0x500a, ov490_s_gamma(ctrl->val, 0xae)); ++ ret |= reg16_write(client, 0x500b, ov490_s_gamma(ctrl->val, 0xbc)); ++ ret |= reg16_write(client, 0x500c, ov490_s_gamma(ctrl->val, 0xcf)); ++ ret |= reg16_write(client, 0x500d, ov490_s_gamma(ctrl->val, 0xde)); ++ ret |= reg16_write(client, 0x500e, ov490_s_gamma(ctrl->val, 0xec)); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xf9); ++ break; ++ case V4L2_CID_SHARPNESS: ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, ctrl->val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xfb); ++ break; ++ case V4L2_CID_AUTOGAIN: ++ case V4L2_CID_GAIN: ++ case V4L2_CID_EXPOSURE: ++ if (ctrl->id == V4L2_CID_AUTOGAIN) ++ priv->autogain = ctrl->val; ++ if (ctrl->id == V4L2_CID_GAIN) ++ priv->gain = ctrl->val; ++ if (ctrl->id == V4L2_CID_EXPOSURE) ++ priv->exposure = ctrl->val; ++ ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, !priv->autogain); ++ ret |= reg16_write(client, 0x5001, priv->exposure >> 8); ++ ret |= reg16_write(client, 0x5002, priv->exposure & 0xff); ++ ret |= reg16_write(client, 0x5003, priv->exposure >> 8); ++ ret |= reg16_write(client, 0x5004, priv->exposure & 0xff); ++ ret |= reg16_write(client, 0x5005, priv->exposure >> 8); ++ ret |= reg16_write(client, 0x5006, priv->exposure & 0xff); ++ ret |= reg16_write(client, 0x5007, priv->gain >> 8); ++ ret |= reg16_write(client, 0x5008, priv->gain & 0xff); ++ ret |= reg16_write(client, 0x5009, priv->gain >> 8); ++ ret |= reg16_write(client, 0x500a, priv->gain & 0xff); ++ ret |= reg16_write(client, 0x500b, priv->gain >> 8); ++ ret |= reg16_write(client, 0x500c, priv->gain & 0xff); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xea); ++ break; ++ case V4L2_CID_AUTO_WHITE_BALANCE: ++ case V4L2_CID_RED_BALANCE: ++ case V4L2_CID_BLUE_BALANCE: ++ if (ctrl->id == V4L2_CID_AUTO_WHITE_BALANCE) ++ priv->awb = ctrl->val; ++ if (ctrl->id == V4L2_CID_RED_BALANCE) { ++ priv->red = ctrl->val; ++ priv->red <<= 8; ++ priv->green_r = priv->red / 2; ++ } ++ if (ctrl->id == V4L2_CID_BLUE_BALANCE) { ++ priv->blue = ctrl->val; ++ priv->blue <<= 8; ++ priv->green_b = priv->blue / 2; ++ } ++ ++ 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->awb); ++ ret |= reg16_write(client, 0x5001, priv->red >> 8); ++ ret |= reg16_write(client, 0x5002, priv->red & 0xff); ++ ret |= reg16_write(client, 0x5003, priv->green_r >> 8); ++ ret |= reg16_write(client, 0x5004, priv->green_r & 0xff); ++ ret |= reg16_write(client, 0x5005, priv->green_b >> 8); ++ ret |= reg16_write(client, 0x5006, priv->green_b & 0xff); ++ ret |= reg16_write(client, 0x5007, priv->blue >> 8); ++ ret |= reg16_write(client, 0x5008, priv->blue & 0xff); ++ ret |= reg16_write(client, 0x5009, priv->red >> 8); ++ ret |= reg16_write(client, 0x500a, priv->red & 0xff); ++ ret |= reg16_write(client, 0x500b, priv->green_r >> 8); ++ ret |= reg16_write(client, 0x500c, priv->green_r & 0xff); ++ ret |= reg16_write(client, 0x500d, priv->green_b >> 8); ++ ret |= reg16_write(client, 0x500e, priv->green_b & 0xff); ++ ret |= reg16_write(client, 0x500f, priv->blue >> 8); ++ ret |= reg16_write(client, 0x5010, priv->blue & 0xff); ++ ret |= reg16_write(client, 0x5011, priv->red >> 8); ++ ret |= reg16_write(client, 0x5012, priv->red & 0xff); ++ ret |= reg16_write(client, 0x5013, priv->green_r >> 8); ++ ret |= reg16_write(client, 0x5014, priv->green_r & 0xff); ++ ret |= reg16_write(client, 0x5015, priv->green_b >> 8); ++ ret |= reg16_write(client, 0x5016, priv->green_b & 0xff); ++ ret |= reg16_write(client, 0x5017, priv->blue >> 8); ++ ret |= reg16_write(client, 0x5018, priv->blue & 0xff); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xeb); ++ break; ++ case V4L2_CID_HFLIP: ++#if 1 ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, ctrl->val); ++ ret |= reg16_write(client, 0x5001, 0x00); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xdc); ++#else ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x01); // read 0x3128 ++ ret |= reg16_write(client, 0x5001, 0x31); ++ ret |= reg16_write(client, 0x5002, 0x28); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_read(client, 0x5000, &val); ++ val &= ~(0x1 << 0); ++ val |= (ctrl->val << 0); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x00); // write 0x3128 ++ ret |= reg16_write(client, 0x5001, 0x31); ++ ret |= reg16_write(client, 0x5002, 0x28); ++ ret |= reg16_write(client, 0x5003, val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x01); // read 0x3291 ++ ret |= reg16_write(client, 0x5001, 0x32); ++ ret |= reg16_write(client, 0x5002, 0x91); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_read(client, 0x5000, &val); ++ val &= ~(0x1 << 1); ++ val |= (ctrl->val << 1); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x00); // write 0x3291 ++ ret |= reg16_write(client, 0x5001, 0x32); ++ ret |= reg16_write(client, 0x5002, 0x91); ++ ret |= reg16_write(client, 0x5003, val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x01); // read 0x3090 ++ ret |= reg16_write(client, 0x5001, 0x30); ++ ret |= reg16_write(client, 0x5002, 0x90); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_read(client, 0x5000, &val); ++ val &= ~(0x1 << 2); ++ val |= (ctrl->val << 2); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x00); // write 0x3090 ++ ret |= reg16_write(client, 0x5001, 0x30); ++ ret |= reg16_write(client, 0x5002, 0x90); ++ ret |= reg16_write(client, 0x5003, val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++#endif ++ break; ++ case V4L2_CID_VFLIP: ++#if 1 ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, ctrl->val); ++ ret |= reg16_write(client, 0x5001, 0x01); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xdc); ++#else ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x01); // read 0x3128 ++ ret |= reg16_write(client, 0x5001, 0x31); ++ ret |= reg16_write(client, 0x5002, 0x28); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_read(client, 0x5000, &val); ++ val &= ~(0x1 << 1); ++ val |= (ctrl->val << 1); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x00); // write 0x3128 ++ ret |= reg16_write(client, 0x5001, 0x31); ++ ret |= reg16_write(client, 0x5002, 0x28); ++ ret |= reg16_write(client, 0x5003, val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x01); // read 0x3291 ++ ret |= reg16_write(client, 0x5001, 0x32); ++ ret |= reg16_write(client, 0x5002, 0x91); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_read(client, 0x5000, &val); ++ val &= ~(0x1 << 2); ++ val |= (ctrl->val << 2); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x00); // write 0x3291 ++ ret |= reg16_write(client, 0x5001, 0x32); ++ ret |= reg16_write(client, 0x5002, 0x91); ++ ret |= reg16_write(client, 0x5003, val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x01); // read 0x3090 ++ ret |= reg16_write(client, 0x5001, 0x30); ++ ret |= reg16_write(client, 0x5002, 0x90); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_read(client, 0x5000, &val); ++ val &= ~(0x1 << 3); ++ val |= (ctrl->val << 3); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x00); // write 0x3090 ++ ret |= reg16_write(client, 0x5001, 0x30); ++ ret |= reg16_write(client, 0x5002, 0x90); ++ ret |= reg16_write(client, 0x5003, val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++#endif ++ break; ++ case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: ++ ret = 0; ++ break; ++ } ++ ++ return ret; ++} ++ ++static const struct v4l2_ctrl_ops ov490_ctrl_ops = { ++ .s_ctrl = ov490_s_ctrl, ++}; ++ ++static struct v4l2_subdev_video_ops ov490_video_ops = { ++ .s_stream = ov490_s_stream, ++ .g_mbus_config = ov490_g_mbus_config, ++}; ++ ++static const struct v4l2_subdev_pad_ops ov490_subdev_pad_ops = { ++ .get_edid = ov490_get_edid, ++ .enum_mbus_code = ov490_enum_mbus_code, ++ .get_selection = ov490_get_selection, ++ .set_selection = ov490_set_selection, ++ .get_fmt = ov490_get_fmt, ++ .set_fmt = ov490_set_fmt, ++}; ++ ++static struct v4l2_subdev_ops ov490_subdev_ops = { ++ .core = &ov490_core_ops, ++ .video = &ov490_video_ops, ++ .pad = &ov490_subdev_pad_ops, ++}; ++ ++static void ov490_otp_id_read(struct i2c_client *client) ++{ ++ struct ov490_priv *priv = to_ov490(client); ++ int i; ++ int otp_bank0_allzero = 1; ++ ++#if 0 ++ /* read camera id from ov490 OTP memory */ ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x28); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0xE084, 0x40); /* manual mode, bank#0 */ ++ reg16_write(client, 0xE081, 1); /* start OTP read */ ++ ++ usleep_range(25000, 26000); /* wait 25 ms */ ++ ++ for (i = 0; i < 6; i++) ++ reg16_read(client, 0xe000 + i + 4, &priv->id[i]); ++#else ++ /* read camera id from ov10640 OTP memory */ ++ ov490_ov10640_write(client, 0x349C, 1); ++ usleep_range(25000, 25500); /* wait 25 ms */ ++ ++ for (i = 0; i < 6; i++) { ++ /* first 6 bytes are equal on all ov10640 */ ++ priv->id[i] = ov490_ov10640_read(client, 0x349e + i + 6); ++ if (priv->id[i]) ++ otp_bank0_allzero = 0; ++ } ++ ++ if (otp_bank0_allzero) { ++ ov490_ov10640_write(client, 0x3495, 0x41); /* bank#1 */ ++ ov490_ov10640_write(client, 0x349C, 1); ++ usleep_range(25000, 25500); /* wait 25 ms */ ++ ++ for (i = 0; i < 6; i++) ++ priv->id[i] = ov490_ov10640_read(client, 0x34ae + i); ++ } ++#endif ++} ++ ++static ssize_t ov490_otp_id_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(to_i2c_client(dev)); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov490_priv *priv = to_ov490(client); ++ ++ return snprintf(buf, 32, "%02x:%02x:%02x:%02x:%02x:%02x\n", ++ priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++} ++ ++static DEVICE_ATTR(otp_id_ov490, S_IRUGO, ov490_otp_id_show, NULL); ++ ++static int ov490_initialize(struct i2c_client *client) ++{ ++ struct ov490_priv *priv = to_ov490(client); ++ u8 val = 0; ++ u8 pid = 0, ver = 0; ++ int ret = 0, timeout, retry_timeout = 3; ++ ++ if (priv->is_fixed_sensor) { ++ dev_info(&client->dev, "ov490/ov10640 fixed-sensor res %dx%d\n", priv->max_width, priv->max_height); ++ return 0; ++ } ++ ++ ov490_s_port(client, 1); ++ ++ /* check and show product ID and manufacturer ID */ ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_read(client, OV490_PID, &pid); ++ reg16_read(client, OV490_VER, &ver); ++ ++ if (OV490_VERSION(pid, ver) != OV490_VERSION_REG) { ++ dev_dbg(&client->dev, "Product ID error %x:%x\n", pid, ver); ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ if (unlikely(conf_link)) ++ goto out; ++ ++again: ++ /* Check if firmware booted by reading stream-on status */ ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x29); ++ usleep_range(100, 150); /* wait 100 us */ ++ for (timeout = 300; timeout > 0; timeout--) { ++ reg16_read(client, 0xd000, &val); ++ if (val == 0x0c) ++ break; ++ mdelay(1); ++ } ++ ++ /* wait firmware apps started by reading OV10640 ID */ ++ for (;timeout > 0; timeout--) { ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x5000, 0x01); ++ reg16_write(client, 0x5001, 0x30); ++ reg16_write(client, 0x5002, 0x0a); ++ reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0xC0, 0xc1); ++ reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(1000, 1500); /* wait 1 ms */ ++ reg16_read(client, 0x5000, &val); ++ if (val == 0xa6) ++ break; ++ mdelay(1); ++ } ++ ++ if (!timeout) { ++ dev_err(&client->dev, "Timeout firmware boot wait, retrying\n"); ++ /* reset OV10640 using RESETB pin controlled by OV490 GPIO0 */ ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x0050, 0x01); ++ reg16_write(client, 0x0054, 0x01); ++ reg16_write(client, 0x0058, 0x00); ++ mdelay(10); ++ reg16_write(client, 0x0058, 0x01); ++ /* reset OV490 using RESETB pin controlled by serializer */ ++ ov490_reset(client); ++ if (retry_timeout--) ++ goto again; ++ } ++ ++ /* read resolution used by current firmware */ ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x82); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_read(client, OV490_ISP_HSIZE_HIGH, &val); ++ priv->max_width = val; ++ reg16_read(client, OV490_ISP_HSIZE_LOW, &val); ++ priv->max_width = (priv->max_width << 8) | val; ++ reg16_read(client, OV490_ISP_VSIZE_HIGH, &val); ++ priv->max_height = val; ++ reg16_read(client, OV490_ISP_VSIZE_LOW, &val); ++ priv->max_height = (priv->max_height << 8) | val; ++ /* Program wizard registers */ ++ ov490_set_regs(client, ov490_regs_wizard, ARRAY_SIZE(ov490_regs_wizard)); ++ /* Set DVP bit swap */ ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x28); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x6009, priv->dvp_order << 4); ++ /* Read OTP IDs */ ++ ov490_otp_id_read(client); ++ ++out: ++ dev_info(&client->dev, "ov490/ov10640 PID %x%x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, ver, priv->max_width, priv->max_height, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++err: ++ ov490_s_port(client, 0); ++ ++ return ret; ++} ++ ++static int ov490_parse_dt(struct device_node *np, struct ov490_priv *priv) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); ++ int i; ++ const char *fixed_sensor; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ int tmp_addr = 0; ++ ++ for (i = 0; ; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; ++ ++ of_node_put(endpoint); ++ ++ of_property_read_u32(endpoint, "dvp-order", &priv->dvp_order); ++ ++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); ++ if (!rendpoint) ++ continue; ++ ++ if (!of_property_read_u32(rendpoint, "max9271-addr", &priv->max9271_addr) && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->max9286_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) { ++ if (of_property_read_u32(rendpoint->parent->parent, "maxim,resetb-gpio", &priv->gpio_resetb)) { ++ priv->gpio_resetb = -1; ++ } else { ++ if (of_property_read_bool(rendpoint->parent->parent, "maxim,resetb-active-high")) ++ priv->active_low_resetb = false; ++ else ++ priv->active_low_resetb = true; ++ } ++ break; ++ } ++ ++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti9x4") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti9x4_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ } ++ ++ if (!priv->max9286_addr && !priv->ti9x4_addr) { ++ dev_err(&client->dev, "deserializer does not present for OV490\n"); ++ return -EINVAL; ++ } ++ ++ ov490_s_port(client, 1); ++ ++ /* setup I2C translator address */ ++ tmp_addr = client->addr; ++ if (priv->max9286_addr) { ++ client->addr = priv->max9271_addr; /* Serializer I2C address */ ++ ++ reg8_write(client, 0x09, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x0A, OV490_I2C_ADDR << 1); /* Sensor native I2C address */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ }; ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x4_addr; /* Deserializer I2C address */ ++ ++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x5d, OV490_I2C_ADDR << 1); /* Sensor native I2C address */ ++ ++ reg8_write(client, 0x6e, 0x9a); /* GPIO0 - fsin, GPIO1 - resetb */ ++ } ++ client->addr = tmp_addr; ++ ++ if (!of_property_read_string(np, "maxim,fixed-sensor", &fixed_sensor) && ++ strcmp(fixed_sensor, "ov490") == 0) { ++ if (of_property_read_u32(np, "maxim,width", &priv->max_width)) ++ priv->max_width = 1280; ++ ++ if (of_property_read_u32(np, "maxim,height", &priv->max_height)) ++ priv->max_height = 966; ++ ++ priv->is_fixed_sensor = true; ++ } ++ ++ /* module params override dts */ ++ if (dvp_order) ++ priv->dvp_order = dvp_order; ++ if (max_width && max_height) { ++ priv->max_width = max_width; ++ priv->max_height = max_height; ++ priv->is_fixed_sensor = true; ++ } ++ ++ return 0; ++} ++ ++static int ov490_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct ov490_priv *priv; ++ struct v4l2_ctrl *ctrl; ++ int ret; ++ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ v4l2_i2c_subdev_init(&priv->sd, client, &ov490_subdev_ops); ++ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; ++ ++ priv->exposure = 0x100; ++ priv->gain = 0x100; ++ priv->autogain = 1; ++ priv->red = 0x400; ++ priv->blue = 0x400; ++ priv->green_r = priv->red / 2; ++ priv->green_b = priv->blue / 2; ++ priv->awb = 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_AUTO_WHITE_BALANCE, 0, 1, 1, priv->autogain); ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_RED_BALANCE, 2, 0xf, 1, priv->red >> 8); ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_BLUE_BALANCE, 2, 0xf, 1, priv->blue >> 8); ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 1); ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ ctrl = v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 9); ++ if (ctrl) ++ ctrl->flags &= ~V4L2_CTRL_FLAG_READ_ONLY; ++ priv->sd.ctrl_handler = &priv->hdl; ++ ++ ret = priv->hdl.error; ++ if (ret) ++ goto cleanup; ++ ++ v4l2_ctrl_handler_setup(&priv->hdl); ++ ++ priv->pad.flags = MEDIA_PAD_FL_SOURCE; ++ priv->sd.entity.flags |= MEDIA_ENT_F_CAM_SENSOR; ++ ret = media_entity_pads_init(&priv->sd.entity, 1, &priv->pad); ++ if (ret < 0) ++ goto cleanup; ++ ++ ret = ov490_parse_dt(client->dev.of_node, priv); ++ if (ret) ++ goto cleanup; ++ ++ ret = ov490_initialize(client); ++ if (ret < 0) ++ goto cleanup; ++ ++ priv->rect.left = 0; ++ priv->rect.top = 0; ++ priv->rect.width = priv->max_width; ++ priv->rect.height = priv->max_height; ++ ++ ret = v4l2_async_register_subdev(&priv->sd); ++ if (ret) ++ goto cleanup; ++ ++ if (device_create_file(&client->dev, &dev_attr_otp_id_ov490) != 0) { ++ dev_err(&client->dev, "sysfs otp_id entry creation failed\n"); ++ goto cleanup; ++ } ++ ++ priv->init_complete = 1; ++ ++ return 0; ++ ++cleanup: ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++#ifdef CONFIG_SOC_CAMERA_OV490_OV10640 ++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", ++ client->addr, client->adapter->name); ++#endif ++ return ret; ++} ++ ++static int ov490_remove(struct i2c_client *client) ++{ ++ struct ov490_priv *priv = i2c_get_clientdata(client); ++ ++ device_remove_file(&client->dev, &dev_attr_otp_id_ov490); ++ v4l2_async_unregister_subdev(&priv->sd); ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_SOC_CAMERA_OV490_OV10640 ++static const struct i2c_device_id ov490_id[] = { ++ { "ov490-ov10640", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, ov490_id); ++ ++static const struct of_device_id ov490_of_ids[] = { ++ { .compatible = "ovti,ov490-ov10640", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ov490_of_ids); ++ ++static struct i2c_driver ov490_i2c_driver = { ++ .driver = { ++ .name = "ov490-ov10640", ++ .of_match_table = ov490_of_ids, ++ }, ++ .probe = ov490_probe, ++ .remove = ov490_remove, ++ .id_table = ov490_id, ++}; ++ ++module_i2c_driver(ov490_i2c_driver); ++ ++MODULE_DESCRIPTION("SoC Camera driver for OV490-OV10640"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); ++#endif +diff --git a/drivers/media/i2c/soc_camera/ov490_ov10640.h b/drivers/media/i2c/soc_camera/ov490_ov10640.h +new file mode 100644 +index 0000000..b22e93e +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov490_ov10640.h +@@ -0,0 +1,102 @@ ++/* ++ * 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. ++ */ ++ ++//#define OV490_DISPLAY_PATTERN ++ ++struct ov490_reg { ++ u16 reg; ++ u8 val; ++}; ++ ++static const struct ov490_reg ov490_regs_wizard[] = { ++/* The following registers should match firmware */ ++{0xfffd, 0x80}, ++{0xfffe, 0x82}, ++{0x0071, 0x11}, ++{0x0075, 0x11}, ++{0xfffe, 0x29}, ++{0x6010, 0x01}, ++/* ov490 EMB line disable in YUV and RAW data, NOTE: EMB line is still used in ISP and sensor */ ++{0xe000, 0x14}, ++#if 0 /* do not disable EMB line in ISP! */ ++{0x4017, 0x00}, ++#endif ++{0xfffe, 0x28}, ++{0x6000, 0x04}, ++{0x6004, 0x00}, ++{0x6008, 0x00}, // PCLK polarity - useless due to silicon bug -> use 0x808000bb register ++{0xfffe, 0x80}, ++{0x0091, 0x00}, ++{0x00bb, 0x1d}, // bit[3]=0 - PCLK polarity workaround ++/* ov10640 EMB line disable */ ++#if 0 /* do not disable EMB line in sensor! */ ++{0xfffe, 0x19}, ++{0x5000, 0x00}, ++{0x5001, 0x30}, ++{0x5002, 0x91}, ++{0x5003, 0x08}, ++{0xfffe, 0x80}, ++{0x00c0, 0xc1}, ++#endif ++/* Ov490 FSIN: app_fsin_from_fsync */ ++{0xfffe, 0x85}, ++{0x0008, 0x00}, ++{0x0009, 0x01}, ++{0x000A, 0x05}, // fsin0 src ++{0x000B, 0x00}, ++{0x0030, 0x02}, // fsin0_delay ++{0x0031, 0x00}, ++{0x0032, 0x00}, ++{0x0033, 0x00}, ++{0x0038, 0x02}, // fsin1_delay ++{0x0039, 0x00}, ++{0x003A, 0x00}, ++{0x003B, 0x00}, ++{0x0070, 0x2C}, // fsin0_length ++{0x0071, 0x01}, ++{0x0072, 0x00}, ++{0x0073, 0x00}, ++{0x0074, 0x64}, // fsin1_length ++{0x0075, 0x00}, ++{0x0076, 0x00}, ++{0x0077, 0x00}, ++{0x0000, 0x14}, ++{0x0001, 0x00}, ++{0x0002, 0x00}, ++{0x0003, 0x00}, ++{0x0004, 0x32}, // load fsin0,load fsin1,load other, it will be cleared automatically. ++{0x0005, 0x00}, ++{0x0006, 0x00}, ++{0x0007, 0x00}, ++{0xfffe, 0x80}, ++{0x0081, 0x00}, // 03;SENSOR FSIN ++/* ov10640 FSIN */ ++{0xfffe, 0x19}, ++{0x5000, 0x00}, ++{0x5001, 0x30}, ++{0x5002, 0x8c}, ++{0x5003, 0xb2}, ++{0xfffe, 0x80}, ++{0x00c0, 0xc1}, ++/* ov10640 HFLIP=1 by default */ ++{0xfffe, 0x19}, ++{0x5000, 0x01}, ++{0x5001, 0x00}, ++{0xfffe, 0x80}, ++{0x00c0, 0xdc}, ++#ifdef OV490_DISPLAY_PATTERN ++{0xfffd, 0x80}, ++{0xfffe, 0x19}, ++{0x5000, 0x02}, ++{0xfffe, 0x80}, ++{0x00c0, 0xd6}, ++#endif ++}; +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..812f367 +index 0000000..a371e22 --- /dev/null -+++ b/drivers/media/i2c/soc_camera/ov490_ov10640.c -@@ -0,0 +1,1133 @@ ++++ b/drivers/media/i2c/soc_camera/ov495_ov2775.c +@@ -0,0 +1,650 @@ +/* -+ * OmniVision ov490-ov10640 sensor camera driver ++ * OmniVision ov495-ov2775 sensor camera driver + * -+ * Copyright (C) 2016-2018 Cogent Embedded, Inc. ++ * 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 @@ -7578,40 +13237,32 @@ index 0000000..812f367 +#include +#include + -+#include "max9286.h" -+#include "ov490_ov10640.h" ++#include "ov495_ov2775.h" + -+#define OV490_I2C_ADDR 0x24 ++#define OV495_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 OV495_PID 0x300a ++#define OV495_VER 0x300b ++#define OV495_VERSION_REG 0x0495 ++#define OV495_VERSION(pid, ver) (((pid) << 8) | ((ver) & 0xff)) + -+#define OV490_ISP_HSIZE_LOW 0x60 -+#define OV490_ISP_HSIZE_HIGH 0x61 -+#define OV490_ISP_VSIZE_LOW 0x62 -+#define OV490_ISP_VSIZE_HIGH 0x63 ++#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 ov490_priv { ++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; -+ char is_fixed_sensor; + int init_complete; + u8 id[6]; + int exposure; + int gain; + int autogain; -+ int red; -+ int green_r; -+ int green_b; -+ int blue; -+ int awb; -+ int dvp_order; + /* serializers */ + int max9286_addr; + int max9271_addr; @@ -7619,79 +13270,28 @@ index 0000000..812f367 + int ti9x3_addr; + int port; + int gpio_resetb; -+ int active_low_resetb; + int gpio_fsin; -+}; -+ -+static int conf_link; -+module_param(conf_link, int, 0644); -+MODULE_PARM_DESC(conf_link, " Force configuration link. Used only if robust firmware flashing required (f.e. recovery)"); -+ -+static int dvp_order; -+module_param(dvp_order, int, 0644); -+MODULE_PARM_DESC(dvp_order, " DVP bus bits order"); -+ -+static int max_width; -+module_param(max_width, int, 0644); -+MODULE_PARM_DESC(max_width, " Fixed sensor width"); + -+static int max_height; -+module_param(max_height, int, 0644); -+MODULE_PARM_DESC(max_height, " Fixed sensor height"); ++}; + -+static inline struct ov490_priv *to_ov490(const struct i2c_client *client) -+{ -+ return container_of(i2c_get_clientdata(client), struct ov490_priv, sd); -+} ++static int force_conf_link; + -+static void ov490_s_port(struct i2c_client *client, int fwd_en) ++static __init int ov495_force_conf_link(char *str) +{ -+ 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(5000, 5500); /* wait 5ms */ -+ client->addr = tmp_addr; -+ }; ++ /* 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 void ov490_reset(struct i2c_client *client) ++static inline struct ov495_priv *to_ov495(const struct i2c_client *client) +{ -+ struct ov490_priv *priv = to_ov490(client); -+ int tmp_addr; -+ -+ if (priv->max9286_addr) { -+ if (priv->gpio_resetb < 1 || priv->gpio_resetb > 5) -+ return; -+ -+ tmp_addr = client->addr; -+ /* get out from sensor reset */ -+ client->addr = priv->max9271_addr; /* MAX9271 I2C address */ -+ reg8_write(client, 0x0f, (0xfe & ~BIT(priv->gpio_resetb)) | -+ (priv->active_low_resetb ? 0 : BIT(priv->gpio_resetb))); /* set GPIOn value to reset */ -+ usleep_range(2000, 2500); /* wait 2ms */ -+ reg8_write(client, 0x0f, (0xfe & ~BIT(priv->gpio_resetb)) | -+ (priv->active_low_resetb ? BIT(priv->gpio_resetb) : 0)); /* set GPIOn value to un-reset */ -+ usleep_range(2000, 2500); /* wait 2ms */ -+ client->addr = tmp_addr; -+ } -+ -+ if (priv->ti9x4_addr) { -+ client->addr = priv->ti9x4_addr; /* TI9x4 I2C address */ -+ -+ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ -+ usleep_range(2000, 2500); /* wait 2ms */ -+ reg8_write(client, 0x6e, 0x8a); /* set GPIO1 value to reset */ -+ usleep_range(2000, 2500); /* wait 2ms */ -+ reg8_write(client, 0x6e, 0x9a); /* set GPIO1 value to un-reset */ -+ } ++ return container_of(i2c_get_clientdata(client), struct ov495_priv, sd); +} + -+static int ov490_set_regs(struct i2c_client *client, -+ const struct ov490_reg *regs, int nr_regs) ++static int ov495_set_regs(struct i2c_client *client, ++ const struct ov495_reg *regs, int nr_regs) +{ + int i; + @@ -7705,54 +13305,18 @@ index 0000000..812f367 + return 0; +} + -+static u8 ov490_ov10640_read(struct i2c_client *client, u16 addr) -+{ -+ u8 reg_val = 0; -+ -+ reg16_write(client, 0xFFFD, 0x80); -+ usleep_range(100, 150); /* wait 100 us */ -+ reg16_write(client, 0xFFFE, 0x19); -+ usleep_range(100, 150); /* wait 100 us */ -+ reg16_write(client, 0x5000, 0x01); /* read operation */ -+ reg16_write(client, 0x5001, addr >> 8); -+ reg16_write(client, 0x5002, addr & 0xff); -+ reg16_write(client, 0xFFFE, 0x80); -+ usleep_range(100, 150); /* wait 100 us */ -+ reg16_write(client, 0x00C0, 0xc1); -+ reg16_write(client, 0xFFFE, 0x19); -+ usleep_range(1000, 1500); /* wait 1 ms */ -+ reg16_read(client, 0x5000, ®_val); -+ -+ return reg_val; -+} -+ -+static void ov490_ov10640_write(struct i2c_client *client, u16 addr, u8 val) -+{ -+ reg16_write(client, 0xFFFD, 0x80); -+ usleep_range(100, 150); /* wait 100 us */ -+ reg16_write(client, 0xFFFE, 0x19); -+ usleep_range(100, 150); /* wait 100 us */ -+ reg16_write(client, 0x5000, 0x00); /* write operation */ -+ reg16_write(client, 0x5001, addr >> 8); -+ reg16_write(client, 0x5002, addr & 0xff); -+ reg16_write(client, 0x5003, val); -+ reg16_write(client, 0xFFFE, 0x80); -+ usleep_range(100, 150); /* wait 100 us */ -+ reg16_write(client, 0x00C0, 0xc1); -+} -+ -+static int ov490_s_stream(struct v4l2_subdev *sd, int enable) ++static int ov495_s_stream(struct v4l2_subdev *sd, int enable) +{ + return 0; +} + -+static int ov490_get_fmt(struct v4l2_subdev *sd, ++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 ov490_priv *priv = to_ov490(client); ++ struct ov495_priv *priv = to_ov495(client); + + if (format->pad) + return -EINVAL; @@ -7766,7 +13330,7 @@ index 0000000..812f367 + return 0; +} + -+static int ov490_set_fmt(struct v4l2_subdev *sd, ++static int ov495_set_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *format) +{ @@ -7782,7 +13346,7 @@ index 0000000..812f367 + return 0; +} + -+static int ov490_enum_mbus_code(struct v4l2_subdev *sd, ++static int ov495_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_mbus_code_enum *code) +{ @@ -7794,464 +13358,175 @@ index 0000000..812f367 + 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) ++static int ov495_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); -+ int ret; -+ u8 val = 0; ++ struct ov495_priv *priv = to_ov495(client); + -+ ret = reg16_read(client, (u16)reg->reg, &val); -+ if (ret < 0) -+ return ret; ++ memcpy(edid->edid, priv->id, 6); + -+ reg->val = val; -+ reg->size = sizeof(u16); ++ 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 ov490_s_register(struct v4l2_subdev *sd, -+ const struct v4l2_dbg_register *reg) ++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); -+ int ret; ++ struct ov495_priv *priv = to_ov495(client); + -+ 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 ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || ++ sel->target != V4L2_SEL_TGT_CROP) ++ return -EINVAL; + -+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 -+}; ++ rect->left = ALIGN(rect->left, 2); ++ rect->top = ALIGN(rect->top, 2); ++ rect->width = ALIGN(rect->width, 2); ++ rect->height = ALIGN(rect->height, 2); + -+static int ov490_s_gamma(int a, int ref) -+{ -+ if ((a + ref) > 0xff) -+ return 0xff; ++ if ((rect->left + rect->width > priv->max_width) || ++ (rect->top + rect->height > priv->max_height)) ++ *rect = priv->rect; + -+ if ((a + ref) < 0) -+ return 0; ++ priv->rect.left = rect->left; ++ priv->rect.top = rect->top; ++ priv->rect.width = rect->width; ++ priv->rect.height = rect->height; + -+ return a + ref; ++ return 0; +} + -+static int ov490_s_ctrl(struct v4l2_ctrl *ctrl) ++static int ov495_get_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) +{ -+ 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; ++ struct ov495_priv *priv = to_ov495(client); + -+ 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_AUTO_WHITE_BALANCE: -+ case V4L2_CID_RED_BALANCE: -+ case V4L2_CID_BLUE_BALANCE: -+ if (ctrl->id == V4L2_CID_AUTO_WHITE_BALANCE) -+ priv->awb = ctrl->val; -+ if (ctrl->id == V4L2_CID_RED_BALANCE) { -+ priv->red = ctrl->val; -+ priv->red <<= 8; -+ priv->green_r = priv->red / 2; -+ } -+ if (ctrl->id == V4L2_CID_BLUE_BALANCE) { -+ priv->blue = ctrl->val; -+ priv->blue <<= 8; -+ priv->green_b = priv->blue / 2; -+ } ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) ++ return -EINVAL; + -+ 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->awb); -+ ret |= reg16_write(client, 0x5001, priv->red >> 8); -+ ret |= reg16_write(client, 0x5002, priv->red & 0xff); -+ ret |= reg16_write(client, 0x5003, priv->green_r >> 8); -+ ret |= reg16_write(client, 0x5004, priv->green_r & 0xff); -+ ret |= reg16_write(client, 0x5005, priv->green_b >> 8); -+ ret |= reg16_write(client, 0x5006, priv->green_b & 0xff); -+ ret |= reg16_write(client, 0x5007, priv->blue >> 8); -+ ret |= reg16_write(client, 0x5008, priv->blue & 0xff); -+ ret |= reg16_write(client, 0x5009, priv->red >> 8); -+ ret |= reg16_write(client, 0x500a, priv->red & 0xff); -+ ret |= reg16_write(client, 0x500b, priv->green_r >> 8); -+ ret |= reg16_write(client, 0x500c, priv->green_r & 0xff); -+ ret |= reg16_write(client, 0x500d, priv->green_b >> 8); -+ ret |= reg16_write(client, 0x500e, priv->green_b & 0xff); -+ ret |= reg16_write(client, 0x500f, priv->blue >> 8); -+ ret |= reg16_write(client, 0x5010, priv->blue & 0xff); -+ ret |= reg16_write(client, 0x5011, priv->red >> 8); -+ ret |= reg16_write(client, 0x5012, priv->red & 0xff); -+ ret |= reg16_write(client, 0x5013, priv->green_r >> 8); -+ ret |= reg16_write(client, 0x5014, priv->green_r & 0xff); -+ ret |= reg16_write(client, 0x5015, priv->green_b >> 8); -+ ret |= reg16_write(client, 0x5016, priv->green_b & 0xff); -+ ret |= reg16_write(client, 0x5017, priv->blue >> 8); -+ ret |= reg16_write(client, 0x5018, priv->blue & 0xff); -+ ret |= reg16_write(client, 0xFFFE, 0x80); -+ usleep_range(100, 150); /* wait 100 us */ -+ ret |= reg16_write(client, 0x00C0, 0xeb); -+ 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); ++ 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; ++ } ++} + -+ 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); ++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; + -+ 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); ++ 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 */ -+ 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); ++ if ((u8)reg->reg == 0xFFFE) + usleep_range(100, 150); /* wait 100 us */ -+ ret |= reg16_write(client, 0x00C0, 0xc1); ++ return ret; ++} +#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); ++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 ++}; + -+ 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); ++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, 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); ++ 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, 0x00C0, 0xc1); -+#endif ++ ret |= reg16_write(client, 0x30C0, 0xdc); ++ ret |= reg16_write(client, 0x3516, 0x01); + break; + case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: + ret = 0; @@ -8261,198 +13536,153 @@ index 0000000..812f367 + return ret; +} + -+static const struct v4l2_ctrl_ops ov490_ctrl_ops = { -+ .s_ctrl = ov490_s_ctrl, ++static const struct v4l2_ctrl_ops ov495_ctrl_ops = { ++ .s_ctrl = ov495_s_ctrl, +}; + -+static struct v4l2_subdev_video_ops ov490_video_ops = { -+ .s_stream = ov490_s_stream, -+ .g_mbus_config = ov490_g_mbus_config, ++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 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 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 ov490_subdev_ops = { -+ .core = &ov490_core_ops, -+ .video = &ov490_video_ops, -+ .pad = &ov490_subdev_pad_ops, ++static struct v4l2_subdev_ops ov495_subdev_ops = { ++ .core = &ov495_core_ops, ++ .video = &ov495_video_ops, ++ .pad = &ov495_subdev_pad_ops, +}; + -+static void ov490_otp_id_read(struct i2c_client *client) ++static void ov495_otp_id_read(struct i2c_client *client) +{ -+ struct ov490_priv *priv = to_ov490(client); ++ struct ov495_priv *priv = to_ov495(client); + int i; -+ int otp_bank0_allzero = 1; + +#if 0 -+ /* read camera id from ov490 OTP memory */ ++ /* read camera id from ov495 OTP memory */ + reg16_write(client, 0xFFFD, 0x80); -+ reg16_write(client, 0xFFFE, 0x28); ++ reg16_write(client, 0xFFFE, 0x20); + usleep_range(100, 150); /* wait 100 us */ -+ reg16_write(client, 0xE084, 0x40); /* manual mode, bank#0 */ -+ reg16_write(client, 0xE081, 1); /* start OTP read */ ++ reg16_write(client, 0x7384, 0x40); /* manual mode, bank#0 */ ++ reg16_write(client, 0x7381, 1); /* start OTP read */ + + usleep_range(25000, 26000); /* wait 25 ms */ + + for (i = 0; i < 6; i++) -+ reg16_read(client, 0xe000 + i + 4, &priv->id[i]); ++ reg16_read(client, 0x7300 + i + 4, &priv->id[i]); +#else -+ /* read camera id from ov10640 OTP memory */ -+ ov490_ov10640_write(client, 0x349C, 1); ++ /* read camera id from ov2775 OTP memory */ ++ reg16_write(client, 0x3516, 0x00); /* unlock write */ ++ reg16_write(client, 0x0FFC, 0); ++ reg16_write(client, 0x0500, 0x00); /* write 0x34a1 -> 1 */ ++ reg16_write(client, 0x0501, 0x34); ++ reg16_write(client, 0x0502, 0xa1); ++ reg16_write(client, 0x0503, 1); ++ reg16_write(client, 0x30C0, 0xc1); ++ + usleep_range(25000, 25500); /* wait 25 ms */ + + for (i = 0; i < 6; i++) { -+ /* first 6 bytes are equal on all ov10640 */ -+ priv->id[i] = ov490_ov10640_read(client, 0x349e + i + 6); -+ if (priv->id[i]) -+ otp_bank0_allzero = 0; -+ } -+ -+ if (otp_bank0_allzero) { -+ ov490_ov10640_write(client, 0x3495, 0x41); /* bank#1 */ -+ ov490_ov10640_write(client, 0x349C, 1); -+ usleep_range(25000, 25500); /* wait 25 ms */ -+ -+ for (i = 0; i < 6; i++) -+ priv->id[i] = ov490_ov10640_read(client, 0x34ae + i); ++ reg16_write(client, 0x3516, 0x00); /* unlock write */ ++ reg16_write(client, 0x0500, 0x01); /* read (0x7a00 + i) */ ++ reg16_write(client, 0x0501, 0x7a); ++ reg16_write(client, 0x0502, 0x00 + i + (i < 3 ? 11 : 3)); /* take bytes 11,12,13,6,7,8 */ ++ reg16_write(client, 0x30C0, 0xc1); ++ usleep_range(1000, 1500); /* wait 1 ms */ ++ reg16_read(client, 0x0500, &priv->id[i]); + } +#endif +} + -+static ssize_t ov490_otp_id_show(struct device *dev, ++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 ov490_priv *priv = to_ov490(client); ++ 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_ov490, S_IRUGO, ov490_otp_id_show, NULL); ++static DEVICE_ATTR(otp_id_ov495, S_IRUGO, ov495_otp_id_show, NULL); + -+static int ov490_initialize(struct i2c_client *client) ++static int ov495_initialize(struct i2c_client *client) +{ -+ struct ov490_priv *priv = to_ov490(client); -+ u8 val = 0; ++ struct ov495_priv *priv = to_ov495(client); + u8 pid = 0, ver = 0; -+ int ret = 0, timeout, retry_timeout = 3; -+ -+ if (priv->is_fixed_sensor) { -+ dev_info(&client->dev, "ov490/ov10640 fixed-sensor res %dx%d\n", priv->max_width, priv->max_height); -+ return 0; -+ } -+ -+ ov490_s_port(client, 1); ++ int ret = 0; ++ int tmp_addr; + + /* 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, OV495_PID, &pid); ++ reg16_read(client, OV495_VER, &ver); + -+ if (OV490_VERSION(pid, ver) != OV490_VERSION_REG) { -+ dev_dbg(&client->dev, "Product ID error %x:%x\n", pid, ver); ++ if (OV495_VERSION(pid, ver) != OV495_VERSION_REG) { ++ dev_err(&client->dev, "Product ID error %x:%x\n", pid, ver); + ret = -ENODEV; + goto err; + } + -+ if (unlikely(conf_link)) -+ goto out; -+ -+again: -+ /* Check if firmware booted by reading stream-on status */ -+ reg16_write(client, 0xFFFD, 0x80); -+ reg16_write(client, 0xFFFE, 0x29); -+ usleep_range(100, 150); /* wait 100 us */ -+ for (timeout = 300; timeout > 0; timeout--) { -+ reg16_read(client, 0xd000, &val); -+ if (val == 0x0c) -+ break; -+ mdelay(1); -+ } -+ -+ /* wait firmware apps started by reading OV10640 ID */ -+ for (;timeout > 0; timeout--) { -+ reg16_write(client, 0xFFFD, 0x80); -+ reg16_write(client, 0xFFFE, 0x19); -+ usleep_range(100, 150); /* wait 100 us */ -+ reg16_write(client, 0x5000, 0x01); -+ reg16_write(client, 0x5001, 0x30); -+ reg16_write(client, 0x5002, 0x0a); -+ reg16_write(client, 0xFFFE, 0x80); -+ usleep_range(100, 150); /* wait 100 us */ -+ reg16_write(client, 0xC0, 0xc1); -+ reg16_write(client, 0xFFFE, 0x19); -+ usleep_range(1000, 1500); /* wait 1 ms */ -+ reg16_read(client, 0x5000, &val); -+ if (val == 0xa6) -+ break; -+ mdelay(1); ++ /* setup XCLK */ ++ tmp_addr = client->addr; ++ if (priv->ti9x4_addr) { ++ /* CLK_OUT=22.5792*160*M/N/CLKDIV -> CLK_OUT=25MHz: CLKDIV=4, M=7, N=253: 22.5792*160/4*7/253=24.989MHz=CLK_OUT */ ++ client->addr = priv->ti9x3_addr; /* Serializer I2C address */ ++ reg8_write(client, 0x06, 0x47); /* Set CLKDIV and M */ ++ reg8_write(client, 0x07, 0xfd); /* Set N */ + } ++ client->addr = tmp_addr; + -+ if (!timeout) { -+ dev_err(&client->dev, "Timeout firmware boot wait, retrying\n"); -+ /* reset OV10640 using RESETB pin controlled by OV490 GPIO0 */ -+ reg16_write(client, 0xFFFD, 0x80); -+ reg16_write(client, 0xFFFE, 0x80); -+ usleep_range(100, 150); /* wait 100 us */ -+ reg16_write(client, 0x0050, 0x01); -+ reg16_write(client, 0x0054, 0x01); -+ reg16_write(client, 0x0058, 0x00); -+ mdelay(10); -+ reg16_write(client, 0x0058, 0x01); -+ /* reset OV490 using RESETB pin controlled by serializer */ -+ ov490_reset(client); -+ if (retry_timeout--) -+ goto again; -+ } ++ 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, OV490_ISP_HSIZE_HIGH, &val); ++ reg16_read(client, OV495_ISP_HSIZE_HIGH, &val); + priv->max_width = val; -+ reg16_read(client, OV490_ISP_HSIZE_LOW, &val); ++ reg16_read(client, OV495_ISP_HSIZE_LOW, &val); + priv->max_width = (priv->max_width << 8) | val; -+ reg16_read(client, OV490_ISP_VSIZE_HIGH, &val); ++ reg16_read(client, OV495_ISP_VSIZE_HIGH, &val); + priv->max_height = val; -+ reg16_read(client, OV490_ISP_VSIZE_LOW, &val); ++ reg16_read(client, OV495_ISP_VSIZE_LOW, &val); + priv->max_height = (priv->max_height << 8) | val; ++#else ++ priv->max_width = 1920; ++ priv->max_height = 1080; ++#endif ++ ++ /* set virtual channel */ ++ ov495_regs_wizard[3].val = 0x1e | (priv->port << 6); + /* Program wizard registers */ -+ 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); ++ ov495_set_regs(client, ov495_regs_wizard, ARRAY_SIZE(ov495_regs_wizard)); + /* Read OTP IDs */ -+ ov490_otp_id_read(client); ++ ov495_otp_id_read(client); + +out: -+ dev_info(&client->dev, "ov490/ov10640 PID %x%x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ dev_info(&client->dev, "ov495/ov2775 PID %x%x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", + pid, ver, priv->max_width, priv->max_height, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); +err: -+ ov490_s_port(client, 0); -+ + return ret; +} + -+static int ov490_parse_dt(struct device_node *np, struct ov490_priv *priv) ++static int ov495_parse_dt(struct device_node *np, struct ov495_priv *priv) +{ + struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); + int i; -+ const char *fixed_sensor; + struct device_node *endpoint = NULL, *rendpoint = NULL; + int tmp_addr = 0; + @@ -8463,26 +13693,10 @@ index 0000000..812f367 + + of_node_put(endpoint); + -+ of_property_read_u32(endpoint, "dvp-order", &priv->dvp_order); -+ + rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); + if (!rendpoint) + continue; + -+ if (!of_property_read_u32(rendpoint, "max9271-addr", &priv->max9271_addr) && -+ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->max9286_addr) && -+ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) { -+ if (of_property_read_u32(rendpoint->parent->parent, "maxim,resetb-gpio", &priv->gpio_resetb)) { -+ priv->gpio_resetb = -1; -+ } else { -+ if (of_property_read_bool(rendpoint->parent->parent, "maxim,resetb-active-high")) -+ priv->active_low_resetb = false; -+ else -+ priv->active_low_resetb = true; -+ } -+ break; -+ } -+ + if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && + !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti9x4") && + !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti9x4_addr) && @@ -8490,61 +13704,34 @@ index 0000000..812f367 + break; + } + -+ if (!priv->max9286_addr && !priv->ti9x4_addr) { -+ dev_err(&client->dev, "deserializer does not present for OV490\n"); ++ if (!priv->ti9x4_addr) { ++ dev_err(&client->dev, "deserializer does not present for OV495\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->ti9x4_addr) { + client->addr = priv->ti9x4_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, 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; + -+ if (!of_property_read_string(np, "maxim,fixed-sensor", &fixed_sensor) && -+ strcmp(fixed_sensor, "ov490") == 0) { -+ if (of_property_read_u32(np, "maxim,width", &priv->max_width)) -+ priv->max_width = 1280; -+ -+ if (of_property_read_u32(np, "maxim,height", &priv->max_height)) -+ priv->max_height = 966; -+ -+ priv->is_fixed_sensor = true; -+ } -+ -+ /* module params override dts */ -+ if (dvp_order) -+ priv->dvp_order = dvp_order; -+ if (max_width && max_height) { -+ priv->max_width = max_width; -+ priv->max_height = max_height; -+ priv->is_fixed_sensor = true; -+ } -+ + return 0; +} + -+static int ov490_probe(struct i2c_client *client, ++static int ov495_probe(struct i2c_client *client, + const struct i2c_device_id *did) +{ -+ struct ov490_priv *priv; ++ struct ov495_priv *priv; + struct v4l2_ctrl *ctrl; + int ret; + @@ -8552,47 +13739,36 @@ index 0000000..812f367 + if (!priv) + return -ENOMEM; + -+ v4l2_i2c_subdev_init(&priv->sd, client, &ov490_subdev_ops); ++ 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; -+ priv->red = 0x400; -+ priv->blue = 0x400; -+ priv->green_r = priv->red / 2; -+ priv->green_b = priv->blue / 2; -+ priv->awb = 1; + v4l2_ctrl_handler_init(&priv->hdl, 4); -+ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, + V4L2_CID_BRIGHTNESS, 0, 16, 1, 7); -+ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, + V4L2_CID_CONTRAST, 0, 16, 1, 7); -+ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, + V4L2_CID_SATURATION, 0, 7, 1, 2); -+ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, + V4L2_CID_HUE, 0, 23, 1, 12); -+ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, + V4L2_CID_GAMMA, -128, 128, 1, 0); -+ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, + V4L2_CID_SHARPNESS, 0, 10, 1, 3); -+ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, + V4L2_CID_AUTOGAIN, 0, 1, 1, priv->autogain); -+ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, + V4L2_CID_GAIN, 0, 0xffff, 1, priv->gain); -+ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, + V4L2_CID_EXPOSURE, 0, 0xffff, 1, priv->exposure); -+ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, -+ V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, priv->autogain); -+ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, -+ V4L2_CID_RED_BALANCE, 2, 0xf, 1, priv->red >> 8); -+ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, -+ V4L2_CID_BLUE_BALANCE, 2, 0xf, 1, priv->blue >> 8); -+ 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_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, + V4L2_CID_VFLIP, 0, 1, 1, 0); -+ ctrl = v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ ctrl = v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, + V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 9); + if (ctrl) + ctrl->flags &= ~V4L2_CTRL_FLAG_READ_ONLY; @@ -8610,11 +13786,11 @@ index 0000000..812f367 + if (ret < 0) + goto cleanup; + -+ ret = ov490_parse_dt(client->dev.of_node, priv); ++ ret = ov495_parse_dt(client->dev.of_node, priv); + if (ret) + goto cleanup; + -+ ret = ov490_initialize(client); ++ ret = ov495_initialize(client); + if (ret < 0) + goto cleanup; + @@ -8627,7 +13803,7 @@ index 0000000..812f367 + if (ret) + goto cleanup; + -+ if (device_create_file(&client->dev, &dev_attr_otp_id_ov490) != 0) { ++ 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; + } @@ -8640,18 +13816,18 @@ index 0000000..812f367 + media_entity_cleanup(&priv->sd.entity); + v4l2_ctrl_handler_free(&priv->hdl); + v4l2_device_unregister_subdev(&priv->sd); -+#ifdef CONFIG_SOC_CAMERA_OV490_OV10640 ++#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 ov490_remove(struct i2c_client *client) ++static int ov495_remove(struct i2c_client *client) +{ -+ struct ov490_priv *priv = i2c_get_clientdata(client); ++ struct ov495_priv *priv = i2c_get_clientdata(client); + -+ device_remove_file(&client->dev, &dev_attr_otp_id_ov490); ++ 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); @@ -8660,45 +13836,45 @@ index 0000000..812f367 + return 0; +} + -+#ifdef CONFIG_SOC_CAMERA_OV490_OV10640 -+static const struct i2c_device_id ov490_id[] = { -+ { "ov490-ov10640", 0 }, ++#ifdef CONFIG_SOC_CAMERA_OV495_OV2775 ++static const struct i2c_device_id ov495_id[] = { ++ { "ov495-ov2775", 0 }, + { } +}; -+MODULE_DEVICE_TABLE(i2c, ov490_id); ++MODULE_DEVICE_TABLE(i2c, ov495_id); + -+static const struct of_device_id ov490_of_ids[] = { -+ { .compatible = "ovti,ov490-ov10640", }, ++static const struct of_device_id ov495_of_ids[] = { ++ { .compatible = "ovti,ov495-ov2775", }, + { } +}; -+MODULE_DEVICE_TABLE(of, ov490_of_ids); ++MODULE_DEVICE_TABLE(of, ov495_of_ids); + -+static struct i2c_driver ov490_i2c_driver = { ++static struct i2c_driver ov495_i2c_driver = { + .driver = { -+ .name = "ov490-ov10640", -+ .of_match_table = ov490_of_ids, ++ .name = "ov495-ov2775", ++ .of_match_table = ov495_of_ids, + }, -+ .probe = ov490_probe, -+ .remove = ov490_remove, -+ .id_table = ov490_id, ++ .probe = ov495_probe, ++ .remove = ov495_remove, ++ .id_table = ov495_id, +}; + -+module_i2c_driver(ov490_i2c_driver); ++module_i2c_driver(ov495_i2c_driver); + -+MODULE_DESCRIPTION("SoC Camera driver for OV490-OV10640"); ++MODULE_DESCRIPTION("SoC Camera driver for OV495-OV2775"); +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 +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..b22e93e +index 0000000..17c94ae --- /dev/null -+++ b/drivers/media/i2c/soc_camera/ov490_ov10640.h -@@ -0,0 +1,102 @@ ++++ b/drivers/media/i2c/soc_camera/ov495_ov2775.h +@@ -0,0 +1,23 @@ +/* -+ * OmniVision ov490-ov10640 sensor camera wizard 1280x1080@30/UYVY/BT601/8bit ++ * OmniVision ov495-ov2775 sensor camera wizard 1920x1080@30/UYVY/MIPI + * -+ * Copyright (C) 2016-2017 Cogent Embedded, Inc. ++ * 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 @@ -8706,107 +13882,28 @@ index 0000000..b22e93e + * option) any later version. + */ + -+//#define OV490_DISPLAY_PATTERN -+ -+struct ov490_reg { ++struct ov495_reg { + u16 reg; + u8 val; +}; + -+static const struct ov490_reg ov490_regs_wizard[] = { -+/* The following registers should match firmware */ -+{0xfffd, 0x80}, -+{0xfffe, 0x82}, -+{0x0071, 0x11}, -+{0x0075, 0x11}, -+{0xfffe, 0x29}, -+{0x6010, 0x01}, -+/* ov490 EMB line disable in YUV and RAW data, NOTE: EMB line is still used in ISP and sensor */ -+{0xe000, 0x14}, -+#if 0 /* do not disable EMB line in ISP! */ -+{0x4017, 0x00}, -+#endif -+{0xfffe, 0x28}, -+{0x6000, 0x04}, -+{0x6004, 0x00}, -+{0x6008, 0x00}, // PCLK polarity - useless due to silicon bug -> use 0x808000bb register -+{0xfffe, 0x80}, -+{0x0091, 0x00}, -+{0x00bb, 0x1d}, // bit[3]=0 - PCLK polarity workaround -+/* ov10640 EMB line disable */ -+#if 0 /* do not disable EMB line in sensor! */ -+{0xfffe, 0x19}, -+{0x5000, 0x00}, -+{0x5001, 0x30}, -+{0x5002, 0x91}, -+{0x5003, 0x08}, -+{0xfffe, 0x80}, -+{0x00c0, 0xc1}, -+#endif -+/* Ov490 FSIN: app_fsin_from_fsync */ -+{0xfffe, 0x85}, -+{0x0008, 0x00}, -+{0x0009, 0x01}, -+{0x000A, 0x05}, // fsin0 src -+{0x000B, 0x00}, -+{0x0030, 0x02}, // fsin0_delay -+{0x0031, 0x00}, -+{0x0032, 0x00}, -+{0x0033, 0x00}, -+{0x0038, 0x02}, // fsin1_delay -+{0x0039, 0x00}, -+{0x003A, 0x00}, -+{0x003B, 0x00}, -+{0x0070, 0x2C}, // fsin0_length -+{0x0071, 0x01}, -+{0x0072, 0x00}, -+{0x0073, 0x00}, -+{0x0074, 0x64}, // fsin1_length -+{0x0075, 0x00}, -+{0x0076, 0x00}, -+{0x0077, 0x00}, -+{0x0000, 0x14}, -+{0x0001, 0x00}, -+{0x0002, 0x00}, -+{0x0003, 0x00}, -+{0x0004, 0x32}, // load fsin0,load fsin1,load other, it will be cleared automatically. -+{0x0005, 0x00}, -+{0x0006, 0x00}, -+{0x0007, 0x00}, -+{0xfffe, 0x80}, -+{0x0081, 0x00}, // 03;SENSOR FSIN -+/* ov10640 FSIN */ -+{0xfffe, 0x19}, -+{0x5000, 0x00}, -+{0x5001, 0x30}, -+{0x5002, 0x8c}, -+{0x5003, 0xb2}, -+{0xfffe, 0x80}, -+{0x00c0, 0xc1}, -+/* ov10640 HFLIP=1 by default */ -+{0xfffe, 0x19}, -+{0x5000, 0x01}, -+{0x5001, 0x00}, -+{0xfffe, 0x80}, -+{0x00c0, 0xdc}, -+#ifdef OV490_DISPLAY_PATTERN -+{0xfffd, 0x80}, -+{0xfffe, 0x19}, -+{0x5000, 0x02}, -+{0xfffe, 0x80}, -+{0x00c0, 0xd6}, -+#endif ++static struct ov495_reg ov495_regs_wizard[] = { ++{0x3516, 0x00}, /* unlock write */ ++{0xFFFD, 0x80}, ++{0xFFFE, 0x20}, ++{0x8017, 0x1e | (0 << 6)}, ++{0x7c10, 0x01}, /* UYVY */ +}; -diff --git a/drivers/media/i2c/soc_camera/ov495_ov2775.c b/drivers/media/i2c/soc_camera/ov495_ov2775.c +diff --git a/drivers/media/i2c/soc_camera/ox03a.c b/drivers/media/i2c/soc_camera/ox03a.c new file mode 100644 -index 0000000..e53c482 +index 0000000..d51512b9 --- /dev/null -+++ b/drivers/media/i2c/soc_camera/ov495_ov2775.c -@@ -0,0 +1,639 @@ ++++ b/drivers/media/i2c/soc_camera/ox03a.c +@@ -0,0 +1,526 @@ +/* -+ * OmniVision ov495-ov2775 sensor camera driver ++ * OmniVision OX03A sensor camera driver + * -+ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * Copyright (C) 2018 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 @@ -8825,106 +13922,88 @@ index 0000000..e53c482 +#include +#include + -+#include "ov495_ov2775.h" ++#include "ox03a.h" + -+#define OV495_I2C_ADDR 0x24 ++#define OX03A_I2C_ADDR 0x36 + -+#define OV495_PID 0x300a -+#define OV495_VER 0x300b -+#define OV495_VERSION_REG 0x0495 -+#define OV495_VERSION(pid, ver) (((pid) << 8) | ((ver) & 0xff)) ++#define OX03A_PID 0x300A ++#define OX03A_VER 0x300B ++#define OX03A_VERSION_REG 0x5803 + -+#define OV495_ISP_HSIZE_LOW 0x60 -+#define OV495_ISP_HSIZE_HIGH 0x61 -+#define OV495_ISP_VSIZE_LOW 0x62 -+#define OV495_ISP_VSIZE_HIGH 0x63 ++#define OX03A_MEDIA_BUS_FMT MEDIA_BUS_FMT_SBGGR12_1X12 + -+struct ov495_priv { ++struct ox03a_priv { + struct v4l2_subdev sd; + struct v4l2_ctrl_handler hdl; + struct media_pad pad; + struct v4l2_rect rect; -+ int max_width; -+ int max_height; + int init_complete; + u8 id[6]; + int exposure; + int gain; + int autogain; + /* serializers */ -+ int max9286_addr; -+ int max9271_addr; + int ti9x4_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) ++static inline struct ox03a_priv *to_ox03a(const struct i2c_client *client) +{ -+ return container_of(i2c_get_clientdata(client), struct ov495_priv, sd); ++ return container_of(i2c_get_clientdata(client), struct ox03a_priv, sd); +} + -+static int ov495_set_regs(struct i2c_client *client, -+ const struct ov495_reg *regs, int nr_regs) ++static int ox03a_set_regs(struct i2c_client *client, ++ const struct ox03a_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); ++ if (regs[i].reg == OX03A_DELAY) { ++ mdelay(regs[i].val); ++ continue; + } ++ ++ reg16_write(client, regs[i].reg, regs[i].val); + } + + return 0; +} + -+static int ov495_s_stream(struct v4l2_subdev *sd, int enable) ++static int ox03a_s_stream(struct v4l2_subdev *sd, int enable) +{ + return 0; +} + -+static int ov495_get_fmt(struct v4l2_subdev *sd, ++static int ox03a_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); ++ struct ox03a_priv *priv = to_ox03a(client); + + if (format->pad) + return -EINVAL; + + mf->width = priv->rect.width; + mf->height = priv->rect.height; -+ mf->code = MEDIA_BUS_FMT_YUYV8_2X8; ++ mf->code = OX03A_MEDIA_BUS_FMT; + mf->colorspace = V4L2_COLORSPACE_SMPTE170M; + mf->field = V4L2_FIELD_NONE; + + return 0; +} + -+static int ov495_set_fmt(struct v4l2_subdev *sd, ++static int ox03a_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->code = OX03A_MEDIA_BUS_FMT; + mf->colorspace = V4L2_COLORSPACE_SMPTE170M; + mf->field = V4L2_FIELD_NONE; + @@ -8934,40 +14013,40 @@ index 0000000..e53c482 + return 0; +} + -+static int ov495_enum_mbus_code(struct v4l2_subdev *sd, ++static int ox03a_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; ++ code->code = OX03A_MEDIA_BUS_FMT; + + return 0; +} + -+static int ov495_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++static int ox03a_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); ++ struct ox03a_priv *priv = to_ox03a(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; ++ edid->edid[8] = OX03A_VERSION_REG >> 8; ++ edid->edid[9] = OX03A_VERSION_REG & 0xff; + + return 0; +} + -+static int ov495_set_selection(struct v4l2_subdev *sd, ++static int ox03a_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); ++ struct ox03a_priv *priv = to_ox03a(client); + + if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || + sel->target != V4L2_SEL_TGT_CROP) @@ -8978,8 +14057,8 @@ index 0000000..e53c482 + 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)) ++ if ((rect->left + rect->width > OX03A_MAX_WIDTH) || ++ (rect->top + rect->height > OX03A_MAX_HEIGHT)) + *rect = priv->rect; + + priv->rect.left = rect->left; @@ -8990,12 +14069,12 @@ index 0000000..e53c482 + return 0; +} + -+static int ov495_get_selection(struct v4l2_subdev *sd, ++static int ox03a_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); ++ struct ox03a_priv *priv = to_ox03a(client); + + if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; @@ -9004,14 +14083,14 @@ index 0000000..e53c482 + 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; ++ sel->r.width = OX03A_MAX_WIDTH; ++ sel->r.height = OX03A_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; ++ sel->r.width = OX03A_MAX_WIDTH; ++ sel->r.height = OX03A_MAX_HEIGHT; + return 0; + case V4L2_SEL_TGT_CROP: + sel->r = priv->rect; @@ -9021,7 +14100,7 @@ index 0000000..e53c482 + } +} + -+static int ov495_g_mbus_config(struct v4l2_subdev *sd, ++static int ox03a_g_mbus_config(struct v4l2_subdev *sd, + struct v4l2_mbus_config *cfg) +{ + cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | @@ -9032,7 +14111,7 @@ index 0000000..e53c482 +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG -+static int ov495_g_register(struct v4l2_subdev *sd, ++static int ox03a_g_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); @@ -9044,38 +14123,32 @@ index 0000000..e53c482 + return ret; + + reg->val = val; -+ reg->size = sizeof(u16); ++ reg->size = sizeof(u8); + + return 0; +} + -+static int ov495_s_register(struct v4l2_subdev *sd, ++static int ox03a_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; ++ return reg16_write(client, (u16)reg->reg, (u8)reg->val); +} +#endif + -+static struct v4l2_subdev_core_ops ov495_core_ops = { ++static struct v4l2_subdev_core_ops ox03a_core_ops = { +#ifdef CONFIG_VIDEO_ADV_DEBUG -+ .g_register = ov495_g_register, -+ .s_register = ov495_s_register, ++ .g_register = ox03a_g_register, ++ .s_register = ox03a_s_register, +#endif +}; + -+static int ov495_s_ctrl(struct v4l2_ctrl *ctrl) ++static int ox03a_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); ++ struct ox03a_priv *priv = to_ox03a(client); + int ret = -EINVAL; + + if (!priv->init_complete) @@ -9083,180 +14156,94 @@ index 0000000..e53c482 + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: -+ break; + case V4L2_CID_CONTRAST: -+ break; + case V4L2_CID_SATURATION: -+ break; + case V4L2_CID_HUE: -+ break; + case V4L2_CID_GAMMA: -+ break; + case V4L2_CID_SHARPNESS: -+ break; + case V4L2_CID_AUTOGAIN: + case V4L2_CID_GAIN: -+ case V4L2_CID_EXPOSURE: -+ break; -+ case V4L2_CID_HFLIP: -+ ret = reg16_write(client, 0x3516, 0x00); -+ ret |= reg16_write(client, 0x0ffc, 0x00); -+ ret |= reg16_write(client, 0x0500, ctrl->val); -+ ret |= reg16_write(client, 0x0501, 0x00); -+ usleep_range(100, 150); /* wait 100 us */ -+ ret |= reg16_write(client, 0x30C0, 0xdc); -+ ret |= reg16_write(client, 0x3516, 0x01); -+ break; -+ case V4L2_CID_VFLIP: -+ ret = reg16_write(client, 0x3516, 0x00); -+ ret |= reg16_write(client, 0x0ffc, 0x00); -+ ret |= reg16_write(client, 0x0500, ctrl->val); -+ ret |= reg16_write(client, 0x0501, 0x01); -+ usleep_range(100, 150); /* wait 100 us */ -+ ret |= reg16_write(client, 0x30C0, 0xdc); -+ ret |= reg16_write(client, 0x3516, 0x01); -+ break; -+ case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: -+ ret = 0; ++ case V4L2_CID_EXPOSURE: ++ case V4L2_CID_HFLIP: ++ case V4L2_CID_VFLIP: + break; + } + + return ret; +} + -+static const struct v4l2_ctrl_ops ov495_ctrl_ops = { -+ .s_ctrl = ov495_s_ctrl, ++static const struct v4l2_ctrl_ops ox03a_ctrl_ops = { ++ .s_ctrl = ox03a_s_ctrl, +}; + -+static struct v4l2_subdev_video_ops ov495_video_ops = { -+ .s_stream = ov495_s_stream, -+ .g_mbus_config = ov495_g_mbus_config, ++static struct v4l2_subdev_video_ops ox03a_video_ops = { ++ .s_stream = ox03a_s_stream, ++ .g_mbus_config = ox03a_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 const struct v4l2_subdev_pad_ops ox03a_subdev_pad_ops = { ++ .get_edid = ox03a_get_edid, ++ .enum_mbus_code = ox03a_enum_mbus_code, ++ .get_selection = ox03a_get_selection, ++ .set_selection = ox03a_set_selection, ++ .get_fmt = ox03a_get_fmt, ++ .set_fmt = ox03a_set_fmt, +}; + -+static struct v4l2_subdev_ops ov495_subdev_ops = { -+ .core = &ov495_core_ops, -+ .video = &ov495_video_ops, -+ .pad = &ov495_subdev_pad_ops, ++static struct v4l2_subdev_ops ox03a_subdev_ops = { ++ .core = &ox03a_core_ops, ++ .video = &ox03a_video_ops, ++ .pad = &ox03a_subdev_pad_ops, +}; + -+static void ov495_otp_id_read(struct i2c_client *client) ++static void ox03a_otp_id_read(struct i2c_client *client) +{ -+ struct ov495_priv *priv = to_ov495(client); -+ int i; -+ -+#if 0 -+ /* read camera id from ov495 OTP memory */ -+ reg16_write(client, 0xFFFD, 0x80); -+ reg16_write(client, 0xFFFE, 0x20); -+ usleep_range(100, 150); /* wait 100 us */ -+ reg16_write(client, 0x7384, 0x40); /* manual mode, bank#0 */ -+ reg16_write(client, 0x7381, 1); /* start OTP read */ -+ -+ usleep_range(25000, 26000); /* wait 25 ms */ -+ -+ for (i = 0; i < 6; i++) -+ reg16_read(client, 0x7300 + i + 4, &priv->id[i]); -+#else -+ /* read camera id from ov2775 OTP memory */ -+ reg16_write(client, 0x3516, 0x00); /* unlock write */ -+ reg16_write(client, 0x0FFC, 0); -+ reg16_write(client, 0x0500, 0x00); /* write 0x34a1 -> 1 */ -+ reg16_write(client, 0x0501, 0x34); -+ reg16_write(client, 0x0502, 0xa1); -+ reg16_write(client, 0x0503, 1); -+ reg16_write(client, 0x30C0, 0xc1); -+ -+ usleep_range(25000, 25500); /* wait 25 ms */ -+ -+ for (i = 0; i < 6; i++) { -+ reg16_write(client, 0x3516, 0x00); /* unlock write */ -+ reg16_write(client, 0x0500, 0x01); /* read (0x7a00 + i) */ -+ reg16_write(client, 0x0501, 0x7a); -+ reg16_write(client, 0x0502, 0x00 + i + (i < 3 ? 11 : 3)); /* take bytes 11,12,13,6,7,8 */ -+ reg16_write(client, 0x30C0, 0xc1); -+ usleep_range(1000, 1500); /* wait 1 ms */ -+ reg16_read(client, 0x0500, &priv->id[i]); -+ } -+#endif +} + -+static ssize_t ov495_otp_id_show(struct device *dev, ++static ssize_t ox03a_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); ++ struct ox03a_priv *priv = to_ox03a(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 DEVICE_ATTR(otp_id_ox03a, S_IRUGO, ox03a_otp_id_show, NULL); + -+static int ov495_initialize(struct i2c_client *client) ++static int ox03a_initialize(struct i2c_client *client) +{ -+ struct ov495_priv *priv = to_ov495(client); -+ u8 pid = 0, ver = 0; ++ struct ox03a_priv *priv = to_ox03a(client); ++ u8 val = 0; ++ u16 pid; + 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); ++ /* check and show model ID */ ++ reg16_read(client, OX03A_PID, &val); ++ pid = val; ++ reg16_read(client, OX03A_VER, &val); ++ pid = (pid << 8) | val; + -+ if (OV495_VERSION(pid, ver) != OV495_VERSION_REG) { -+ dev_err(&client->dev, "Product ID error %x:%x\n", pid, ver); ++ if (pid != OX03A_VERSION_REG) { ++ dev_dbg(&client->dev, "Product ID error %x\n", pid); + ret = -ENODEV; + goto err; + } + -+ if (unlikely(force_conf_link)) -+ goto out; -+ -+#if 0 -+ /* read resolution used by current firmware */ -+ reg16_write(client, 0xFFFD, 0x80); -+ reg16_write(client, 0xFFFE, 0x82); -+ usleep_range(100, 150); /* wait 100 us */ -+ reg16_read(client, OV495_ISP_HSIZE_HIGH, &val); -+ priv->max_width = val; -+ reg16_read(client, OV495_ISP_HSIZE_LOW, &val); -+ priv->max_width = (priv->max_width << 8) | val; -+ reg16_read(client, OV495_ISP_VSIZE_HIGH, &val); -+ priv->max_height = val; -+ reg16_read(client, OV495_ISP_VSIZE_LOW, &val); -+ priv->max_height = (priv->max_height << 8) | val; -+#else -+ priv->max_width = 1920; -+ priv->max_height = 1080; -+#endif -+ -+ /* set virtual channel */ -+ ov495_regs_wizard[3].val = 0x1e | (priv->port << 6); + /* Program wizard registers */ -+ ov495_set_regs(client, ov495_regs_wizard, ARRAY_SIZE(ov495_regs_wizard)); ++ ox03a_set_regs(client, ox03a_regs_wizard, ARRAY_SIZE(ox03a_regs_wizard)); + /* Read OTP IDs */ -+ ov495_otp_id_read(client); ++ ox03a_otp_id_read(client); + -+out: -+ dev_info(&client->dev, "ov495/ov2775 PID %x%x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", -+ pid, ver, priv->max_width, priv->max_height, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++ dev_info(&client->dev, "ox03a PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, OX03A_MAX_WIDTH, OX03A_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) ++static int ox03a_parse_dt(struct device_node *np, struct ox03a_priv *priv) +{ + struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); + int i; @@ -9282,7 +14269,7 @@ index 0000000..e53c482 + } + + if (!priv->ti9x4_addr) { -+ dev_err(&client->dev, "deserializer does not present for OV495\n"); ++ dev_err(&client->dev, "deserializer does not present\n"); + return -EINVAL; + } + @@ -9290,65 +14277,62 @@ index 0000000..e53c482 + tmp_addr = client->addr; + if (priv->ti9x4_addr) { + client->addr = priv->ti9x4_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, 0x5d, OX03A_I2C_ADDR << 1); /* Sensor native I2C address */ ++// reg8_write(client, 0x6e, 0xa9); /* GPIO0 - reset, GPIO1 - fsin */ + -+ 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 = priv->ti9x3_addr; /* Serializer I2C address */ ++// reg8_write(client, 0x0d, 0x03); /* unreset gpios */ ++// reg8_write(client, 0x0e, 0xf0); /* unreset gpios */ + } + client->addr = tmp_addr; + ++ mdelay(10); ++ + return 0; +} + -+static int ov495_probe(struct i2c_client *client, ++static int ox03a_probe(struct i2c_client *client, + const struct i2c_device_id *did) +{ -+ struct ov495_priv *priv; -+ struct v4l2_ctrl *ctrl; ++ struct ox03a_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); ++ v4l2_i2c_subdev_init(&priv->sd, client, &ox03a_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_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops, + V4L2_CID_BRIGHTNESS, 0, 16, 1, 7); -+ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops, + V4L2_CID_CONTRAST, 0, 16, 1, 7); -+ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops, + V4L2_CID_SATURATION, 0, 7, 1, 2); -+ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops, + V4L2_CID_HUE, 0, 23, 1, 12); -+ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops, + V4L2_CID_GAMMA, -128, 128, 1, 0); -+ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops, + V4L2_CID_SHARPNESS, 0, 10, 1, 3); -+ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops, + V4L2_CID_AUTOGAIN, 0, 1, 1, priv->autogain); -+ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops, + V4L2_CID_GAIN, 0, 0xffff, 1, priv->gain); -+ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ox03a_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_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 1); ++ v4l2_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops, + V4L2_CID_VFLIP, 0, 1, 1, 0); -+ ctrl = v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, -+ V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 9); -+ if (ctrl) -+ ctrl->flags &= ~V4L2_CTRL_FLAG_READ_ONLY; + priv->sd.ctrl_handler = &priv->hdl; + + ret = priv->hdl.error; @@ -9363,24 +14347,24 @@ index 0000000..e53c482 + if (ret < 0) + goto cleanup; + -+ ret = ov495_parse_dt(client->dev.of_node, priv); ++ ret = ox03a_parse_dt(client->dev.of_node, priv); + if (ret) + goto cleanup; + -+ ret = ov495_initialize(client); ++ ret = ox03a_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; ++ priv->rect.width = OX03A_MAX_WIDTH; ++ priv->rect.height = OX03A_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) { ++ if (device_create_file(&client->dev, &dev_attr_otp_id_ox03a) != 0) { + dev_err(&client->dev, "sysfs otp_id entry creation failed\n"); + goto cleanup; + } @@ -9393,18 +14377,18 @@ index 0000000..e53c482 + media_entity_cleanup(&priv->sd.entity); + v4l2_ctrl_handler_free(&priv->hdl); + v4l2_device_unregister_subdev(&priv->sd); -+#ifdef CONFIG_SOC_CAMERA_OV495_OV2775 ++#ifdef CONFIG_SOC_CAMERA_OX03A + 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) ++static int ox03a_remove(struct i2c_client *client) +{ -+ struct ov495_priv *priv = i2c_get_clientdata(client); ++ struct ox03a_priv *priv = i2c_get_clientdata(client); + -+ device_remove_file(&client->dev, &dev_attr_otp_id_ov495); ++ device_remove_file(&client->dev, &dev_attr_otp_id_ox03a); + v4l2_async_unregister_subdev(&priv->sd); + media_entity_cleanup(&priv->sd.entity); + v4l2_ctrl_handler_free(&priv->hdl); @@ -9413,45 +14397,45 @@ index 0000000..e53c482 + return 0; +} + -+#ifdef CONFIG_SOC_CAMERA_OV495_OV2775 -+static const struct i2c_device_id ov495_id[] = { -+ { "ov495-ov2775", 0 }, ++#ifdef CONFIG_SOC_CAMERA_OX03A ++static const struct i2c_device_id ox03a_id[] = { ++ { "ox03a", 0 }, + { } +}; -+MODULE_DEVICE_TABLE(i2c, ov495_id); ++MODULE_DEVICE_TABLE(i2c, ox03a_id); + -+static const struct of_device_id ov495_of_ids[] = { -+ { .compatible = "ovti,ov495-ov2775", }, ++static const struct of_device_id ox03a_of_ids[] = { ++ { .compatible = "ovti,ox03a", }, + { } +}; -+MODULE_DEVICE_TABLE(of, ov495_of_ids); ++MODULE_DEVICE_TABLE(of, ox03a_of_ids); + -+static struct i2c_driver ov495_i2c_driver = { ++static struct i2c_driver ox03a_i2c_driver = { + .driver = { -+ .name = "ov495-ov2775", -+ .of_match_table = ov495_of_ids, ++ .name = "ox03a", ++ .of_match_table = ox03a_of_ids, + }, -+ .probe = ov495_probe, -+ .remove = ov495_remove, -+ .id_table = ov495_id, ++ .probe = ox03a_probe, ++ .remove = ox03a_remove, ++ .id_table = ox03a_id, +}; + -+module_i2c_driver(ov495_i2c_driver); ++module_i2c_driver(ox03a_i2c_driver); + -+MODULE_DESCRIPTION("SoC Camera driver for OV495-OV2775"); ++MODULE_DESCRIPTION("SoC Camera driver for OX03A"); +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 +diff --git a/drivers/media/i2c/soc_camera/ox03a.h b/drivers/media/i2c/soc_camera/ox03a.h new file mode 100644 -index 0000000..17c94ae +index 0000000..b69273a --- /dev/null -+++ b/drivers/media/i2c/soc_camera/ov495_ov2775.h -@@ -0,0 +1,23 @@ ++++ b/drivers/media/i2c/soc_camera/ox03a.h +@@ -0,0 +1,1724 @@ +/* -+ * OmniVision ov495-ov2775 sensor camera wizard 1920x1080@30/UYVY/MIPI ++ * OmniVision OX03A sensor camera wizard 1920x1080@30/BGGR/MIPI + * -+ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * Copyright (C) 2018 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 @@ -9459,21 +14443,1722 @@ index 0000000..17c94ae + * option) any later version. + */ + -+struct ov495_reg { ++#define OX03A_DISPLAY_PATTERN_COLOR_BAR ++ ++#define OX03A_MAX_WIDTH 1920 ++#define OX03A_MAX_HEIGHT 1080 ++ ++#define OX03A_DELAY 0xffff ++#define OX03A_DT 0x2c /* MIPI Data Type RAW12 */ ++ ++struct ox03a_reg { + u16 reg; + u8 val; +}; + -+static struct ov495_reg ov495_regs_wizard[] = { -+{0x3516, 0x00}, /* unlock write */ -+{0xFFFD, 0x80}, -+{0xFFFE, 0x20}, -+{0x8017, 0x1e | (0 << 6)}, -+{0x7c10, 0x01}, /* UYVY */ ++/* wizard: MIPI 1920x1280 3x12 30fps 750MBPS */ ++static const struct ox03a_reg ox03a_regs_wizard[] = { ++{0x0103, 0x01}, // s/w reset ++{OX03A_DELAY, 10}, // Wait 10ms ++{0x0100, 0x00}, ++{0x0102, 0x00}, ++{0x0103, 0x00}, ++{0x0104, 0x04}, ++{0x0105, 0x00}, ++{0x0106, 0x00}, ++{0x0107, 0x00}, ++{0x0109, 0x00}, ++{0x0300, 0x00}, ++{0x0301, 0x01}, ++{0x0302, 0x00}, ++{0x0303, 0x02}, ++{0x0304, 0x00}, ++{0x0305, 0x3c}, ++{0x0306, 0x00}, ++{0x0307, 0x00}, ++{0x0308, 0x04}, ++{0x0309, 0x02}, ++{0x030a, 0x00}, ++{0x030c, 0x00}, ++{0x030d, 0x00}, ++{0x0310, 0x00}, ++{0x0311, 0x00}, ++{0x0312, 0x00}, ++{0x0313, 0x00}, ++{0x0314, 0x00}, ++{0x0315, 0x00}, ++{0x0316, 0x00}, ++{0x0317, 0x12}, ++{0x0318, 0x01}, ++{0x0320, 0x00}, ++{0x0321, 0x01}, ++{0x0322, 0x00}, ++{0x0323, 0x02}, ++{0x0324, 0x00}, ++{0x0325, 0x6c}, ++{0x0326, 0x00}, ++{0x0327, 0x05}, ++{0x0328, 0x05}, ++{0x0329, 0x01}, ++{0x032a, 0x02}, ++{0x032b, 0x00}, ++{0x032c, 0x00}, ++{0x0400, 0xe7}, ++{0x0401, 0xff}, ++{0x0404, 0x2b}, ++{0x0405, 0x32}, ++{0x0406, 0x33}, ++{0x0407, 0x8f}, ++{0x0408, 0x0c}, ++{0x040a, 0x00}, ++{0x0410, 0xe7}, ++{0x0411, 0xff}, ++{0x0414, 0x2b}, ++{0x0415, 0x32}, ++{0x0416, 0x33}, ++{0x0417, 0x8f}, ++{0x0418, 0x0c}, ++{0x041a, 0x00}, ++{0x2803, 0x00}, ++{0x3000, 0x00}, ++{0x3001, 0x03}, ++{0x3002, 0x03}, ++{0x3003, 0x00}, ++{0x3004, 0x04}, ++{0x3005, 0x00}, ++{0x3006, 0x00}, ++{0x3007, 0x04}, ++{0x3008, 0x00}, ++{0x3009, 0x06}, ++{0x300d, 0x11}, ++{0x300e, 0x11}, ++{0x300f, 0x11}, ++{0x3012, 0x41}, ++{0x3016, 0xf0}, ++{0x3017, 0xf0}, ++{0x3018, 0xf0}, ++{0x3019, 0xf0}, ++{0x301a, 0xf0}, ++{0x301b, 0xb4}, ++{0x301c, 0x01}, ++{0x301d, 0x02}, ++{0x301e, 0xb8}, ++{0x301f, 0xe1}, ++{0x3020, 0x01}, ++{0x3021, 0x00}, ++{0x3022, 0xf8}, ++{0x3023, 0xf0}, ++{0x3024, 0xf0}, ++{0x3025, 0x02}, ++{0x3026, 0x00}, ++{0x3027, 0x00}, ++{0x3028, 0xf0}, ++{0x3029, 0x80}, ++{0x3035, 0x6c}, ++{0x3036, 0x42}, ++{0x3037, 0x20}, ++{0x3038, 0x00}, ++{0x3700, 0x26}, ++{0x3701, 0x1e}, ++{0x3702, 0x25}, ++{0x3703, 0x28}, ++{0x3704, 0x0f}, ++{0x3705, 0x00}, ++{0x3706, 0x39}, ++{0x3707, 0x0a}, ++{0x3708, 0x36}, ++{0x3709, 0x41}, ++{0x370a, 0x00}, ++{0x370b, 0xa3}, ++{0x370c, 0x0f}, ++{0x370d, 0x00}, ++{0x370e, 0xa6}, ++{0x370f, 0x95}, ++{0x3710, 0x15}, ++{0x3711, 0x72}, ++{0x3712, 0x12}, ++{0x3713, 0x00}, ++{0x3714, 0x22}, ++{0x3715, 0x00}, ++{0x3716, 0x04}, ++{0x3717, 0x02}, ++{0x3718, 0x09}, ++{0x3719, 0x1f}, ++{0x371a, 0x0c}, ++{0x371b, 0x16}, ++{0x371c, 0x00}, ++{0x371d, 0x08}, ++{0x371e, 0x00}, ++{0x371f, 0x02}, ++{0x3720, 0x03}, ++{0x3721, 0x1c}, ++{0x3722, 0x87}, ++{0x3723, 0x08}, ++{0x3724, 0x0d}, ++{0x3725, 0x08}, ++{0x3726, 0x0d}, ++{0x3727, 0x08}, ++{0x3728, 0x04}, ++{0x3729, 0x0c}, ++{0x372a, 0x01}, ++{0x372b, 0x01}, ++{0x372c, 0x17}, ++{0x372d, 0x01}, ++{0x372e, 0x35}, ++{0x372f, 0x43}, ++{0x3730, 0x04}, ++{0x3731, 0x06}, ++{0x3732, 0x01}, ++{0x3733, 0x41}, ++{0x3734, 0x0a}, ++{0x3735, 0x11}, ++{0x3736, 0x11}, ++{0x3737, 0x00}, ++{0x3738, 0x54}, ++{0x3739, 0x54}, ++{0x373a, 0x54}, ++{0x373b, 0x54}, ++{0x373c, 0x11}, ++{0x373d, 0x11}, ++{0x373e, 0x00}, ++{0x373f, 0x4c}, ++{0x3740, 0x4c}, ++{0x3741, 0x4c}, ++{0x3742, 0x23}, ++{0x3743, 0x01}, ++{0x3744, 0x16}, ++{0x3745, 0x08}, ++{0x3746, 0x03}, ++{0x3747, 0x01}, ++{0x3748, 0x07}, ++{0x3749, 0x01}, ++{0x374a, 0x07}, ++{0x374b, 0x03}, ++{0x374c, 0xb1}, ++{0x374d, 0x01}, ++{0x374e, 0x01}, ++{0x374f, 0x01}, ++{0x3750, 0x07}, ++{0x3751, 0x02}, ++{0x3752, 0x03}, ++{0x3753, 0xd0}, ++{0x3754, 0x08}, ++{0x3755, 0x00}, ++{0x3758, 0xdd}, ++{0x3759, 0x50}, ++{0x375a, 0x49}, ++{0x375b, 0x02}, ++{0x375c, 0x2f}, ++{0x375d, 0x00}, ++{0x375e, 0x0f}, ++{0x375f, 0x03}, ++{0x3760, 0x13}, ++{0x3761, 0x12}, ++{0x3762, 0x1c}, ++{0x3763, 0x03}, ++{0x3764, 0x0d}, ++{0x3765, 0x25}, ++{0x3766, 0x08}, ++{0x3767, 0x08}, ++{0x3768, 0x21}, ++{0x3769, 0x01}, ++{0x376a, 0x01}, ++{0x376b, 0x00}, ++{0x376c, 0x15}, ++{0x376d, 0x08}, ++{0x376e, 0x08}, ++{0x376f, 0x08}, ++{0x3770, 0x91}, ++{0x3771, 0x00}, ++{0x3772, 0x00}, ++{0x3773, 0x00}, ++{0x3774, 0x02}, ++{0x3775, 0x00}, ++{0x3776, 0x00}, ++{0x3777, 0x00}, ++{0x3778, 0x00}, ++{0x3779, 0x22}, ++{0x377a, 0x00}, ++{0x377b, 0x00}, ++{0x377c, 0x48}, ++{0x377d, 0x00}, ++{0x377e, 0x00}, ++{0x377f, 0x07}, ++{0x3780, 0x00}, ++{0x3781, 0x02}, ++{0x3782, 0x04}, ++{0x3783, 0x02}, ++{0x3784, 0x08}, ++{0x3785, 0x08}, ++{0x3786, 0x00}, ++{0x3787, 0x04}, ++{0x3788, 0x02}, ++{0x3789, 0x02}, ++{0x378a, 0x04}, ++{0x378b, 0x00}, ++{0x378c, 0x00}, ++{0x378d, 0x00}, ++{0x378e, 0x00}, ++{0x378f, 0x00}, ++{0x3790, 0x10}, ++{0x3791, 0x05}, ++{0x3792, 0x31}, ++{0x3793, 0x00}, ++{0x3795, 0x00}, ++{0x3796, 0x00}, ++{0x3797, 0x00}, ++{0x3798, 0x00}, ++{0x3799, 0x00}, ++{0x379a, 0x00}, ++{0x379b, 0x10}, ++{0x379c, 0x01}, ++{0x379d, 0x00}, ++{0x379e, 0x0d}, ++{0x379f, 0x03}, ++{0x37a0, 0x08}, ++{0x37a1, 0x80}, ++{0x37a2, 0x03}, ++{0x37a3, 0x05}, ++{0x37a4, 0x04}, ++{0x37a5, 0x14}, ++{0x37a6, 0x17}, ++{0x37a7, 0x14}, ++{0x37a8, 0x05}, ++{0x37a9, 0x08}, ++{0x37aa, 0x05}, ++{0x37ab, 0x06}, ++{0x37ac, 0x05}, ++{0x37ad, 0x0d}, ++{0x37ae, 0x0d}, ++{0x37af, 0x01}, ++{0x37b0, 0x0c}, ++{0x37b1, 0x05}, ++{0x37b2, 0x08}, ++{0x37b3, 0x0a}, ++{0x37b4, 0x08}, ++{0x37b5, 0x08}, ++{0x37b6, 0x08}, ++{0x37b7, 0x08}, ++{0x37b8, 0xff}, ++{0x37b9, 0x01}, ++{0x37ba, 0x08}, ++{0x37bb, 0x08}, ++{0x37bd, 0x01}, ++{0x37be, 0x01}, ++{0x37bf, 0x01}, ++{0x37c0, 0x01}, ++{0x37c1, 0x11}, ++{0x37c2, 0x11}, ++{0x37c3, 0x00}, ++{0x37c4, 0x63}, ++{0x37c5, 0x63}, ++{0x37c6, 0x63}, ++{0x37c7, 0x34}, ++{0x37c8, 0x21}, ++{0x37c9, 0x00}, ++{0x37ca, 0x08}, ++{0x37cb, 0x00}, ++{0x37cc, 0x40}, ++{0x37cd, 0x00}, ++{0x37ce, 0x01}, ++{0x37cf, 0x08}, ++{0x37d0, 0x00}, ++{0x37d1, 0x39}, ++{0x37d2, 0x00}, ++{0x37d3, 0xa3}, ++{0x37d4, 0x00}, ++{0x37d5, 0x39}, ++{0x37d6, 0x00}, ++{0x37d7, 0xa3}, ++{0x37da, 0x00}, ++{0x37db, 0x00}, ++{0x37dc, 0x00}, ++{0x37dd, 0x00}, ++{0x37de, 0x00}, ++{0x37df, 0x00}, ++{0x37e0, 0x00}, ++{0x37e1, 0x00}, ++{0x37e2, 0x00}, ++{0x37e3, 0x00}, ++{0x37e4, 0x00}, ++{0x37e5, 0x00}, ++{0x37e6, 0x00}, ++{0x37e7, 0x00}, ++{0x37e8, 0x00}, ++{0x37e9, 0x00}, ++{0x37ea, 0x00}, ++{0x37eb, 0x00}, ++{0x37ec, 0x00}, ++{0x37ed, 0x00}, ++{0x37ee, 0x00}, ++{0x37ef, 0x00}, ++{0x37f0, 0x00}, ++{0x37f1, 0x00}, ++{0x37f2, 0x00}, ++{0x37f3, 0x00}, ++{0x37f4, 0x00}, ++{0x37f5, 0x00}, ++{0x37f6, 0x00}, ++{0x37f7, 0x00}, ++{0x37f8, 0x00}, ++{0x37f9, 0x00}, ++{0x37fa, 0x00}, ++{0x37fb, 0x00}, ++{0x37fc, 0x00}, ++{0x37fd, 0x00}, ++{0x37fe, 0x00}, ++{0x37ff, 0x00}, ++{0x3c00, 0x00}, ++{0x3c01, 0x11}, ++{0x3c02, 0x20}, ++{0x3c03, 0x04}, ++{0x3c04, 0x04}, ++{0x3c05, 0x00}, ++{0x3c06, 0x29}, ++{0x3c07, 0x01}, ++{0x3c08, 0x05}, ++{0x3c09, 0x0c}, ++{0x3c0a, 0x04}, ++{0x3c0b, 0xa8}, ++{0x3c0c, 0x11}, ++{0x3c0d, 0x08}, ++{0x3c0e, 0x03}, ++{0x3c0f, 0x02}, ++{0x3c10, 0x01}, ++{0x3c11, 0x08}, ++{0x3c12, 0x89}, ++{0x3c13, 0x21}, ++{0x3c14, 0x81}, ++{0x3c15, 0x21}, ++{0x3c16, 0x11}, ++{0x3c17, 0x01}, ++{0x3c18, 0x0c}, ++{0x3c19, 0x00}, ++{0x3c1a, 0x16}, ++{0x3c1b, 0x81}, ++{0x3c1c, 0x04}, ++{0x3c1d, 0x16}, ++{0x3c1e, 0x11}, ++{0x3c1f, 0x3a}, ++{0x3c20, 0x20}, ++{0x3c21, 0x00}, ++{0x3c22, 0x17}, ++{0x3c23, 0x07}, ++{0x3c24, 0x1a}, ++{0x3c25, 0x1e}, ++{0x3c26, 0x24}, ++{0x3c27, 0x37}, ++{0x3c28, 0x0a}, ++{0x3c29, 0x14}, ++{0x3c2a, 0xd1}, ++{0x3c2b, 0x27}, ++{0x3c2c, 0x33}, ++{0x3c2d, 0x0c}, ++{0x3c2e, 0x12}, ++{0x3c2f, 0x08}, ++{0x3c30, 0x16}, ++{0x3c31, 0x24}, ++{0x3c32, 0x35}, ++{0x3c33, 0x29}, ++{0x3c34, 0x31}, ++{0x3c35, 0x21}, ++{0x3c36, 0x11}, ++{0x3c37, 0x12}, ++{0x3c38, 0x11}, ++{0x3c39, 0x11}, ++{0x3c3a, 0x08}, ++{0x3c3b, 0x38}, ++{0x3c3c, 0x03}, ++{0x3c3d, 0x23}, ++{0x3c3e, 0x05}, ++{0x3c3f, 0x0a}, ++{0x3c40, 0xc1}, ++{0x3c41, 0x04}, ++{0x3c42, 0x01}, ++{0x3c43, 0x18}, ++{0x3c44, 0x21}, ++{0x3c45, 0x20}, ++{0x3c46, 0x0b}, ++{0x3c47, 0x11}, ++{0x3c48, 0x11}, ++{0x3c4a, 0x02}, ++{0x3c4b, 0x63}, ++{0x3c4c, 0x02}, ++{0x3c4d, 0x63}, ++{0x3c4e, 0x00}, ++{0x3c4f, 0x2a}, ++{0x3c50, 0x2a}, ++{0x3c51, 0x2a}, ++{0x3c52, 0x2a}, ++{0x3c53, 0x08}, ++{0x3c54, 0x1d}, ++{0x3c55, 0xeb}, ++{0x3c56, 0x24}, ++{0x3c57, 0x10}, ++{0x3c58, 0x10}, ++{0x3c59, 0x16}, ++{0x3c5a, 0x55}, ++{0x3c5b, 0x25}, ++{0x3c5c, 0x8e}, ++{0x3ce0, 0x00}, ++{0x3ce1, 0x00}, ++{0x3ce2, 0x00}, ++{0x3ce3, 0x00}, ++{0x3ce4, 0x00}, ++{0x3ce5, 0x00}, ++{0x3ce6, 0x00}, ++{0x3ce7, 0x00}, ++{0x3ce8, 0x00}, ++{0x3ce9, 0x00}, ++{0x3cea, 0x00}, ++{0x3ceb, 0x00}, ++{0x3cec, 0x00}, ++{0x3ced, 0x00}, ++{0x3cee, 0x00}, ++{0x3cef, 0x00}, ++{0x3cf0, 0x00}, ++{0x3cf1, 0x00}, ++{0x3cf2, 0x00}, ++{0x3cf3, 0x00}, ++{0x3cf4, 0x00}, ++{0x3cf5, 0x00}, ++{0x3cf6, 0x00}, ++{0x3cf7, 0x00}, ++{0x3cf8, 0x00}, ++{0x3cf9, 0x00}, ++{0x3cfa, 0x00}, ++{0x3cfb, 0x00}, ++{0x3cfc, 0x00}, ++{0x3cfd, 0x00}, ++{0x3cfe, 0x00}, ++{0x3cff, 0x00}, ++{0x3100, 0x00}, ++{0x3101, 0x32}, ++{0x3102, 0x00}, ++{0x3103, 0x25}, ++{0x3104, 0x01}, ++{0x3105, 0x11}, ++{0x3106, 0x10}, ++{0x3107, 0x01}, ++{0x3108, 0x01}, ++{0x3109, 0x00}, ++{0x3182, 0x10}, ++{0x3183, 0xff}, ++{0x3184, 0xff}, ++{0x3187, 0xff}, ++{0x3189, 0x00}, ++{0x318a, 0x00}, ++{0x318b, 0x00}, ++{0x318c, 0x00}, ++{0x318d, 0x00}, ++{0x318e, 0x00}, ++{0x318f, 0x00}, ++{0x3190, 0x00}, ++{0x3191, 0x00}, ++{0x3192, 0x00}, ++{0x3193, 0x00}, ++{0x3194, 0x00}, ++{0x3200, 0x00}, ++{0x3201, 0x08}, ++{0x3202, 0x10}, ++{0x3203, 0x18}, ++{0x3204, 0x20}, ++{0x3205, 0x30}, ++{0x3206, 0x00}, ++{0x3209, 0x00}, ++{0x320a, 0x00}, ++{0x320b, 0x00}, ++{0x320c, 0x00}, ++{0x320d, 0x01}, ++{0x3216, 0x01}, ++{0x3217, 0x00}, ++{0x3218, 0xf7}, ++{0x3219, 0x55}, ++{0x321b, 0x00}, ++{0x3220, 0x1c}, ++{0x3221, 0x00}, ++{0x3304, 0x04}, ++{0x3305, 0x00}, ++{0x3306, 0x03}, ++{0x3307, 0x00}, ++{0x3308, 0x00}, ++{0x3309, 0x00}, ++{0x330a, 0x00}, ++{0x330b, 0x00}, ++{0x330c, 0x00}, ++{0x330d, 0x00}, ++{0x330e, 0x00}, ++{0x330f, 0x00}, ++{0x3310, 0x06}, ++{0x3311, 0x05}, ++{0x3312, 0x55}, ++{0x3313, 0x0a}, ++{0x3314, 0xaa}, ++{0x3315, 0x0f}, ++{0x3316, 0xf0}, ++{0x3317, 0x00}, ++{0x3400, 0x08}, ++{0x3401, 0x00}, ++{0x3402, 0x00}, ++{0x3403, 0xb1}, ++{0x3404, 0x00}, ++{0x3405, 0x0f}, ++{0x3406, 0x08}, ++{0x3407, 0x08}, ++{0x3408, 0x01}, ++{0x3409, 0x02}, ++{0x340a, 0x02}, ++{0x340c, 0x10}, ++{0x340d, 0x00}, ++{0x3410, 0x00}, ++{0x3412, 0x00}, ++{0x3413, 0x00}, ++{0x3414, 0x00}, ++{0x3415, 0x00}, ++{0x3416, 0x00}, ++{0x3417, 0x00}, ++{0x3420, 0x00}, ++{0x3421, 0x00}, ++{0x3422, 0x00}, ++{0x3423, 0x00}, ++{0x3424, 0x00}, ++{0x3425, 0x00}, ++{0x3426, 0x00}, ++{0x3427, 0x00}, ++{0x3428, 0x00}, ++{0x3429, 0x00}, ++{0x342a, 0x00}, ++{0x342b, 0x00}, ++{0x3501, 0x00}, ++{0x3502, 0x24}, ++{0x3503, 0xa8}, ++{0x3504, 0x08}, ++{0x3506, 0x00}, ++{0x3507, 0x00}, ++{0x3508, 0x01}, ++{0x3509, 0x00}, ++{0x350a, 0x01}, ++{0x350b, 0x00}, ++{0x350c, 0x00}, ++{0x350d, 0x00}, ++{0x3541, 0x00}, ++{0x3542, 0x40}, ++{0x3543, 0xa8}, ++{0x3544, 0x08}, ++{0x3546, 0x00}, ++{0x3547, 0x00}, ++{0x3548, 0x01}, ++{0x3549, 0x00}, ++{0x354a, 0x01}, ++{0x354b, 0x00}, ++{0x354c, 0x00}, ++{0x354d, 0x00}, ++{0x3581, 0x00}, ++{0x3582, 0x24}, ++{0x3583, 0xa8}, ++{0x3584, 0x08}, ++{0x3586, 0x00}, ++{0x3587, 0x00}, ++{0x3588, 0x01}, ++{0x3589, 0x00}, ++{0x358a, 0x01}, ++{0x358b, 0x00}, ++{0x358c, 0x00}, ++{0x358d, 0x00}, ++{0x3600, 0x00}, ++{0x3601, 0x70}, ++{0x3602, 0x42}, ++{0x3603, 0xe3}, ++{0x3604, 0x93}, ++{0x3605, 0x40}, ++{0x3606, 0x80}, ++{0x3607, 0x4a}, ++{0x3608, 0x98}, ++{0x3609, 0x70}, ++{0x360a, 0x90}, ++{0x360b, 0x0a}, ++{0x360c, 0x40}, ++{0x360d, 0x88}, ++{0x360e, 0x88}, ++{0x360f, 0x88}, ++{0x3610, 0x89}, ++{0x3611, 0x4f}, ++{0x3612, 0x4f}, ++{0x3613, 0xba}, ++{0x3614, 0x99}, ++{0x3615, 0x99}, ++{0x3616, 0x00}, ++{0x3617, 0x00}, ++{0x3618, 0x18}, ++{0x3619, 0x00}, ++{0x3620, 0x02}, ++{0x3621, 0x80}, ++{0x3622, 0x00}, ++{0x3623, 0x00}, ++{0x3624, 0x00}, ++{0x3625, 0x00}, ++{0x3626, 0x0e}, ++{0x3627, 0x0f}, ++{0x3628, 0x0a}, ++{0x3629, 0x0a}, ++{0x362a, 0x0e}, ++{0x362b, 0x0e}, ++{0x362c, 0x0e}, ++{0x362d, 0x0e}, ++{0x362e, 0x00}, ++{0x362f, 0x00}, ++{0x3630, 0x00}, ++{0x3631, 0x00}, ++{0x3632, 0x99}, ++{0x3633, 0x99}, ++{0x3634, 0x30}, ++{0x3635, 0x30}, ++{0x3636, 0x30}, ++{0x3637, 0x30}, ++{0x3638, 0x00}, ++{0x3639, 0x00}, ++{0x363a, 0x00}, ++{0x363b, 0x0f}, ++{0x363c, 0x0f}, ++{0x363d, 0x0a}, ++{0x363e, 0x0a}, ++{0x363f, 0x0a}, ++{0x3640, 0x0a}, ++{0x3641, 0x0a}, ++{0x3642, 0x0a}, ++{0x3643, 0x10}, ++{0x3644, 0x00}, ++{0x3645, 0x10}, ++{0x3646, 0x16}, ++{0x3647, 0x10}, ++{0x3648, 0x00}, ++{0x3649, 0x13}, ++{0x364a, 0x1d}, ++{0x364b, 0x00}, ++{0x364c, 0x0e}, ++{0x364d, 0x0e}, ++{0x364e, 0x0e}, ++{0x364f, 0x0e}, ++{0x3650, 0x00}, ++{0x3651, 0x00}, ++{0x3652, 0xc5}, ++{0x3653, 0x00}, ++{0x3654, 0x40}, ++{0x3655, 0x00}, ++{0x3656, 0xcf}, ++{0x3657, 0x2b}, ++{0x3658, 0x09}, ++{0x3659, 0x00}, ++{0x365a, 0x00}, ++{0x365b, 0x00}, ++{0x365c, 0x00}, ++{0x365d, 0x00}, ++{0x3660, 0x01}, ++{0x3661, 0x07}, ++{0x3662, 0x00}, ++{0x3663, 0x20}, ++{0x3664, 0x00}, ++{0x3665, 0x12}, ++{0x3666, 0x13}, ++{0x3667, 0x14}, ++{0x3668, 0x95}, ++{0x3669, 0x16}, ++{0x366a, 0x00}, ++{0x366b, 0x00}, ++{0x366c, 0x00}, ++{0x366d, 0x00}, ++{0x366e, 0x00}, ++{0x366f, 0xc4}, ++{0x3670, 0x6f}, ++{0x3671, 0x0b}, ++{0x3672, 0x1d}, ++{0x3673, 0x6a}, ++{0x3674, 0x6f}, ++{0x3675, 0x1d}, ++{0x3676, 0x6f}, ++{0x3677, 0x1d}, ++{0x3678, 0x80}, ++{0x3679, 0x04}, ++{0x367a, 0x00}, ++{0x367b, 0x04}, ++{0x367c, 0x00}, ++{0x367d, 0x00}, ++{0x367e, 0x00}, ++{0x367f, 0x00}, ++{0x3680, 0x00}, ++{0x3800, 0x00}, ++{0x3801, 0x00}, ++{0x3802, 0x00}, ++{0x3803, 0x04}, ++{0x3804, 0x07}, ++{0x3805, 0x8f}, ++{0x3806, 0x05}, ++{0x3807, 0x0b}, ++{0x3808, 0x07}, ++{0x3809, 0x80}, ++{0x380a, 0x05}, ++{0x380b, 0x00}, ++{0x380c, 0x02}, ++{0x380d, 0x14}, ++{0x380e, 0x05}, ++{0x380f, 0x40}, ++{0x3810, 0x00}, ++{0x3811, 0x08}, ++{0x3812, 0x00}, ++{0x3813, 0x04}, ++{0x3814, 0x01}, ++{0x3815, 0x01}, ++{0x3816, 0x01}, ++{0x3817, 0x01}, ++{0x3818, 0x00}, ++{0x3819, 0x00}, ++{0x381a, 0x00}, ++{0x381b, 0x01}, ++{0x381c, 0x08}, ++{0x381d, 0x00}, ++{0x3820, 0x00}, ++{0x3821, 0x20}, ++{0x3822, 0x04}, ++{0x3823, 0x08}, ++{0x3824, 0x00}, ++{0x3825, 0x20}, ++{0x3826, 0x00}, ++{0x3827, 0x08}, ++{0x3828, 0x38}, ++{0x382a, 0x00}, ++{0x382b, 0x00}, ++{0x382c, 0x00}, ++{0x382d, 0x00}, ++{0x3832, 0x00}, ++{0x3833, 0x00}, ++{0x3834, 0x00}, ++{0x3838, 0x00}, ++{0x3839, 0x00}, ++{0x383a, 0x00}, ++{0x383b, 0x00}, ++{0x383c, 0x48}, ++{0x383d, 0x20}, ++{0x383e, 0x00}, ++{0x3842, 0x00}, ++{0x3843, 0x00}, ++{0x3844, 0x00}, ++{0x384c, 0x02}, ++{0x384d, 0x14}, ++{0x384e, 0x00}, ++{0x384f, 0x40}, ++{0x3850, 0x01}, ++{0x3851, 0x02}, ++{0x3852, 0x01}, ++{0x3853, 0x00}, ++{0x3854, 0x00}, ++{0x3855, 0x05}, ++{0x3856, 0x05}, ++{0x3857, 0x33}, ++{0x3858, 0x7c}, ++{0x3859, 0x00}, ++{0x385a, 0x03}, ++{0x385b, 0x05}, ++{0x385c, 0x32}, ++{0x385d, 0x00}, ++{0x385e, 0x12}, ++{0x385f, 0x00}, ++{0x3860, 0x10}, ++{0x3861, 0x00}, ++{0x3862, 0x40}, ++{0x3863, 0x00}, ++{0x3864, 0x40}, ++{0x3865, 0x00}, ++{0x3866, 0x40}, ++{0x3881, 0x02}, ++{0x3882, 0x00}, ++{0x3883, 0x08}, ++{0x3b40, 0x3e}, ++{0x3b41, 0x00}, ++{0x3b42, 0x02}, ++{0x3b43, 0x00}, ++{0x3b44, 0x03}, ++{0x3b45, 0x00}, ++{0x3b46, 0x03}, ++{0x3b47, 0x00}, ++{0x3b80, 0x00}, ++{0x3b81, 0x00}, ++{0x3b82, 0x07}, ++{0x3b83, 0x87}, ++{0x3b84, 0x36}, ++{0x3b85, 0x00}, ++{0x3b86, 0x00}, ++{0x3b87, 0x04}, ++{0x3b88, 0x00}, ++{0x3b89, 0x04}, ++{0x3b8a, 0x00}, ++{0x3b8b, 0x0a}, ++{0x3b8c, 0x00}, ++{0x3b8d, 0x01}, ++{0x3b8e, 0x03}, ++{0x3b8f, 0xe8}, ++{0x3d82, 0xbc}, ++{0x3d83, 0x08}, ++{0x3d84, 0x00}, ++{0x3d85, 0x1b}, ++{0x3d86, 0x02}, ++{0x3d87, 0x0a}, ++{0x3d88, 0x00}, ++{0x3d89, 0x00}, ++{0x3d8a, 0x03}, ++{0x3d8b, 0xff}, ++{0x3d8c, 0x00}, ++{0x3d8d, 0x00}, ++{0x3d90, 0x00}, ++{0x3d91, 0x00}, ++{0x3d92, 0xe2}, ++{0x3d93, 0x46}, ++{0x3d94, 0x14}, ++{0x3d95, 0x06}, ++{0x3d96, 0x01}, ++{0x3d97, 0x00}, ++{0x3d98, 0x00}, ++{0x3d99, 0x00}, ++{0x3d9a, 0x00}, ++{0x3d9b, 0x00}, ++{0x3d9c, 0x00}, ++{0x3d9d, 0x00}, ++{0x3d9e, 0x00}, ++{0x3d9f, 0x00}, ++{0x3da0, 0x00}, ++{0x3da1, 0x00}, ++{0x3da2, 0x00}, ++{0x3da4, 0x00}, ++{0x3e00, 0x00}, ++{0x3e01, 0x00}, ++{0x3e02, 0x0f}, ++{0x3e03, 0xdb}, ++{0x3e04, 0x14}, ++{0x3e05, 0x00}, ++{0x3e06, 0x03}, ++{0x3e07, 0x40}, ++{0x3e08, 0x00}, ++{0x3e09, 0x00}, ++{0x3e0a, 0x00}, ++{0x3e0b, 0x00}, ++{0x3e0c, 0x00}, ++{0x3e0d, 0x00}, ++{0x3e0e, 0x00}, ++{0x3f00, 0x04}, ++{0x3f01, 0x00}, ++{0x3f02, 0x00}, ++{0x3f03, 0x01}, ++{0x4000, 0xf8}, ++{0x4001, 0xeb}, ++{0x4004, 0x00}, ++{0x4005, 0x40}, ++{0x4006, 0x00}, ++{0x4007, 0x10}, ++{0x4008, 0x00}, ++{0x4009, 0x05}, ++{0x400a, 0x02}, ++{0x400b, 0x00}, ++{0x400c, 0x00}, ++{0x400d, 0x10}, ++{0x400e, 0x00}, ++{0x400f, 0xa0}, ++{0x4010, 0x10}, ++{0x4011, 0xff}, ++{0x4012, 0x08}, ++{0x4013, 0x02}, ++{0x4014, 0x02}, ++{0x4015, 0x02}, ++{0x4016, 0x00}, ++{0x4017, 0x04}, ++{0x4018, 0x18}, ++{0x4019, 0x04}, ++{0x401a, 0x58}, ++{0x4020, 0x00}, ++{0x4021, 0x00}, ++{0x4022, 0x00}, ++{0x4023, 0x00}, ++{0x4024, 0x00}, ++{0x4025, 0x00}, ++{0x4026, 0x00}, ++{0x4027, 0x00}, ++{0x4028, 0x4f}, ++{0x4029, 0x01}, ++{0x402a, 0x00}, ++{0x402b, 0x00}, ++{0x402c, 0x00}, ++{0x402d, 0x00}, ++{0x402e, 0x00}, ++{0x402f, 0x40}, ++{0x4030, 0x00}, ++{0x4031, 0x40}, ++{0x4032, 0x9e}, ++{0x4033, 0x80}, ++{0x4034, 0x00}, ++{0x4035, 0x80}, ++{0x4036, 0x00}, ++{0x4037, 0x80}, ++{0x4038, 0x00}, ++{0x4039, 0x80}, ++{0x403a, 0x00}, ++{0x403b, 0x80}, ++{0x403c, 0x00}, ++{0x403d, 0x00}, ++{0x4040, 0x00}, ++{0x4041, 0x00}, ++{0x4042, 0x00}, ++{0x4043, 0x00}, ++{0x4044, 0x00}, ++{0x4045, 0x00}, ++{0x4046, 0x00}, ++{0x4047, 0x00}, ++{0x4048, 0x00}, ++{0x4049, 0x00}, ++{0x404a, 0x00}, ++{0x404b, 0x00}, ++{0x404c, 0x00}, ++{0x404d, 0x00}, ++{0x404e, 0x00}, ++{0x404f, 0x00}, ++{0x4050, 0x00}, ++{0x4051, 0x05}, ++{0x4052, 0x00}, ++{0x4053, 0x80}, ++{0x4054, 0x00}, ++{0x4055, 0x80}, ++{0x4056, 0x00}, ++{0x4057, 0x80}, ++{0x4058, 0x00}, ++{0x4059, 0x80}, ++{0x405a, 0x30}, ++{0x405b, 0x18}, ++{0x405c, 0x00}, ++{0x405d, 0x00}, ++{0x405e, 0x00}, ++{0x405f, 0x00}, ++{0x4060, 0x00}, ++{0x4065, 0x00}, ++{0x4066, 0x02}, ++{0x406d, 0x00}, ++{0x406e, 0x00}, ++{0x406f, 0x00}, ++{0x40a0, 0x00}, ++{0x40a1, 0x00}, ++{0x40a2, 0x00}, ++{0x40a3, 0x00}, ++{0x40a4, 0x00}, ++{0x40a5, 0x00}, ++{0x40a6, 0x00}, ++{0x40a7, 0x00}, ++{0x40c0, 0x00}, ++{0x40c1, 0x00}, ++{0x40c2, 0x00}, ++{0x40c3, 0x00}, ++{0x40c4, 0x00}, ++{0x40c5, 0x00}, ++{0x40c6, 0x00}, ++{0x40c7, 0x00}, ++{0x40c8, 0x00}, ++{0x40c9, 0x00}, ++{0x40ca, 0x00}, ++{0x40cb, 0x00}, ++{0x40cc, 0x00}, ++{0x40cd, 0x00}, ++{0x40ce, 0x00}, ++{0x40cf, 0x00}, ++{0x4200, 0x00}, ++{0x4201, 0x00}, ++{0x4202, 0x00}, ++{0x4203, 0x00}, ++{0x4204, 0x00}, ++{0x4205, 0x00}, ++{0x4206, 0x00}, ++{0x4207, 0x00}, ++{0x4208, 0x00}, ++{0x4300, 0x00}, ++{0x4301, 0x00}, ++{0x4302, 0x00}, ++{0x4303, 0x00}, ++{0x4304, 0x00}, ++{0x4305, 0x00}, ++{0x4306, 0x00}, ++{0x4307, 0x00}, ++{0x4308, 0x00}, ++{0x4309, 0x00}, ++{0x430a, 0x00}, ++{0x430b, 0xff}, ++{0x430c, 0xff}, ++{0x430d, 0x00}, ++{0x430e, 0x00}, ++{0x430f, 0x02}, ++{0x4500, 0x16}, ++{0x4501, 0x18}, ++{0x4502, 0x00}, ++{0x4503, 0x00}, ++{0x4504, 0x01}, ++{0x4505, 0x00}, ++{0x4506, 0x32}, ++{0x4507, 0x07}, ++{0x4508, 0x1a}, ++{0x4580, 0x68}, ++{0x4581, 0xc7}, ++{0x4582, 0x07}, ++{0x4583, 0x07}, ++{0x4584, 0xec}, ++{0x4585, 0x09}, ++{0x4586, 0xae}, ++{0x4587, 0x04}, ++{0x4588, 0x52}, ++{0x4589, 0x05}, ++{0x458a, 0x47}, ++{0x458b, 0x02}, ++{0x458c, 0xe2}, ++{0x458d, 0x03}, ++{0x458e, 0x85}, ++{0x458f, 0x00}, ++{0x4590, 0x20}, ++{0x4591, 0x09}, ++{0x4592, 0x60}, ++{0x45a6, 0x18}, ++{0x4600, 0x00}, ++{0x4601, 0x30}, ++{0x4602, 0x00}, ++{0x4603, 0x01}, ++{0x4604, 0x00}, ++{0x4605, 0x03}, ++{0x4609, 0x00}, ++{0x460a, 0x30}, ++{0x460b, 0x00}, ++{0x460c, 0x30}, ++{0x460d, 0x01}, ++{0x460e, 0x00}, ++{0x4700, 0x2a}, ++{0x4702, 0x00}, ++{0x4703, 0x80}, ++{0x4704, 0x00}, ++{0x4705, 0x10}, ++{0x4706, 0xaa}, ++{0x4707, 0x55}, ++{0x4708, 0x99}, ++{0x4709, 0x66}, ++{0x470a, 0x08}, ++{0x470b, 0x88}, ++{0x470c, 0x00}, ++{0x470d, 0x02}, ++{0x470e, 0x00}, ++{0x470f, 0x00}, ++{0x4710, 0x00}, ++{0x4711, 0x00}, ++{0x4712, 0x00}, ++{0x4713, 0x00}, ++{0x4800, 0x04}, ++{0x4802, 0x00}, ++{0x4803, 0x00}, ++{0x4804, 0x08}, ++{0x4805, 0x00}, ++{0x4806, 0x00}, ++{0x4807, 0x03}, ++{0x4808, 0x18}, ++{0x480e, 0x04}, ++{0x4810, 0xff}, ++{0x4811, 0xff}, ++{0x4813, 0xe4}, // VC ++{0x4814, 0x2a}, ++{0x4815, 0x2b}, ++{0x4816, 0x2b}, ++{0x4818, 0x00}, ++{0x4819, 0x70}, ++{0x481a, 0x00}, ++{0x481b, 0x3c}, ++{0x481c, 0x01}, ++{0x481d, 0x2c}, ++{0x481e, 0x5f}, ++{0x481f, 0x26}, ++{0x4820, 0x00}, ++{0x4821, 0x3c}, ++{0x4822, 0x00}, ++{0x4823, 0x3c}, ++{0x4824, 0x00}, ++{0x4825, 0x32}, ++{0x4826, 0x32}, ++{0x4827, 0x55}, ++{0x4828, 0x00}, ++{0x4829, 0x64}, ++{0x482a, 0x06}, ++{0x482b, 0x04}, ++{0x482c, 0x00}, ++{0x482d, 0x00}, ++{0x482e, 0x34}, ++{0x482f, 0x00}, ++{0x4830, 0x00}, ++{0x4831, 0x64}, ++{0x4832, 0x00}, ++{0x4833, 0x10}, ++{0x4837, 0x15}, ++{0x4838, 0x00}, ++{0x4839, 0x00}, ++{0x483c, 0x10}, ++{0x483d, 0x00}, ++{0x484a, 0x3f}, ++{0x484b, 0x67}, ++{0x484c, 0x00}, ++{0x484e, 0x10}, ++{0x4850, 0x40}, ++{0x4851, 0xaa}, ++{0x4852, 0xff}, ++{0x4853, 0x8a}, ++{0x4854, 0x08}, ++{0x4855, 0x30}, ++{0x4856, 0x01}, ++{0x4860, 0x00}, ++{0x4861, 0xa0}, ++{0x4862, 0x01}, ++{0x4863, 0x01}, ++{0x4864, 0x02}, ++{0x4865, 0x66}, ++{0x4866, 0x99}, ++{0x4867, 0x88}, ++{0x4868, 0xaa}, ++{0x4869, 0xff}, ++{0x486a, 0x3f}, ++{0x486b, 0x84}, ++{0x486c, 0x36}, ++{0x486d, 0x00}, ++{0x486e, 0x84}, ++{0x486f, 0x36}, ++{0x4870, 0x00}, ++{0x4880, 0x00}, ++{0x4881, 0x00}, ++{0x4882, 0x00}, ++{0x4883, 0x00}, ++{0x4884, 0x08}, ++{0x4885, 0x00}, ++{0x4886, 0x00}, ++{0x4900, 0x08}, ++{0x4901, 0x00}, ++{0x4902, 0x00}, ++{0x4903, 0x80}, ++{0x4f00, 0xff}, ++{0x4f01, 0xff}, ++{0x4f04, 0x00}, ++{0x4f05, 0x01}, ++{0x5180, 0x04}, ++{0x5181, 0x00}, ++{0x5182, 0x04}, ++{0x5183, 0x00}, ++{0x5184, 0x04}, ++{0x5185, 0x00}, ++{0x5186, 0x04}, ++{0x5187, 0x00}, ++{0x5188, 0x00}, ++{0x5189, 0x00}, ++{0x518a, 0x00}, ++{0x518b, 0x10}, ++{0x51a0, 0x04}, ++{0x51a1, 0x00}, ++{0x51a2, 0x04}, ++{0x51a3, 0x00}, ++{0x51a4, 0x04}, ++{0x51a5, 0x00}, ++{0x51a6, 0x04}, ++{0x51a7, 0x00}, ++{0x51a8, 0x00}, ++{0x51a9, 0x00}, ++{0x51aa, 0x00}, ++{0x51ab, 0x10}, ++{0x51c0, 0x04}, ++{0x51c1, 0x00}, ++{0x51c2, 0x04}, ++{0x51c3, 0x00}, ++{0x51c4, 0x04}, ++{0x51c5, 0x00}, ++{0x51c6, 0x04}, ++{0x51c7, 0x00}, ++{0x51c8, 0x00}, ++{0x51c9, 0x00}, ++{0x51ca, 0x00}, ++{0x51cb, 0x10}, ++{0x5380, 0x19}, ++{0x5381, 0x94}, ++{0x5382, 0x2e}, ++{0x5383, 0x24}, ++{0x5384, 0x12}, ++{0x5385, 0x41}, ++{0x5386, 0x48}, ++{0x5387, 0x84}, ++{0x5388, 0x40}, ++{0x5389, 0x00}, ++{0x538a, 0x00}, ++{0x538b, 0x03}, ++{0x538c, 0x00}, ++{0x538d, 0x0f}, ++{0x538e, 0x00}, ++{0x538f, 0x3f}, ++{0x5390, 0x0f}, ++{0x5391, 0xfd}, ++{0x5392, 0xf5}, ++{0x5393, 0xf5}, ++{0x5394, 0x02}, ++{0x5395, 0xff}, ++{0x5396, 0x00}, ++{0x5397, 0x00}, ++{0x53a0, 0x41}, ++{0x53a2, 0x04}, ++{0x53a3, 0x00}, ++{0x53a4, 0x04}, ++{0x53a5, 0x00}, ++{0x53a6, 0x04}, ++{0x53a7, 0x00}, ++{0x53ac, 0x04}, ++{0x53ad, 0x00}, ++{0x53ae, 0x04}, ++{0x53af, 0x00}, ++{0x53b0, 0x04}, ++{0x53b1, 0x00}, ++{0x5400, 0x19}, ++{0x5401, 0x94}, ++{0x5402, 0x2e}, ++{0x5403, 0x24}, ++{0x5404, 0x12}, ++{0x5405, 0x41}, ++{0x5406, 0x48}, ++{0x5407, 0x84}, ++{0x5408, 0x40}, ++{0x5409, 0x00}, ++{0x540a, 0x00}, ++{0x540b, 0x03}, ++{0x540c, 0x00}, ++{0x540d, 0x0f}, ++{0x540e, 0x00}, ++{0x540f, 0x3f}, ++{0x5410, 0x0f}, ++{0x5411, 0xfd}, ++{0x5412, 0xf5}, ++{0x5413, 0xf5}, ++{0x5414, 0x02}, ++{0x5415, 0xff}, ++{0x5416, 0x00}, ++{0x5417, 0x00}, ++{0x5420, 0x41}, ++{0x5422, 0x04}, ++{0x5423, 0x00}, ++{0x5424, 0x04}, ++{0x5425, 0x00}, ++{0x5426, 0x04}, ++{0x5427, 0x00}, ++{0x542c, 0x04}, ++{0x542d, 0x00}, ++{0x542e, 0x04}, ++{0x542f, 0x00}, ++{0x5430, 0x04}, ++{0x5431, 0x00}, ++{0x5480, 0x19}, ++{0x5481, 0x94}, ++{0x5482, 0x2e}, ++{0x5483, 0x24}, ++{0x5484, 0x12}, ++{0x5485, 0x41}, ++{0x5486, 0x48}, ++{0x5487, 0x84}, ++{0x5488, 0x40}, ++{0x5489, 0x00}, ++{0x548a, 0x00}, ++{0x548b, 0x03}, ++{0x548c, 0x00}, ++{0x548d, 0x0f}, ++{0x548e, 0x00}, ++{0x548f, 0x3f}, ++{0x5490, 0x0f}, ++{0x5491, 0xfd}, ++{0x5492, 0xf5}, ++{0x5493, 0xf5}, ++{0x5494, 0x02}, ++{0x5495, 0xff}, ++{0x5496, 0x00}, ++{0x5497, 0x00}, ++{0x54a0, 0x41}, ++{0x54a2, 0x04}, ++{0x54a3, 0x00}, ++{0x54a4, 0x04}, ++{0x54a5, 0x00}, ++{0x54a6, 0x04}, ++{0x54a7, 0x00}, ++{0x54ac, 0x04}, ++{0x54ad, 0x00}, ++{0x54ae, 0x04}, ++{0x54af, 0x00}, ++{0x54b0, 0x04}, ++{0x54b1, 0x00}, ++{0x5800, 0x19}, ++{0x5801, 0x03}, ++{0x5802, 0x60}, ++{0x5803, 0xf0}, ++{0x5804, 0x00}, ++{0x5805, 0x40}, ++{0x5806, 0x01}, ++{0x5807, 0x00}, ++{0x5808, 0x60}, ++{0x5809, 0xf0}, ++{0x580a, 0x33}, ++{0x580b, 0x10}, ++{0x580c, 0x04}, ++{0x580d, 0x00}, ++{0x580e, 0x10}, ++{0x580f, 0x10}, ++{0x5810, 0x02}, ++{0x5811, 0x08}, ++{0x5812, 0x38}, ++{0x5813, 0x00}, ++{0x5814, 0x00}, ++{0x5815, 0x00}, ++{0x5816, 0x00}, ++{0x5000, 0x81}, ++{0x5001, 0x42}, ++{0x5002, 0x19}, ++{0x5003, 0x16}, ++{0x5004, 0x02}, ++{0x5005, 0x00}, ++{0x5006, 0x01}, ++{0x5007, 0x00}, ++{0x5008, 0x00}, ++{0x5009, 0x40}, ++{0x500a, 0x00}, ++{0x500b, 0x00}, ++{0x500c, 0x00}, ++{0x500d, 0x00}, ++{0x500e, 0x00}, ++{0x500f, 0x00}, ++{0x5010, 0x07}, ++{0x5011, 0x8f}, ++{0x5012, 0x05}, ++{0x5013, 0x0f}, ++{0x5014, 0x01}, ++{0x5015, 0x01}, ++{0x5016, 0x01}, ++{0x5017, 0x01}, ++{0x5018, 0x00}, ++{0x5019, 0x00}, ++{0x501a, 0x00}, ++{0x501b, 0x10}, ++{0x501c, 0x00}, ++{0x501d, 0x10}, ++{0x501e, 0x00}, ++{0x501f, 0x10}, ++{0x5020, 0x04}, ++{0x5021, 0x00}, ++{0x5022, 0x04}, ++{0x5023, 0x00}, ++{0x5024, 0x04}, ++{0x5025, 0x00}, ++{0x5026, 0x00}, ++{0x5027, 0x10}, ++{0x5028, 0x00}, ++{0x5029, 0x10}, ++{0x502a, 0x00}, ++{0x502b, 0x10}, ++{0x502c, 0x00}, ++{0x502d, 0x10}, ++{0x502e, 0x00}, ++{0x502f, 0x10}, ++{0x5030, 0x00}, ++{0x5031, 0x10}, ++{0x5032, 0x04}, ++{0x5033, 0x00}, ++{0x5034, 0x04}, ++{0x5035, 0x00}, ++{0x5036, 0x04}, ++{0x5037, 0x00}, ++{0x5038, 0x00}, ++{0x5039, 0x10}, ++{0x503a, 0x00}, ++{0x503b, 0x10}, ++{0x503c, 0x00}, ++{0x503d, 0x10}, ++{0x503e, 0x00}, ++{0x503f, 0x00}, ++{0x5040, 0x00}, ++{0x5041, 0x01}, ++{0x5042, 0x00}, ++{0x5043, 0x00}, ++{0x5600, 0x0f}, ++{0x5601, 0xab}, ++{0x5602, 0x02}, ++{0x5603, 0x58}, ++{0x5604, 0x03}, ++{0x5605, 0x20}, ++{0x5606, 0x02}, ++{0x5607, 0x58}, ++{0x5608, 0x03}, ++{0x5609, 0x20}, ++{0x560a, 0x02}, ++{0x560b, 0x58}, ++{0x560c, 0x03}, ++{0x560d, 0x20}, ++{0x560e, 0x02}, ++{0x560f, 0x58}, ++{0x5610, 0x03}, ++{0x5611, 0x20}, ++{0x5612, 0x02}, ++{0x5613, 0x58}, ++{0x5614, 0x03}, ++{0x5615, 0x20}, ++{0x5616, 0x02}, ++{0x5617, 0x58}, ++{0x5618, 0x03}, ++{0x5619, 0x20}, ++{0x5640, 0x0f}, ++{0x5641, 0xab}, ++{0x5642, 0x02}, ++{0x5643, 0x58}, ++{0x5644, 0x03}, ++{0x5645, 0x20}, ++{0x5646, 0x02}, ++{0x5647, 0x58}, ++{0x5648, 0x03}, ++{0x5649, 0x20}, ++{0x564a, 0x02}, ++{0x564b, 0x58}, ++{0x564c, 0x03}, ++{0x564d, 0x20}, ++{0x564e, 0x02}, ++{0x564f, 0x58}, ++{0x5650, 0x03}, ++{0x5651, 0x20}, ++{0x5652, 0x02}, ++{0x5653, 0x58}, ++{0x5654, 0x03}, ++{0x5655, 0x20}, ++{0x5656, 0x02}, ++{0x5657, 0x58}, ++{0x5658, 0x03}, ++{0x5659, 0x20}, ++{0x5680, 0x0f}, ++{0x5681, 0xab}, ++{0x5682, 0x02}, ++{0x5683, 0x58}, ++{0x5684, 0x03}, ++{0x5685, 0x20}, ++{0x5686, 0x02}, ++{0x5687, 0x58}, ++{0x5688, 0x03}, ++{0x5689, 0x20}, ++{0x568a, 0x02}, ++{0x568b, 0x58}, ++{0x568c, 0x03}, ++{0x568d, 0x20}, ++{0x568e, 0x02}, ++{0x568f, 0x58}, ++{0x5690, 0x03}, ++{0x5691, 0x20}, ++{0x5692, 0x02}, ++{0x5693, 0x58}, ++{0x5694, 0x03}, ++{0x5695, 0x20}, ++{0x5696, 0x02}, ++{0x5697, 0x58}, ++{0x5698, 0x03}, ++{0x5699, 0x20}, ++{0x5700, 0x00}, ++{0x5701, 0x00}, ++{0x5702, 0x00}, ++{0x5703, 0x00}, ++{0x5704, 0x02}, ++{0x5705, 0x80}, ++{0x5706, 0x01}, ++{0x5707, 0xe0}, ++{0x5708, 0x00}, ++{0x5709, 0x0e}, ++{0x5740, 0x00}, ++{0x5741, 0x00}, ++{0x5742, 0x00}, ++{0x5743, 0x00}, ++{0x5744, 0x02}, ++{0x5745, 0x80}, ++{0x5746, 0x01}, ++{0x5747, 0xe0}, ++{0x5748, 0x00}, ++{0x5749, 0x0e}, ++{0x5780, 0x00}, ++{0x5781, 0x00}, ++{0x5782, 0x00}, ++{0x5783, 0x00}, ++{0x5784, 0x02}, ++{0x5785, 0x80}, ++{0x5786, 0x01}, ++{0x5787, 0xe0}, ++{0x5788, 0x00}, ++{0x5789, 0x0e}, ++{0x5200, 0x70}, ++{0x5201, 0x80}, ++{0x5202, 0x73}, ++{0x5203, 0xff}, ++{0x5204, 0x02}, ++{0x5205, 0x6c}, ++{0x5206, 0x00}, ++{0x5207, 0x00}, ++{0x5209, 0x08}, ++{0x520a, 0x00}, ++{0x520b, 0x07}, ++{0x520c, 0x01}, ++{0x520d, 0x01}, ++{0x520e, 0x01}, ++{0x520f, 0x01}, ++{0x5210, 0x00}, ++{0x5211, 0x00}, ++{0x5212, 0x00}, ++{0x5213, 0x00}, ++{0x5214, 0x00}, ++{0x5215, 0x00}, ++{0x5216, 0x07}, ++{0x5217, 0x8b}, ++{0x5218, 0x00}, ++{0x5219, 0x00}, ++{0x5280, 0x00}, ++{0x5281, 0x00}, ++{0x5282, 0xff}, ++{0x5283, 0xff}, ++{0x5284, 0x02}, ++{0x5285, 0x6c}, ++{0x5286, 0x00}, ++{0x5287, 0x00}, ++{0x5289, 0x08}, ++{0x528a, 0x00}, ++{0x528b, 0x07}, ++{0x528c, 0x01}, ++{0x528d, 0x01}, ++{0x528e, 0x01}, ++{0x528f, 0x01}, ++{0x5290, 0x00}, ++{0x5291, 0x00}, ++{0x5292, 0x00}, ++{0x5293, 0x00}, ++{0x5294, 0x00}, ++{0x5295, 0x00}, ++{0x5296, 0x07}, ++{0x5297, 0x8b}, ++{0x5298, 0x00}, ++{0x5299, 0x00}, ++{0x5300, 0x00}, ++{0x5301, 0x00}, ++{0x5302, 0xff}, ++{0x5303, 0xff}, ++{0x5304, 0x02}, ++{0x5305, 0x6c}, ++{0x5306, 0x00}, ++{0x5307, 0x00}, ++{0x5309, 0x08}, ++{0x530a, 0x00}, ++{0x530b, 0x07}, ++{0x530c, 0x01}, ++{0x530d, 0x01}, ++{0x530e, 0x01}, ++{0x530f, 0x01}, ++{0x5310, 0x00}, ++{0x5311, 0x00}, ++{0x5312, 0x00}, ++{0x5313, 0x00}, ++{0x5314, 0x00}, ++{0x5315, 0x00}, ++{0x5316, 0x07}, ++{0x5317, 0x8b}, ++{0x5318, 0x00}, ++{0x5319, 0x00}, ++#ifdef OX03A_DISPLAY_PATTERN_COLOR_BAR ++{0x5080, 0x80}, /* Rolling test pattern for HCG */ ++#else ++{0x5080, 0x00}, ++#endif ++{0x5081, 0x01}, ++{0x5082, 0xb0}, ++{0x5083, 0x0f}, ++{0x5084, 0x00}, ++{0x5085, 0x00}, ++{0x5086, 0x00}, ++{0x5087, 0x01}, ++{0x5088, 0x00}, ++{0x5089, 0x00}, ++{0x508a, 0x00}, ++{0x508b, 0x00}, ++{0x508c, 0x00}, ++{0x508d, 0x00}, ++{0x508e, 0x00}, ++{0x508f, 0x00}, ++{0x5090, 0x00}, ++{0x5091, 0x00}, ++{0x5092, 0x00}, ++{0x5093, 0x00}, ++{0x5094, 0x00}, ++{0x5095, 0x00}, ++{0x5096, 0x00}, ++{0x5097, 0x00}, ++#ifdef OX03A_DISPLAY_PATTERN_COLOR_BAR ++{0x50c0, 0x80}, /* Rolling test pattern for LCG */ ++#else ++{0x50c0, 0x00}, ++#endif ++{0x50c1, 0x01}, ++{0x50c2, 0xb0}, ++{0x50c3, 0x0f}, ++{0x50c4, 0x00}, ++{0x50c5, 0x00}, ++{0x50c6, 0x00}, ++{0x50c7, 0x01}, ++{0x50c8, 0x00}, ++{0x50c9, 0x00}, ++{0x50ca, 0x00}, ++{0x50cb, 0x00}, ++{0x50cc, 0x00}, ++{0x50cd, 0x00}, ++{0x50ce, 0x00}, ++{0x50cf, 0x00}, ++{0x50d0, 0x00}, ++{0x50d1, 0x00}, ++{0x50d2, 0x00}, ++{0x50d3, 0x00}, ++{0x50d4, 0x00}, ++{0x50d5, 0x00}, ++{0x50d6, 0x00}, ++{0x50d7, 0x00}, ++#ifdef OX03A_DISPLAY_PATTERN_COLOR_BAR ++{0x5100, 0x80}, /* Rolling test pattern for VS */ ++#else ++{0x5100, 0x00}, ++#endif ++{0x5101, 0x01}, ++{0x5102, 0xb0}, ++{0x5103, 0x0f}, ++{0x5104, 0x00}, ++{0x5105, 0x00}, ++{0x5106, 0x00}, ++{0x5107, 0x01}, ++{0x5108, 0x00}, ++{0x5109, 0x00}, ++{0x510a, 0x00}, ++{0x510b, 0x00}, ++{0x510c, 0x00}, ++{0x510d, 0x00}, ++{0x510e, 0x00}, ++{0x510f, 0x00}, ++{0x5110, 0x00}, ++{0x5111, 0x00}, ++{0x5112, 0x00}, ++{0x5113, 0x00}, ++{0x5114, 0x00}, ++{0x5115, 0x00}, ++{0x5116, 0x00}, ++{0x5117, 0x00}, ++{0x380e, 0x05}, ++{0x380f, 0x34}, ++{0x380c, 0x06}, ++{0x380d, 0xcc}, ++{0x384c, 0x03}, ++{0x384d, 0xc0}, ++{0x4603, 0x01}, ++{0x4601, 0x00}, ++{0x3501, 0x01}, ++{0x0100, 0x01}, +}; diff --git a/drivers/media/i2c/soc_camera/ti9x4.c b/drivers/media/i2c/soc_camera/ti9x4.c new file mode 100644 -index 0000000..a4c7b3f +index 0000000..222db9b --- /dev/null +++ b/drivers/media/i2c/soc_camera/ti9x4.c @@ -0,0 +1,518 @@ @@ -9698,7 +16383,7 @@ index 0000000..a4c7b3f + reg8_write(client, 0x6d, port_config); + reg8_write(client, 0x7c, port_config2); + reg8_write(client, 0x70, (idx << 6) | 0x1e); /* CSI data type: yuv422 8-bit, assign VC */ -+ reg8_write(client, 0x71, (idx << 6) | 0x2a); /* CSI data type: RAW8, assign VC */ ++ reg8_write(client, 0x71, (idx << 6) | 0x2c); /* CSI data type: RAW12, assign VC */ + reg8_write(client, 0xbc, 0x00); /* Setup minimal time between FV and LV to 3 PCLKs */ + reg8_write(client, 0x6e, 0x88); /* Sensor reset: backchannel GPIO0/GPIO1 set low */ +} @@ -10158,7 +16843,7 @@ index 0000000..b53b4c6 +} +#endif /* _TI9X4_H */ diff --git a/drivers/media/platform/soc_camera/rcar_csi2.c b/drivers/media/platform/soc_camera/rcar_csi2.c -index 4d95da6..2ef27e8 100644 +index 4d95da6..53fc644 100644 --- a/drivers/media/platform/soc_camera/rcar_csi2.c +++ b/drivers/media/platform/soc_camera/rcar_csi2.c @@ -37,8 +37,9 @@ @@ -10191,6 +16876,15 @@ index 4d95da6..2ef27e8 100644 #define RCAR_CSI2_PHYCNT_SHUTDOWNZ (1 << 17) #define RCAR_CSI2_PHYCNT_RSTZ (1 << 16) #define RCAR_CSI2_PHYCNT_ENABLECLK (1 << 4) +@@ -80,7 +86,7 @@ + + #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_ON (0 << 6) + #define RCAR_CSI2_VCDT_SEL_DTN (1 << 0) + + #define RCAR_CSI2_LINKCNT_MONITOR_EN (1 << 31) @@ -106,6 +112,9 @@ #define RCAR_CSI2_LSWAP_L0SEL_PLANE2 (2 << 0) #define RCAR_CSI2_LSWAP_L0SEL_PLANE3 (3 << 0) @@ -10524,7 +17218,7 @@ index 4d95da6..2ef27e8 100644 } return ret; -@@ -543,18 +642,19 @@ static int rcar_csi2_parse_dt(struct device_node *np, +@@ -543,39 +642,30 @@ static int rcar_csi2_parse_dt(struct device_node *np, return -EINVAL; v4l2_of_parse_endpoint(endpoint, &bus_cfg); @@ -10550,25 +17244,42 @@ index 4d95da6..2ef27e8 100644 for (i = 0; i < VC_MAX_CHANNEL; i++) { sprintf(csi_name, "csi2_vc%d", i); -@@ -573,6 +673,8 @@ static int rcar_csi2_parse_dt(struct device_node *np, - config->vcdt |= (0x24 << (i * 16)); - else if (!strcmp(str, "ycbcr422")) - config->vcdt |= (0x1e << (i * 16)); -+ else if (!strcmp(str, "raw8")) -+ config->vcdt |= (0x2a << (i * 16)); - else - config->vcdt |= 0; + 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; -@@ -587,6 +689,8 @@ static int rcar_csi2_parse_dt(struct device_node *np, - config->vcdt2 |= (0x24 << (j * 16)); - else if (!strcmp(str, "ycbcr422")) - config->vcdt2 |= (0x1e << (j * 16)); -+ else if (!strcmp(str, "raw8")) -+ config->vcdt2 |= (0x2a << (j * 16)); - else - config->vcdt2 |= 0; + 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)); +@@ -583,13 +673,6 @@ static int rcar_csi2_parse_dt(struct device_node *np, + if (i >= 2) { + int j = (i - 2); -@@ -608,6 +712,7 @@ static int rcar_csi2_probe(struct platform_device *pdev) +- 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)); +@@ -608,6 +691,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; @@ -10576,7 +17287,7 @@ index 4d95da6..2ef27e8 100644 dev_dbg(&pdev->dev, "CSI2 probed.\n"); -@@ -618,12 +723,7 @@ static int rcar_csi2_probe(struct platform_device *pdev) +@@ -618,12 +702,7 @@ static int rcar_csi2_probe(struct platform_device *pdev) if (ret) return ret; @@ -10590,7 +17301,7 @@ index 4d95da6..2ef27e8 100644 } else { pdata = pdev->dev.platform_data; if (!pdata) -@@ -655,23 +755,27 @@ static int rcar_csi2_probe(struct platform_device *pdev) +@@ -655,23 +734,27 @@ static int rcar_csi2_probe(struct platform_device *pdev) return ret; priv->pdev = pdev; @@ -10628,7 +17339,7 @@ index 4d95da6..2ef27e8 100644 spin_lock_init(&priv->lock); -@@ -684,10 +788,11 @@ static int rcar_csi2_probe(struct platform_device *pdev) +@@ -684,10 +767,11 @@ static int rcar_csi2_probe(struct platform_device *pdev) static int rcar_csi2_remove(struct platform_device *pdev) { @@ -11082,7 +17793,7 @@ index 74fb005..f6119e5 100644 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 +index edd1c1d..ae04c6e 100644 --- a/drivers/media/platform/soc_camera/soc_camera.c +++ b/drivers/media/platform/soc_camera/soc_camera.c @@ -49,7 +49,7 @@ @@ -11094,7 +17805,7 @@ index edd1c1d..54f4c9d 100644 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, +@@ -1106,6 +1106,44 @@ static int soc_camera_s_parm(struct file *file, void *fh, return -ENOIOCTLCMD; } @@ -11109,11 +17820,37 @@ index edd1c1d..54f4c9d 100644 + + return -ENOIOCTLCMD; +} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int soc_camera_g_register(struct file *file, void *priv, ++ struct v4l2_dbg_register *reg) ++{ ++ struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ ++ if (ici->ops->get_register) ++ return ici->ops->get_register(icd, reg); ++ ++ return -ENOIOCTLCMD; ++} ++ ++static int soc_camera_s_register(struct file *file, void *priv, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ ++ if (ici->ops->set_register) ++ return ici->ops->set_register(icd, reg); ++ ++ return -ENOIOCTLCMD; ++} ++#endif + 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) +@@ -1664,7 +1702,7 @@ static void scan_of_host(struct soc_camera_host *ici) of_node_put(ren); if (i) { @@ -11122,16 +17859,20 @@ index edd1c1d..54f4c9d 100644 break; } } -@@ -2077,6 +2089,7 @@ static int soc_camera_device_register(struct soc_camera_device *icd) +@@ -2077,6 +2115,11 @@ 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, ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .vidioc_g_register = soc_camera_g_register, ++ .vidioc_s_register = soc_camera_s_register, ++#endif }; 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 +index e3e665e..b47d515 100644 --- a/drivers/media/platform/soc_camera/soc_mediabus.c +++ b/drivers/media/platform/soc_camera/soc_mediabus.c @@ -57,6 +57,16 @@ @@ -11151,7 +17892,24 @@ index e3e665e..84754a4 100644 .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, +@@ -382,6 +392,16 @@ + .order = SOC_MBUS_ORDER_LE, + .layout = SOC_MBUS_LAYOUT_PACKED, + }, ++}, { ++ .code = MEDIA_BUS_FMT_SBGGR16_1X16, ++ .fmt = { ++ .fourcc = V4L2_PIX_FMT_SBGGR16, ++ .name = "Bayer 16 RGGB", ++ .bits_per_sample = 16, ++ .packing = SOC_MBUS_PACKING_NONE, ++ .order = SOC_MBUS_ORDER_LE, ++ .layout = SOC_MBUS_LAYOUT_PACKED, ++ }, + }, + }; + +@@ -403,6 +423,10 @@ int soc_mbus_samples_per_pixel(const struct soc_mbus_pixelfmt *mf, *numerator = 2; *denominator = 1; return 0; @@ -11162,7 +17920,7 @@ index e3e665e..84754a4 100644 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) +@@ -428,6 +452,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; @@ -11193,14 +17951,18 @@ index 2ff7737..e5f3f53 100644 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 +index 1a15c3e..76e90be 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h -@@ -125,6 +125,7 @@ struct soc_camera_host_ops { +@@ -125,6 +125,11 @@ 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 *); ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ int (*get_register)(struct soc_camera_device *, struct v4l2_dbg_register *reg); ++ int (*set_register)(struct soc_camera_device *, const struct v4l2_dbg_register *reg); ++#endif }; #define SOCAM_SENSOR_INVERT_PCLK (1 << 0) -- cgit 1.2.3-korg From 04b39e732e6b3ec5bccee567d3ed44aaa1ae9d6e Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Wed, 11 Apr 2018 19:13:19 +0300 Subject: Add VideoBox with ISP dts files Add dts files for VideoBox to be used with ISP (ISP driver provided separately) --- .../0040-arm64-dts-renesas-add-ADAS-boards.patch | 166 ++++++++++++++++++++- 1 file changed, 162 insertions(+), 4 deletions(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch index 88ed3ec..ce37154 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0040-arm64-dts-renesas-add-ADAS-boards.patch @@ -35,7 +35,7 @@ Videobox Mini V2 board on R8A7798 SoC Signed-off-by: Vladimir Barinov --- - arch/arm64/boot/dts/renesas/Makefile | 27 + + arch/arm64/boot/dts/renesas/Makefile | 30 + arch/arm64/boot/dts/renesas/legacy/Makefile | 8 + .../renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts | 1624 +++++++++++++++++++ .../renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts | 441 ++++++ @@ -78,12 +78,14 @@ Signed-off-by: Vladimir Barinov arch/arm64/boot/dts/renesas/r8a7797-es1-v3msk.dts | 17 + arch/arm64/boot/dts/renesas/r8a7797-es1.dtsi | 116 ++ arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts | 520 +++++++ + .../boot/dts/renesas/r8a7797-v3msk-vbm-v2-isp.dts | 69 + .../boot/dts/renesas/r8a7797-v3msk-vbm-v2.dts | 81 + arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts | 507 ++++++ arch/arm64/boot/dts/renesas/r8a7797-v3msk-view.dts | 297 ++++ arch/arm64/boot/dts/renesas/r8a7797-v3msk.dts | 345 +++++ arch/arm64/boot/dts/renesas/r8a7797-v3mzf.dts | 462 ++++++ arch/arm64/boot/dts/renesas/r8a7798-condor.dts | 963 ++++++++++++ + .../boot/dts/renesas/r8a7798-v3hsk-vbm-v2-isp.dts | 70 + .../boot/dts/renesas/r8a7798-v3hsk-vbm-v2.dts | 72 + arch/arm64/boot/dts/renesas/r8a7798-v3hsk-vbm.dts | 505 ++++++ arch/arm64/boot/dts/renesas/r8a7798-v3hsk.dts | 358 +++++ @@ -95,7 +97,7 @@ Signed-off-by: Vladimir Barinov arch/arm64/boot/dts/renesas/ulcb-vb.dtsi | 1610 +++++++++++++++++++ arch/arm64/boot/dts/renesas/ulcb-vb2.dtsi | 1605 +++++++++++++++++++ arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi | 543 +++++++ - 60 files changed, 21084 insertions(+) + 62 files changed, 21226 insertions(+) create mode 100644 arch/arm64/boot/dts/renesas/legacy/Makefile create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v0.dts create mode 100644 arch/arm64/boot/dts/renesas/legacy/r8a7795-es1-h3ulcb-kf-v1.dts @@ -138,12 +140,14 @@ Signed-off-by: Vladimir Barinov create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-es1-v3msk.dts create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-es1.dtsi create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-v3msk-kf.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm-v2-isp.dts create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm-v2.dts create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm.dts create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-v3msk-view.dts create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-v3msk.dts create mode 100644 arch/arm64/boot/dts/renesas/r8a7797-v3mzf.dts create mode 100644 arch/arm64/boot/dts/renesas/r8a7798-condor.dts + create mode 100644 arch/arm64/boot/dts/renesas/r8a7798-v3hsk-vbm-v2-isp.dts create mode 100644 arch/arm64/boot/dts/renesas/r8a7798-v3hsk-vbm-v2.dts create mode 100644 arch/arm64/boot/dts/renesas/r8a7798-v3hsk-vbm.dts create mode 100644 arch/arm64/boot/dts/renesas/r8a7798-v3hsk.dts @@ -157,10 +161,10 @@ Signed-off-by: Vladimir Barinov create mode 100644 arch/arm64/boot/dts/renesas/ulcb-vbm.dtsi diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile -index f9c71df..6219e6f 100644 +index f9c71df..077666a 100644 --- a/arch/arm64/boot/dts/renesas/Makefile +++ b/arch/arm64/boot/dts/renesas/Makefile -@@ -6,5 +6,32 @@ dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-xs.dtb +@@ -6,5 +6,35 @@ dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-xs.dtb dtb-$(CONFIG_ARCH_R8A77965) += r8a77965-salvator-x.dtb dtb-$(CONFIG_ARCH_R8A77965) += r8a77965-salvator-xs.dtb @@ -187,6 +191,9 @@ index f9c71df..6219e6f 100644 +dtb-$(CONFIG_ARCH_R8A7798) += r8a7798-v3hsk.dtb +dtb-$(CONFIG_ARCH_R8A7798) += r8a7798-v3hsk-vbm.dtb +dtb-$(CONFIG_ARCH_R8A7798) += r8a7798-v3hsk-vbm-v2.dtb ++# boards with ISP ++dtb-$(CONFIG_ARCH_R8A7797) += r8a7797-v3msk-vbm-v2-isp.dtb ++dtb-$(CONFIG_ARCH_R8A7798) += r8a7798-v3hsk-vbm-v2-isp.dtb + +# ADAS legacy boards +subdir-y := legacy @@ -11701,6 +11708,81 @@ index 0000000..862236f + }; + }; +}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm-v2-isp.dts b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm-v2-isp.dts +new file mode 100644 +index 0000000..2d95bc9 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm-v2-isp.dts +@@ -0,0 +1,69 @@ ++/* ++ * Device Tree Source for the V3MSK Videobox Mini V2 board on r8a7797 ++ * ++ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "r8a7797-v3msk-vbm-v2.dts" ++ ++&ov106xx_in0 { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&isp0ep0>; ++}; ++ ++&ti9x4_csi0ep0 { ++ csi-rate = <1450>; ++ remote-endpoint = <&csi2_40_ep>; ++}; ++ ++&isp0 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ isp0ep0: endpoint { ++ csi,select = "csi40"; ++ virtual,channel = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ }; ++ port@1 { ++ csi0isp0ep0: endpoint { ++ remote-endpoint = <&csi2_40_ep>; ++ }; ++ }; ++ port@2 { ++ isp0_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ isp0_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin0 { ++ status = "disabled"; ++}; ++ ++&vin1 { ++ status = "disabled"; ++}; ++ ++&vin2 { ++ status = "disabled"; ++}; ++ ++&vin3 { ++ status = "disabled"; ++}; diff --git a/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm-v2.dts b/arch/arm64/boot/dts/renesas/r8a7797-v3msk-vbm-v2.dts new file mode 100644 index 0000000..74a3df6 @@ -14392,6 +14474,82 @@ index 0000000..4dd7a28 + }; + }; +}; +diff --git a/arch/arm64/boot/dts/renesas/r8a7798-v3hsk-vbm-v2-isp.dts b/arch/arm64/boot/dts/renesas/r8a7798-v3hsk-vbm-v2-isp.dts +new file mode 100644 +index 0000000..584a5e5 +--- /dev/null ++++ b/arch/arm64/boot/dts/renesas/r8a7798-v3hsk-vbm-v2-isp.dts +@@ -0,0 +1,70 @@ ++/* ++ ++ * Device Tree Source for the V3HSK Videobox Mini V2 board on r8a7798 ++ * ++ * Copyright (C) 2018 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 "r8a7798-v3hsk-vbm-v2.dts" ++ ++&ov106xx_in0 { ++ clock-lanes = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&isp1ep0>; ++}; ++ ++&ti9x4_csi0ep0 { ++ csi-rate = <1450>; ++ remote-endpoint = <&csi2_41_ep>; ++}; ++ ++&isp1 { ++ status = "okay"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ isp1ep0: endpoint { ++ csi,select = "csi41"; ++ virtual,channel = <0>; ++ data-lanes = <1 2 3 4>; ++ remote-endpoint = <&ov106xx_in0>; ++ }; ++ }; ++ port@1 { ++ csi0isp1ep0: endpoint { ++ remote-endpoint = <&csi2_41_ep>; ++ }; ++ }; ++ port@2 { ++ isp1_max9286_des0ep0: endpoint@0 { ++ remote-endpoint = <&max9286_des0ep0>; ++ }; ++ isp1_ti9x4_des0ep0: endpoint@1 { ++ remote-endpoint = <&ti9x4_des0ep0>; ++ }; ++ }; ++ }; ++}; ++ ++&vin4 { ++ status = "disabled"; ++}; ++ ++&vin5 { ++ status = "disabled"; ++}; ++ ++&vin6 { ++ status = "disabled"; ++}; ++ ++&vin7 { ++ status = "disabled"; ++}; diff --git a/arch/arm64/boot/dts/renesas/r8a7798-v3hsk-vbm-v2.dts b/arch/arm64/boot/dts/renesas/r8a7798-v3hsk-vbm-v2.dts new file mode 100644 index 0000000..7bf1d6f -- cgit 1.2.3-korg From 3f45a1e38d74542c427a0bbcdc9c6136161b89af Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Wed, 11 Apr 2018 19:15:00 +0300 Subject: Enable ISP kernel config option (ISP driver is not provided on github) --- meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/condor.cfg | 1 + meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/eagle.cfg | 1 + meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3hsk.cfg | 1 + meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3msk.cfg | 1 + meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3mzf.cfg | 1 + meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas_4.9.bbappend | 2 ++ 6 files changed, 7 insertions(+) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/condor.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/condor.cfg index 7322e21..c0300de 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/condor.cfg +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/condor.cfg @@ -13,6 +13,7 @@ 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_ISP_LEGACY=y # CONFIG_VIDEO_RCAR_VIN is not set # CONFIG_VIDEO_RCAR_CSI2 is not set CONFIG_SOC_CAMERA=y 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 index ca8cee8..3a07f36 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/eagle.cfg +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/eagle.cfg @@ -13,6 +13,7 @@ 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_ISP_LEGACY=y # CONFIG_VIDEO_RCAR_VIN is not set # CONFIG_VIDEO_RCAR_CSI2 is not set CONFIG_SOC_CAMERA=y diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3hsk.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3hsk.cfg index 3713001..218909c 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3hsk.cfg +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3hsk.cfg @@ -16,6 +16,7 @@ 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_ISP_LEGACY=y # CONFIG_VIDEO_RCAR_VIN is not set # CONFIG_VIDEO_RCAR_CSI2 is not set CONFIG_SOC_CAMERA=y diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3msk.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3msk.cfg index a3c72d5..c32752e 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3msk.cfg +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3msk.cfg @@ -16,6 +16,7 @@ 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_ISP_LEGACY=y # CONFIG_VIDEO_RCAR_VIN is not set # CONFIG_VIDEO_RCAR_CSI2 is not set CONFIG_SOC_CAMERA=y diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3mzf.cfg b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3mzf.cfg index cd41866..3d3bc5a 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3mzf.cfg +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/v3mzf.cfg @@ -10,6 +10,7 @@ CONFIG_DUMMY=y CONFIG_VIDEO_ADV_DEBUG=y CONFIG_VIDEO_RCAR_VIN_LEGACY=y CONFIG_VIDEO_RCAR_CSI2_LEGACY=y +CONFIG_VIDEO_RCAR_ISP_LEGACY=y # CONFIG_VIDEO_RCAR_VIN is not set # CONFIG_VIDEO_RCAR_CSI2 is not set CONFIG_SOC_CAMERA=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 index 7e86a78..c7c7f96 100644 --- 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 @@ -144,6 +144,7 @@ KERNEL_DEVICETREE_append_v3msk = " \ renesas/r8a7797-v3msk-kf.dtb \ renesas/r8a7797-v3msk-vbm.dtb \ renesas/r8a7797-v3msk-vbm-v2.dtb \ + renesas/r8a7797-v3msk-vbm-v2-isp.dtb \ renesas/r8a7797-v3msk-view.dtb \ " @@ -159,6 +160,7 @@ KERNEL_DEVICETREE_append_v3hsk = " \ renesas/r8a7798-v3hsk.dtb \ renesas/r8a7798-v3hsk-vbm.dtb \ renesas/r8a7798-v3hsk-vbm-v2.dtb \ + renesas/r8a7798-v3hsk-vbm-v2-isp.dtb \ " # V3H VIP devices -- cgit 1.2.3-korg From 19455db9f65c51565ac8af8ceecf627e88fdd5f7 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Wed, 11 Apr 2018 19:09:47 +0300 Subject: V3M: add ISP resources in dtsi --- ...as-r8a7797-Add-Renesas-R8A7797-SoC-suppor.patch | 25 ++++++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') 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 index 1f2b11c..0b67bc1 100644 --- 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 @@ -8,7 +8,7 @@ This adds Renesas R8A7797 SoC support Signed-off-by: Vladimir Barinov --- arch/arm64/Kconfig.platforms | 8 + - arch/arm64/boot/dts/renesas/r8a7797.dtsi | 1156 +++++++++++ + arch/arm64/boot/dts/renesas/r8a7797.dtsi | 1168 +++++++++++ drivers/clk/renesas/Kconfig | 1 + drivers/clk/renesas/Makefile | 1 + drivers/clk/renesas/r8a7797-cpg-mssr.c | 232 +++ @@ -47,7 +47,7 @@ Signed-off-by: Vladimir Barinov drivers/thermal/rcar_gen3_thermal.c | 29 + include/dt-bindings/clock/r8a7797-cpg-mssr.h | 48 + include/dt-bindings/power/r8a7797-sysc.h | 32 + - 40 files changed, 4489 insertions(+), 29 deletions(-) + 40 files changed, 4501 insertions(+), 29 deletions(-) create mode 100644 arch/arm64/boot/dts/renesas/r8a7797.dtsi create mode 100644 drivers/clk/renesas/r8a7797-cpg-mssr.c create mode 100644 drivers/pinctrl/sh-pfc/pfc-r8a7797.c @@ -76,10 +76,10 @@ index ebe0a37..9cebaad 100644 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..5319b1a +index 0000000..faefe8a --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7797.dtsi -@@ -0,0 +1,1156 @@ +@@ -0,0 +1,1167 @@ +/* + * Device Tree Source for the r8a7797 SoC + * @@ -115,6 +115,7 @@ index 0000000..5319b1a + vin2 = &vin2; + vin3 = &vin3; + tsc0 = &tsc1; ++ isp0 = &isp0; + }; + + psci { @@ -1234,6 +1235,16 @@ index 0000000..5319b1a + clocks = <&cpg CPG_MOD 820>; + power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; + }; ++ ++ isp0: isp@fec00000 { ++ compatible = "renesas,isp-r8a7797"; ++ reg = <0 0xfec00000 0 0x20000>, ++ <0 0xfed00000 0 0x4000>; ++ interrupts = , ++ ; ++ clocks = <&cpg CPG_MOD 817>; ++ power-domains = <&sysc R8A7797_PD_ALWAYS_ON>; ++ }; + }; +}; diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig @@ -1821,10 +1832,10 @@ index ecae864..d5fa06c 100644 lvdcr0 |= LVDCR0_LVRES; diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c -index 74c17d8..149c107 100644 +index 156fe5f..ea451cd 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) +@@ -836,6 +836,7 @@ static u32 rcar_i2c_func(struct i2c_adapter *adap) { .compatible = "renesas,i2c-r8a7795", .data = (void *)I2C_RCAR_GEN3 }, { .compatible = "renesas,i2c-r8a7796", .data = (void *)I2C_RCAR_GEN3 }, { .compatible = "renesas,i2c-r8a77965", .data = (void *)I2C_RCAR_GEN3 }, @@ -5171,7 +5182,7 @@ index 1b33c50..63f943d 100644 { .compatible = "renesas,sh73a0", .data = &soc_shmobile_ag5 }, #endif diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c -index 36e70db..a2606fe 100644 +index 2d3ac0b..1488964 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c @@ -216,7 +216,8 @@ static int msiof_rcar_is_gen3(struct device *dev) -- cgit 1.2.3-korg From 1f30c03ce70466b2e48cc0ace8cb8ce7d3fa1f2c Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Wed, 11 Apr 2018 19:10:10 +0300 Subject: V3H: add ISP resources in dtsi --- ...as-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch | 40 +++++++++++++++++----- 1 file changed, 31 insertions(+), 9 deletions(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch index 7d57c38..321258f 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch @@ -9,7 +9,7 @@ Signed-off-by: Vladimir Barinov Signed-off-by: Mikhail Ulyanov --- arch/arm64/Kconfig.platforms | 8 + - arch/arm64/boot/dts/renesas/r8a7798.dtsi | 1700 +++++++++++++ + arch/arm64/boot/dts/renesas/r8a7798.dtsi | 1724 ++++++++++++++ drivers/clk/renesas/Kconfig | 1 + drivers/clk/renesas/Makefile | 1 + drivers/clk/renesas/r8a7798-cpg-mssr.c | 292 +++ @@ -47,7 +47,7 @@ Signed-off-by: Mikhail Ulyanov drivers/thermal/rcar_gen3_thermal.c | 10 + include/dt-bindings/clock/r8a7798-cpg-mssr.h | 56 + include/dt-bindings/power/r8a7798-sysc.h | 46 + - 39 files changed, 5618 insertions(+), 33 deletions(-) + 39 files changed, 5642 insertions(+), 33 deletions(-) create mode 100644 arch/arm64/boot/dts/renesas/r8a7798.dtsi create mode 100644 drivers/clk/renesas/r8a7798-cpg-mssr.c create mode 100644 drivers/pinctrl/sh-pfc/pfc-r8a7798.c @@ -76,10 +76,10 @@ index 9cebaad..3646b6e 100644 help diff --git a/arch/arm64/boot/dts/renesas/r8a7798.dtsi b/arch/arm64/boot/dts/renesas/r8a7798.dtsi new file mode 100644 -index 0000000..6412a24 +index 0000000..00bd4d6 --- /dev/null +++ b/arch/arm64/boot/dts/renesas/r8a7798.dtsi -@@ -0,0 +1,1700 @@ +@@ -0,0 +1,1722 @@ +/* + * Device Tree Source for the r8a7798 SoC + * @@ -131,6 +131,8 @@ index 0000000..6412a24 + vin15 = &vin15; + tsc0 = &tsc1; + tsc1 = &tsc2; ++ isp0 = &isp0; ++ isp1 = &isp1; + }; + + psci { @@ -1778,6 +1780,26 @@ index 0000000..6412a24 + clocks = <&cpg CPG_MOD 1000>; + power-domains = <&sysc R8A7798_PD_A3VIP2>; + }; ++ ++ isp0: isp@fec00000 { ++ compatible = "renesas,isp-r8a7798"; ++ reg = <0 0xfec00000 0 0x20000>, ++ <0 0xfed00000 0 0x4000>; ++ interrupts = , ++ ; ++ clocks = <&cpg CPG_MOD 817>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ }; ++ ++ isp1: isp@fee00000 { ++ compatible = "renesas,isp-r8a7798"; ++ reg = <0 0xfee00000 0 0x20000>, ++ <0 0xfed20000 0 0x4000>; ++ interrupts = , ++ ; ++ clocks = <&cpg CPG_MOD 814>; ++ power-domains = <&sysc R8A7798_PD_ALWAYS_ON>; ++ }; + }; +}; diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig @@ -2253,10 +2275,10 @@ index 3916b63..22c7713 100644 rgrp->dptsr_planes); diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c -index 149c107..0ad583a 100644 +index ea451cd..6528f72 100644 --- a/drivers/i2c/busses/i2c-rcar.c +++ b/drivers/i2c/busses/i2c-rcar.c -@@ -808,6 +808,7 @@ static u32 rcar_i2c_func(struct i2c_adapter *adap) +@@ -837,6 +837,7 @@ static u32 rcar_i2c_func(struct i2c_adapter *adap) { .compatible = "renesas,i2c-r8a7796", .data = (void *)I2C_RCAR_GEN3 }, { .compatible = "renesas,i2c-r8a77965", .data = (void *)I2C_RCAR_GEN3 }, { .compatible = "renesas,i2c-r8a7797", .data = (void *)I2C_RCAR_GEN3 }, @@ -2279,7 +2301,7 @@ index 1ae9174..41e14fa 100644 }, }; diff --git a/drivers/media/platform/soc_camera/Kconfig b/drivers/media/platform/soc_camera/Kconfig -index 5539c5d..fc7d829 100644 +index d60909a..4ed8009 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 @@ -2292,7 +2314,7 @@ index 5539c5d..fc7d829 100644 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 2ef27e8..98f271f 100644 +index 53fc644..20ffba1 100644 --- a/drivers/media/platform/soc_camera/rcar_csi2.c +++ b/drivers/media/platform/soc_camera/rcar_csi2.c @@ -163,6 +163,11 @@ @@ -6317,7 +6339,7 @@ index 63f943d..b1fcae1 100644 { .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 a2606fe..13fd706 100644 +index 1488964..9ae47e5 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c @@ -217,7 +217,8 @@ static int msiof_rcar_is_gen3(struct device *dev) -- cgit 1.2.3-korg From a6131f564f4a5d7da72fe18d327c28fd2e4f234a Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Wed, 11 Apr 2018 19:11:28 +0300 Subject: LVDS Sensors: add OX03A initial, IMX390, fix OV2775 This adds sensor OX03A, IMX390 Fix pll for OV2775 Fix refclk for all TI953 users Add ADV_DEBUG for soc_platform drivers --- .../linux-renesas/0030-Gen3-LVDS-cameras.patch | 11966 +++++++++++++++---- 1 file changed, 9364 insertions(+), 2602 deletions(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') 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 index fe71743..1623d12 100644 --- 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 @@ -6,45 +6,51 @@ Subject: [PATCH] Gen3: LVDS cameras This add Gen3 LVDS cameras support: - deserializers: MAX9286, DS90UB954/960/964 - cameras: ov10635, ov490+ov10640, ov495+OV2775, ar0132, ar0220, - ap0101+ar014x, ov2775 + ap0101+ar014x, ov2775, imx390, ox03a Signed-off-by: Vladimir Barinov --- drivers/media/i2c/soc_camera/Kconfig | 19 + drivers/media/i2c/soc_camera/Makefile | 3 + - drivers/media/i2c/soc_camera/ap0101_ar014x.c | 588 +++++++ + drivers/media/i2c/soc_camera/ap0101_ar014x.c | 588 ++++ drivers/media/i2c/soc_camera/ap0101_ar014x.h | 28 + - drivers/media/i2c/soc_camera/ar0132.c | 565 +++++++ - drivers/media/i2c/soc_camera/ar0132.h | 213 +++ - drivers/media/i2c/soc_camera/ar0220.c | 528 +++++++ - drivers/media/i2c/soc_camera/ar0220.h | 309 ++++ - drivers/media/i2c/soc_camera/max9286.c | 692 ++++++++ - drivers/media/i2c/soc_camera/max9286.h | 244 +++ - drivers/media/i2c/soc_camera/ov10635.c | 759 +++++++++ - drivers/media/i2c/soc_camera/ov10635.h | 1139 +++++++++++++ + drivers/media/i2c/soc_camera/ar0132.c | 565 ++++ + drivers/media/i2c/soc_camera/ar0132.h | 212 ++ + drivers/media/i2c/soc_camera/ar0220.c | 538 +++ + drivers/media/i2c/soc_camera/ar0220.h | 43 + + drivers/media/i2c/soc_camera/imx390.c | 533 +++ + drivers/media/i2c/soc_camera/imx390.h | 3817 ++++++++++++++++++++++ + drivers/media/i2c/soc_camera/max9286.c | 692 ++++ + drivers/media/i2c/soc_camera/max9286.h | 244 ++ + drivers/media/i2c/soc_camera/ov10635.c | 759 +++++ + drivers/media/i2c/soc_camera/ov10635.h | 1139 +++++++ drivers/media/i2c/soc_camera/ov10635_debug.h | 54 + - drivers/media/i2c/soc_camera/ov106xx.c | 139 ++ - drivers/media/i2c/soc_camera/ov2775.c | 527 +++++++ - drivers/media/i2c/soc_camera/ov2775.h | 1841 ++++++++++++++++++++++ - drivers/media/i2c/soc_camera/ov490_ov10640.c | 1133 +++++++++++++ - drivers/media/i2c/soc_camera/ov490_ov10640.h | 102 ++ - drivers/media/i2c/soc_camera/ov495_ov2775.c | 639 ++++++++ + drivers/media/i2c/soc_camera/ov106xx.c | 161 + + drivers/media/i2c/soc_camera/ov2775.c | 538 +++ + drivers/media/i2c/soc_camera/ov2775.h | 1841 +++++++++++ + drivers/media/i2c/soc_camera/ov490_ov10640.c | 1133 +++++++ + drivers/media/i2c/soc_camera/ov490_ov10640.h | 102 + + drivers/media/i2c/soc_camera/ov495_ov2775.c | 650 ++++ drivers/media/i2c/soc_camera/ov495_ov2775.h | 23 + - drivers/media/i2c/soc_camera/ti9x4.c | 518 ++++++ - drivers/media/i2c/soc_camera/ti9x4.h | 156 ++ - drivers/media/platform/soc_camera/rcar_csi2.c | 297 ++-- - drivers/media/platform/soc_camera/rcar_vin.c | 194 ++- - drivers/media/platform/soc_camera/soc_camera.c | 17 +- - drivers/media/platform/soc_camera/soc_mediabus.c | 16 + + drivers/media/i2c/soc_camera/ox03a.c | 526 +++ + drivers/media/i2c/soc_camera/ox03a.h | 1724 ++++++++++ + drivers/media/i2c/soc_camera/ti9x4.c | 518 +++ + drivers/media/i2c/soc_camera/ti9x4.h | 156 + + drivers/media/platform/soc_camera/rcar_csi2.c | 312 +- + drivers/media/platform/soc_camera/rcar_vin.c | 194 +- + drivers/media/platform/soc_camera/soc_camera.c | 47 +- + drivers/media/platform/soc_camera/soc_mediabus.c | 26 + include/media/drv-intf/soc_mediabus.h | 3 + - include/media/soc_camera.h | 1 + - 28 files changed, 10638 insertions(+), 109 deletions(-) + include/media/soc_camera.h | 5 + + 32 files changed, 17066 insertions(+), 127 deletions(-) create mode 100644 drivers/media/i2c/soc_camera/ap0101_ar014x.c create mode 100644 drivers/media/i2c/soc_camera/ap0101_ar014x.h create mode 100644 drivers/media/i2c/soc_camera/ar0132.c create mode 100644 drivers/media/i2c/soc_camera/ar0132.h create mode 100644 drivers/media/i2c/soc_camera/ar0220.c create mode 100644 drivers/media/i2c/soc_camera/ar0220.h + create mode 100644 drivers/media/i2c/soc_camera/imx390.c + create mode 100644 drivers/media/i2c/soc_camera/imx390.h create mode 100644 drivers/media/i2c/soc_camera/max9286.c create mode 100644 drivers/media/i2c/soc_camera/max9286.h create mode 100644 drivers/media/i2c/soc_camera/ov10635.c @@ -57,6 +63,8 @@ Signed-off-by: Vladimir Barinov 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/ox03a.c + create mode 100644 drivers/media/i2c/soc_camera/ox03a.h create mode 100644 drivers/media/i2c/soc_camera/ti9x4.c create mode 100644 drivers/media/i2c/soc_camera/ti9x4.h @@ -736,7 +744,7 @@ index 0000000..16599a1 +}; diff --git a/drivers/media/i2c/soc_camera/ar0132.c b/drivers/media/i2c/soc_camera/ar0132.c new file mode 100644 -index 0000000..e124e6a +index 0000000..c0ac733 --- /dev/null +++ b/drivers/media/i2c/soc_camera/ar0132.c @@ -0,0 +1,565 @@ @@ -770,7 +778,7 @@ index 0000000..e124e6a +#define AR0132_PID 0x3000 +#define AR0132_VERSION_REG 0x2400 + -+#define AR0132_MEDIA_BUS_FMT MEDIA_BUS_FMT_SBGGR12_1X12 ++#define AR0132_MEDIA_BUS_FMT MEDIA_BUS_FMT_SGRBG12_1X12 + +struct ar0132_priv { + struct v4l2_subdev sd; @@ -1307,10 +1315,10 @@ index 0000000..e124e6a +#endif diff --git a/drivers/media/i2c/soc_camera/ar0132.h b/drivers/media/i2c/soc_camera/ar0132.h new file mode 100644 -index 0000000..bafa193 +index 0000000..7dfc4e3 --- /dev/null +++ b/drivers/media/i2c/soc_camera/ar0132.h -@@ -0,0 +1,213 @@ +@@ -0,0 +1,212 @@ +/* + * ON Semiconductor AR0132 sensor camera wizard 1110x620@30/BGGR/BT601/12bit + * @@ -1327,16 +1335,15 @@ index 0000000..bafa193 + +#define AR0132_EMBEDDED_LINE + -+#define AR0132_MAX_WIDTH 1665 // (1110*3/2) ++#define AR0132_MAX_WIDTH 1104 +#define AR0132_MAX_HEIGHT 624 + +#define AR0132_DELAY 0xffff + +#define AR0132_MAX_ROI_DIM_X 1288 +#define AR0132_MAX_ROI_DIM_Y 968 -+#define AR0132_InfoLines 4 + -+#define AR0132_ROI_DIM_X 1110 // 1104 ++#define AR0132_ROI_DIM_X 1104 +#define AR0132_ROI_DIM_Y 620 // AR0132_MAX_HEIGHT + +#define AR0132_ROI_Y_START 0x00AE @@ -1370,11 +1377,11 @@ index 0000000..bafa193 + //256: Walking 1 test pattern (12 bit) +#ifdef AR0132_DISPLAY_PATTERN_FIXED +{0x3070, 0x0001}, ++#endif +{0x3072, 0x0123}, // R +{0x3074, 0x0456}, // G(GR row) +{0x3076, 0x0abc}, // B +{0x3078, 0x0def}, // G(GB row) -+#endif +#ifdef AR0132_DISPLAY_PATTERN_COLOR_BAR +{0x3070, 0x0002}, +#endif @@ -1526,10 +1533,10 @@ index 0000000..bafa193 +}; diff --git a/drivers/media/i2c/soc_camera/ar0220.c b/drivers/media/i2c/soc_camera/ar0220.c new file mode 100644 -index 0000000..ef2eb51 +index 0000000..eb20187 --- /dev/null +++ b/drivers/media/i2c/soc_camera/ar0220.c -@@ -0,0 +1,528 @@ +@@ -0,0 +1,538 @@ +/* + * ON Semiconductor AR0220 sensor camera driver + * @@ -1560,7 +1567,7 @@ index 0000000..ef2eb51 +#define AR0220_PID 0x3000 +#define AR0220_VERSION_REG 0x0C54 + -+#define AR0220_MEDIA_BUS_FMT MEDIA_BUS_FMT_SBGGR8_1X8 ++#define AR0220_MEDIA_BUS_FMT MEDIA_BUS_FMT_SGRBG14_1X14 + +struct ar0220_priv { + struct v4l2_subdev sd; @@ -1578,7 +1585,6 @@ index 0000000..ef2eb51 + int port; + int gpio_resetb; + int gpio_fsin; -+ +}; + +static inline struct ar0220_priv *to_ar0220(const struct i2c_client *client) @@ -1850,6 +1856,7 @@ index 0000000..ef2eb51 + u16 val = 0; + u16 pid = 0; + int ret = 0; ++ int tmp_addr; + + /* check and show model ID */ + reg16_read16(client, AR0220_PID, &pid); @@ -1860,6 +1867,16 @@ index 0000000..ef2eb51 + goto err; + } + ++ /* setup XCLK */ ++ tmp_addr = client->addr; ++ if (priv->ti9x4_addr) { ++ /* CLK_OUT=22.5792*160*M/N/CLKDIV -> CLK_OUT=27MHz: CLKDIV=2, M=15, N=251: 22.5792*160/8*15/251=26.987MHz=CLK_OUT */ ++ client->addr = priv->ti9x3_addr; /* Serializer I2C address */ ++ reg8_write(client, 0x06, 0x6f); /* Set CLKDIV and M */ ++ reg8_write(client, 0x07, 0xfb); /* Set N */ ++ } ++ client->addr = tmp_addr; ++ + /* Program wizard registers */ + ar0220_set_regs(client, ar0220_regs_wizard, ARRAY_SIZE(ar0220_regs_wizard)); + @@ -2060,7 +2077,7 @@ index 0000000..ef2eb51 +#endif diff --git a/drivers/media/i2c/soc_camera/ar0220.h b/drivers/media/i2c/soc_camera/ar0220.h new file mode 100644 -index 0000000..74bfdd2 +index 0000000..205c351 --- /dev/null +++ b/drivers/media/i2c/soc_camera/ar0220.h @@ -0,0 +1,43 @@ @@ -2078,7 +2095,7 @@ index 0000000..74bfdd2 +//#define AR0220_DISPLAY_PATTERN_FIXED +//#define AR0220_DISPLAY_PATTERN_COLOR_BAR + -+#define AR0220_MAX_WIDTH 3648 // (1820*2=3640) <- must be multiple of 16 - requred by R-CAR VIN ++#define AR0220_MAX_WIDTH 1820 +#define AR0220_MAX_HEIGHT 944 + +#define AR0220_DELAY 0xffff @@ -2107,16 +2124,16 @@ index 0000000..74bfdd2 +#endif +{AR0220_DELAY, 100}, // Wait 100ms +}; -diff --git a/drivers/media/i2c/soc_camera/max9286.c b/drivers/media/i2c/soc_camera/max9286.c +diff --git a/drivers/media/i2c/soc_camera/imx390.c b/drivers/media/i2c/soc_camera/imx390.c new file mode 100644 -index 0000000..c850196 +index 0000000..61f430d --- /dev/null -+++ b/drivers/media/i2c/soc_camera/max9286.c -@@ -0,0 +1,692 @@ ++++ b/drivers/media/i2c/soc_camera/imx390.c +@@ -0,0 +1,533 @@ +/* -+ * MAXIM max9286 GMSL driver ++ * OmniVision IMX390 sensor camera driver + * -+ * Copyright (C) 2015-2018 Cogent Embedded, Inc. ++ * Copyright (C) 2018 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 @@ -2125,384 +2142,213 @@ index 0000000..c850196 + */ + +#include ++#include +#include +#include -+#include -+#include +#include + ++#include +#include -+#include ++#include +#include -+#include + -+#include "max9286.h" ++#include "imx390.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 ++#define IMX390_I2C_ADDR 0x21 + -+struct max9286_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 him; -+ int hsync; -+ int vsync; -+ int timeout; -+ int poc_delay; -+ atomic_t use_count; -+ u32 csi2_outord; -+ struct i2c_client *client; -+ int max9271_addr_map[4]; -+ int ser_id; -+ struct gpio_desc *poc_gpio[4]; /* PoC power supply */ -+}; ++#define IMX390_PID 0x0330 ++#define IMX390_VER 0x0330 ++#define IMX390_VERSION_REG 0x1515 + -+static char fsync_mode_default[20] = "manual"; /* manual, automatic, semi-automatic, external */ ++#define IMX390_MEDIA_BUS_FMT MEDIA_BUS_FMT_SRGGB12_1X12 + -+static int conf_link; -+module_param(conf_link, int, 0644); -+MODULE_PARM_DESC(conf_link, " Force configuration link. Used only if robust firmware flashing required (f.e. recovery)"); ++struct imx390_priv { ++ struct v4l2_subdev sd; ++ struct v4l2_ctrl_handler hdl; ++ struct media_pad pad; ++ struct v4l2_rect rect; ++ int init_complete; ++ u8 id[6]; ++ int exposure; ++ int gain; ++ int autogain; ++ /* serializers */ ++ int ti9x4_addr; ++ int ti9x3_addr; ++ int port; ++ int gpio_resetb; ++ int gpio_fsin; ++}; + -+static int poc_trig; -+module_param(poc_trig, int, 0644); -+MODULE_PARM_DESC(poc_trig, " Use PoC triggering during reverse channel setup. Useful on systems with dedicated PoC and unstable ser-des lock"); ++static inline struct imx390_priv *to_imx390(const struct i2c_client *client) ++{ ++ return container_of(i2c_get_clientdata(client), struct imx390_priv, sd); ++} + -+static int him; -+module_param(him, int, 0644); -+MODULE_PARM_DESC(him, " Use High-Immunity mode (default: leagacy mode)"); ++static int imx390_set_regs(struct i2c_client *client, ++ const struct imx390_reg *regs, int nr_regs) ++{ ++ int i; + -+static int fsync_period; -+module_param(fsync_period, int, 0644); -+MODULE_PARM_DESC(fsync_period, " Frame sync period (default: 3.2MHz)"); ++ for (i = 0; i < nr_regs; i++) { ++ if (regs[i].reg == IMX390_DELAY) { ++ mdelay(regs[i].val); ++ continue; ++ } + -+static int hsync; -+module_param(hsync, int, 0644); -+MODULE_PARM_DESC(hsync, " HSYNC invertion (default: 0 - not inverted)"); ++ reg16_write(client, regs[i].reg, regs[i].val); ++ } + -+static int vsync = 1; -+module_param(vsync, int, 0644); -+MODULE_PARM_DESC(vsync, " VSYNC invertion (default: 1 - inverted)"); ++ return 0; ++} + -+static int gpio_resetb; -+module_param(gpio_resetb, int, 0644); -+MODULE_PARM_DESC(gpio_resetb, " Serializer GPIO reset (default: 0 - not used)"); ++static int imx390_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ return 0; ++} + -+static int active_low_resetb; -+module_param(active_low_resetb, int, 0644); -+MODULE_PARM_DESC(active_low_resetb, " Serializer GPIO reset level (default: 0 - active high)"); ++static int imx390_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 imx390_priv *priv = to_imx390(client); + -+static int poc_delay; -+module_param(poc_delay, int, 0644); -+MODULE_PARM_DESC(poc_delay, " Delay in ms after POC enable (default: 0 ms)"); ++ if (format->pad) ++ return -EINVAL; + -+static char* ser_name(int id) -+{ -+ switch (id) { -+ case MAX9271_ID: -+ return "MAX9271"; -+ case MAX96705_ID: -+ return "MAX96705"; -+ default: -+ return "unknown"; -+ } ++ mf->width = priv->rect.width; ++ mf->height = priv->rect.height; ++ mf->code = IMX390_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ return 0; +} + -+static void max9286_preinit(struct i2c_client *client, int addr) ++static int imx390_set_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) +{ -+ struct max9286_priv *priv = i2c_get_clientdata(client); ++ struct v4l2_mbus_framefmt *mf = &format->format; + -+ 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 */ -+ reg8_write(client, 0x1c, priv->him ? 0xf4 : 0x04); /* high-immunity or legacy mode */ ++ mf->code = IMX390_MEDIA_BUS_FMT; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ if (format->which == V4L2_SUBDEV_FORMAT_TRY) ++ cfg->try_fmt = *mf; ++ ++ return 0; +} + -+static void max9286_sensor_reset(struct i2c_client *client, int addr, int reset_on) ++static int imx390_enum_mbus_code(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_mbus_code_enum *code) +{ -+ struct max9286_priv *priv = i2c_get_clientdata(client); ++ if (code->pad || code->index > 0) ++ return -EINVAL; + -+ if (priv->gpio_resetb < 1 || priv->gpio_resetb > 5) -+ return; ++ code->code = IMX390_MEDIA_BUS_FMT; + -+ /* sensor reset/unreset */ -+ client->addr = addr; /* MAX9271-CAMx I2C */ -+ reg8_write(client, 0x0f, (0xfe & ~BIT(priv->gpio_resetb)) | /* set GPIOn value to reset/unreset */ -+ ((priv->active_low_resetb ? BIT(priv->gpio_resetb) : 0) ^ reset_on)); -+ reg8_write(client, 0x0e, 0x42 | BIT(priv->gpio_resetb)); /* set GPIOn direction output */ ++ return 0; +} + -+static void max9286_postinit(struct i2c_client *client, int addr) ++static int imx390_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) +{ -+ struct max9286_priv *priv = i2c_get_clientdata(client); -+ int idx; -+ -+ for (idx = 0; idx < priv->links; idx++) { -+ client->addr = priv->des_addr; /* MAX9286 I2C */ -+ reg8_write(client, 0x0a, 0x11 << idx); /* enable reverse/forward control for CAMx */ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct imx390_priv *priv = to_imx390(client); + -+ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C */ -+ max9286_sensor_reset(client, client->addr, 0); /* sensor unreset */ -+ } ++ memcpy(edid->edid, priv->id, 6); + -+ 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 */ ++ edid->edid[6] = 0xff; ++ edid->edid[7] = client->addr; ++ edid->edid[8] = IMX390_VERSION_REG >> 8; ++ edid->edid[9] = IMX390_VERSION_REG & 0xff; + -+ if (strcmp(priv->fsync_mode, "manual") == 0) { -+ 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 */ -+ } ++ return 0; +} + -+static int max9286_reverse_channel_setup(struct i2c_client *client, int idx) ++static int imx390_set_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) +{ -+ struct max9286_priv *priv = i2c_get_clientdata(client); -+ u8 val = 0; -+ int timeout = priv->timeout; -+ char timeout_str[10]; -+ int ret = 0; ++ struct v4l2_rect *rect = &sel->r; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct imx390_priv *priv = to_imx390(client); + -+ /* 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 */ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || ++ sel->target != V4L2_SEL_TGT_CROP) ++ return -EINVAL; + -+ 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 */ ++ rect->left = ALIGN(rect->left, 2); ++ rect->top = ALIGN(rect->top, 2); ++ rect->width = ALIGN(rect->width, 2); ++ rect->height = ALIGN(rect->height, 2); + -+ client->addr = 0x40; /* MAX9271-CAMx I2C */ -+ reg8_write(client, 0x04, 0x43); /* wake-up, enable reverse_control/conf_link */ -+ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ -+ reg8_write(client, 0x08, 0x01); /* reverse channel receiver high threshold enable */ -+ reg8_write(client, 0x97, priv->him ? 0xaf : 0x5f); /* enable reverse control channel programming (MAX96705-MAX96711 only) */ -+ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ if ((rect->left + rect->width > IMX390_MAX_WIDTH) || ++ (rect->top + rect->height > IMX390_MAX_HEIGHT)) ++ *rect = priv->rect; + -+ 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 */ ++ priv->rect.left = rect->left; ++ priv->rect.top = rect->top; ++ priv->rect.width = rect->width; ++ priv->rect.height = rect->height; + -+ client->addr = 0x40; /* MAX9271-CAMx I2C */ -+ reg8_read(client, 0x1e, &val); /* read max9271 ID */ -+ if (val == MAX9271_ID || val == MAX96705_ID || --timeout == 0) { -+ priv->ser_id = val; -+ break; -+ } ++ return 0; ++} + -+ /* Check if already initialized (after reboot/reset ?) */ -+ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C */ -+ reg8_read(client, 0x1e, &val); /* read max9271 ID */ -+ if (val == MAX9271_ID || val == MAX96705_ID) { -+ priv->ser_id = val; -+ reg8_write(client, 0x04, 0x43); /* enable reverse_control/conf_link */ -+ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ -+ ret = -EADDRINUSE; -+ break; -+ } -+ -+ if (timeout == priv->timeout / 2 && poc_trig) { -+ if (!IS_ERR(priv->poc_gpio[idx])) { -+ gpiod_direction_output(priv->poc_gpio[idx], 0); /* POC power off */ -+ mdelay(200); -+ gpiod_direction_output(priv->poc_gpio[idx], 1); /* POC power on */ -+ mdelay(priv->poc_delay); -+ } -+ } -+ } -+ -+ max9286_sensor_reset(client, client->addr, 1); /* sensor reset */ -+ -+ if (!timeout) { -+ ret = -ETIMEDOUT; -+ goto out; -+ } -+ -+ priv->links_mask |= BIT(idx); -+ priv->csi2_outord &= ~(0x3 << (idx * 2)); -+ priv->csi2_outord |= ((hweight8(priv->links_mask) - 1) << (idx * 2)); -+ -+out: -+ sprintf(timeout_str, "retries=%d", priv->timeout - timeout); -+ dev_info(&client->dev, "link%d %s %sat 0x%x %s %s\n", idx, ser_name(priv->ser_id), -+ ret == -EADDRINUSE ? "already " : "", priv->max9271_addr_map[idx], -+ ret == -ETIMEDOUT ? "not found: timeout GMSL link establish" : "", -+ priv->timeout - timeout? timeout_str : ""); -+ -+ return ret; -+} -+ -+static void max9286_initial_setup(struct i2c_client *client) -+{ -+ struct max9286_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); -+ } -+ -+ /* Start GMSL initialization with FSYNC disabled. This is required for some odd LVDS cameras */ -+ reg8_write(client, 0x01, 0xc0); /* ECU (aka MCU) based FrameSync using GPI-to-GPO */ -+ 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, 0x63, 0); /* disable overlap window */ -+ reg8_write(client, 0x64, 0); -+ reg8_write(client, 0x0c, 0x91 | (priv->vsync ? BIT(3) : 0) | (priv->hsync ? BIT(2) : 0)); /* enable HS/VS encoding, use D14/15 for HS/VS, invert HS/VS */ -+ reg8_write(client, 0x19, 0x0c); /* Drive HSTRAIL state for 120ns after the last payload bit */ -+} -+ -+static void max9286_gmsl_link_setup(struct i2c_client *client, int idx) ++static int imx390_get_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) +{ -+ struct max9286_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 */ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct imx390_priv *priv = to_imx390(client); + -+ if (priv->ser_id == MAX96705_ID) { -+ /* setup crossbar in DBL mode: reverse DVP bus */ -+ reg8_write(client, 0x20, 0x07); -+ reg8_write(client, 0x21, 0x06); -+ reg8_write(client, 0x22, 0x05); -+ reg8_write(client, 0x23, 0x04); -+ reg8_write(client, 0x24, 0x03); -+ reg8_write(client, 0x25, 0x02); -+ reg8_write(client, 0x26, 0x01); -+ reg8_write(client, 0x27, 0x00); ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) ++ return -EINVAL; + -+ reg8_write(client, 0x30, 0x17); -+ reg8_write(client, 0x31, 0x16); -+ reg8_write(client, 0x32, 0x15); -+ reg8_write(client, 0x33, 0x14); -+ reg8_write(client, 0x34, 0x13); -+ reg8_write(client, 0x35, 0x12); -+ reg8_write(client, 0x36, 0x11); -+ reg8_write(client, 0x37, 0x10); ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = IMX390_MAX_WIDTH; ++ sel->r.height = IMX390_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = IMX390_MAX_WIDTH; ++ sel->r.height = IMX390_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP: ++ sel->r = priv->rect; ++ return 0; ++ default: ++ return -EINVAL; + } -+ -+ client->addr = priv->des_addr; /* MAX9286-CAMx I2C */ -+ reg8_write(client, 0x34, 0x22 | MAXIM_I2C_I2C_SPEED); /* disable artificial ACK, I2C speed set */ -+ usleep_range(2000, 2500); /* wait 2ms */ -+ -+ /* I2C translator setup */ -+ client->addr = 0x40; /* MAX9271-CAMx I2C */ -+// reg8_write(client, 0x09, maxim_map[2][idx] << 1); /* SENSOR I2C translated - must be set by sensor driver */ -+// reg8_write(client, 0x0A, 0x30 << 1); /* SENSOR I2C native - must be set by sensor driver */ -+ reg8_write(client, 0x0B, BROADCAST << 1); /* broadcast I2C */ -+ reg8_write(client, 0x0C, priv->max9271_addr_map[idx] << 1); /* MAX9271-CAMx I2C new */ -+ /* I2C addresse change */ -+ reg8_write(client, 0x01, priv->des_addr << 1); /* MAX9286 I2C */ -+ reg8_write(client, 0x00, priv->max9271_addr_map[idx] << 1); /* MAX9271-CAM0 I2C new */ -+ usleep_range(2000, 2500); /* wait 2ms */ -+ /* put MAX9271 in configuration link state */ -+ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C new */ -+ reg8_write(client, 0x04, 0x43); /* enable reverse_control/conf_link */ -+ usleep_range(2000, 2500); /* wait 2ms */ -+#ifdef MAXIM_DUMP -+ client->addr = priv->des_addr; /* MAX9286-CAMx I2C */ -+ maxim_max927x_dump_regs(client); -+ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C new */ -+ maxim_max927x_dump_regs(client); -+#endif +} + -+static int max9286_initialize(struct i2c_client *client) ++static int imx390_g_mbus_config(struct v4l2_subdev *sd, ++ struct v4l2_mbus_config *cfg) +{ -+ struct max9286_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_preinit(client, priv->des_quirk_addr); -+ -+ max9286_preinit(client, priv->des_addr); -+ max9286_initial_setup(client); -+ -+ for (idx = 0; idx < priv->links; idx++) { -+ if (!IS_ERR(priv->poc_gpio[idx])) { -+ gpiod_direction_output(priv->poc_gpio[idx], 1); /* POC power on */ -+ mdelay(priv->poc_delay); -+ } -+ -+ ret = max9286_reverse_channel_setup(client, idx); -+ if (ret) -+ continue; -+ max9286_gmsl_link_setup(client, idx); -+ } -+ -+ max9286_postinit(client, priv->des_addr); -+ -+ client->addr = priv->des_addr; ++ 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 max9286_g_register(struct v4l2_subdev *sd, -+ struct v4l2_dbg_register *reg) ++static int imx390_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) +{ -+ struct max9286_priv *priv = v4l2_get_subdevdata(sd); -+ struct i2c_client *client = priv->client; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); + int ret; + u8 val = 0; + -+ ret = reg8_read(client, (u8)reg->reg, &val); ++ ret = reg16_read(client, (u16)reg->reg, &val); + if (ret < 0) + return ret; + @@ -2512,187 +2358,138 @@ index 0000000..c850196 + return 0; +} + -+static int max9286_s_register(struct v4l2_subdev *sd, -+ const struct v4l2_dbg_register *reg) ++static int imx390_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) +{ -+ struct max9286_priv *priv = v4l2_get_subdevdata(sd); -+ struct i2c_client *client = priv->client; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); + -+ return reg8_write(client, (u8)reg->reg, (u8)reg->val); ++ return reg16_write(client, (u16)reg->reg, (u8)reg->val); +} +#endif + -+static int max9286_s_power(struct v4l2_subdev *sd, int on) ++static struct v4l2_subdev_core_ops imx390_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = imx390_g_register, ++ .s_register = imx390_s_register, ++#endif ++}; ++ ++static int imx390_s_ctrl(struct v4l2_ctrl *ctrl) +{ -+ struct max9286_priv *priv = v4l2_get_subdevdata(sd); -+ struct i2c_client *client = priv->client; ++ struct v4l2_subdev *sd = to_sd(ctrl); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct imx390_priv *priv = to_imx390(client); ++ int ret = -EINVAL; + -+ 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 */ ++ if (!priv->init_complete) ++ return 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_BRIGHTNESS: ++ case V4L2_CID_CONTRAST: ++ case V4L2_CID_SATURATION: ++ case V4L2_CID_HUE: ++ case V4L2_CID_GAMMA: ++ case V4L2_CID_SHARPNESS: ++ case V4L2_CID_AUTOGAIN: ++ case V4L2_CID_GAIN: ++ case V4L2_CID_EXPOSURE: ++ case V4L2_CID_HFLIP: ++ case V4L2_CID_VFLIP: ++ break; + } + -+ return 0; ++ return ret; +} + -+static int max9286_registered_async(struct v4l2_subdev *sd) -+{ -+ struct max9286_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 */ ++static const struct v4l2_ctrl_ops imx390_ctrl_ops = { ++ .s_ctrl = imx390_s_ctrl, ++}; + -+ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx */ -+ reg8_write(client, 0x04, conf_link ? 0x43 : 0x83); /* enable serial_link */ -+ usleep_range(2000, 2500); /* wait 2ms after changing reverse_control */ ++static struct v4l2_subdev_video_ops imx390_video_ops = { ++ .s_stream = imx390_s_stream, ++ .g_mbus_config = imx390_g_mbus_config, ++}; + -+ 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 */ ++static const struct v4l2_subdev_pad_ops imx390_subdev_pad_ops = { ++ .get_edid = imx390_get_edid, ++ .enum_mbus_code = imx390_enum_mbus_code, ++ .get_selection = imx390_get_selection, ++ .set_selection = imx390_set_selection, ++ .get_fmt = imx390_get_fmt, ++ .set_fmt = imx390_set_fmt, ++}; + -+ client->addr = tmp_addr; ++static struct v4l2_subdev_ops imx390_subdev_ops = { ++ .core = &imx390_core_ops, ++ .video = &imx390_video_ops, ++ .pad = &imx390_subdev_pad_ops, ++}; + -+ return 0; ++static void imx390_otp_id_read(struct i2c_client *client) ++{ +} + -+static struct v4l2_subdev_core_ops max9286_subdev_core_ops = { -+#ifdef CONFIG_VIDEO_ADV_DEBUG -+ .g_register = max9286_g_register, -+ .s_register = max9286_s_register, -+#endif -+ .s_power = max9286_s_power, -+ .registered_async = max9286_registered_async, -+}; -+ -+static struct v4l2_subdev_ops max9286_subdev_ops = { -+ .core = &max9286_subdev_core_ops, -+}; -+ -+static int max9286_parse_dt(struct i2c_client *client) ++static ssize_t imx390_otp_id_show(struct device *dev, ++ struct device_attribute *attr, char *buf) +{ -+ struct max9286_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; -+ u8 val = 0; -+ char poc_name[10]; -+ -+ 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); -+ } ++ struct v4l2_subdev *sd = i2c_get_clientdata(to_i2c_client(dev)); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct imx390_priv *priv = to_imx390(client); + -+ mdelay(250); ++ 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]); ++} + -+ for (i = 0; i < 4; i++) { -+ sprintf(poc_name, "POC%d", i); -+ priv->poc_gpio[i] = devm_gpiod_get_optional(&client->dev, poc_name, 0); -+ } ++static DEVICE_ATTR(otp_id_imx390, S_IRUGO, imx390_otp_id_show, NULL); + -+ 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; -+ } ++static int imx390_initialize(struct i2c_client *client) ++{ ++ struct imx390_priv *priv = to_imx390(client); ++ u8 val = 0; ++ u16 pid; ++ int ret = 0; ++ int tmp_addr; + -+ 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); ++ /* check and show model ID */ ++ reg16_read(client, IMX390_PID, &val); ++ pid = val; ++ reg16_read(client, IMX390_VER, &val); ++ pid = (pid << 8) | val; + -+ 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 = 0; -+ else -+ priv->active_low_resetb = 1; ++ if (pid != IMX390_VERSION_REG) { ++ dev_dbg(&client->dev, "Product ID error %x\n", pid); ++ ret = -ENODEV; ++ goto err; + } + -+ 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; -+ if (of_property_read_u32(np, "maxim,him", &priv->him)) -+ priv->him = 0; -+ if (of_property_read_u32(np, "maxim,hsync", &priv->hsync)) -+ priv->hsync = 0; -+ if (of_property_read_u32(np, "maxim,vsync", &priv->vsync)) -+ priv->vsync = 1; -+ if (of_property_read_u32(np, "maxim,poc-delay", &priv->poc_delay)) -+ priv->poc_delay = 50; -+ -+ /* module params override dts */ -+ if (him) -+ priv->him = him; -+ if (fsync_period) { -+ priv->fsync_period = fsync_period; -+ priv->fsync_mode = fsync_mode_default; ++ /* setup XCLK */ ++ tmp_addr = client->addr; ++ if (priv->ti9x4_addr) { ++ /* CLK_OUT=22.5792*160*M/N/CLKDIV -> CLK_OUT=25MHz: CLKDIV=4, M=7, N=253: 22.5792*160/4*7/253=24.989MHz=CLK_OUT */ ++ client->addr = priv->ti9x3_addr; /* Serializer I2C address */ ++ reg8_write(client, 0x06, 0x47); /* Set CLKDIV and M */ ++ reg8_write(client, 0x07, 0xfd); /* Set N */ + } -+ if (hsync) -+ priv->hsync = hsync; -+ if (!vsync) -+ priv->vsync = vsync; -+ if (gpio_resetb) -+ priv->gpio_resetb = gpio_resetb; -+ if (active_low_resetb) -+ priv->active_low_resetb = active_low_resetb; -+ if (poc_delay) -+ priv->poc_delay = poc_delay; -+ -+ 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; -+ } ++ client->addr = tmp_addr; + -+ priv->sd_of_node[i] = endpoint; -+ } ++ /* Program wizard registers */ ++ imx390_set_regs(client, imx390_regs_wizard, ARRAY_SIZE(imx390_regs_wizard)); ++ /* Read OTP IDs */ ++ imx390_otp_id_read(client); + -+ return 0; ++ dev_info(&client->dev, "imx390 PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, IMX390_MAX_WIDTH, IMX390_MAX_HEIGHT, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++err: ++ return ret; +} + -+static void max9286_setup_remote_endpoint(struct i2c_client *client) ++static int imx390_parse_dt(struct device_node *np, struct imx390_priv *priv) +{ -+ struct max9286_priv *priv = i2c_get_clientdata(client); -+ struct device_node *np = client->dev.of_node; -+ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); + int i; -+ struct property *csi_rate_prop, *dvp_order_prop; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ int tmp_addr = 0; + + for (i = 0; ; i++) { + endpoint = of_graph_get_next_endpoint(np, endpoint); @@ -2705,116 +2502,177 @@ index 0000000..c850196 + 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); -+ } ++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti9x4") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti9x4_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ } + -+ dvp_order_prop = of_find_property(endpoint, "dvp-order", NULL); -+ if (dvp_order_prop) -+ of_update_property(rendpoint, dvp_order_prop); ++ if (!priv->ti9x4_addr) { ++ dev_err(&client->dev, "deserializer does not present\n"); ++ return -EINVAL; ++ } ++ ++ /* setup I2C translator address */ ++ tmp_addr = client->addr; ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x4_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, IMX390_I2C_ADDR << 1); /* Sensor native I2C address */ ++// reg8_write(client, 0x6e, 0xa9); /* GPIO0 - reset, GPIO1 - fsin */ + } ++ client->addr = tmp_addr; ++ ++ mdelay(10); ++ ++ return 0; +} + -+static int max9286_probe(struct i2c_client *client, -+ const struct i2c_device_id *did) ++static int imx390_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) +{ -+ struct max9286_priv *priv; -+ int err, i; ++ struct imx390_priv *priv; ++ int ret; + + 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; ++ v4l2_i2c_subdev_init(&priv->sd, client, &imx390_subdev_ops); ++ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; + -+ err = max9286_parse_dt(client); -+ if (err) -+ goto out; ++ priv->exposure = 0x100; ++ priv->gain = 0x100; ++ priv->autogain = 1; ++ v4l2_ctrl_handler_init(&priv->hdl, 4); ++ v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, ++ V4L2_CID_BRIGHTNESS, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, ++ V4L2_CID_CONTRAST, 0, 16, 1, 7); ++ v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, ++ V4L2_CID_SATURATION, 0, 7, 1, 2); ++ v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, ++ V4L2_CID_HUE, 0, 23, 1, 12); ++ v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, ++ V4L2_CID_GAMMA, -128, 128, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, ++ V4L2_CID_SHARPNESS, 0, 10, 1, 3); ++ v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, ++ V4L2_CID_AUTOGAIN, 0, 1, 1, priv->autogain); ++ v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, ++ V4L2_CID_GAIN, 0, 0xffff, 1, priv->gain); ++ v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, ++ V4L2_CID_EXPOSURE, 0, 0xffff, 1, priv->exposure); ++ v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 1); ++ v4l2_ctrl_new_std(&priv->hdl, &imx390_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ priv->sd.ctrl_handler = &priv->hdl; + -+ err = max9286_initialize(client); -+ if (err < 0) -+ goto out; ++ ret = priv->hdl.error; ++ if (ret) ++ goto cleanup; + -+ max9286_setup_remote_endpoint(client); ++ v4l2_ctrl_handler_setup(&priv->hdl); + -+ for (i = 0; i < 4; i++) { -+ v4l2_subdev_init(&priv->sd[i], &max9286_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]; ++ 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; + -+ 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); ++ ret = imx390_parse_dt(client->dev.of_node, priv); ++ if (ret) ++ goto cleanup; + -+ err = v4l2_async_register_subdev(&priv->sd[i]); -+ if (err < 0) -+ goto out; -+ } -+out: -+ return err; -+} ++ ret = imx390_initialize(client); ++ if (ret < 0) ++ goto cleanup; + -+static int max9286_remove(struct i2c_client *client) -+{ -+ struct max9286_priv *priv = i2c_get_clientdata(client); -+ int i; ++ priv->rect.left = 0; ++ priv->rect.top = 0; ++ priv->rect.width = IMX390_MAX_WIDTH; ++ priv->rect.height = IMX390_MAX_HEIGHT; + -+ for (i = 0; i < 4; i++) { -+ v4l2_async_unregister_subdev(&priv->sd[i]); -+ v4l2_device_unregister_subdev(&priv->sd[i]); -+ } ++ ret = v4l2_async_register_subdev(&priv->sd); ++ if (ret) ++ goto cleanup; + -+ return 0; ++ if (device_create_file(&client->dev, &dev_attr_otp_id_imx390) != 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_IMX390 ++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", ++ client->addr, client->adapter->name); ++#endif ++ return ret; +} + -+static const struct of_device_id max9286_dt_ids[] = { -+ { .compatible = "maxim,max9286" }, -+ {}, ++static int imx390_remove(struct i2c_client *client) ++{ ++ struct imx390_priv *priv = i2c_get_clientdata(client); ++ ++ device_remove_file(&client->dev, &dev_attr_otp_id_imx390); ++ 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_IMX390 ++static const struct i2c_device_id imx390_id[] = { ++ { "imx390", 0 }, ++ { } +}; -+MODULE_DEVICE_TABLE(of, max9286_dt_ids); ++MODULE_DEVICE_TABLE(i2c, imx390_id); + -+static const struct i2c_device_id max9286_id[] = { -+ { "max9286", 0 }, ++static const struct of_device_id imx390_of_ids[] = { ++ { .compatible = "sony,imx390", }, + { } +}; -+MODULE_DEVICE_TABLE(i2c, max9286_id); ++MODULE_DEVICE_TABLE(of, imx390_of_ids); + -+static struct i2c_driver max9286_i2c_driver = { ++static struct i2c_driver imx390_i2c_driver = { + .driver = { -+ .name = "max9286", -+ .of_match_table = of_match_ptr(max9286_dt_ids), ++ .name = "imx390", ++ .of_match_table = imx390_of_ids, + }, -+ .probe = max9286_probe, -+ .remove = max9286_remove, -+ .id_table = max9286_id, ++ .probe = imx390_probe, ++ .remove = imx390_remove, ++ .id_table = imx390_id, +}; + -+module_i2c_driver(max9286_i2c_driver); ++module_i2c_driver(imx390_i2c_driver); + -+MODULE_DESCRIPTION("GMSL driver for MAX9286"); ++MODULE_DESCRIPTION("SoC Camera driver for IMX390"); +MODULE_AUTHOR("Vladimir Barinov"); +MODULE_LICENSE("GPL"); -diff --git a/drivers/media/i2c/soc_camera/max9286.h b/drivers/media/i2c/soc_camera/max9286.h ++#endif +diff --git a/drivers/media/i2c/soc_camera/imx390.h b/drivers/media/i2c/soc_camera/imx390.h new file mode 100644 -index 0000000..6c2a9e0 +index 0000000..4217cd9 --- /dev/null -+++ b/drivers/media/i2c/soc_camera/max9286.h -@@ -0,0 +1,244 @@ ++++ b/drivers/media/i2c/soc_camera/imx390.h +@@ -0,0 +1,3817 @@ +/* -+ * MAXIM max9286-max9271 GMSL driver include file ++ * OmniVision IMX390 sensor camera wizard 1920x1080@30/BGGR/MIPI + * -+ * Copyright (C) 2015-2017 Cogent Embedded, Inc. ++ * Copyright (C) 2018 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 @@ -2822,1012 +2680,4768 @@ index 0000000..6c2a9e0 + * option) any later version. + */ + -+#ifndef _MAX9286_MAX9271_H -+#define _MAX9286_MAX9271_H ++//#define IMX390_DISPLAY_PATTERN_COLOR_BAR + -+//#define DEBUG -+#ifdef DEBUG -+//#define WRITE_VERIFY -+#define MAXIM_DUMP -+#undef dev_dbg -+#define dev_dbg dev_info ++#define IMX390_MAX_WIDTH 1920 ++#define IMX390_MAX_HEIGHT 1080 ++ ++#define IMX390_DELAY 0xffff ++#define IMX390_DT 0x2c /* MIPI Data Type RAW12 */ ++ ++struct imx390_reg { ++ u16 reg; ++ u8 val; ++}; ++ ++/* wizard: MIPI 1920x1080 RAW12 Linear 30fps 700Mbps */ ++static const struct imx390_reg imx390_regs_wizard[] = { ++{0x000C, 0xF2}, ++{0x000D, 0x02}, ++{0x000E, 0x00}, ++{0x0010, 0xF2}, ++{0x0011, 0x02}, ++{0x0012, 0x00}, ++{0x0018, 0x15}, ++{0x0019, 0x00}, ++{0x001A, 0x0C}, ++{0x001B, 0x00}, ++{0x0038, 0x00}, ++{0x003C, 0x00}, ++{0x003D, 0x00}, ++{0x003E, 0x00}, ++{0x0040, 0x00}, ++{0x0041, 0x00}, ++{0x0042, 0x00}, ++{0x0044, 0x00}, ++{0x0045, 0x00}, ++{0x0046, 0x00}, ++{0x0048, 0x00}, ++{0x0049, 0x00}, ++{0x004A, 0x00}, ++{0x004C, 0x00}, ++{0x004D, 0x00}, ++{0x004E, 0x00}, ++{0x0050, 0x00}, ++{0x0051, 0x00}, ++{0x0052, 0x00}, ++{0x0054, 0x00}, ++{0x0055, 0x00}, ++{0x0056, 0x00}, ++{0x0058, 0x00}, ++{0x0059, 0x00}, ++{0x005A, 0x00}, ++{0x005C, 0x00}, ++{0x005D, 0x00}, ++{0x005E, 0x00}, ++{0x0060, 0x00}, ++{0x0061, 0x00}, ++{0x0062, 0x00}, ++{0x0064, 0x00}, ++{0x0065, 0x00}, ++{0x0066, 0x00}, ++{0x0068, 0x00}, ++{0x0069, 0x00}, ++{0x006A, 0x00}, ++{0x0078, 0x00}, ++{0x007C, 0x00}, ++{0x007D, 0x00}, ++{0x0080, 0x00}, ++{0x0081, 0x00}, ++{0x00F4, 0x1C}, ++{0x00F5, 0xF8}, ++{0x00F6, 0x01}, ++{0x00F8, 0x03}, ++{0x00F9, 0x00}, ++{0x00FA, 0x00}, ++{0x00FB, 0x00}, ++{0x0114, 0x00}, ++{0x0115, 0x01}, ++{0x0118, 0x20}, ++{0x0119, 0x03}, ++{0x011A, 0x00}, ++{0x011B, 0x41}, ++{0x011C, 0x80}, ++{0x011D, 0x00}, ++{0x0120, 0x20}, ++{0x0121, 0x00}, ++{0x0122, 0x00}, ++{0x0123, 0x44}, ++{0x0124, 0x00}, ++{0x0125, 0x01}, ++{0x0128, 0xAC}, ++{0x0129, 0x0D}, ++{0x012A, 0x00}, ++{0x012B, 0xA4}, ++{0x012C, 0x00}, ++{0x012D, 0x01}, ++{0x0130, 0xC4}, ++{0x0131, 0x09}, ++{0x0132, 0x00}, ++{0x0133, 0xDA}, ++//{0x013A, ,3}, ++{0x013B, 0x01}, ++//{0x013C, ,3}, ++//{0x013D, ,3}, ++//{0x013E, ,3}, ++//{0x0140, ,3}, ++//{0x0141, ,3}, ++//{0x0142, ,3}, ++//{0x0144, ,3}, ++//{0x0145, ,3}, ++//{0x0146, ,3}, ++//{0x0148, ,3}, ++//{0x0149, ,3}, ++//{0x014A, ,3}, ++//{0x014C, ,3}, ++//{0x014D, ,3}, ++//{0x014E, ,3}, ++//{0x0150, ,3}, ++//{0x0151, ,3}, ++//{0x0152, ,3}, ++//{0x0154, ,3}, ++//{0x0155, ,3}, ++//{0x0156, ,3}, ++//{0x0158, ,3}, ++//{0x0159, ,3}, ++//{0x015A, ,3}, ++//{0x015C, ,3}, ++//{0x015D, ,3}, ++//{0x015E, ,3}, ++//{0x0160, ,3}, ++//{0x0161, ,3}, ++//{0x0162, ,3}, ++//{0x0164, ,3}, ++//{0x0165, ,3}, ++//{0x0166, ,3}, ++//{0x0168, ,3}, ++//{0x0169, ,3}, ++//{0x016A, ,3}, ++//{0x016C, ,3}, ++//{0x016D, ,3}, ++//{0x016E, ,3}, ++//{0x0170, ,3}, ++//{0x0171, ,3}, ++//{0x0172, ,3}, ++//{0x0174, ,3}, ++//{0x0175, ,3}, ++//{0x0176, ,3}, ++//{0x0178, ,3}, ++//{0x0179, ,3}, ++//{0x017A, ,3}, ++//{0x017C, ,3}, ++//{0x017D, ,3}, ++//{0x017E, ,3}, ++//{0x0180, ,3}, ++//{0x0181, ,3}, ++//{0x0182, ,3}, ++//{0x0184, ,3}, ++//{0x0185, ,3}, ++//{0x0186, ,3}, ++//{0x0188, ,3}, ++//{0x0189, ,3}, ++//{0x018A, ,3}, ++//{0x018C, ,3}, ++//{0x018D, ,3}, ++//{0x018E, ,3}, ++//{0x0190, ,3}, ++//{0x0191, ,3}, ++//{0x0192, ,3}, ++//{0x0194, ,3}, ++//{0x0195, ,3}, ++//{0x0196, ,3}, ++//{0x0198, ,3}, ++//{0x0199, ,3}, ++//{0x019A, ,3}, ++//{0x019B, ,3}, ++//{0x019C, ,3}, ++//{0x019D, ,3}, ++//{0x019E, ,3}, ++//{0x019F, ,3}, ++//{0x01A0, ,3}, ++//{0x01A1, ,3}, ++//{0x01A2, ,3}, ++//{0x01A3, ,3}, ++//{0x01A4, ,3}, ++//{0x01A5, ,3}, ++//{0x01A6, ,3}, ++//{0x01A7, ,3}, ++//{0x01A8, ,3}, ++//{0x01A9, ,3}, ++//{0x01AA, ,3}, ++//{0x01AB, ,3}, ++//{0x01AC, ,3}, ++//{0x01AD, ,3}, ++//{0x01AE, ,3}, ++//{0x01AF, ,3}, ++//{0x01B0, ,3}, ++//{0x01B1, ,3}, ++//{0x01B2, ,3}, ++//{0x01B3, ,3}, ++//{0x01B4, ,3}, ++//{0x01B5, ,3}, ++//{0x01B6, ,3}, ++//{0x01B7, ,3}, ++//{0x01B8, ,3}, ++//{0x01B9, ,3}, ++//{0x01BA, ,3}, ++//{0x01BB, ,3}, ++//{0x01BC, ,3}, ++//{0x01BD, ,3}, ++//{0x01BE, ,3}, ++//{0x01BF, ,3}, ++//{0x01C0, ,3}, ++//{0x01C1, ,3}, ++//{0x01C2, ,3}, ++//{0x01C3, ,3}, ++{0x01C4, 0x00}, ++{0x01C5, 0x00}, ++{0x01CC, 0x01}, ++{0x01D0, 0x09}, ++{0x01D4, 0x01}, ++{0x0232, 0x7E}, ++{0x0233, 0x00}, ++{0x0390, 0x00}, ++{0x0391, 0x00}, ++{0x0392, 0x00}, ++#ifdef IMX390_DISPLAY_PATTERN_COLOR_BAR ++{0x01DB, 0x32}, ++{0x03C0, 0x02}, ++#else ++{0x03C0, 0x00}, ++#endif ++{0x2000, 0x55}, ++{0x2001, 0x55}, ++{0x2002, 0x55}, ++{0x2003, 0x05}, ++{0x2004, 0x02}, ++{0x2008, 0x65}, ++{0x2009, 0x04}, ++{0x200A, 0x00}, ++{0x200C, 0x30}, ++{0x200D, 0x11}, ++{0x2010, 0x04}, ++{0x2014, 0x01}, ++{0x2018, 0x02}, ++{0x2019, 0x04}, ++{0x201A, 0x00}, ++{0x201C, 0x21}, ++{0x201D, 0x11}, ++{0x201E, 0x00}, ++{0x201F, 0x00}, ++{0x2020, 0xBC}, ++{0x2021, 0x00}, ++{0x2022, 0x7F}, ++{0x2023, 0x00}, ++{0x2024, 0xBA}, ++{0x2025, 0x00}, ++{0x2026, 0x81}, ++{0x2027, 0x00}, ++{0x2028, 0x7D}, ++{0x2029, 0x90}, ++{0x202A, 0x05}, ++{0x202C, 0xFC}, ++{0x202D, 0x02}, ++{0x202E, 0x25}, ++{0x202F, 0x03}, ++{0x2030, 0x05}, ++{0x2031, 0x02}, ++{0x2032, 0xCA}, ++{0x2033, 0x02}, ++{0x2034, 0xFC}, ++{0x2035, 0x02}, ++{0x2036, 0x25}, ++{0x2037, 0x03}, ++{0x2038, 0x25}, ++{0x2039, 0x97}, ++{0x203A, 0xEC}, ++{0x203B, 0x01}, ++{0x203C, 0xF5}, ++{0x203D, 0x8E}, ++{0x203E, 0x0C}, ++{0x203F, 0x2D}, ++{0x2040, 0x69}, ++{0x2041, 0x01}, ++{0x2042, 0x8E}, ++{0x2043, 0x01}, ++{0x2044, 0x0C}, ++{0x2045, 0x02}, ++{0x2046, 0x31}, ++{0x2047, 0x02}, ++{0x2048, 0x6A}, ++{0x2049, 0x01}, ++{0x204A, 0x8E}, ++{0x204B, 0x01}, ++{0x204C, 0x0D}, ++{0x204D, 0x02}, ++{0x204E, 0x31}, ++{0x204F, 0x02}, ++{0x2050, 0x7B}, ++{0x2051, 0x00}, ++{0x2052, 0x7D}, ++{0x2053, 0x00}, ++{0x2054, 0x95}, ++{0x2055, 0x00}, ++{0x2056, 0x97}, ++{0x2057, 0x00}, ++{0x2058, 0xAD}, ++{0x2059, 0x00}, ++{0x205A, 0xAF}, ++{0x205B, 0x00}, ++{0x205C, 0x92}, ++{0x205D, 0x00}, ++{0x205E, 0x94}, ++{0x205F, 0x00}, ++{0x2060, 0x8E}, ++{0x2061, 0x00}, ++{0x2062, 0x90}, ++{0x2063, 0x00}, ++{0x2064, 0xB1}, ++{0x2065, 0x00}, ++{0x2066, 0xB3}, ++{0x2067, 0x00}, ++{0x2068, 0x08}, ++{0x2069, 0x00}, ++{0x206A, 0x04}, ++{0x206B, 0x00}, ++{0x206C, 0x84}, ++{0x206D, 0x00}, ++{0x206E, 0x80}, ++{0x206F, 0x00}, ++{0x2070, 0x04}, ++{0x2071, 0x00}, ++{0x2072, 0x46}, ++{0x2073, 0x00}, ++{0x2074, 0xE9}, ++{0x2075, 0x01}, ++{0x2076, 0x74}, ++{0x2077, 0x02}, ++{0x2078, 0x80}, ++{0x2079, 0x00}, ++{0x207A, 0xC1}, ++{0x207B, 0x00}, ++{0x207C, 0xFF}, ++{0x207D, 0x03}, ++{0x207E, 0xFF}, ++{0x207F, 0x03}, ++{0x2080, 0x78}, ++{0x2081, 0x00}, ++{0x2082, 0x6A}, ++{0x2083, 0x01}, ++{0x2084, 0xE4}, ++{0x2085, 0x01}, ++{0x2086, 0x2B}, ++{0x2087, 0x03}, ++{0x2088, 0x00}, ++{0x2089, 0x00}, ++{0x208A, 0xFF}, ++{0x208B, 0x03}, ++{0x208C, 0xFF}, ++{0x208D, 0x03}, ++{0x208E, 0xFF}, ++{0x208F, 0x03}, ++{0x2090, 0x7D}, ++{0x2091, 0x00}, ++{0x2092, 0x62}, ++{0x2093, 0x01}, ++{0x2094, 0xE9}, ++{0x2095, 0x01}, ++{0x2096, 0x00}, ++{0x2097, 0x00}, ++{0x2098, 0x7C}, ++{0x2099, 0x00}, ++{0x209A, 0x21}, ++{0x209B, 0x03}, ++{0x209C, 0xE9}, ++{0x209D, 0x01}, ++{0x209E, 0x21}, ++{0x209F, 0x03}, ++{0x20A0, 0xFF}, ++{0x20A1, 0x03}, ++{0x20A2, 0xFF}, ++{0x20A3, 0x03}, ++{0x20A4, 0xFF}, ++{0x20A5, 0x03}, ++{0x20A6, 0xFF}, ++{0x20A7, 0x03}, ++{0x20A8, 0xFF}, ++{0x20A9, 0x03}, ++{0x20AA, 0xFF}, ++{0x20AB, 0x03}, ++{0x20AC, 0xFF}, ++{0x20AD, 0x03}, ++{0x20AE, 0xFF}, ++{0x20AF, 0x03}, ++{0x20B0, 0xFF}, ++{0x20B1, 0x03}, ++{0x20B2, 0xFF}, ++{0x20B3, 0x03}, ++{0x20B4, 0x87}, ++{0x20B5, 0xCC}, ++{0x20B6, 0x87}, ++{0x20B7, 0x08}, ++{0x20B8, 0xF4}, ++{0x20B9, 0xA5}, ++{0x20BA, 0x07}, ++{0x20BC, 0x1F}, ++{0x20BD, 0x01}, ++{0x20BE, 0xF6}, ++{0x20BF, 0x00}, ++{0x20C0, 0x90}, ++{0x20C1, 0x01}, ++{0x20C2, 0x67}, ++{0x20C3, 0x01}, ++{0x20C4, 0xFF}, ++{0x20C5, 0x03}, ++{0x20C6, 0xFF}, ++{0x20C7, 0x03}, ++{0x20C8, 0x33}, ++{0x20C9, 0x02}, ++{0x20CA, 0x0A}, ++{0x20CB, 0x02}, ++{0x20CC, 0x7F}, ++{0x20CD, 0x00}, ++{0x20CE, 0xD2}, ++{0x20CF, 0x00}, ++{0x20D0, 0x81}, ++{0x20D1, 0x00}, ++{0x20D2, 0x87}, ++{0x20D3, 0x00}, ++{0x20D4, 0x09}, ++{0x20D5, 0x00}, ++{0x20D8, 0x7F}, ++{0x20D9, 0x00}, ++{0x20DA, 0x62}, ++{0x20DB, 0x01}, ++{0x20DC, 0x7F}, ++{0x20DD, 0x00}, ++{0x20DE, 0x62}, ++{0x20DF, 0x01}, ++{0x20E0, 0x65}, ++{0x20E1, 0x00}, ++{0x20E2, 0x75}, ++{0x20E3, 0x00}, ++{0x20E4, 0xE0}, ++{0x20E5, 0x00}, ++{0x20E6, 0xF0}, ++{0x20E7, 0x00}, ++{0x20E8, 0x4C}, ++{0x20E9, 0x01}, ++{0x20EA, 0x5C}, ++{0x20EB, 0x01}, ++{0x20EC, 0xD1}, ++{0x20ED, 0x01}, ++{0x20EE, 0xE1}, ++{0x20EF, 0x01}, ++{0x20F0, 0x93}, ++{0x20F1, 0x02}, ++{0x20F2, 0xA3}, ++{0x20F3, 0x02}, ++{0x20F4, 0x0D}, ++{0x20F5, 0x03}, ++{0x20F6, 0x1D}, ++{0x20F7, 0x03}, ++{0x20F8, 0x57}, ++{0x20F9, 0x00}, ++{0x20FA, 0x7B}, ++{0x20FB, 0x00}, ++{0x20FC, 0xD2}, ++{0x20FD, 0x00}, ++{0x20FE, 0xF6}, ++{0x20FF, 0x00}, ++{0x2100, 0x3E}, ++{0x2101, 0x01}, ++{0x2102, 0x60}, ++{0x2103, 0x01}, ++{0x2104, 0xC3}, ++{0x2105, 0x01}, ++{0x2106, 0xE5}, ++{0x2107, 0x01}, ++{0x2108, 0x85}, ++{0x2109, 0x02}, ++{0x210A, 0xA9}, ++{0x210B, 0x02}, ++{0x210C, 0xFF}, ++{0x210D, 0x02}, ++{0x210E, 0x21}, ++{0x210F, 0x03}, ++{0x2110, 0xFF}, ++{0x2111, 0x03}, ++{0x2112, 0x00}, ++{0x2113, 0x00}, ++{0x2114, 0xFF}, ++{0x2115, 0x03}, ++{0x2116, 0xFF}, ++{0x2117, 0x03}, ++{0x2118, 0xFF}, ++{0x2119, 0x03}, ++{0x211A, 0xFF}, ++{0x211B, 0x03}, ++{0x211C, 0xFF}, ++{0x211D, 0x03}, ++{0x211E, 0xFF}, ++{0x211F, 0x03}, ++{0x2120, 0xFF}, ++{0x2121, 0x03}, ++{0x2122, 0xFF}, ++{0x2123, 0x03}, ++{0x2124, 0xFF}, ++{0x2125, 0x03}, ++{0x2126, 0xFF}, ++{0x2127, 0x03}, ++{0x2128, 0x7D}, ++{0x2129, 0x90}, ++{0x212A, 0xD5}, ++{0x212B, 0x07}, ++{0x212C, 0x64}, ++{0x212D, 0x01}, ++{0x2130, 0x5F}, ++{0x2131, 0x7D}, ++{0x2132, 0x05}, ++{0x2134, 0x78}, ++{0x2135, 0x00}, ++{0x2136, 0x76}, ++{0x2137, 0x00}, ++{0x2138, 0xF3}, ++{0x2139, 0x00}, ++{0x213A, 0xF1}, ++{0x213B, 0x00}, ++{0x213C, 0xA6}, ++{0x213D, 0x02}, ++{0x213E, 0xA4}, ++{0x213F, 0x02}, ++{0x2140, 0x7D}, ++{0x2141, 0x00}, ++{0x2142, 0x8D}, ++{0x2143, 0x00}, ++{0x2144, 0xA1}, ++{0x2145, 0x01}, ++{0x2146, 0xB1}, ++{0x2147, 0x01}, ++{0x2148, 0xAB}, ++{0x2149, 0x02}, ++{0x214A, 0xBB}, ++{0x214B, 0x02}, ++{0x214C, 0x17}, ++{0x214D, 0x5C}, ++{0x214E, 0x00}, ++{0x2150, 0x00}, ++{0x2151, 0x00}, ++{0x2152, 0xF8}, ++{0x2153, 0x00}, ++{0x2154, 0xBE}, ++{0x2155, 0x00}, ++{0x2156, 0x7D}, ++{0x2157, 0x00}, ++{0x2158, 0x25}, ++{0x2159, 0x00}, ++{0x215A, 0x7D}, ++{0x215B, 0x00}, ++{0x215C, 0x62}, ++{0x215D, 0x01}, ++{0x215E, 0xFF}, ++{0x215F, 0x03}, ++{0x2160, 0x26}, ++{0x2161, 0x00}, ++{0x2162, 0x7D}, ++{0x2163, 0x00}, ++{0x2164, 0x63}, ++{0x2165, 0x01}, ++{0x2166, 0xFF}, ++{0x2167, 0x03}, ++{0x2168, 0xCB}, ++{0x2169, 0x02}, ++{0x216A, 0xCF}, ++{0x216B, 0x02}, ++{0x216C, 0xFF}, ++{0x216D, 0x03}, ++{0x216E, 0xFF}, ++{0x216F, 0x03}, ++{0x2170, 0xFF}, ++{0x2171, 0x03}, ++{0x2172, 0xFF}, ++{0x2173, 0x03}, ++{0x2174, 0xFF}, ++{0x2175, 0x03}, ++{0x2176, 0xFF}, ++{0x2177, 0x03}, ++{0x2178, 0x7E}, ++{0x2179, 0x00}, ++{0x217A, 0xBD}, ++{0x217B, 0x00}, ++{0x217C, 0xEC}, ++{0x217D, 0x01}, ++{0x217E, 0x7B}, ++{0x217F, 0x02}, ++{0x2180, 0xD1}, ++{0x2181, 0x02}, ++{0x2182, 0x25}, ++{0x2183, 0x03}, ++{0x2184, 0x7F}, ++{0x2185, 0x00}, ++{0x2186, 0xBD}, ++{0x2187, 0x00}, ++{0x2188, 0xED}, ++{0x2189, 0x01}, ++{0x218A, 0x7B}, ++{0x218B, 0x02}, ++{0x218C, 0xD2}, ++{0x218D, 0x02}, ++{0x218E, 0x25}, ++{0x218F, 0x03}, ++{0x2190, 0xFF}, ++{0x2191, 0x03}, ++{0x2192, 0xFF}, ++{0x2193, 0x03}, ++{0x2194, 0xE9}, ++{0x2195, 0x01}, ++{0x2196, 0x21}, ++{0x2197, 0x03}, ++{0x2198, 0x17}, ++{0x2199, 0xFC}, ++{0x219A, 0x7F}, ++{0x219B, 0x01}, ++{0x219C, 0xFF}, ++{0x219D, 0x03}, ++{0x21A0, 0x1B}, ++{0x21A1, 0x1B}, ++{0x21A2, 0x1B}, ++{0x21A3, 0x1B}, ++{0x21A4, 0x2E}, ++{0x21A5, 0x80}, ++{0x21A6, 0x00}, ++{0x21A8, 0x04}, ++{0x21A9, 0x98}, ++{0x21AA, 0x60}, ++{0x21AB, 0x03}, ++{0x21AC, 0x7F}, ++{0x21AD, 0x80}, ++{0x21AE, 0x09}, ++{0x21B0, 0x1C}, ++{0x21B1, 0x00}, ++{0x21B2, 0xA0}, ++{0x21B3, 0x00}, ++{0x21B4, 0x0C}, ++{0x21B5, 0x00}, ++{0x21B6, 0x2D}, ++{0x21B7, 0x00}, ++{0x21B8, 0x20}, ++{0x21B9, 0x00}, ++{0x21BA, 0x02}, ++{0x21BB, 0x00}, ++{0x21BC, 0xCC}, ++{0x21BD, 0x00}, ++{0x21BE, 0x4A}, ++{0x21BF, 0x00}, ++{0x21C0, 0xD0}, ++{0x21C1, 0x00}, ++{0x21C2, 0x44}, ++{0x21C3, 0x00}, ++{0x21C4, 0x00}, ++{0x21C5, 0xE0}, ++{0x21C6, 0x00}, ++{0x21C8, 0x11}, ++{0x21C9, 0x00}, ++{0x21CA, 0x02}, ++{0x21CC, 0x08}, ++{0x21CD, 0xC0}, ++{0x21CE, 0x0C}, ++{0x21D0, 0x44}, ++{0x21D1, 0x00}, ++{0x21D2, 0x02}, ++{0x21D4, 0x02}, ++{0x21D5, 0x20}, ++{0x21D6, 0x2C}, ++{0x21D8, 0xFE}, ++{0x21D9, 0x9D}, ++{0x21DA, 0xDF}, ++{0x21DB, 0x03}, ++{0x21DC, 0x62}, ++{0x21DD, 0x01}, ++{0x21DE, 0x7F}, ++{0x21DF, 0x00}, ++{0x21E0, 0xB7}, ++{0x21E1, 0x01}, ++{0x21E2, 0xB5}, ++{0x21E3, 0x01}, ++{0x21E4, 0xC1}, ++{0x21E5, 0x02}, ++{0x21E6, 0xBF}, ++{0x21E7, 0x02}, ++{0x21E8, 0xB3}, ++{0x21E9, 0x0D}, ++{0x21EA, 0x00}, ++{0x21EB, 0x04}, ++#if 1 ++{0x21EC, 0x90}, ++{0x21ED, 0x07}, ++{0x21EE, 0x58}, ++{0x21EF, 0x04}, ++#else ++{0x21EC, 0x80}, ++{0x21ED, 0x07}, ++{0x21EE, 0x38}, ++{0x21EF, 0x04}, ++#endif ++{0x21F0, 0x54}, ++{0x21F1, 0x04}, ++{0x21F4, 0x02}, ++{0x21F5, 0x00}, ++{0x21F6, 0x00}, ++{0x21F8, 0x3C}, ++{0x21F9, 0x00}, ++{0x21FC, 0x28}, ++{0x21FD, 0x00}, ++{0x21FE, 0x3C}, ++{0x21FF, 0x00}, ++{0x2200, 0x00}, ++{0x2204, 0x4C}, ++{0x2205, 0x04}, ++{0x2206, 0x65}, ++{0x2207, 0x04}, ++{0x2208, 0x0A}, ++{0x2209, 0x00}, ++{0x220C, 0x47}, ++{0x220D, 0x00}, ++{0x220E, 0x1F}, ++{0x220F, 0x00}, ++{0x2210, 0x17}, ++{0x2211, 0x00}, ++{0x2212, 0x0F}, ++{0x2213, 0x00}, ++{0x2214, 0x17}, ++{0x2215, 0x00}, ++{0x2216, 0x47}, ++{0x2217, 0x00}, ++{0x2218, 0x0F}, ++{0x2219, 0x00}, ++{0x221A, 0x0F}, ++{0x221B, 0x00}, ++{0x221C, 0x03}, ++{0x2220, 0x20}, ++{0x2221, 0x20}, ++{0x2222, 0x22}, ++{0x2223, 0x02}, ++{0x2224, 0xA7}, ++{0x2225, 0xAA}, ++{0x2226, 0x80}, ++{0x2227, 0x08}, ++{0x2228, 0x01}, ++{0x22B2, 0x92}, ++{0x22B4, 0x20}, ++{0x22B5, 0x00}, ++{0x22B6, 0x20}, ++{0x22B7, 0x00}, ++{0x22B8, 0x20}, ++{0x22B9, 0x00}, ++{0x22BA, 0x20}, ++{0x22BB, 0x00}, ++{0x22BC, 0x20}, ++{0x22BD, 0x00}, ++{0x22BE, 0x20}, ++{0x22BF, 0x00}, ++{0x22C0, 0x20}, ++{0x22C1, 0x00}, ++{0x22C2, 0x20}, ++{0x22C3, 0x00}, ++{0x22C4, 0x20}, ++{0x22C5, 0x00}, ++{0x22C6, 0x20}, ++{0x22C7, 0x00}, ++{0x22C8, 0x20}, ++{0x22C9, 0x00}, ++{0x22CA, 0x20}, ++{0x22CB, 0x00}, ++{0x22CC, 0x20}, ++{0x22CD, 0x00}, ++{0x22CE, 0x20}, ++{0x22CF, 0x00}, ++{0x22DA, 0x00}, ++{0x2308, 0x01}, ++{0x2311, 0x09}, ++{0x2318, 0x40}, ++{0x2319, 0xCD}, ++{0x231A, 0x54}, ++{0x2324, 0x20}, ++{0x2325, 0x00}, ++{0x2328, 0x00}, ++{0x2354, 0x0C}, ++{0x23C0, 0x5D}, ++{0x244C, 0x00}, ++{0x244D, 0x02}, ++{0x244E, 0x54}, ++{0x244F, 0x02}, ++{0x24A0, 0x00}, ++{0x24DA, 0x6F}, ++{0x24DB, 0x00}, ++{0x24DC, 0x62}, ++{0x24DD, 0x01}, ++{0x24EA, 0x32}, ++{0x24EB, 0x00}, ++{0x24EC, 0xDC}, ++{0x24ED, 0x00}, ++{0x24FA, 0x32}, ++{0x24FB, 0x00}, ++{0x24FC, 0xDD}, ++{0x24FD, 0x00}, ++{0x254A, 0x15}, ++{0x254B, 0x01}, ++{0x255A, 0x15}, ++{0x255B, 0x01}, ++{0x2560, 0x01}, ++{0x2561, 0x00}, ++{0x2562, 0x2A}, ++{0x2563, 0x00}, ++{0x2564, 0xF8}, ++{0x2565, 0x00}, ++{0x2566, 0x15}, ++{0x2567, 0x01}, ++{0x2568, 0x0C}, ++{0x2569, 0x02}, ++{0x256A, 0x31}, ++{0x256B, 0x02}, ++{0x2578, 0x90}, ++{0x2579, 0x01}, ++{0x257A, 0x92}, ++{0x257B, 0x01}, ++{0x257C, 0xB8}, ++{0x257D, 0x02}, ++{0x257E, 0xBA}, ++{0x257F, 0x02}, ++{0x2584, 0x90}, ++{0x2585, 0x01}, ++{0x2586, 0x92}, ++{0x2587, 0x01}, ++{0x2588, 0xB8}, ++{0x2589, 0x02}, ++{0x258A, 0xBA}, ++{0x258B, 0x02}, ++{0x26B8, 0x10}, ++{0x26B9, 0x00}, ++{0x26BA, 0x33}, ++{0x26BB, 0x00}, ++{0x26BC, 0x89}, ++{0x26BD, 0x00}, ++{0x26BE, 0xB0}, ++{0x26BF, 0x00}, ++{0x26C4, 0x4E}, ++{0x26C5, 0x00}, ++{0x26C8, 0xC9}, ++{0x26C9, 0x00}, ++{0x26CC, 0x35}, ++{0x26CD, 0x01}, ++{0x26D0, 0xBA}, ++{0x26D1, 0x01}, ++{0x26D4, 0x7C}, ++{0x26D5, 0x02}, ++{0x26D8, 0xF6}, ++{0x26D9, 0x02}, ++{0x26DE, 0x51}, ++{0x26DF, 0x00}, ++{0x26E0, 0x7F}, ++{0x26E1, 0x00}, ++{0x26E2, 0xCC}, ++{0x26E3, 0x00}, ++{0x26E4, 0xF8}, ++{0x26E5, 0x00}, ++{0x26E6, 0x38}, ++{0x26E7, 0x01}, ++{0x26E8, 0x65}, ++{0x26E9, 0x01}, ++{0x26EA, 0xBD}, ++{0x26EB, 0x01}, ++{0x26EE, 0x7F}, ++{0x26EF, 0x02}, ++{0x26F0, 0xAB}, ++{0x26F1, 0x02}, ++{0x26F2, 0xF9}, ++{0x26F3, 0x02}, ++{0x2722, 0x59}, ++{0x2723, 0x02}, ++{0x2938, 0x55}, ++{0x2939, 0x00}, ++{0x293A, 0x17}, ++{0x293B, 0x00}, ++{0x293C, 0xD0}, ++{0x293D, 0x00}, ++{0x293E, 0x91}, ++{0x293F, 0x00}, ++{0x2940, 0x3C}, ++{0x2941, 0x01}, ++{0x2942, 0x0C}, ++{0x2943, 0x01}, ++{0x2944, 0xC1}, ++{0x2945, 0x01}, ++{0x2946, 0x76}, ++{0x2947, 0x01}, ++{0x2948, 0x83}, ++{0x2949, 0x02}, ++{0x294A, 0xFB}, ++{0x294B, 0x01}, ++{0x294C, 0xFD}, ++{0x294D, 0x02}, ++{0x294E, 0xBF}, ++{0x294F, 0x02}, ++{0x2A06, 0xFF}, ++{0x2A07, 0x03}, ++{0x2A20, 0x00}, ++{0x2A21, 0x00}, ++{0x2A22, 0x7D}, ++{0x2A23, 0x00}, ++{0x2B11, 0x19}, ++{0x2B13, 0x15}, ++{0x2B14, 0x14}, ++{0x2B15, 0x13}, ++{0x2B16, 0x12}, ++{0x2B17, 0x11}, ++{0x2B18, 0x10}, ++{0x2B19, 0x0F}, ++{0x2B1A, 0x0E}, ++{0x2B1B, 0x0D}, ++{0x2B1C, 0x0C}, ++{0x2B1D, 0x0B}, ++{0x2B1E, 0x0A}, ++{0x2B1F, 0x09}, ++{0x2B20, 0x08}, ++{0x2B21, 0x07}, ++{0x2B22, 0x06}, ++{0x2B23, 0x05}, ++{0x2B24, 0x04}, ++{0x2B25, 0x03}, ++{0x2B26, 0x03}, ++{0x2B38, 0x01}, ++{0x2B45, 0xE3}, ++{0x2B50, 0x01}, ++{0x2B51, 0x00}, ++//{0x2B62, ,3}, ++{0x2B6D, 0x47}, ++{0x2B70, 0x02}, ++{0x2B71, 0x02}, ++{0x2B72, 0x02}, ++{0x2B7F, 0x7F}, ++{0x2B80, 0x94}, ++{0x2B81, 0x06}, ++{0x2B87, 0x1B}, ++{0x2B88, 0x1B}, ++{0x2B89, 0x17}, ++{0x2B8A, 0x12}, ++{0x2B8B, 0x12}, ++{0x2B8D, 0x2B}, ++{0x2B8E, 0x2B}, ++{0x2B8F, 0x2B}, ++{0x2B90, 0x7F}, ++{0x2B91, 0x1F}, ++{0x2B94, 0x7F}, ++{0x2B95, 0x27}, ++{0x2B98, 0x7F}, ++{0x2B99, 0x57}, ++{0x2BA8, 0xBC}, ++{0x2BA9, 0x62}, ++{0x2BC1, 0x70}, ++{0x2BC5, 0x80}, ++{0x2BD5, 0x30}, ++{0x2BD6, 0xF0}, ++{0x2BD8, 0xDB}, ++{0x2BD9, 0xF6}, ++{0x2BDA, 0x63}, ++{0x2BDB, 0x0C}, ++{0x2BDC, 0x5C}, ++{0x2C98, 0xE1}, ++{0x2C99, 0x2E}, ++{0x2C9B, 0x86}, ++{0x2CA9, 0x80}, ++{0x2CAA, 0x01}, ++{0x2D39, 0x0E}, ++{0x2D54, 0x00}, ++{0x2D5B, 0x58}, ++{0x3000, 0x00}, ++{0x3001, 0x40}, ++{0x3002, 0x23}, ++{0x3003, 0xA1}, ++{0x3004, 0x00}, ++{0x3005, 0x20}, ++{0x3006, 0x94}, ++{0x3007, 0x00}, ++{0x3008, 0x06}, ++{0x3009, 0xB4}, ++{0x300A, 0x1F}, ++{0x300B, 0x28}, ++{0x300C, 0x00}, ++{0x300D, 0x18}, ++{0x300E, 0x90}, ++{0x300F, 0x97}, ++{0x3010, 0x00}, ++{0x3011, 0x40}, ++{0x3012, 0x21}, ++{0x3013, 0x21}, ++{0x3014, 0x00}, ++{0x3015, 0x20}, ++{0x3016, 0x94}, ++{0x3017, 0x00}, ++{0x3018, 0x00}, ++{0x3019, 0x09}, ++{0x301A, 0x46}, ++{0x301B, 0x28}, ++//{0x3053, ,3}, ++{0x3070, 0xC1}, ++{0x3071, 0x81}, ++{0x3072, 0x29}, ++{0x3073, 0x81}, ++//{0x3370, ,3}, ++//{0x3374, ,3}, ++//{0x3375, ,3}, ++//{0x3376, ,3}, ++//{0x3377, ,3}, ++#if 1 ++{0x3410, 0x90}, ++{0x3411, 0x07}, ++{0x3418, 0x48}, ++{0x3419, 0x04}, ++#else ++{0x3410, 0x80}, ++{0x3411, 0x07}, ++{0x3418, 0x38}, ++{0x3419, 0x04}, +#endif ++//{0x34C0, ,3}, ++//{0x34C1, ,3}, ++//{0x34C2, ,3}, ++//{0x34C3, ,3}, ++//{0x34C4, ,3}, ++//{0x34C5, ,3}, ++//{0x34C6, ,3}, ++//{0x34C7, ,3}, ++//{0x34C8, ,3}, ++//{0x34C9, ,3}, ++//{0x34CA, ,3}, ++//{0x34CB, ,3}, ++//{0x34CC, ,3}, ++//{0x34CD, ,3}, ++//{0x34CE, ,3}, ++//{0x34CF, ,3}, ++{0x3584, 0x00}, ++{0x3586, 0x00}, ++{0x3587, 0x01}, ++{0x3588, 0xE6}, ++{0x3589, 0x00}, ++{0x3590, 0x00}, ++{0x3591, 0x00}, ++{0x3594, 0x40}, ++{0x3598, 0x03}, ++{0x3599, 0x00}, ++{0x359A, 0x80}, ++{0x359B, 0x00}, ++{0x359C, 0x00}, ++{0x359D, 0x01}, ++{0x359E, 0x00}, ++{0x359F, 0x02}, ++{0x35A0, 0x00}, ++{0x35A1, 0x04}, ++{0x35A2, 0x20}, ++{0x35A3, 0x00}, ++{0x35A4, 0x40}, ++{0x35A5, 0x00}, ++{0x35A6, 0x80}, ++{0x35A7, 0x00}, ++{0x35A8, 0x00}, ++{0x35A9, 0x01}, ++{0x35AA, 0x3A}, ++{0x35AB, 0x00}, ++{0x35AC, 0x80}, ++{0x35AD, 0x00}, ++{0x35AE, 0x00}, ++{0x35AF, 0x01}, ++{0x35B0, 0x00}, ++{0x35B1, 0x02}, ++{0x35B2, 0x00}, ++{0x35B3, 0x04}, ++{0x35B4, 0x02}, ++{0x35B5, 0x00}, ++{0x35B6, 0x04}, ++{0x35B7, 0x00}, ++{0x35B8, 0x08}, ++{0x35B9, 0x00}, ++{0x35BA, 0x10}, ++{0x35BB, 0x00}, ++{0x35BC, 0x03}, ++{0x35BD, 0x00}, ++{0x35C8, 0x00}, ++{0x35C9, 0x01}, ++{0x35CA, 0x00}, ++{0x35CB, 0x04}, ++{0x35CC, 0x00}, ++{0x35CD, 0x10}, ++{0x35CE, 0x00}, ++{0x35CF, 0x40}, ++{0x35D0, 0x00}, ++{0x35D1, 0x0C}, ++{0x35D2, 0x00}, ++{0x35D3, 0x0C}, ++{0x35D4, 0x00}, ++{0x35D5, 0x0C}, ++{0x35D6, 0x00}, ++{0x35D7, 0x0C}, ++{0x35D8, 0x00}, ++{0x35D9, 0x00}, ++{0x35DA, 0x08}, ++{0x35DB, 0x00}, ++{0x35DC, 0xD8}, ++{0x35DD, 0x0E}, ++{0x35F0, 0x00}, ++{0x35F1, 0x10}, ++{0x35F2, 0x00}, ++{0x35F3, 0x10}, ++{0x35F4, 0x00}, ++{0x35F5, 0x10}, ++{0x35F6, 0x00}, ++{0x35F7, 0x03}, ++{0x35F8, 0x00}, ++{0x35F9, 0x01}, ++{0x35FA, 0x38}, ++{0x35FB, 0x00}, ++{0x35FC, 0xB3}, ++{0x35FD, 0x01}, ++{0x35FE, 0x00}, ++{0x35FF, 0x00}, ++{0x3600, 0x04}, ++{0x3601, 0x06}, ++{0x3604, 0x03}, ++{0x3605, 0x00}, ++{0x3608, 0x03}, ++{0x3609, 0x00}, ++{0x360C, 0x00}, ++{0x360D, 0x00}, ++{0x3610, 0x10}, ++{0x3611, 0x01}, ++{0x3612, 0x00}, ++{0x3613, 0x00}, ++{0x3614, 0x00}, ++{0x3615, 0x00}, ++{0x361C, 0x00}, ++{0x361D, 0x01}, ++{0x361E, 0x00}, ++{0x361F, 0x01}, ++{0x3620, 0x01}, ++{0x3621, 0x00}, ++{0x3622, 0xB0}, ++{0x3623, 0x04}, ++{0x3624, 0xDC}, ++{0x3625, 0x05}, ++{0x3626, 0x00}, ++{0x3627, 0x01}, ++{0x3628, 0xFF}, ++{0x3629, 0x0F}, ++{0x362A, 0x00}, ++{0x362B, 0x10}, ++{0x362C, 0x00}, ++{0x362D, 0x01}, ++//{0x3630, ,3}, ++//{0x3631, ,3}, ++//{0x3632, ,3}, ++//{0x3633, ,3}, ++//{0x3634, ,3}, ++//{0x3635, ,3}, ++//{0x3636, ,3}, ++//{0x3637, ,3}, ++//{0x3638, ,3}, ++//{0x3639, ,3}, ++//{0x363A, ,3}, ++//{0x363B, ,3}, ++//{0x363C, ,3}, ++//{0x363D, ,3}, ++//{0x363E, ,3}, ++//{0x363F, ,3}, ++{0x36C4, 0x99}, ++{0x36C5, 0x09}, ++{0x36C6, 0x18}, ++{0x36C7, 0x07}, ++{0x36C8, 0x65}, ++{0x36C9, 0x0E}, ++{0x36CC, 0x99}, ++{0x36CD, 0x01}, ++{0x36CE, 0x47}, ++{0x36CF, 0x00}, ++{0x36D0, 0x04}, ++{0x36D1, 0x00}, ++{0x36D4, 0x65}, ++{0x36D5, 0x0E}, ++{0x36D6, 0xA4}, ++{0x36D7, 0x0A}, ++{0x36D8, 0x65}, ++{0x36D9, 0x0E}, ++{0x36DC, 0x65}, ++{0x36DD, 0x0E}, ++{0x36DE, 0xA4}, ++{0x36DF, 0x0A}, ++{0x36E0, 0x65}, ++{0x36E1, 0x0E}, ++{0x36E4, 0x65}, ++{0x36E5, 0x0E}, ++{0x36E6, 0xA4}, ++{0x36E7, 0x0A}, ++{0x36E8, 0x65}, ++{0x36E9, 0x0E}, ++{0x36EE, 0x00}, ++{0x36EF, 0x00}, ++{0x36F0, 0x00}, ++{0x36F1, 0x80}, ++{0x36F8, 0x00}, ++{0x3702, 0x03}, ++{0x3703, 0x04}, ++{0x3704, 0x08}, ++{0x370E, 0x0E}, ++{0x3718, 0x62}, ++{0x3719, 0x4A}, ++{0x371A, 0x38}, ++{0x371B, 0x20}, ++{0x371C, 0x64}, ++{0x371D, 0x42}, ++{0x371E, 0x32}, ++{0x371F, 0x1B}, ++{0x3720, 0x98}, ++{0x3721, 0xA0}, ++{0x3722, 0xA8}, ++{0x3723, 0xB0}, ++{0x3748, 0xA5}, ++{0x3749, 0x9B}, ++{0x374A, 0x91}, ++{0x374B, 0x7D}, ++{0x37C0, 0x00}, ++{0x37C1, 0x00}, ++{0x37C2, 0x00}, ++{0x37C4, 0x00}, ++{0x37C5, 0x00}, ++{0x37C6, 0x00}, ++{0x37C8, 0x00}, ++{0x37C9, 0x00}, ++{0x37CA, 0x00}, ++{0x37CC, 0x00}, ++{0x37CD, 0x00}, ++{0x37CE, 0x00}, ++{0x37D0, 0x00}, ++{0x37D1, 0x00}, ++{0x37D2, 0x00}, ++{0x37D4, 0x00}, ++{0x37D5, 0x00}, ++{0x37D6, 0x00}, ++{0x37D8, 0x00}, ++{0x37D9, 0x00}, ++{0x37DA, 0x00}, ++{0x37DC, 0x00}, ++{0x37DD, 0x00}, ++{0x37DE, 0x00}, ++{0x37E0, 0x00}, ++{0x37E1, 0x00}, ++{0x37E2, 0x00}, ++{0x37E4, 0x00}, ++{0x37E5, 0x00}, ++{0x37E6, 0x00}, ++{0x37E8, 0x00}, ++{0x37E9, 0x00}, ++{0x37EA, 0x00}, ++{0x37EC, 0x00}, ++{0x37ED, 0x00}, ++{0x37EE, 0x00}, ++{0x37F0, 0x00}, ++{0x37F4, 0x00}, ++{0x37F5, 0x1E}, ++{0x37F6, 0x34}, ++{0x37F7, 0x00}, ++{0x37F8, 0xFF}, ++{0x37F9, 0xFF}, ++{0x37FA, 0x03}, ++{0x37FC, 0x00}, ++{0x37FD, 0x00}, ++{0x37FE, 0x04}, ++{0x3800, 0xFF}, ++{0x3801, 0xFF}, ++{0x3802, 0x03}, ++{0x3804, 0x00}, ++{0x3805, 0x00}, ++{0x3806, 0x04}, ++{0x3808, 0x00}, ++{0x3809, 0x00}, ++{0x380A, 0x00}, ++{0x380C, 0x00}, ++{0x380D, 0x00}, ++{0x380E, 0x00}, ++{0x3810, 0x00}, ++{0x3811, 0x00}, ++{0x3812, 0x00}, ++{0x3814, 0x00}, ++{0x3815, 0x00}, ++{0x3816, 0x00}, ++{0x3818, 0x00}, ++{0x3819, 0x00}, ++{0x381A, 0x00}, ++{0x381C, 0x00}, ++{0x381D, 0x00}, ++{0x381E, 0x00}, ++{0x3820, 0x00}, ++{0x3821, 0x00}, ++{0x3822, 0x00}, ++{0x3824, 0x00}, ++{0x3825, 0x00}, ++{0x3826, 0x00}, ++{0x3828, 0x00}, ++{0x3829, 0x00}, ++{0x382A, 0x00}, ++{0x382C, 0x00}, ++{0x382D, 0x00}, ++{0x382E, 0x00}, ++{0x3830, 0x00}, ++{0x3831, 0x00}, ++{0x3832, 0x00}, ++{0x3834, 0x00}, ++{0x3835, 0x00}, ++{0x3836, 0x00}, ++{0x3838, 0x22}, ++{0x3839, 0x00}, ++{0x383A, 0x25}, ++{0x383B, 0x00}, ++{0x383C, 0x1A}, ++{0x383D, 0x00}, ++{0x383E, 0x26}, ++{0x383F, 0x00}, ++{0x3840, 0x07}, ++{0x3841, 0x00}, ++{0x3842, 0x06}, ++{0x3843, 0x00}, ++{0x3844, 0x03}, ++{0x3845, 0x00}, ++{0x3846, 0x02}, ++{0x3847, 0x00}, ++{0x3848, 0xFB}, ++{0x3849, 0xFF}, ++{0x384A, 0xFF}, ++{0x384B, 0xFF}, ++{0x384C, 0xF3}, ++{0x384D, 0xFF}, ++{0x384E, 0xF2}, ++{0x384F, 0xFF}, ++{0x3850, 0xFF}, ++{0x3851, 0x0F}, ++{0x3852, 0x00}, ++{0x3853, 0x10}, ++{0x3854, 0xFF}, ++{0x3855, 0x0F}, ++{0x3856, 0x00}, ++{0x3857, 0x10}, ++{0x3858, 0xFF}, ++{0x3859, 0x0F}, ++{0x385A, 0x00}, ++{0x385B, 0x10}, ++{0x385C, 0x02}, ++{0x385D, 0x00}, ++{0x385E, 0x06}, ++{0x385F, 0x00}, ++{0x3860, 0x06}, ++{0x3861, 0x00}, ++{0x3862, 0x08}, ++{0x3863, 0x00}, ++{0x3864, 0x02}, ++{0x3865, 0x00}, ++{0x38A0, 0x01}, ++{0x38A1, 0x01}, ++{0x38A2, 0x00}, ++{0x38A3, 0x01}, ++{0x38A4, 0x07}, ++{0x38A5, 0x00}, ++{0x38A6, 0x04}, ++{0x38A7, 0x05}, ++{0x38A8, 0x00}, ++{0x38A9, 0x00}, ++{0x38AC, 0x00}, ++{0x38AD, 0x00}, ++{0x38AE, 0x01}, ++{0x38B0, 0x02}, ++{0x38B2, 0x22}, ++{0x38B3, 0x00}, ++{0x38B4, 0x17}, ++{0x38B5, 0x00}, ++{0x38B6, 0x11}, ++{0x38B7, 0x00}, ++{0x38B8, 0x0E}, ++{0x38B9, 0x00}, ++{0x38BA, 0x2A}, ++{0x38BB, 0x00}, ++{0x38BC, 0x1C}, ++{0x38BD, 0x00}, ++{0x38BE, 0x14}, ++{0x38BF, 0x00}, ++{0x38C0, 0x10}, ++{0x38C1, 0x00}, ++{0x38C2, 0x31}, ++{0x38C3, 0x00}, ++{0x38C4, 0x21}, ++{0x38C5, 0x00}, ++{0x38C6, 0x18}, ++{0x38C7, 0x00}, ++{0x38C8, 0x12}, ++{0x38C9, 0x00}, ++{0x38CA, 0x3C}, ++{0x38CB, 0x00}, ++{0x38CC, 0x29}, ++{0x38CD, 0x00}, ++{0x38CE, 0x1D}, ++{0x38CF, 0x00}, ++{0x38D0, 0x15}, ++{0x38D1, 0x00}, ++{0x38D2, 0x4E}, ++{0x38D3, 0x00}, ++{0x38D4, 0x35}, ++{0x38D5, 0x00}, ++{0x38D6, 0x26}, ++{0x38D7, 0x00}, ++{0x38D8, 0x1A}, ++{0x38D9, 0x00}, ++{0x38DA, 0x69}, ++{0x38DB, 0x00}, ++{0x38DC, 0x48}, ++{0x38DD, 0x00}, ++{0x38DE, 0x33}, ++{0x38DF, 0x00}, ++{0x38E0, 0x22}, ++{0x38E1, 0x00}, ++{0x38E2, 0x93}, ++{0x38E3, 0x00}, ++{0x38E4, 0x64}, ++{0x38E5, 0x00}, ++{0x38E6, 0x48}, ++{0x38E7, 0x00}, ++{0x38E8, 0x30}, ++{0x38E9, 0x00}, ++{0x38EA, 0xD3}, ++{0x38EB, 0x00}, ++{0x38EC, 0x90}, ++{0x38ED, 0x00}, ++{0x38EE, 0x69}, ++{0x38EF, 0x00}, ++{0x38F0, 0x49}, ++{0x38F1, 0x00}, ++{0x38F2, 0x39}, ++{0x38F3, 0x01}, ++{0x38F4, 0xD5}, ++{0x38F5, 0x00}, ++{0x38F6, 0x9F}, ++{0x38F7, 0x00}, ++{0x38F8, 0x75}, ++{0x38F9, 0x00}, ++{0x38FA, 0x00}, ++{0x38FB, 0x01}, ++{0x38FC, 0x00}, ++{0x38FD, 0x01}, ++{0x38FE, 0x00}, ++{0x38FF, 0x01}, ++{0x3900, 0x00}, ++{0x3901, 0x01}, ++{0x3902, 0x60}, ++{0x3903, 0x00}, ++{0x3904, 0x25}, ++{0x3905, 0x00}, ++{0x3906, 0x18}, ++{0x3907, 0x00}, ++{0x3908, 0x10}, ++{0x3909, 0x00}, ++{0x390A, 0xFF}, ++{0x390B, 0x00}, ++{0x390C, 0xD5}, ++{0x390D, 0x00}, ++{0x390E, 0xAA}, ++{0x390F, 0x00}, ++{0x3910, 0x85}, ++{0x3911, 0x00}, ++{0x3912, 0xFF}, ++{0x3913, 0x00}, ++{0x3914, 0xD5}, ++{0x3915, 0x00}, ++{0x3916, 0xAA}, ++{0x3917, 0x00}, ++{0x3918, 0x85}, ++{0x3919, 0x00}, ++{0x391A, 0xFF}, ++{0x391B, 0x00}, ++{0x391C, 0xD5}, ++{0x391D, 0x00}, ++{0x391E, 0xAA}, ++{0x391F, 0x00}, ++{0x3920, 0x85}, ++{0x3921, 0x00}, ++{0x3922, 0x40}, ++{0x3923, 0x00}, ++{0x3924, 0x40}, ++{0x3925, 0x00}, ++{0x3926, 0x40}, ++{0x3927, 0x00}, ++{0x3928, 0x40}, ++{0x3929, 0x00}, ++{0x392A, 0x80}, ++{0x392B, 0x00}, ++{0x392C, 0x80}, ++{0x392D, 0x00}, ++{0x392E, 0x80}, ++{0x392F, 0x00}, ++{0x3930, 0x80}, ++{0x3931, 0x00}, ++{0x3932, 0x4C}, ++{0x3933, 0x4C}, ++{0x3934, 0x4C}, ++{0x3940, 0x01}, ++{0x3941, 0x01}, ++{0x3942, 0x00}, ++{0x3943, 0x01}, ++{0x3944, 0x07}, ++{0x3945, 0x00}, ++{0x3946, 0x04}, ++{0x3947, 0x05}, ++{0x3948, 0x00}, ++{0x3949, 0x00}, ++{0x394C, 0x00}, ++{0x394D, 0x00}, ++{0x394E, 0x01}, ++{0x3950, 0x03}, ++{0x3952, 0x14}, ++{0x3953, 0x00}, ++{0x3954, 0x0F}, ++{0x3955, 0x00}, ++{0x3956, 0x0E}, ++{0x3957, 0x00}, ++{0x3958, 0x0E}, ++{0x3959, 0x00}, ++{0x395A, 0x19}, ++{0x395B, 0x00}, ++{0x395C, 0x11}, ++{0x395D, 0x00}, ++{0x395E, 0x0F}, ++{0x395F, 0x00}, ++{0x3960, 0x0E}, ++{0x3961, 0x00}, ++{0x3962, 0x1C}, ++{0x3963, 0x00}, ++{0x3964, 0x13}, ++{0x3965, 0x00}, ++{0x3966, 0x0F}, ++{0x3967, 0x00}, ++{0x3968, 0x0E}, ++{0x3969, 0x00}, ++{0x396A, 0x23}, ++{0x396B, 0x00}, ++{0x396C, 0x15}, ++{0x396D, 0x00}, ++{0x396E, 0x11}, ++{0x396F, 0x00}, ++{0x3970, 0x0E}, ++{0x3971, 0x00}, ++{0x3972, 0x2E}, ++{0x3973, 0x00}, ++{0x3974, 0x1A}, ++{0x3975, 0x00}, ++{0x3976, 0x14}, ++{0x3977, 0x00}, ++{0x3978, 0x0F}, ++{0x3979, 0x00}, ++{0x397A, 0x3E}, ++{0x397B, 0x00}, ++{0x397C, 0x23}, ++{0x397D, 0x00}, ++{0x397E, 0x1A}, ++{0x397F, 0x00}, ++{0x3980, 0x12}, ++{0x3981, 0x00}, ++{0x3982, 0x56}, ++{0x3983, 0x00}, ++{0x3984, 0x31}, ++{0x3985, 0x00}, ++{0x3986, 0x25}, ++{0x3987, 0x00}, ++{0x3988, 0x1A}, ++{0x3989, 0x00}, ++{0x398A, 0x7B}, ++{0x398B, 0x00}, ++{0x398C, 0x49}, ++{0x398D, 0x00}, ++{0x398E, 0x39}, ++{0x398F, 0x00}, ++{0x3990, 0x2C}, ++{0x3991, 0x00}, ++{0x3992, 0xB4}, ++{0x3993, 0x00}, ++{0x3994, 0x75}, ++{0x3995, 0x00}, ++{0x3996, 0x61}, ++{0x3997, 0x00}, ++{0x3998, 0x53}, ++{0x3999, 0x00}, ++{0x399A, 0x00}, ++{0x399B, 0x01}, ++{0x399C, 0x00}, ++{0x399D, 0x01}, ++{0x399E, 0x00}, ++{0x399F, 0x01}, ++{0x39A0, 0x00}, ++{0x39A1, 0x01}, ++{0x39A2, 0x60}, ++{0x39A3, 0x00}, ++{0x39A4, 0x20}, ++{0x39A5, 0x00}, ++{0x39A6, 0x15}, ++{0x39A7, 0x00}, ++{0x39A8, 0x10}, ++{0x39A9, 0x00}, ++{0x39AA, 0xFF}, ++{0x39AB, 0x00}, ++{0x39AC, 0xD5}, ++{0x39AD, 0x00}, ++{0x39AE, 0xAA}, ++{0x39AF, 0x00}, ++{0x39B0, 0x85}, ++{0x39B1, 0x00}, ++{0x39B2, 0xFF}, ++{0x39B3, 0x00}, ++{0x39B4, 0xD5}, ++{0x39B5, 0x00}, ++{0x39B6, 0xAA}, ++{0x39B7, 0x00}, ++{0x39B8, 0x85}, ++{0x39B9, 0x00}, ++{0x39BA, 0xFF}, ++{0x39BB, 0x00}, ++{0x39BC, 0xD5}, ++{0x39BD, 0x00}, ++{0x39BE, 0xAA}, ++{0x39BF, 0x00}, ++{0x39C0, 0x85}, ++{0x39C1, 0x00}, ++{0x39C2, 0x40}, ++{0x39C3, 0x00}, ++{0x39C4, 0x40}, ++{0x39C5, 0x00}, ++{0x39C6, 0x40}, ++{0x39C7, 0x00}, ++{0x39C8, 0x40}, ++{0x39C9, 0x00}, ++{0x39CA, 0x80}, ++{0x39CB, 0x00}, ++{0x39CC, 0x80}, ++{0x39CD, 0x00}, ++{0x39CE, 0x80}, ++{0x39CF, 0x00}, ++{0x39D0, 0x80}, ++{0x39D1, 0x00}, ++{0x39D2, 0x4C}, ++{0x39D3, 0x4C}, ++{0x39D4, 0x4C}, ++{0x39E0, 0x01}, ++{0x39E1, 0x00}, ++{0x39E4, 0x40}, ++{0x39E5, 0x01}, ++{0x39E6, 0x01}, ++{0x39E8, 0x00}, ++{0x39E9, 0x01}, ++{0x39EA, 0x00}, ++{0x39EB, 0x00}, ++{0x39EC, 0x01}, ++{0x39ED, 0x00}, ++{0x39EE, 0x01}, ++{0x39F0, 0x03}, ++{0x39F1, 0x04}, ++{0x39F2, 0x0E}, ++{0x39F4, 0x1C}, ++{0x39F5, 0x00}, ++{0x39F6, 0x13}, ++{0x39F7, 0x00}, ++{0x39F8, 0x0D}, ++{0x39F9, 0x00}, ++{0x39FA, 0x07}, ++{0x39FB, 0x00}, ++{0x39FC, 0x38}, ++{0x39FD, 0x00}, ++{0x39FE, 0x1C}, ++{0x39FF, 0x00}, ++{0x3A00, 0x11}, ++{0x3A01, 0x00}, ++{0x3A02, 0x08}, ++{0x3A03, 0x00}, ++{0x3A04, 0x4A}, ++{0x3A05, 0x00}, ++{0x3A06, 0x23}, ++{0x3A07, 0x00}, ++{0x3A08, 0x15}, ++{0x3A09, 0x00}, ++{0x3A0A, 0x09}, ++{0x3A0B, 0x00}, ++{0x3A0C, 0x65}, ++{0x3A0D, 0x00}, ++{0x3A0E, 0x2D}, ++{0x3A0F, 0x00}, ++{0x3A10, 0x1A}, ++{0x3A11, 0x00}, ++{0x3A12, 0x0B}, ++{0x3A13, 0x00}, ++{0x3A14, 0x8D}, ++{0x3A15, 0x00}, ++{0x3A16, 0x3D}, ++{0x3A17, 0x00}, ++{0x3A18, 0x23}, ++{0x3A19, 0x00}, ++{0x3A1A, 0x0E}, ++{0x3A1B, 0x00}, ++{0x3A1C, 0xC5}, ++{0x3A1D, 0x00}, ++{0x3A1E, 0x55}, ++{0x3A1F, 0x00}, ++{0x3A20, 0x30}, ++{0x3A21, 0x00}, ++{0x3A22, 0x13}, ++{0x3A23, 0x00}, ++{0x3A24, 0x16}, ++{0x3A25, 0x01}, ++{0x3A26, 0x76}, ++{0x3A27, 0x00}, ++{0x3A28, 0x42}, ++{0x3A29, 0x00}, ++{0x3A2A, 0x1A}, ++{0x3A2B, 0x00}, ++{0x3A2C, 0x88}, ++{0x3A2D, 0x01}, ++{0x3A2E, 0xA7}, ++{0x3A2F, 0x00}, ++{0x3A30, 0x5D}, ++{0x3A31, 0x00}, ++{0x3A32, 0x24}, ++{0x3A33, 0x00}, ++{0x3A34, 0x2A}, ++{0x3A35, 0x02}, ++{0x3A36, 0xEB}, ++{0x3A37, 0x00}, ++{0x3A38, 0x83}, ++{0x3A39, 0x00}, ++{0x3A3A, 0x32}, ++{0x3A3B, 0x00}, ++{0x3A3C, 0x00}, ++{0x3A3D, 0x01}, ++{0x3A3E, 0x00}, ++{0x3A3F, 0x01}, ++{0x3A40, 0x00}, ++{0x3A41, 0x01}, ++{0x3A42, 0x00}, ++{0x3A43, 0x01}, ++{0x3A44, 0x70}, ++{0x3A45, 0x00}, ++{0x3A46, 0x25}, ++{0x3A47, 0x00}, ++{0x3A48, 0x18}, ++{0x3A49, 0x00}, ++{0x3A4A, 0x10}, ++{0x3A4B, 0x00}, ++{0x3A4C, 0xFF}, ++{0x3A4D, 0x00}, ++{0x3A4E, 0xD5}, ++{0x3A4F, 0x00}, ++{0x3A50, 0xAA}, ++{0x3A51, 0x00}, ++{0x3A52, 0x85}, ++{0x3A53, 0x00}, ++{0x3A54, 0xFF}, ++{0x3A55, 0x00}, ++{0x3A56, 0xD5}, ++{0x3A57, 0x00}, ++{0x3A58, 0xAA}, ++{0x3A59, 0x00}, ++{0x3A5A, 0x85}, ++{0x3A5B, 0x00}, ++{0x3A5C, 0xFF}, ++{0x3A5D, 0x00}, ++{0x3A5E, 0xD5}, ++{0x3A5F, 0x00}, ++{0x3A60, 0xAA}, ++{0x3A61, 0x00}, ++{0x3A62, 0x85}, ++{0x3A63, 0x00}, ++{0x3A64, 0x1C}, ++{0x3A65, 0x00}, ++{0x3A66, 0x13}, ++{0x3A67, 0x00}, ++{0x3A68, 0x0D}, ++{0x3A69, 0x00}, ++{0x3A6A, 0x07}, ++{0x3A6B, 0x00}, ++{0x3A6C, 0x0D}, ++{0x3A6D, 0x00}, ++{0x3A6E, 0x0B}, ++{0x3A6F, 0x00}, ++{0x3A70, 0x06}, ++{0x3A71, 0x00}, ++{0x3A72, 0x05}, ++{0x3A73, 0x00}, ++{0x3A74, 0x19}, ++{0x3A75, 0x00}, ++{0x3A76, 0x14}, ++{0x3A77, 0x00}, ++{0x3A78, 0x0F}, ++{0x3A79, 0x00}, ++{0x3A7A, 0x0A}, ++{0x3A7B, 0x00}, ++{0x3A7C, 0x80}, ++{0x3A7D, 0x00}, ++{0x3A7E, 0x80}, ++{0x3A7F, 0x00}, ++{0x3A80, 0x80}, ++{0x3A81, 0x00}, ++{0x3A82, 0x80}, ++{0x3A83, 0x00}, ++{0x3A84, 0x08}, ++{0x3A85, 0x00}, ++{0x3A86, 0x05}, ++{0x3A87, 0x00}, ++{0x3A88, 0x04}, ++{0x3A89, 0x00}, ++{0x3A8A, 0x03}, ++{0x3A8B, 0x00}, ++{0x3A8C, 0xCD}, ++{0x3A8D, 0x00}, ++{0x3A8E, 0xAA}, ++{0x3A8F, 0x00}, ++{0x3A90, 0x8C}, ++{0x3A91, 0x00}, ++{0x3A92, 0x64}, ++{0x3A93, 0x00}, ++{0x3A94, 0xCD}, ++{0x3A95, 0x00}, ++{0x3A96, 0xAA}, ++{0x3A97, 0x00}, ++{0x3A98, 0x8C}, ++{0x3A99, 0x00}, ++{0x3A9A, 0x64}, ++{0x3A9B, 0x00}, ++{0x3A9C, 0x08}, ++{0x3A9D, 0x10}, ++{0x3A9E, 0x4C}, ++{0x3A9F, 0x4C}, ++{0x3AA0, 0x4C}, ++{0x3AA1, 0x04}, ++{0x3AA2, 0x05}, ++{0x3AC0, 0x01}, ++{0x3AC4, 0x81}, ++{0x3AC5, 0x00}, ++{0x3AC6, 0x00}, ++{0x3AC7, 0x00}, ++{0x3AC8, 0x00}, ++{0x3AC9, 0x00}, ++{0x3ACA, 0x00}, ++{0x3ACB, 0x00}, ++{0x3ACC, 0x02}, ++{0x3ACD, 0x00}, ++{0x3ACE, 0x81}, ++{0x3ACF, 0x00}, ++{0x3AD0, 0x00}, ++{0x3AD1, 0x00}, ++{0x3AD2, 0xFD}, ++{0x3AD3, 0x03}, ++{0x3AD4, 0x02}, ++{0x3AD5, 0x00}, ++{0x3AD6, 0x00}, ++{0x3AD7, 0x00}, ++{0x3AD8, 0x81}, ++{0x3AD9, 0x00}, ++{0x3ADA, 0xFD}, ++{0x3ADB, 0x03}, ++{0x3ADC, 0xFF}, ++{0x3ADD, 0x03}, ++{0x3ADE, 0x01}, ++{0x3ADF, 0x00}, ++{0x3AE0, 0x01}, ++{0x3AE1, 0x00}, ++{0x3AE2, 0x7E}, ++{0x3AE3, 0x00}, ++{0x3AF4, 0x00}, ++{0x3AF6, 0x40}, ++{0x3AF7, 0x1E}, ++{0x3AF8, 0x01}, ++{0x3AFA, 0x63}, ++{0x3AFB, 0x09}, ++{0x3AFC, 0x11}, ++{0x3AFD, 0x09}, ++{0x3AFE, 0x00}, ++{0x3AFF, 0x00}, ++{0x3B00, 0x00}, ++{0x3B01, 0x00}, ++{0x3B02, 0x84}, ++{0x3B03, 0x06}, ++{0x3B04, 0x30}, ++{0x3B05, 0x06}, ++{0x3B06, 0x00}, ++{0x3B07, 0x00}, ++{0x3B08, 0x00}, ++{0x3B09, 0x00}, ++{0x3B0A, 0x00}, ++{0x3B0B, 0x00}, ++{0x3B0C, 0x00}, ++{0x3B0D, 0x00}, ++{0x3B0E, 0x00}, ++{0x3B0F, 0x00}, ++{0x3B10, 0x00}, ++{0x3B11, 0x00}, ++{0x3B12, 0x00}, ++{0x3B13, 0x00}, ++{0x3B14, 0x00}, ++{0x3B15, 0x00}, ++{0x3B16, 0x00}, ++{0x3B17, 0x00}, ++{0x3B18, 0x00}, ++{0x3B19, 0x00}, ++{0x3B1A, 0x00}, ++{0x3B1B, 0x00}, ++{0x3B1C, 0x00}, ++{0x3B1D, 0x00}, ++{0x3B1E, 0x00}, ++{0x3B1F, 0x00}, ++{0x3B20, 0x00}, ++{0x3B21, 0x00}, ++{0x3B22, 0x00}, ++{0x3B23, 0x00}, ++{0x3B24, 0x00}, ++{0x3B25, 0x00}, ++{0x3B26, 0x00}, ++{0x3B27, 0x00}, ++{0x3B28, 0x00}, ++{0x3B29, 0x00}, ++{0x3B2A, 0x00}, ++{0x3B2C, 0x00}, ++{0x3B2E, 0x00}, ++{0x3B30, 0x00}, ++{0x3B32, 0x0C}, ++{0x4000, 0xD1}, ++{0x4001, 0xC0}, ++{0x4002, 0xC0}, ++{0x4003, 0xB8}, ++{0x4004, 0xC0}, ++{0x4005, 0xB8}, ++{0x4006, 0xB9}, ++{0x4007, 0xB7}, ++{0x4008, 0xB0}, ++{0x4009, 0xAB}, ++{0x400A, 0xAC}, ++{0x400B, 0xAB}, ++{0x400C, 0xA8}, ++{0x400D, 0xA6}, ++{0x400E, 0xA6}, ++{0x400F, 0xA5}, ++{0x4010, 0xA2}, ++{0x4011, 0xA0}, ++{0x4012, 0xA0}, ++{0x4013, 0x9F}, ++{0x4014, 0xA4}, ++{0x4015, 0xA2}, ++{0x4016, 0xA2}, ++{0x4017, 0x9C}, ++{0x4018, 0xA8}, ++{0x4019, 0xA6}, ++{0x401A, 0xA8}, ++{0x401B, 0xAA}, ++{0x401C, 0xB0}, ++{0x401D, 0xAE}, ++{0x401E, 0xAE}, ++{0x401F, 0xAE}, ++{0x4020, 0xBA}, ++{0x4021, 0xAE}, ++{0x4022, 0xAF}, ++{0x4023, 0xAE}, ++{0x4024, 0xC6}, ++{0x4025, 0xBD}, ++{0x4026, 0xBD}, ++{0x4027, 0xBA}, ++{0x4028, 0xB0}, ++{0x4029, 0xA9}, ++{0x402A, 0xAA}, ++{0x402B, 0xA8}, ++{0x402C, 0x9F}, ++{0x402D, 0x9C}, ++{0x402E, 0x9C}, ++{0x402F, 0x9B}, ++{0x4030, 0x93}, ++{0x4031, 0x91}, ++{0x4032, 0x92}, ++{0x4033, 0x91}, ++{0x4034, 0x8D}, ++{0x4035, 0x8C}, ++{0x4036, 0x8C}, ++{0x4037, 0x8C}, ++{0x4038, 0x8F}, ++{0x4039, 0x8E}, ++{0x403A, 0x8E}, ++{0x403B, 0x8E}, ++{0x403C, 0x98}, ++{0x403D, 0x96}, ++{0x403E, 0x96}, ++{0x403F, 0x95}, ++{0x4040, 0xA4}, ++{0x4041, 0xA0}, ++{0x4042, 0xA0}, ++{0x4043, 0x9E}, ++{0x4044, 0xB3}, ++{0x4045, 0xAE}, ++{0x4046, 0xAF}, ++{0x4047, 0xAB}, ++{0x4048, 0xC2}, ++{0x4049, 0xB7}, ++{0x404A, 0xB8}, ++{0x404B, 0xB5}, ++{0x404C, 0xAB}, ++{0x404D, 0xA4}, ++{0x404E, 0xA5}, ++{0x404F, 0xA3}, ++{0x4050, 0x99}, ++{0x4051, 0x96}, ++{0x4052, 0x96}, ++{0x4053, 0x96}, ++{0x4054, 0x8B}, ++{0x4055, 0x8A}, ++{0x4056, 0x8A}, ++{0x4057, 0x8A}, ++{0x4058, 0x82}, ++{0x4059, 0x81}, ++{0x405A, 0x81}, ++{0x405B, 0x81}, ++{0x405C, 0x85}, ++{0x405D, 0x86}, ++{0x405E, 0x85}, ++{0x405F, 0x85}, ++{0x4060, 0x90}, ++{0x4061, 0x90}, ++{0x4062, 0x8F}, ++{0x4063, 0x8F}, ++{0x4064, 0x9D}, ++{0x4065, 0x9B}, ++{0x4066, 0x9B}, ++{0x4067, 0x9A}, ++{0x4068, 0xAF}, ++{0x4069, 0xAA}, ++{0x406A, 0xAC}, ++{0x406B, 0xAA}, ++{0x406C, 0xC2}, ++{0x406D, 0xB7}, ++{0x406E, 0xB8}, ++{0x406F, 0xB5}, ++{0x4070, 0xAB}, ++{0x4071, 0xA4}, ++{0x4072, 0xA4}, ++{0x4073, 0xA3}, ++{0x4074, 0x99}, ++{0x4075, 0x96}, ++{0x4076, 0x96}, ++{0x4077, 0x96}, ++{0x4078, 0x8B}, ++{0x4079, 0x8A}, ++{0x407A, 0x8A}, ++{0x407B, 0x8A}, ++{0x407C, 0x82}, ++{0x407D, 0x82}, ++{0x407E, 0x82}, ++{0x407F, 0x82}, ++{0x4080, 0x85}, ++{0x4081, 0x86}, ++{0x4082, 0x86}, ++{0x4083, 0x86}, ++{0x4084, 0x90}, ++{0x4085, 0x90}, ++{0x4086, 0x8F}, ++{0x4087, 0x8F}, ++{0x4088, 0x9D}, ++{0x4089, 0x9B}, ++{0x408A, 0x9B}, ++{0x408B, 0x99}, ++{0x408C, 0xAE}, ++{0x408D, 0xAA}, ++{0x408E, 0xAA}, ++{0x408F, 0xA7}, ++{0x4090, 0xC7}, ++{0x4091, 0xBA}, ++{0x4092, 0xBC}, ++{0x4093, 0xB9}, ++{0x4094, 0xB1}, ++{0x4095, 0xA8}, ++{0x4096, 0xA8}, ++{0x4097, 0xA7}, ++{0x4098, 0x9F}, ++{0x4099, 0x9B}, ++{0x409A, 0x9B}, ++{0x409B, 0x9B}, ++{0x409C, 0x93}, ++{0x409D, 0x91}, ++{0x409E, 0x91}, ++{0x409F, 0x91}, ++{0x40A0, 0x8D}, ++{0x40A1, 0x8C}, ++{0x40A2, 0x8C}, ++{0x40A3, 0x8C}, ++{0x40A4, 0x8E}, ++{0x40A5, 0x8E}, ++{0x40A6, 0x8D}, ++{0x40A7, 0x8D}, ++{0x40A8, 0x96}, ++{0x40A9, 0x95}, ++{0x40AA, 0x95}, ++{0x40AB, 0x94}, ++{0x40AC, 0xA2}, ++{0x40AD, 0x9F}, ++{0x40AE, 0x9F}, ++{0x40AF, 0x9D}, ++{0x40B0, 0xB1}, ++{0x40B1, 0xAC}, ++{0x40B2, 0xAB}, ++{0x40B3, 0xAA}, ++{0x40B4, 0xD3}, ++{0x40B5, 0xBC}, ++{0x40B6, 0xBD}, ++{0x40B7, 0xBC}, ++{0x40B8, 0xC1}, ++{0x40B9, 0xB7}, ++{0x40BA, 0xB7}, ++{0x40BB, 0xB5}, ++{0x40BC, 0xB0}, ++{0x40BD, 0xAA}, ++{0x40BE, 0xAA}, ++{0x40BF, 0xAA}, ++{0x40C0, 0xA8}, ++{0x40C1, 0xA4}, ++{0x40C2, 0xA4}, ++{0x40C3, 0xA4}, ++{0x40C4, 0xA2}, ++{0x40C5, 0x9F}, ++{0x40C6, 0x9F}, ++{0x40C7, 0x9F}, ++{0x40C8, 0xA3}, ++{0x40C9, 0xA0}, ++{0x40CA, 0xA0}, ++{0x40CB, 0xA0}, ++{0x40CC, 0xA6}, ++{0x40CD, 0xA3}, ++{0x40CE, 0xA3}, ++{0x40CF, 0xA2}, ++{0x40D0, 0xAF}, ++{0x40D1, 0xAB}, ++{0x40D2, 0xAA}, ++{0x40D3, 0xA8}, ++{0x40D4, 0xBA}, ++{0x40D5, 0xAE}, ++{0x40D6, 0xAE}, ++{0x40D7, 0xAB}, ++{0x4100, 0xBD}, ++{0x4101, 0xBA}, ++{0x4102, 0xBD}, ++{0x4103, 0xB7}, ++{0x4104, 0xB7}, ++{0x4105, 0xB7}, ++{0x4106, 0xB8}, ++{0x4107, 0xB5}, ++{0x4108, 0xAB}, ++{0x4109, 0xAA}, ++{0x410A, 0xAC}, ++{0x410B, 0xAB}, ++{0x410C, 0xA4}, ++{0x410D, 0xA5}, ++{0x410E, 0xA5}, ++{0x410F, 0xA4}, ++{0x4110, 0x9F}, ++{0x4111, 0xA0}, ++{0x4112, 0xA0}, ++{0x4113, 0x9F}, ++{0x4114, 0xA0}, ++{0x4115, 0xA0}, ++{0x4116, 0xA0}, ++{0x4117, 0x9F}, ++{0x4118, 0xA1}, ++{0x4119, 0xA1}, ++{0x411A, 0xA1}, ++{0x411B, 0xA0}, ++{0x411C, 0xA7}, ++{0x411D, 0xA6}, ++{0x411E, 0xA6}, ++{0x411F, 0xA6}, ++{0x4120, 0xA7}, ++{0x4121, 0xA6}, ++{0x4122, 0xA6}, ++{0x4123, 0xA3}, ++{0x4124, 0xB9}, ++{0x4125, 0xB9}, ++{0x4126, 0xBA}, ++{0x4127, 0xB8}, ++{0x4128, 0xA6}, ++{0x4129, 0xA7}, ++{0x412A, 0xA7}, ++{0x412B, 0xA6}, ++{0x412C, 0x9B}, ++{0x412D, 0x9B}, ++{0x412E, 0x9B}, ++{0x412F, 0x9B}, ++{0x4130, 0x91}, ++{0x4131, 0x92}, ++{0x4132, 0x92}, ++{0x4133, 0x91}, ++{0x4134, 0x8C}, ++{0x4135, 0x8C}, ++{0x4136, 0x8C}, ++{0x4137, 0x8C}, ++{0x4138, 0x8D}, ++{0x4139, 0x8D}, ++{0x413A, 0x8D}, ++{0x413B, 0x8D}, ++{0x413C, 0x93}, ++{0x413D, 0x93}, ++{0x413E, 0x93}, ++{0x413F, 0x92}, ++{0x4140, 0x9A}, ++{0x4141, 0x9A}, ++{0x4142, 0x9A}, ++{0x4143, 0x99}, ++{0x4144, 0xA7}, ++{0x4145, 0xA5}, ++{0x4146, 0xA6}, ++{0x4147, 0xA6}, ++{0x4148, 0xB8}, ++{0x4149, 0xB4}, ++{0x414A, 0xB4}, ++{0x414B, 0xB3}, ++{0x414C, 0xA3}, ++{0x414D, 0xA2}, ++{0x414E, 0xA3}, ++{0x414F, 0xA2}, ++{0x4150, 0x96}, ++{0x4151, 0x96}, ++{0x4152, 0x96}, ++{0x4153, 0x96}, ++{0x4154, 0x8A}, ++{0x4155, 0x8A}, ++{0x4156, 0x8A}, ++{0x4157, 0x8A}, ++{0x4158, 0x82}, ++{0x4159, 0x82}, ++{0x415A, 0x82}, ++{0x415B, 0x82}, ++{0x415C, 0x84}, ++{0x415D, 0x85}, ++{0x415E, 0x84}, ++{0x415F, 0x84}, ++{0x4160, 0x8D}, ++{0x4161, 0x8D}, ++{0x4162, 0x8D}, ++{0x4163, 0x8D}, ++{0x4164, 0x96}, ++{0x4165, 0x96}, ++{0x4166, 0x96}, ++{0x4167, 0x95}, ++{0x4168, 0xA5}, ++{0x4169, 0xA2}, ++{0x416A, 0xA3}, ++{0x416B, 0xA2}, ++{0x416C, 0xB7}, ++{0x416D, 0xB3}, ++{0x416E, 0xB5}, ++{0x416F, 0xB4}, ++{0x4170, 0xA4}, ++{0x4171, 0xA2}, ++{0x4172, 0xA3}, ++{0x4173, 0xA2}, ++{0x4174, 0x97}, ++{0x4175, 0x96}, ++{0x4176, 0x96}, ++{0x4177, 0x96}, ++{0x4178, 0x8B}, ++{0x4179, 0x8A}, ++{0x417A, 0x8A}, ++{0x417B, 0x8A}, ++{0x417C, 0x81}, ++{0x417D, 0x81}, ++{0x417E, 0x81}, ++{0x417F, 0x81}, ++{0x4180, 0x84}, ++{0x4181, 0x84}, ++{0x4182, 0x84}, ++{0x4183, 0x84}, ++{0x4184, 0x8C}, ++{0x4185, 0x8D}, ++{0x4186, 0x8D}, ++{0x4187, 0x8D}, ++{0x4188, 0x95}, ++{0x4189, 0x96}, ++{0x418A, 0x96}, ++{0x418B, 0x95}, ++{0x418C, 0xA1}, ++{0x418D, 0xA1}, ++{0x418E, 0xA1}, ++{0x418F, 0xA0}, ++{0x4190, 0xBC}, ++{0x4191, 0xB8}, ++{0x4192, 0xB8}, ++{0x4193, 0xB9}, ++{0x4194, 0xA8}, ++{0x4195, 0xA5}, ++{0x4196, 0xA6}, ++{0x4197, 0xA5}, ++{0x4198, 0x9C}, ++{0x4199, 0x9A}, ++{0x419A, 0x9A}, ++{0x419B, 0x9A}, ++{0x419C, 0x91}, ++{0x419D, 0x91}, ++{0x419E, 0x91}, ++{0x419F, 0x91}, ++{0x41A0, 0x8B}, ++{0x41A1, 0x8B}, ++{0x41A2, 0x8B}, ++{0x41A3, 0x8B}, ++{0x41A4, 0x8C}, ++{0x41A5, 0x8C}, ++{0x41A6, 0x8C}, ++{0x41A7, 0x8C}, ++{0x41A8, 0x91}, ++{0x41A9, 0x92}, ++{0x41AA, 0x91}, ++{0x41AB, 0x91}, ++{0x41AC, 0x98}, ++{0x41AD, 0x99}, ++{0x41AE, 0x99}, ++{0x41AF, 0x98}, ++{0x41B0, 0xA3}, ++{0x41B1, 0xA3}, ++{0x41B2, 0xA3}, ++{0x41B3, 0xA2}, ++{0x41B4, 0xC1}, ++{0x41B5, 0xB8}, ++{0x41B6, 0xB9}, ++{0x41B7, 0xBA}, ++{0x41B8, 0xB8}, ++{0x41B9, 0xB4}, ++{0x41BA, 0xB4}, ++{0x41BB, 0xB4}, ++{0x41BC, 0xAA}, ++{0x41BD, 0xA7}, ++{0x41BE, 0xA7}, ++{0x41BF, 0xA8}, ++{0x41C0, 0xA4}, ++{0x41C1, 0xA2}, ++{0x41C2, 0xA2}, ++{0x41C3, 0xA3}, ++{0x41C4, 0x9E}, ++{0x41C5, 0x9D}, ++{0x41C6, 0x9D}, ++{0x41C7, 0x9D}, ++{0x41C8, 0x9E}, ++{0x41C9, 0x9D}, ++{0x41CA, 0x9D}, ++{0x41CB, 0x9D}, ++{0x41CC, 0x9E}, ++{0x41CD, 0x9E}, ++{0x41CE, 0x9E}, ++{0x41CF, 0x9E}, ++{0x41D0, 0xA3}, ++{0x41D1, 0xA3}, ++{0x41D2, 0xA2}, ++{0x41D3, 0xA1}, ++{0x41D4, 0xA7}, ++{0x41D5, 0xA7}, ++{0x41D6, 0xA7}, ++{0x41D7, 0xA3}, ++{0x4200, 0xCE}, ++{0x4201, 0xC0}, ++{0x4202, 0xC1}, ++{0x4203, 0xB9}, ++{0x4204, 0xC3}, ++{0x4205, 0xB9}, ++{0x4206, 0xBC}, ++{0x4207, 0xBD}, ++{0x4208, 0xB3}, ++{0x4209, 0xAE}, ++{0x420A, 0xAF}, ++{0x420B, 0xAE}, ++{0x420C, 0xAA}, ++{0x420D, 0xA8}, ++{0x420E, 0xA8}, ++{0x420F, 0xA6}, ++{0x4210, 0xA4}, ++{0x4211, 0xA2}, ++{0x4212, 0xA2}, ++{0x4213, 0xA0}, ++{0x4214, 0xA4}, ++{0x4215, 0xA3}, ++{0x4216, 0xA2}, ++{0x4217, 0xA0}, ++{0x4218, 0xA7}, ++{0x4219, 0xA5}, ++{0x421A, 0xA3}, ++{0x421B, 0xA1}, ++{0x421C, 0xB0}, ++{0x421D, 0xA8}, ++{0x421E, 0xA8}, ++{0x421F, 0xA6}, ++{0x4220, 0xB4}, ++{0x4221, 0xAA}, ++{0x4222, 0xA5}, ++{0x4223, 0xA3}, ++{0x4224, 0xC7}, ++{0x4225, 0xBC}, ++{0x4226, 0xBE}, ++{0x4227, 0xBC}, ++{0x4228, 0xB0}, ++{0x4229, 0xA9}, ++{0x422A, 0xA9}, ++{0x422B, 0xA8}, ++{0x422C, 0xA0}, ++{0x422D, 0x9D}, ++{0x422E, 0x9D}, ++{0x422F, 0x9C}, ++{0x4230, 0x94}, ++{0x4231, 0x93}, ++{0x4232, 0x93}, ++{0x4233, 0x92}, ++{0x4234, 0x8E}, ++{0x4235, 0x8D}, ++{0x4236, 0x8D}, ++{0x4237, 0x8C}, ++{0x4238, 0x8F}, ++{0x4239, 0x8E}, ++{0x423A, 0x8E}, ++{0x423B, 0x8D}, ++{0x423C, 0x96}, ++{0x423D, 0x94}, ++{0x423E, 0x94}, ++{0x423F, 0x92}, ++{0x4240, 0xA1}, ++{0x4241, 0x9C}, ++{0x4242, 0x9C}, ++{0x4243, 0x99}, ++{0x4244, 0xB0}, ++{0x4245, 0xA8}, ++{0x4246, 0xAB}, ++{0x4247, 0xA7}, ++{0x4248, 0xC3}, ++{0x4249, 0xB7}, ++{0x424A, 0xB7}, ++{0x424B, 0xBC}, ++{0x424C, 0xAB}, ++{0x424D, 0xA4}, ++{0x424E, 0xA5}, ++{0x424F, 0xA5}, ++{0x4250, 0x9A}, ++{0x4251, 0x97}, ++{0x4252, 0x97}, ++{0x4253, 0x98}, ++{0x4254, 0x8C}, ++{0x4255, 0x8B}, ++{0x4256, 0x8B}, ++{0x4257, 0x8B}, ++{0x4258, 0x82}, ++{0x4259, 0x82}, ++{0x425A, 0x82}, ++{0x425B, 0x82}, ++{0x425C, 0x85}, ++{0x425D, 0x85}, ++{0x425E, 0x85}, ++{0x425F, 0x84}, ++{0x4260, 0x8F}, ++{0x4261, 0x8E}, ++{0x4262, 0x8E}, ++{0x4263, 0x8D}, ++{0x4264, 0x9B}, ++{0x4265, 0x98}, ++{0x4266, 0x98}, ++{0x4267, 0x95}, ++{0x4268, 0xAE}, ++{0x4269, 0xA5}, ++{0x426A, 0xA7}, ++{0x426B, 0xA2}, ++{0x426C, 0xC2}, ++{0x426D, 0xB7}, ++{0x426E, 0xB8}, ++{0x426F, 0xB9}, ++{0x4270, 0xAA}, ++{0x4271, 0xA4}, ++{0x4272, 0xA4}, ++{0x4273, 0xA5}, ++{0x4274, 0x99}, ++{0x4275, 0x96}, ++{0x4276, 0x97}, ++{0x4277, 0x98}, ++{0x4278, 0x8B}, ++{0x4279, 0x8A}, ++{0x427A, 0x8A}, ++{0x427B, 0x8B}, ++{0x427C, 0x81}, ++{0x427D, 0x81}, ++{0x427E, 0x81}, ++{0x427F, 0x82}, ++{0x4280, 0x84}, ++{0x4281, 0x84}, ++{0x4282, 0x84}, ++{0x4283, 0x84}, ++{0x4284, 0x8E}, ++{0x4285, 0x8E}, ++{0x4286, 0x8D}, ++{0x4287, 0x8C}, ++{0x4288, 0x9A}, ++{0x4289, 0x97}, ++{0x428A, 0x97}, ++{0x428B, 0x95}, ++{0x428C, 0xAA}, ++{0x428D, 0xA3}, ++{0x428E, 0xA3}, ++{0x428F, 0xA2}, ++{0x4290, 0xC7}, ++{0x4291, 0xBA}, ++{0x4292, 0xC0}, ++{0x4293, 0xC3}, ++{0x4294, 0xB0}, ++{0x4295, 0xA7}, ++{0x4296, 0xA7}, ++{0x4297, 0xA9}, ++{0x4298, 0x9F}, ++{0x4299, 0x9B}, ++{0x429A, 0x9B}, ++{0x429B, 0x9D}, ++{0x429C, 0x93}, ++{0x429D, 0x91}, ++{0x429E, 0x91}, ++{0x429F, 0x92}, ++{0x42A0, 0x8C}, ++{0x42A1, 0x8B}, ++{0x42A2, 0x8B}, ++{0x42A3, 0x8C}, ++{0x42A4, 0x8D}, ++{0x42A5, 0x8C}, ++{0x42A6, 0x8C}, ++{0x42A7, 0x8C}, ++{0x42A8, 0x94}, ++{0x42A9, 0x93}, ++{0x42AA, 0x92}, ++{0x42AB, 0x91}, ++{0x42AC, 0x9E}, ++{0x42AD, 0x9B}, ++{0x42AE, 0x9B}, ++{0x42AF, 0x98}, ++{0x42B0, 0xAC}, ++{0x42B1, 0xA6}, ++{0x42B2, 0xA6}, ++{0x42B3, 0xA2}, ++{0x42B4, 0xCE}, ++{0x42B5, 0xBA}, ++{0x42B6, 0xBC}, ++{0x42B7, 0xB7}, ++{0x42B8, 0xC5}, ++{0x42B9, 0xB5}, ++{0x42BA, 0xBA}, ++{0x42BB, 0xC0}, ++{0x42BC, 0xB1}, ++{0x42BD, 0xA8}, ++{0x42BE, 0xAE}, ++{0x42BF, 0xAF}, ++{0x42C0, 0xA7}, ++{0x42C1, 0xA3}, ++{0x42C2, 0xA3}, ++{0x42C3, 0xA5}, ++{0x42C4, 0xA0}, ++{0x42C5, 0x9D}, ++{0x42C6, 0x9D}, ++{0x42C7, 0x9F}, ++{0x42C8, 0xA0}, ++{0x42C9, 0x9E}, ++{0x42CA, 0x9E}, ++{0x42CB, 0x9F}, ++{0x42CC, 0xA2}, ++{0x42CD, 0xA0}, ++{0x42CE, 0xA0}, ++{0x42CF, 0xA0}, ++{0x42D0, 0xA8}, ++{0x42D1, 0xA5}, ++{0x42D2, 0xA5}, ++{0x42D3, 0xA2}, ++{0x42D4, 0xB3}, ++{0x42D5, 0xAA}, ++{0x42D6, 0xAB}, ++{0x42D7, 0xA3}, ++{0x42D8, 0x00}, ++{0x42D9, 0x00}, ++{0x4300, 0xA2}, ++{0x4301, 0xAE}, ++{0x4302, 0xAD}, ++{0x4303, 0xB5}, ++{0x4304, 0x95}, ++{0x4305, 0x9A}, ++{0x4306, 0x98}, ++{0x4307, 0x9B}, ++{0x4308, 0x8D}, ++{0x4309, 0x90}, ++{0x430A, 0x8F}, ++{0x430B, 0x91}, ++{0x430C, 0x86}, ++{0x430D, 0x88}, ++{0x430E, 0x87}, ++{0x430F, 0x89}, ++{0x4310, 0x86}, ++{0x4311, 0x87}, ++{0x4312, 0x86}, ++{0x4313, 0x88}, ++{0x4314, 0x89}, ++{0x4315, 0x88}, ++{0x4316, 0x88}, ++{0x4317, 0x8E}, ++{0x4318, 0x90}, ++{0x4319, 0x8F}, ++{0x431A, 0x8C}, ++{0x431B, 0x8C}, ++{0x431C, 0x9C}, ++{0x431D, 0x99}, ++{0x431E, 0x98}, ++{0x431F, 0x99}, ++{0x4320, 0xAB}, ++{0x4321, 0xB0}, ++{0x4322, 0xAD}, ++{0x4323, 0xAF}, ++{0x4324, 0x9B}, ++{0x4325, 0x9F}, ++{0x4326, 0x9E}, ++{0x4327, 0xA1}, ++{0x4328, 0x8E}, ++{0x4329, 0x91}, ++{0x432A, 0x90}, ++{0x432B, 0x93}, ++{0x432C, 0x86}, ++{0x432D, 0x88}, ++{0x432E, 0x87}, ++{0x432F, 0x89}, ++{0x4330, 0x82}, ++{0x4331, 0x84}, ++{0x4332, 0x83}, ++{0x4333, 0x84}, ++{0x4334, 0x82}, ++{0x4335, 0x82}, ++{0x4336, 0x82}, ++{0x4337, 0x83}, ++{0x4338, 0x85}, ++{0x4339, 0x84}, ++{0x433A, 0x84}, ++{0x433B, 0x85}, ++{0x433C, 0x8A}, ++{0x433D, 0x89}, ++{0x433E, 0x88}, ++{0x433F, 0x89}, ++{0x4340, 0x93}, ++{0x4341, 0x91}, ++{0x4342, 0x91}, ++{0x4343, 0x93}, ++{0x4344, 0xA0}, ++{0x4345, 0x9E}, ++{0x4346, 0x9D}, ++{0x4347, 0xA1}, ++{0x4348, 0x95}, ++{0x4349, 0x9B}, ++{0x434A, 0x9A}, ++{0x434B, 0x9C}, ++{0x434C, 0x8A}, ++{0x434D, 0x8D}, ++{0x434E, 0x8C}, ++{0x434F, 0x8D}, ++{0x4350, 0x83}, ++{0x4351, 0x85}, ++{0x4352, 0x84}, ++{0x4353, 0x85}, ++{0x4354, 0x80}, ++{0x4355, 0x81}, ++{0x4356, 0x81}, ++{0x4357, 0x81}, ++{0x4358, 0x80}, ++{0x4359, 0x80}, ++{0x435A, 0x80}, ++{0x435B, 0x80}, ++{0x435C, 0x82}, ++{0x435D, 0x81}, ++{0x435E, 0x81}, ++{0x435F, 0x81}, ++{0x4360, 0x85}, ++{0x4361, 0x84}, ++{0x4362, 0x84}, ++{0x4363, 0x85}, ++{0x4364, 0x8D}, ++{0x4365, 0x8B}, ++{0x4366, 0x8B}, ++{0x4367, 0x8D}, ++{0x4368, 0x98}, ++{0x4369, 0x98}, ++{0x436A, 0x95}, ++{0x436B, 0x98}, ++{0x436C, 0x95}, ++{0x436D, 0x9A}, ++{0x436E, 0x99}, ++{0x436F, 0x9A}, ++{0x4370, 0x8A}, ++{0x4371, 0x8D}, ++{0x4372, 0x8C}, ++{0x4373, 0x8C}, ++{0x4374, 0x83}, ++{0x4375, 0x85}, ++{0x4376, 0x84}, ++{0x4377, 0x84}, ++{0x4378, 0x80}, ++{0x4379, 0x80}, ++{0x437A, 0x80}, ++{0x437B, 0x80}, ++{0x437C, 0x7F}, ++{0x437D, 0x7F}, ++{0x437E, 0x7F}, ++{0x437F, 0x7F}, ++{0x4380, 0x81}, ++{0x4381, 0x80}, ++{0x4382, 0x80}, ++{0x4383, 0x81}, ++{0x4384, 0x84}, ++{0x4385, 0x83}, ++{0x4386, 0x83}, ++{0x4387, 0x84}, ++{0x4388, 0x8B}, ++{0x4389, 0x8A}, ++{0x438A, 0x8A}, ++{0x438B, 0x8C}, ++{0x438C, 0x97}, ++{0x438D, 0x96}, ++{0x438E, 0x96}, ++{0x438F, 0x99}, ++{0x4390, 0x99}, ++{0x4391, 0x9F}, ++{0x4392, 0x9E}, ++{0x4393, 0x9D}, ++{0x4394, 0x8D}, ++{0x4395, 0x90}, ++{0x4396, 0x90}, ++{0x4397, 0x8F}, ++{0x4398, 0x85}, ++{0x4399, 0x87}, ++{0x439A, 0x87}, ++{0x439B, 0x86}, ++{0x439C, 0x81}, ++{0x439D, 0x83}, ++{0x439E, 0x82}, ++{0x439F, 0x82}, ++{0x43A0, 0x80}, ++{0x43A1, 0x81}, ++{0x43A2, 0x81}, ++{0x43A3, 0x81}, ++{0x43A4, 0x82}, ++{0x43A5, 0x82}, ++{0x43A6, 0x82}, ++{0x43A7, 0x82}, ++{0x43A8, 0x86}, ++{0x43A9, 0x85}, ++{0x43AA, 0x85}, ++{0x43AB, 0x87}, ++{0x43AC, 0x8D}, ++{0x43AD, 0x8D}, ++{0x43AE, 0x8D}, ++{0x43AF, 0x90}, ++{0x43B0, 0x9A}, ++{0x43B1, 0x9A}, ++{0x43B2, 0x9B}, ++{0x43B3, 0x9D}, ++{0x43B4, 0xA0}, ++{0x43B5, 0xAD}, ++{0x43B6, 0xAC}, ++{0x43B7, 0xAA}, ++{0x43B8, 0x93}, ++{0x43B9, 0x97}, ++{0x43BA, 0x97}, ++{0x43BB, 0x96}, ++{0x43BC, 0x8B}, ++{0x43BD, 0x8E}, ++{0x43BE, 0x8E}, ++{0x43BF, 0x8C}, ++{0x43C0, 0x83}, ++{0x43C1, 0x85}, ++{0x43C2, 0x85}, ++{0x43C3, 0x84}, ++{0x43C4, 0x82}, ++{0x43C5, 0x84}, ++{0x43C6, 0x83}, ++{0x43C7, 0x83}, ++{0x43C8, 0x83}, ++{0x43C9, 0x84}, ++{0x43CA, 0x84}, ++{0x43CB, 0x85}, ++{0x43CC, 0x8A}, ++{0x43CD, 0x8A}, ++{0x43CE, 0x8A}, ++{0x43CF, 0x8C}, ++{0x43D0, 0x92}, ++{0x43D1, 0x93}, ++{0x43D2, 0x93}, ++{0x43D3, 0x96}, ++{0x43D4, 0x9F}, ++{0x43D5, 0xA6}, ++{0x43D6, 0xA5}, ++{0x43D7, 0xAA}, ++{0x4400, 0xA1}, ++{0x4401, 0xAB}, ++{0x4402, 0xA7}, ++{0x4403, 0xB0}, ++{0x4404, 0x91}, ++{0x4405, 0x96}, ++{0x4406, 0x94}, ++{0x4407, 0x99}, ++{0x4408, 0x8A}, ++{0x4409, 0x8E}, ++{0x440A, 0x8C}, ++{0x440B, 0x8F}, ++{0x440C, 0x85}, ++{0x440D, 0x86}, ++{0x440E, 0x86}, ++{0x440F, 0x88}, ++{0x4410, 0x85}, ++{0x4411, 0x86}, ++{0x4412, 0x85}, ++{0x4413, 0x87}, ++{0x4414, 0x88}, ++{0x4415, 0x87}, ++{0x4416, 0x87}, ++{0x4417, 0x89}, ++{0x4418, 0x91}, ++{0x4419, 0x8F}, ++{0x441A, 0x8F}, ++{0x441B, 0x90}, ++{0x441C, 0x9C}, ++{0x441D, 0x9B}, ++{0x441E, 0x9A}, ++{0x441F, 0x9A}, ++{0x4420, 0xB3}, ++{0x4421, 0xB1}, ++{0x4422, 0xB0}, ++{0x4423, 0xB2}, ++{0x4424, 0x96}, ++{0x4425, 0x9C}, ++{0x4426, 0x9A}, ++{0x4427, 0x9E}, ++{0x4428, 0x8B}, ++{0x4429, 0x8F}, ++{0x442A, 0x8E}, ++{0x442B, 0x91}, ++{0x442C, 0x84}, ++{0x442D, 0x87}, ++{0x442E, 0x86}, ++{0x442F, 0x88}, ++{0x4430, 0x82}, ++{0x4431, 0x83}, ++{0x4432, 0x82}, ++{0x4433, 0x84}, ++{0x4434, 0x82}, ++{0x4435, 0x82}, ++{0x4436, 0x82}, ++{0x4437, 0x83}, ++{0x4438, 0x84}, ++{0x4439, 0x84}, ++{0x443A, 0x84}, ++{0x443B, 0x84}, ++{0x443C, 0x8B}, ++{0x443D, 0x89}, ++{0x443E, 0x89}, ++{0x443F, 0x89}, ++{0x4440, 0x95}, ++{0x4441, 0x93}, ++{0x4442, 0x93}, ++{0x4443, 0x93}, ++{0x4444, 0xA2}, ++{0x4445, 0xA2}, ++{0x4446, 0xA1}, ++{0x4447, 0xA0}, ++{0x4448, 0x8F}, ++{0x4449, 0x97}, ++{0x444A, 0x97}, ++{0x444B, 0x98}, ++{0x444C, 0x87}, ++{0x444D, 0x8B}, ++{0x444E, 0x8A}, ++{0x444F, 0x8B}, ++{0x4450, 0x81}, ++{0x4451, 0x83}, ++{0x4452, 0x83}, ++{0x4453, 0x84}, ++{0x4454, 0x7F}, ++{0x4455, 0x80}, ++{0x4456, 0x80}, ++{0x4457, 0x81}, ++{0x4458, 0x80}, ++{0x4459, 0x80}, ++{0x445A, 0x80}, ++{0x445B, 0x80}, ++{0x445C, 0x82}, ++{0x445D, 0x81}, ++{0x445E, 0x81}, ++{0x445F, 0x81}, ++{0x4460, 0x87}, ++{0x4461, 0x85}, ++{0x4462, 0x85}, ++{0x4463, 0x86}, ++{0x4464, 0x90}, ++{0x4465, 0x8E}, ++{0x4466, 0x8E}, ++{0x4467, 0x8E}, ++{0x4468, 0x9B}, ++{0x4469, 0x9C}, ++{0x446A, 0x9A}, ++{0x446B, 0x9A}, ++{0x446C, 0x91}, ++{0x446D, 0x97}, ++{0x446E, 0x95}, ++{0x446F, 0x95}, ++{0x4470, 0x87}, ++{0x4471, 0x8A}, ++{0x4472, 0x8A}, ++{0x4473, 0x89}, ++{0x4474, 0x81}, ++{0x4475, 0x83}, ++{0x4476, 0x83}, ++{0x4477, 0x83}, ++{0x4478, 0x7F}, ++{0x4479, 0x80}, ++{0x447A, 0x80}, ++{0x447B, 0x80}, ++{0x447C, 0x80}, ++{0x447D, 0x80}, ++{0x447E, 0x80}, ++{0x447F, 0x7F}, ++{0x4480, 0x81}, ++{0x4481, 0x81}, ++{0x4482, 0x81}, ++{0x4483, 0x81}, ++{0x4484, 0x85}, ++{0x4485, 0x85}, ++{0x4486, 0x85}, ++{0x4487, 0x85}, ++{0x4488, 0x8E}, ++{0x4489, 0x8D}, ++{0x448A, 0x8D}, ++{0x448B, 0x8E}, ++{0x448C, 0x9D}, ++{0x448D, 0x9C}, ++{0x448E, 0x9C}, ++{0x448F, 0x9C}, ++{0x4490, 0x94}, ++{0x4491, 0x9B}, ++{0x4492, 0x9A}, ++{0x4493, 0x97}, ++{0x4494, 0x8A}, ++{0x4495, 0x8E}, ++{0x4496, 0x8E}, ++{0x4497, 0x8C}, ++{0x4498, 0x84}, ++{0x4499, 0x86}, ++{0x449A, 0x86}, ++{0x449B, 0x84}, ++{0x449C, 0x81}, ++{0x449D, 0x83}, ++{0x449E, 0x83}, ++{0x449F, 0x81}, ++{0x44A0, 0x81}, ++{0x44A1, 0x82}, ++{0x44A2, 0x82}, ++{0x44A3, 0x81}, ++{0x44A4, 0x83}, ++{0x44A5, 0x83}, ++{0x44A6, 0x83}, ++{0x44A7, 0x83}, ++{0x44A8, 0x88}, ++{0x44A9, 0x88}, ++{0x44AA, 0x88}, ++{0x44AB, 0x88}, ++{0x44AC, 0x91}, ++{0x44AD, 0x91}, ++{0x44AE, 0x91}, ++{0x44AF, 0x92}, ++{0x44B0, 0xA0}, ++{0x44B1, 0xA0}, ++{0x44B2, 0xA0}, ++{0x44B3, 0xA0}, ++{0x44B4, 0x9E}, ++{0x44B5, 0xA9}, ++{0x44B6, 0xA8}, ++{0x44B7, 0xA3}, ++{0x44B8, 0x90}, ++{0x44B9, 0x95}, ++{0x44BA, 0x95}, ++{0x44BB, 0x92}, ++{0x44BC, 0x8A}, ++{0x44BD, 0x8E}, ++{0x44BE, 0x8E}, ++{0x44BF, 0x8B}, ++{0x44C0, 0x84}, ++{0x44C1, 0x86}, ++{0x44C2, 0x86}, ++{0x44C3, 0x84}, ++{0x44C4, 0x84}, ++{0x44C5, 0x85}, ++{0x44C6, 0x85}, ++{0x44C7, 0x84}, ++{0x44C8, 0x86}, ++{0x44C9, 0x87}, ++{0x44CA, 0x87}, ++{0x44CB, 0x86}, ++{0x44CC, 0x8D}, ++{0x44CD, 0x8E}, ++{0x44CE, 0x8E}, ++{0x44CF, 0x8D}, ++{0x44D0, 0x98}, ++{0x44D1, 0x98}, ++{0x44D2, 0x99}, ++{0x44D3, 0x9A}, ++{0x44D4, 0xA9}, ++{0x44D5, 0xAA}, ++{0x44D6, 0xAA}, ++{0x44D7, 0xAD}, ++{0x4500, 0x9F}, ++{0x4501, 0xA8}, ++{0x4502, 0xA5}, ++{0x4503, 0xAF}, ++{0x4504, 0x8F}, ++{0x4505, 0x96}, ++{0x4506, 0x92}, ++{0x4507, 0x94}, ++{0x4508, 0x89}, ++{0x4509, 0x8D}, ++{0x450A, 0x8A}, ++{0x450B, 0x8E}, ++{0x450C, 0x84}, ++{0x450D, 0x85}, ++{0x450E, 0x84}, ++{0x450F, 0x87}, ++{0x4510, 0x84}, ++{0x4511, 0x85}, ++{0x4512, 0x84}, ++{0x4513, 0x86}, ++{0x4514, 0x87}, ++{0x4515, 0x86}, ++{0x4516, 0x86}, ++{0x4517, 0x88}, ++{0x4518, 0x8F}, ++{0x4519, 0x8D}, ++{0x451A, 0x8D}, ++{0x451B, 0x8F}, ++{0x451C, 0x9A}, ++{0x451D, 0x9A}, ++{0x451E, 0x98}, ++{0x451F, 0x9A}, ++{0x4520, 0xAF}, ++{0x4521, 0xAF}, ++{0x4522, 0xB2}, ++{0x4523, 0xB1}, ++{0x4524, 0x95}, ++{0x4525, 0x9B}, ++{0x4526, 0x97}, ++{0x4527, 0x9C}, ++{0x4528, 0x8A}, ++{0x4529, 0x8E}, ++{0x452A, 0x8D}, ++{0x452B, 0x90}, ++{0x452C, 0x84}, ++{0x452D, 0x86}, ++{0x452E, 0x85}, ++{0x452F, 0x87}, ++{0x4530, 0x81}, ++{0x4531, 0x82}, ++{0x4532, 0x82}, ++{0x4533, 0x83}, ++{0x4534, 0x81}, ++{0x4535, 0x81}, ++{0x4536, 0x81}, ++{0x4537, 0x82}, ++{0x4538, 0x84}, ++{0x4539, 0x83}, ++{0x453A, 0x83}, ++{0x453B, 0x84}, ++{0x453C, 0x8A}, ++{0x453D, 0x88}, ++{0x453E, 0x88}, ++{0x453F, 0x89}, ++{0x4540, 0x94}, ++{0x4541, 0x92}, ++{0x4542, 0x91}, ++{0x4543, 0x92}, ++{0x4544, 0xA1}, ++{0x4545, 0xA0}, ++{0x4546, 0x9C}, ++{0x4547, 0x9D}, ++{0x4548, 0x8F}, ++{0x4549, 0x96}, ++{0x454A, 0x95}, ++{0x454B, 0x92}, ++{0x454C, 0x87}, ++{0x454D, 0x8A}, ++{0x454E, 0x89}, ++{0x454F, 0x8A}, ++{0x4550, 0x81}, ++{0x4551, 0x83}, ++{0x4552, 0x82}, ++{0x4553, 0x83}, ++{0x4554, 0x7F}, ++{0x4555, 0x80}, ++{0x4556, 0x80}, ++{0x4557, 0x81}, ++{0x4558, 0x7F}, ++{0x4559, 0x80}, ++{0x455A, 0x7F}, ++{0x455B, 0x80}, ++{0x455C, 0x81}, ++{0x455D, 0x81}, ++{0x455E, 0x81}, ++{0x455F, 0x81}, ++{0x4560, 0x86}, ++{0x4561, 0x85}, ++{0x4562, 0x85}, ++{0x4563, 0x85}, ++{0x4564, 0x8F}, ++{0x4565, 0x8D}, ++{0x4566, 0x8D}, ++{0x4567, 0x8D}, ++{0x4568, 0x99}, ++{0x4569, 0x9A}, ++{0x456A, 0x97}, ++{0x456B, 0x99}, ++{0x456C, 0x90}, ++{0x456D, 0x95}, ++{0x456E, 0x93}, ++{0x456F, 0x92}, ++{0x4570, 0x87}, ++{0x4571, 0x8A}, ++{0x4572, 0x88}, ++{0x4573, 0x87}, ++{0x4574, 0x81}, ++{0x4575, 0x83}, ++{0x4576, 0x82}, ++{0x4577, 0x82}, ++{0x4578, 0x7F}, ++{0x4579, 0x80}, ++{0x457A, 0x80}, ++{0x457B, 0x80}, ++{0x457C, 0x80}, ++{0x457D, 0x80}, ++{0x457E, 0x80}, ++{0x457F, 0x80}, ++{0x4580, 0x81}, ++{0x4581, 0x81}, ++{0x4582, 0x81}, ++{0x4583, 0x81}, ++{0x4584, 0x85}, ++{0x4585, 0x85}, ++{0x4586, 0x84}, ++{0x4587, 0x85}, ++{0x4588, 0x8E}, ++{0x4589, 0x8D}, ++{0x458A, 0x8C}, ++{0x458B, 0x8D}, ++{0x458C, 0x9B}, ++{0x458D, 0x9B}, ++{0x458E, 0x9A}, ++{0x458F, 0x98}, ++{0x4590, 0x94}, ++{0x4591, 0x9A}, ++{0x4592, 0x94}, ++{0x4593, 0x90}, ++{0x4594, 0x8A}, ++{0x4595, 0x8D}, ++{0x4596, 0x8C}, ++{0x4597, 0x89}, ++{0x4598, 0x84}, ++{0x4599, 0x86}, ++{0x459A, 0x85}, ++{0x459B, 0x83}, ++{0x459C, 0x82}, ++{0x459D, 0x83}, ++{0x459E, 0x82}, ++{0x459F, 0x80}, ++{0x45A0, 0x81}, ++{0x45A1, 0x82}, ++{0x45A2, 0x81}, ++{0x45A3, 0x80}, ++{0x45A4, 0x83}, ++{0x45A5, 0x83}, ++{0x45A6, 0x83}, ++{0x45A7, 0x83}, ++{0x45A8, 0x88}, ++{0x45A9, 0x87}, ++{0x45AA, 0x87}, ++{0x45AB, 0x88}, ++{0x45AC, 0x91}, ++{0x45AD, 0x90}, ++{0x45AE, 0x90}, ++{0x45AF, 0x91}, ++{0x45B0, 0x9F}, ++{0x45B1, 0x9F}, ++{0x45B2, 0x9E}, ++{0x45B3, 0x9F}, ++{0x45B4, 0x9F}, ++{0x45B5, 0xA8}, ++{0x45B6, 0xA6}, ++{0x45B7, 0xA7}, ++{0x45B8, 0x8D}, ++{0x45B9, 0x95}, ++{0x45BA, 0x90}, ++{0x45BB, 0x8A}, ++{0x45BC, 0x89}, ++{0x45BD, 0x8D}, ++{0x45BE, 0x88}, ++{0x45BF, 0x86}, ++{0x45C0, 0x84}, ++{0x45C1, 0x86}, ++{0x45C2, 0x85}, ++{0x45C3, 0x82}, ++{0x45C4, 0x84}, ++{0x45C5, 0x85}, ++{0x45C6, 0x85}, ++{0x45C7, 0x83}, ++{0x45C8, 0x86}, ++{0x45C9, 0x86}, ++{0x45CA, 0x86}, ++{0x45CB, 0x85}, ++{0x45CC, 0x8E}, ++{0x45CD, 0x8D}, ++{0x45CE, 0x8D}, ++{0x45CF, 0x8C}, ++{0x45D0, 0x99}, ++{0x45D1, 0x98}, ++{0x45D2, 0x98}, ++{0x45D3, 0x98}, ++{0x45D4, 0xA6}, ++{0x45D5, 0xA9}, ++{0x45D6, 0xA7}, ++{0x45D7, 0xAC}, ++{0x7000, 0xAB}, ++{0x7001, 0xBA}, ++{0x7002, 0x40}, ++{0x7003, 0x02}, ++{0x7004, 0x00}, ++{0x7005, 0x00}, ++{0x7006, 0x00}, ++{0x7007, 0x00}, ++{0x7008, 0x00}, ++{0x7009, 0x00}, ++{0x700A, 0x00}, ++{0x700B, 0x00}, ++{0x700C, 0x00}, ++{0x700D, 0x00}, ++{0x700E, 0x00}, ++{0x700F, 0x00}, ++{0x7010, 0x55}, ++{0x7011, 0x88}, ++{0x7012, 0x40}, ++{0x7013, 0x01}, ++{0x7014, 0x72}, ++{0x7015, 0xF1}, ++{0x7016, 0x02}, ++{0x7017, 0xF8}, ++{0x7018, 0x00}, ++{0x7019, 0x00}, ++{0x701A, 0x00}, ++{0x701B, 0x00}, ++{0x701C, 0x00}, ++{0x701D, 0x00}, ++{0x701E, 0x00}, ++{0x701F, 0x00}, ++{0x7020, 0x00}, ++{0x7021, 0x00}, ++{0x7022, 0x00}, ++{0x7023, 0x00}, ++{0x7024, 0x00}, ++{0x7025, 0x00}, ++{0x7026, 0x00}, ++{0x7027, 0x00}, ++{0x7028, 0x00}, ++{0x7029, 0x00}, ++{0x702A, 0x00}, ++{0x702B, 0x00}, ++{0x702C, 0x00}, ++{0x702D, 0x00}, ++{0x702E, 0x00}, ++{0x702F, 0x00}, ++{0x7030, 0x00}, ++{0x7031, 0x00}, ++{0x7032, 0x00}, ++{0x7033, 0x00}, ++{0x7034, 0x00}, ++{0x7035, 0x00}, ++{0x7036, 0x00}, ++{0x7037, 0x00}, ++{0x7038, 0x00}, ++{0x7039, 0x00}, ++{0x703A, 0x00}, ++{0x703B, 0x00}, ++{0x703C, 0x00}, ++{0x703D, 0x00}, ++{0x703E, 0x00}, ++{0x703F, 0x00}, ++{0x7040, 0x00}, ++{0x7041, 0x00}, ++{0x7042, 0x00}, ++{0x7043, 0x00}, ++{0x7044, 0x00}, ++{0x7045, 0x00}, ++{0x7046, 0x00}, ++{0x7047, 0x00}, ++{0x7048, 0x00}, ++{0x7049, 0x00}, ++{0x704A, 0x00}, ++{0x704B, 0x00}, ++{0x704C, 0x00}, ++{0x704D, 0x00}, ++{0x704E, 0x00}, ++{0x704F, 0x00}, ++{0x7050, 0x00}, ++{0x7051, 0x00}, ++{0x7052, 0x00}, ++{0x7053, 0x00}, ++{0x7054, 0x00}, ++{0x7055, 0x00}, ++{0x7056, 0x00}, ++{0x7057, 0x00}, ++{0x7058, 0x00}, ++{0x7059, 0x00}, ++{0x705A, 0x00}, ++{0x705B, 0x00}, ++{0x705C, 0x00}, ++{0x705D, 0x00}, ++{0x705E, 0x00}, ++{0x705F, 0x00}, ++{0x7060, 0x00}, ++{0x7061, 0x00}, ++{0x7062, 0x00}, ++{0x7063, 0x00}, ++{0x7064, 0x00}, ++{0x7065, 0x00}, ++{0x7066, 0x00}, ++{0x7067, 0x00}, ++{0x7068, 0x00}, ++{0x7069, 0x00}, ++{0x706A, 0x00}, ++{0x706B, 0x00}, ++{0x706C, 0x00}, ++{0x706D, 0x00}, ++{0x706E, 0x00}, ++{0x706F, 0x00}, ++{0x7070, 0x00}, ++{0x7071, 0x00}, ++{0x7072, 0x00}, ++{0x7073, 0x00}, ++{0x7074, 0x00}, ++{0x7075, 0x00}, ++{0x7076, 0x00}, ++{0x7077, 0x00}, ++{0x7078, 0x00}, ++{0x7079, 0x00}, ++{0x707A, 0x00}, ++{0x707B, 0x00}, ++{0x707C, 0x00}, ++{0x707D, 0x00}, ++{0x707E, 0x00}, ++{0x707F, 0x00}, ++{0x7080, 0x00}, ++{0x7081, 0x00}, ++{0x7082, 0x00}, ++{0x7083, 0x00}, ++{0x7084, 0x00}, ++{0x7085, 0x00}, ++{0x7086, 0x00}, ++{0x7087, 0x00}, ++{0x7088, 0x00}, ++{0x7089, 0x00}, ++{0x708A, 0x00}, ++{0x708B, 0x00}, ++{0x708C, 0x00}, ++{0x708D, 0x00}, ++{0x708E, 0x00}, ++{0x708F, 0x00}, ++{0x7090, 0x00}, ++{0x7091, 0xF0}, ++{0x7092, 0x02}, ++{0x7093, 0xF8}, ++{0x7094, 0x8D}, ++{0x7095, 0xF6}, ++{0x7096, 0xFA}, ++{0x7097, 0xFF}, ++{0x7098, 0xF0}, ++{0x7099, 0xB5}, ++{0x709A, 0x04}, ++{0x709B, 0x46}, ++{0x709C, 0x8F}, ++{0x709D, 0xB0}, ++{0x709E, 0x5F}, ++{0x709F, 0x48}, ++{0x70A0, 0x0C}, ++{0x70A1, 0x90}, ++{0x70A2, 0x5F}, ++{0x70A3, 0x48}, ++{0x70A4, 0x06}, ++{0x70A5, 0x90}, ++{0x70A6, 0x20}, ++{0x70A7, 0x46}, ++{0x70A8, 0x34}, ++{0x70A9, 0x30}, ++{0x70AA, 0x0B}, ++{0x70AB, 0x90}, ++{0x70AC, 0x5B}, ++{0x70AD, 0x48}, ++{0x70AE, 0x5A}, ++{0x70AF, 0x49}, ++{0x70B0, 0x26}, ++{0x70B1, 0x46}, ++{0x70B2, 0x66}, ++{0x70B3, 0x30}, ++{0x70B4, 0x3A}, ++{0x70B5, 0x31}, ++{0x70B6, 0x3C}, ++{0x70B7, 0x36}, ++{0x70B8, 0x05}, ++{0x70B9, 0x90}, ++{0x70BA, 0x0A}, ++{0x70BB, 0x30}, ++{0x70BC, 0x04}, ++{0x70BD, 0x90}, ++{0x70BE, 0x59}, ++{0x70BF, 0x48}, ++{0x70C0, 0x55}, ++{0x70C1, 0x4A}, ++{0x70C2, 0x40}, ++{0x70C3, 0x6E}, ++{0x70C4, 0xC0}, ++{0x70C5, 0x07}, ++{0x70C6, 0x7D}, ++{0x70C7, 0xD1}, ++{0x70C8, 0x17}, ++{0x70C9, 0x88}, ++{0x70CA, 0x0A}, ++{0x70CB, 0x5E}, ++{0x70CC, 0x0D}, ++{0x70CD, 0x92}, ++{0x70CE, 0x53}, ++{0x70CF, 0x49}, ++{0x70D0, 0x55}, ++{0x70D1, 0x48}, ++{0x70D2, 0x94}, ++{0x70D3, 0x31}, ++{0x70D4, 0x89}, ++{0x70D5, 0x6B}, ++{0x70D6, 0x80}, ++{0x70D7, 0x68}, ++{0x70D8, 0x09}, ++{0x70D9, 0x02}, ++{0x70DA, 0x00}, ++{0x70DB, 0x03}, ++{0x70DC, 0x09}, ++{0x70DD, 0x0E}, ++{0x70DE, 0x00}, ++{0x70DF, 0x0B}, ++{0x70E0, 0x49}, ++{0x70E1, 0x1C}, ++{0x70E2, 0x48}, ++{0x70E3, 0x43}, ++{0x70E4, 0x4D}, ++{0x70E5, 0x49}, ++{0x70E6, 0x6C}, ++{0x70E7, 0x39}, ++{0x70E8, 0x8A}, ++{0x70E9, 0x6A}, ++{0x70EA, 0x07}, ++{0x70EB, 0x92}, ++{0x70EC, 0xCA}, ++{0x70ED, 0x6A}, ++{0x70EE, 0x00}, ++{0x70EF, 0x21}, ++{0x70F0, 0xC9}, ++{0x70F1, 0x43}, ++{0x70F2, 0x03}, ++{0x70F3, 0x92}, ++{0x70F4, 0x00}, ++{0x70F5, 0x22}, ++{0x70F6, 0x00}, ++{0x70F7, 0x91}, ++{0x70F8, 0x01}, ++{0x70F9, 0x92}, ++{0x70FA, 0x39}, ++{0x70FB, 0x46}, ++{0x70FC, 0x8F}, ++{0x70FD, 0xF6}, ++{0x70FE, 0xCE}, ++{0x70FF, 0xFB}, ++{0x7100, 0x01}, ++{0x7101, 0x22}, ++{0x7102, 0x00}, ++{0x7103, 0x23}, ++{0x7104, 0x8C}, ++{0x7105, 0xF6}, ++{0x7106, 0x02}, ++{0x7107, 0xFA}, ++{0x7108, 0x00}, ++{0x7109, 0x21}, ++{0x710A, 0x05}, ++{0x710B, 0x46}, ++{0x710C, 0x01}, ++{0x710D, 0x91}, ++{0x710E, 0x00}, ++{0x710F, 0x90}, ++{0x7110, 0x39}, ++{0x7111, 0x46}, ++{0x7112, 0x07}, ++{0x7113, 0x98}, ++{0x7114, 0x8F}, ++{0x7115, 0xF6}, ++{0x7116, 0xC2}, ++{0x7117, 0xFB}, ++{0x7118, 0x0D}, ++{0x7119, 0x9A}, ++{0x711A, 0xD3}, ++{0x711B, 0x17}, ++{0x711C, 0x80}, ++{0x711D, 0x18}, ++{0x711E, 0x59}, ++{0x711F, 0x41}, ++{0x7120, 0x01}, ++{0x7121, 0x22}, ++{0x7122, 0x00}, ++{0x7123, 0x23}, ++{0x7124, 0x8C}, ++{0x7125, 0xF6}, ++{0x7126, 0xCD}, ++{0x7127, 0xF9}, ++{0x7128, 0x07}, ++{0x7129, 0x90}, ++{0x712A, 0x00}, ++{0x712B, 0x20}, ++{0x712C, 0x01}, ++{0x712D, 0x90}, ++{0x712E, 0x00}, ++{0x712F, 0x95}, ++{0x7130, 0x39}, ++{0x7131, 0x46}, ++{0x7132, 0x03}, ++{0x7133, 0x98}, ++{0x7134, 0x8F}, ++{0x7135, 0xF6}, ++{0x7136, 0xB2}, ++{0x7137, 0xFB}, ++{0x7138, 0x01}, ++{0x7139, 0x22}, ++{0x713A, 0x00}, ++{0x713B, 0x23}, ++{0x713C, 0x8C}, ++{0x713D, 0xF6}, ++{0x713E, 0xE6}, ++{0x713F, 0xF9}, ++{0x7140, 0x02}, ++{0x7141, 0x46}, ++{0x7142, 0x07}, ++{0x7143, 0x98}, ++{0x7144, 0x00}, ++{0x7145, 0x23}, ++{0x7146, 0x81}, ++{0x7147, 0x0B}, ++{0x7148, 0x80}, ++{0x7149, 0x04}, ++{0x714A, 0x7A}, ++{0x714B, 0xF6}, ++{0x714C, 0x54}, ++{0x714D, 0xF8}, ++{0x714E, 0x37}, ++{0x714F, 0x4A}, ++{0x7150, 0x00}, ++{0x7151, 0x23}, ++{0x7152, 0x00}, ++{0x7153, 0x92}, ++{0x7154, 0x01}, ++{0x7155, 0x93}, ++{0x7156, 0x01}, ++{0x7157, 0x22}, ++{0x7158, 0x8C}, ++{0x7159, 0xF6}, ++{0x715A, 0xD8}, ++{0x715B, 0xF9}, ++{0x715C, 0x05}, ++{0x715D, 0x46}, ++{0x715E, 0x60}, ++{0x715F, 0x68}, ++{0x7160, 0x00}, ++{0x7161, 0x23}, ++{0x7162, 0x01}, ++{0x7163, 0x0C}, ++{0x7164, 0x00}, ++{0x7165, 0x04}, ++{0x7166, 0xE2}, ++{0x7167, 0x68}, ++{0x7168, 0x7A}, ++{0x7169, 0xF6}, ++{0x716A, 0x45}, ++{0x716B, 0xF8}, ++{0x716C, 0x00}, ++{0x716D, 0x22}, ++{0x716E, 0xD2}, ++{0x716F, 0x43}, ++{0x7170, 0x00}, ++{0x7171, 0x23}, ++{0x7172, 0x00}, ++{0x7173, 0x92}, ++{0x7174, 0x01}, ++{0x7175, 0x93}, ++{0x7176, 0x1A}, ++{0x7177, 0x46}, ++{0x7178, 0x8C}, ++{0x7179, 0xF6}, ++{0x717A, 0xC8}, ++{0x717B, 0xF9}, ++{0x717C, 0x29}, ++{0x717D, 0x46}, ++{0x717E, 0x8F}, ++{0x717F, 0xF6}, ++{0x7180, 0x8D}, ++{0x7181, 0xFB}, ++{0x7182, 0x8A}, ++{0x7183, 0x03}, ++{0x7184, 0x80}, ++{0x7185, 0x0C}, ++{0x7186, 0x10}, ++{0x7187, 0x43}, ++{0x7188, 0x00}, ++{0x7189, 0x22}, ++{0x718A, 0xD2}, ++{0x718B, 0x43}, ++{0x718C, 0x00}, ++{0x718D, 0x23}, ++{0x718E, 0x00}, ++{0x718F, 0x92}, ++{0x7190, 0x89}, ++{0x7191, 0x0C}, ++{0x7192, 0x01}, ++{0x7193, 0x93}, ++{0x7194, 0x1A}, ++{0x7195, 0x46}, ++{0x7196, 0x8C}, ++{0x7197, 0xF6}, ++{0x7198, 0xB9}, ++{0x7199, 0xF9}, ++{0x719A, 0x00}, ++{0x719B, 0x24}, ++{0x719C, 0x03}, ++{0x719D, 0x90}, ++{0x719E, 0x0C}, ++{0x719F, 0x98}, ++{0x71A0, 0x61}, ++{0x71A1, 0x00}, ++{0x71A2, 0x45}, ++{0x71A3, 0x5A}, ++{0x71A4, 0x06}, ++{0x71A5, 0x98}, ++{0x71A6, 0x22}, ++{0x71A7, 0x4A}, ++{0x71A8, 0x40}, ++{0x71A9, 0x5A}, ++{0x71AA, 0x00}, ++{0x71AB, 0x21}, ++{0x71AC, 0x8C}, ++{0x71AD, 0xF6}, ++{0x71AE, 0xBE}, ++{0x71AF, 0xF9}, ++{0x71B0, 0x07}, ++{0x71B1, 0x46}, ++{0x71B2, 0x28}, ++{0x71B3, 0x46}, ++{0x71B4, 0x03}, ++{0x71B5, 0x99}, ++{0x71B6, 0x8F}, ++{0x71B7, 0xF6}, ++{0x71B8, 0x71}, ++{0x71B9, 0xFB}, ++{0x71BA, 0x3A}, ++{0x71BB, 0x46}, ++{0x71BC, 0x00}, ++{0x71BD, 0x23}, ++{0x71BE, 0x79}, ++{0x71BF, 0xF6}, ++{0x71C0, 0xCA}, ++{0x71C1, 0xFF}, ++{0x71C2, 0x00}, ++{0x71C3, 0xE0}, ++{0x71C4, 0x0F}, ++{0x71C5, 0xE0}, ++{0x71C6, 0x8A}, ++{0x71C7, 0x02}, ++{0x71C8, 0x80}, ++{0x71C9, 0x0D}, ++{0x71CA, 0x10}, ++{0x71CB, 0x43}, ++{0x71CC, 0x19}, ++{0x71CD, 0x4A}, ++{0x71CE, 0x00}, ++{0x71CF, 0x23}, ++{0x71D0, 0x00}, ++{0x71D1, 0x92}, ++{0x71D2, 0x89}, ++{0x71D3, 0x0D}, ++{0x71D4, 0x01}, ++{0x71D5, 0x93}, ++{0x71D6, 0x40}, ++{0x71D7, 0x22}, ++{0x71D8, 0x8C}, ++{0x71D9, 0xF6}, ++{0x71DA, 0x98}, ++{0x71DB, 0xF9}, ++{0x71DC, 0xA1}, ++{0x71DD, 0x00}, ++{0x71DE, 0x64}, ++{0x71DF, 0x1C}, ++{0x71E0, 0x70}, ++{0x71E1, 0x50}, ++{0x71E2, 0x04}, ++{0x71E3, 0x2C}, ++{0x71E4, 0xDB}, ++{0x71E5, 0xD3}, ++{0x71E6, 0x14}, ++{0x71E7, 0x4D}, ++{0x71E8, 0x00}, ++{0x71E9, 0x24}, ++{0x71EA, 0x0B}, ++{0x71EB, 0x98}, ++{0x71EC, 0x67}, ++{0x71ED, 0x00}, ++{0x71EE, 0xC0}, ++{0x71EF, 0x5B}, ++{0x71F0, 0x2A}, ++{0x71F1, 0x46}, ++{0x71F2, 0x40}, ++{0x71F3, 0x21}, ++{0x71F4, 0x8C}, ++{0x71F5, 0xF6}, ++{0x71F6, 0x9A}, ++{0x71F7, 0xF9}, ++{0x71F8, 0x05}, ++{0x71F9, 0x99}, ++{0x71FA, 0x0E}, ++{0x71FB, 0x4A}, ++{0x71FC, 0xC8}, ++{0x71FD, 0x53}, ++{0x71FE, 0xA7}, ++{0x71FF, 0x00}, ++{0x7200, 0xF0}, ++{0x7201, 0x59}, ++{0x7202, 0x40}, ++{0x7203, 0x21}, ++{0x7204, 0x8C}, ++{0x7205, 0xF6}, ++{0x7206, 0x7B}, ++{0x7207, 0xF9}, ++{0x7208, 0x04}, ++{0x7209, 0x99}, ++{0x720A, 0x64}, ++{0x720B, 0x1C}, ++{0x720C, 0xC8}, ++{0x720D, 0x51}, ++{0x720E, 0x04}, ++{0x720F, 0x2C}, ++{0x7210, 0xEB}, ++{0x7211, 0xD3}, ++{0x7212, 0x0F}, ++{0x7213, 0xB0}, ++{0x7214, 0xF0}, ++{0x7215, 0xBD}, ++{0x7216, 0x00}, ++{0x7217, 0x00}, ++{0x7218, 0x76}, ++{0x7219, 0x69}, ++{0x721A, 0x18}, ++{0x721B, 0x00}, ++{0x721C, 0xEC}, ++{0x721D, 0x58}, ++{0x721E, 0x18}, ++{0x721F, 0x00}, ++{0x7220, 0x38}, ++{0x7221, 0x36}, ++{0x7222, 0x18}, ++{0x7223, 0x00}, ++{0x7224, 0x00}, ++{0x7225, 0x35}, ++{0x7226, 0x18}, ++{0x7227, 0x00}, ++{0x7228, 0x00}, ++{0x7229, 0x20}, ++{0x722A, 0x18}, ++{0x722B, 0x00}, ++{0x722C, 0xFF}, ++{0x722D, 0xFF}, ++{0x722E, 0xFF}, ++{0x722F, 0x3F}, ++{0x7230, 0xFF}, ++{0x7231, 0x07}, ++{0x7232, 0x00}, ++{0x7233, 0x00}, ++{0x7234, 0xFF}, ++{0x7235, 0xFF}, ++{0x7236, 0x07}, ++{0x7237, 0x00}, ++{0x7238, 0xFF}, ++{0x7239, 0x1F}, ++{0x723A, 0x00}, ++{0x723B, 0x00}, ++{0x723C, 0x01}, ++{0x723D, 0xF6}, ++{0x723E, 0x45}, ++{0x723F, 0x12}, ++{0x0000, 0x00}, ++}; +diff --git a/drivers/media/i2c/soc_camera/max9286.c b/drivers/media/i2c/soc_camera/max9286.c +new file mode 100644 +index 0000000..c850196 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/max9286.c +@@ -0,0 +1,692 @@ ++/* ++ * MAXIM max9286 GMSL driver ++ * ++ * Copyright (C) 2015-2018 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 REG8_NUM_RETRIES 1 /* number of read/write retries */ -+#define REG16_NUM_RETRIES 10 /* number of read/write retries */ -+#define MAX9271_ID 0x9 -+#define MAX96705_ID 0x41 -+#define MAX9286_ID 0x40 -+#define BROADCAST 0x6f ++#include ++#include ++#include ++#include ++#include ++#include + -+static inline int reg8_read(struct i2c_client *client, u8 reg, u8 *val) -+{ -+ int ret, retries; ++#include ++#include ++#include ++#include + -+ for (retries = REG8_NUM_RETRIES; retries; retries--) { -+ ret = i2c_smbus_read_byte_data(client, reg); -+ if (!(ret < 0)) -+ break; -+ } ++#include "max9286.h" + -+ if (ret < 0) { -+ dev_dbg(&client->dev, -+ "read fail: chip 0x%x register 0x%x: %d\n", -+ client->addr, reg, ret); -+ } else { -+ *val = ret; -+ } ++#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 + -+ return ret < 0 ? ret : 0; -+} ++struct max9286_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 him; ++ int hsync; ++ int vsync; ++ int timeout; ++ int poc_delay; ++ atomic_t use_count; ++ u32 csi2_outord; ++ struct i2c_client *client; ++ int max9271_addr_map[4]; ++ int ser_id; ++ struct gpio_desc *poc_gpio[4]; /* PoC power supply */ ++}; + -+static inline int reg8_write(struct i2c_client *client, u8 reg, u8 val) -+{ -+ int ret, retries; ++static char fsync_mode_default[20] = "manual"; /* manual, automatic, semi-automatic, external */ + -+ for (retries = REG8_NUM_RETRIES; retries; retries--) { -+ ret = i2c_smbus_write_byte_data(client, reg, val); -+ if (!(ret < 0)) -+ break; -+ } ++static int conf_link; ++module_param(conf_link, int, 0644); ++MODULE_PARM_DESC(conf_link, " Force configuration link. Used only if robust firmware flashing required (f.e. recovery)"); + -+ 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 -+ } ++static int poc_trig; ++module_param(poc_trig, int, 0644); ++MODULE_PARM_DESC(poc_trig, " Use PoC triggering during reverse channel setup. Useful on systems with dedicated PoC and unstable ser-des lock"); + -+ return ret < 0 ? ret : 0; -+} ++static int him; ++module_param(him, int, 0644); ++MODULE_PARM_DESC(him, " Use High-Immunity mode (default: leagacy mode)"); + -+static inline int reg16_read(struct i2c_client *client, u16 reg, u8 *val) -+{ -+ int ret, retries; -+ u8 buf[2] = {reg >> 8, reg & 0xff}; ++static int fsync_period; ++module_param(fsync_period, int, 0644); ++MODULE_PARM_DESC(fsync_period, " Frame sync period (default: 3.2MHz)"); + -+ 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; -+ } -+ } ++static int hsync; ++module_param(hsync, int, 0644); ++MODULE_PARM_DESC(hsync, " HSYNC invertion (default: 0 - not inverted)"); + -+ 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]; -+ } ++static int vsync = 1; ++module_param(vsync, int, 0644); ++MODULE_PARM_DESC(vsync, " VSYNC invertion (default: 1 - inverted)"); + -+ return ret < 0 ? ret : 0; -+} ++static int gpio_resetb; ++module_param(gpio_resetb, int, 0644); ++MODULE_PARM_DESC(gpio_resetb, " Serializer GPIO reset (default: 0 - not used)"); + -+static inline int reg16_write(struct i2c_client *client, u16 reg, u8 val) -+{ -+ int ret, retries; -+ u8 buf[3] = {reg >> 8, reg & 0xff, val}; ++static int active_low_resetb; ++module_param(active_low_resetb, int, 0644); ++MODULE_PARM_DESC(active_low_resetb, " Serializer GPIO reset level (default: 0 - active high)"); + -+ for (retries = REG16_NUM_RETRIES; retries; retries--) { -+ ret = i2c_master_send(client, buf, 3); -+ if (ret == 3) -+ break; -+ } ++static int poc_delay; ++module_param(poc_delay, int, 0644); ++MODULE_PARM_DESC(poc_delay, " Delay in ms after POC enable (default: 0 ms)"); + -+ 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 ++static char* ser_name(int id) ++{ ++ switch (id) { ++ case MAX9271_ID: ++ return "MAX9271"; ++ case MAX96705_ID: ++ return "MAX96705"; ++ default: ++ return "unknown"; + } -+ -+ return ret < 0 ? ret : 0; +} + -+ -+static inline int reg16_read16(struct i2c_client *client, u16 reg, u16 *val) ++static void max9286_preinit(struct i2c_client *client, int addr) +{ -+ int ret, retries; -+ u8 buf[2] = {reg >> 8, reg & 0xff}; ++ struct max9286_priv *priv = i2c_get_clientdata(client); + -+ for (retries = REG8_NUM_RETRIES; retries; retries--) { -+ ret = i2c_master_send(client, buf, 2); -+ if (ret == 2) { -+ ret = i2c_master_recv(client, buf, 2); -+ if (ret == 2) -+ break; -+ } -+ } ++ 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 */ ++ reg8_write(client, 0x1c, priv->him ? 0xf4 : 0x04); /* high-immunity or legacy mode */ ++} + -+ if (ret < 0) { -+ dev_err(&client->dev, -+ "read fail: chip 0x%x register 0x%x: %d\n", -+ client->addr, reg, ret); -+ } else { -+ *val = ((u16)buf[0] << 8) | buf[1]; -+ } ++static void max9286_sensor_reset(struct i2c_client *client, int addr, int reset_on) ++{ ++ struct max9286_priv *priv = i2c_get_clientdata(client); + -+ return ret < 0 ? ret : 0; ++ if (priv->gpio_resetb < 1 || priv->gpio_resetb > 5) ++ return; ++ ++ /* sensor reset/unreset */ ++ client->addr = addr; /* MAX9271-CAMx I2C */ ++ reg8_write(client, 0x0f, (0xfe & ~BIT(priv->gpio_resetb)) | /* set GPIOn value to reset/unreset */ ++ ((priv->active_low_resetb ? BIT(priv->gpio_resetb) : 0) ^ reset_on)); ++ reg8_write(client, 0x0e, 0x42 | BIT(priv->gpio_resetb)); /* set GPIOn direction output */ +} + -+static inline int reg16_write16(struct i2c_client *client, u16 reg, u16 val) ++static void max9286_postinit(struct i2c_client *client, int addr) +{ -+ int ret, retries; -+ u8 buf[4] = {reg >> 8, reg & 0xff, val >> 8, val & 0xff}; ++ struct max9286_priv *priv = i2c_get_clientdata(client); ++ int idx; + -+ for (retries = REG8_NUM_RETRIES; retries; retries--) { -+ ret = i2c_master_send(client, buf, 4); -+ if (ret == 4) -+ break; -+ } ++ for (idx = 0; idx < priv->links; idx++) { ++ client->addr = priv->des_addr; /* MAX9286 I2C */ ++ reg8_write(client, 0x0a, 0x11 << idx); /* enable reverse/forward control for CAMx */ + -+ if (ret < 0) { -+ dev_err(&client->dev, -+ "write fail: chip 0x%x register 0x%x: %d\n", -+ client->addr, reg, ret); ++ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C */ ++ max9286_sensor_reset(client, client->addr, 0); /* sensor unreset */ + } + -+ return ret < 0 ? ret : 0; -+} ++ 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 */ + ++ if (strcmp(priv->fsync_mode, "manual") == 0) { ++ 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 */ ++ } ++} + -+#ifdef MAXIM_DUMP -+static void maxim_ovsensor_dump_regs(struct i2c_client *client) ++static int max9286_reverse_channel_setup(struct i2c_client *client, int idx) +{ -+ int ret, i; ++ struct max9286_priv *priv = i2c_get_clientdata(client); + u8 val = 0; -+ u16 regs[] = {0x300a, 0x300b, 0x300c}; -+ -+ dev_dbg(&client->dev, "dump regs 0x%x\n", client->addr); ++ int timeout = priv->timeout; ++ char timeout_str[10]; ++ int ret = 0; + -+ 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); -+ } -+} ++ /* 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 */ + -+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, -+ }; ++ 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 */ + -+ dev_dbg(&client->dev, "dump regs 0x%x\n", client->addr); ++ client->addr = 0x40; /* MAX9271-CAMx I2C */ ++ reg8_write(client, 0x04, 0x43); /* wake-up, enable reverse_control/conf_link */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ ++ reg8_write(client, 0x08, 0x01); /* reverse channel receiver high threshold enable */ ++ reg8_write(client, 0x97, priv->him ? 0xaf : 0x5f); /* enable reverse control channel programming (MAX96705-MAX96711 only) */ ++ usleep_range(2000, 2500); /* wait 2ms after any change of reverse channel settings */ + -+ 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); -+ } -+} ++ 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 */ + -+static void maxim_max927x_dump_regs(struct i2c_client *client) -+{ -+ int ret; -+ u8 reg; ++ client->addr = 0x40; /* MAX9271-CAMx I2C */ ++ reg8_read(client, 0x1e, &val); /* read max9271 ID */ ++ if (val == MAX9271_ID || val == MAX96705_ID || --timeout == 0) { ++ priv->ser_id = val; ++ break; ++ } + -+ dev_dbg(&client->dev, "dump regs 0x%x\n", client->addr); ++ /* Check if already initialized (after reboot/reset ?) */ ++ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C */ ++ reg8_read(client, 0x1e, &val); /* read max9271 ID */ ++ if (val == MAX9271_ID || val == MAX96705_ID) { ++ priv->ser_id = val; ++ 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; ++ } + -+ 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"); ++ if (timeout == priv->timeout / 2 && poc_trig) { ++ if (!IS_ERR(priv->poc_gpio[idx])) { ++ gpiod_direction_output(priv->poc_gpio[idx], 0); /* POC power off */ ++ mdelay(200); ++ gpiod_direction_output(priv->poc_gpio[idx], 1); /* POC power on */ ++ mdelay(priv->poc_delay); ++ } ++ } + } -+} -+#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..8c06e59 ---- /dev/null -+++ b/drivers/media/i2c/soc_camera/ov10635.c -@@ -0,0 +1,759 @@ -+/* -+ * 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 -+#include -+#include -+#include -+#include ++ max9286_sensor_reset(client, client->addr, 1); /* sensor reset */ + -+#include -+#include -+#include -+#include ++ if (!timeout) { ++ ret = -ETIMEDOUT; ++ goto out; ++ } + -+#include "max9286.h" -+#include "ov10635.h" ++ priv->links_mask |= BIT(idx); ++ priv->csi2_outord &= ~(0x3 << (idx * 2)); ++ priv->csi2_outord |= ((hweight8(priv->links_mask) - 1) << (idx * 2)); + -+#define OV10635_I2C_ADDR 0x30 ++out: ++ sprintf(timeout_str, "retries=%d", priv->timeout - timeout); ++ dev_info(&client->dev, "link%d %s %sat 0x%x %s %s\n", idx, ser_name(priv->ser_id), ++ ret == -EADDRINUSE ? "already " : "", priv->max9271_addr_map[idx], ++ ret == -ETIMEDOUT ? "not found: timeout GMSL link establish" : "", ++ priv->timeout - timeout? timeout_str : ""); + -+#define OV10635_PID 0x300a -+#define OV10635_VER 0x300b -+#define OV10635_VERSION_REG 0xa635 -+#define OV10635_VERSION(pid, ver) (((pid) << 8) | ((ver) & 0xff)) ++ return ret; ++} + -+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) ++static void max9286_initial_setup(struct i2c_client *client) +{ -+ return container_of(i2c_get_clientdata(client), struct ov10635_priv, sd); -+} ++ struct max9286_priv *priv = i2c_get_clientdata(client); + -+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) -+{ -+ return &container_of(ctrl->handler, struct ov10635_priv, hdl)->sd; -+} ++ /* 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); ++ } + -+static void ov10635_s_port(struct i2c_client *client, int fwd_en) -+{ -+ struct ov10635_priv *priv = to_ov10635(client); -+ int tmp_addr; ++ /* Start GMSL initialization with FSYNC disabled. This is required for some odd LVDS cameras */ ++ reg8_write(client, 0x01, 0xc0); /* ECU (aka MCU) based FrameSync using GPI-to-GPO */ ++ 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); + -+ 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(5000, 5500); /* wait 5ms */ -+ client->addr = tmp_addr; -+ }; ++ reg8_write(client, 0x63, 0); /* disable overlap window */ ++ reg8_write(client, 0x64, 0); ++ reg8_write(client, 0x0c, 0x91 | (priv->vsync ? BIT(3) : 0) | (priv->hsync ? BIT(2) : 0)); /* enable HS/VS encoding, use D14/15 for HS/VS, invert HS/VS */ ++ reg8_write(client, 0x19, 0x0c); /* Drive HSTRAIL state for 120ns after the last payload bit */ +} + -+static int ov10635_set_regs(struct i2c_client *client, -+ const struct ov10635_reg *regs, int nr_regs) ++static void max9286_gmsl_link_setup(struct i2c_client *client, int idx) +{ -+ int i; ++ struct max9286_priv *priv = i2c_get_clientdata(client); + -+ 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); -+ } ++ /* 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 */ ++ ++ if (priv->ser_id == MAX96705_ID) { ++ /* setup crossbar in DBL mode: reverse DVP bus */ ++ reg8_write(client, 0x20, 0x07); ++ reg8_write(client, 0x21, 0x06); ++ reg8_write(client, 0x22, 0x05); ++ reg8_write(client, 0x23, 0x04); ++ reg8_write(client, 0x24, 0x03); ++ reg8_write(client, 0x25, 0x02); ++ reg8_write(client, 0x26, 0x01); ++ reg8_write(client, 0x27, 0x00); ++ ++ reg8_write(client, 0x30, 0x17); ++ reg8_write(client, 0x31, 0x16); ++ reg8_write(client, 0x32, 0x15); ++ reg8_write(client, 0x33, 0x14); ++ reg8_write(client, 0x34, 0x13); ++ reg8_write(client, 0x35, 0x12); ++ reg8_write(client, 0x36, 0x11); ++ reg8_write(client, 0x37, 0x10); + } + -+ return 0; -+} ++ 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 */ + -+static int ov10635_s_stream(struct v4l2_subdev *sd, int enable) -+{ -+ return 0; ++ /* I2C translator setup */ ++ client->addr = 0x40; /* MAX9271-CAMx I2C */ ++// reg8_write(client, 0x09, maxim_map[2][idx] << 1); /* SENSOR I2C translated - must be set by sensor driver */ ++// reg8_write(client, 0x0A, 0x30 << 1); /* SENSOR I2C native - must be set by sensor driver */ ++ reg8_write(client, 0x0B, BROADCAST << 1); /* broadcast I2C */ ++ reg8_write(client, 0x0C, priv->max9271_addr_map[idx] << 1); /* MAX9271-CAMx I2C new */ ++ /* I2C addresse change */ ++ reg8_write(client, 0x01, priv->des_addr << 1); /* MAX9286 I2C */ ++ reg8_write(client, 0x00, priv->max9271_addr_map[idx] << 1); /* MAX9271-CAM0 I2C new */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ /* put MAX9271 in configuration link state */ ++ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C new */ ++ reg8_write(client, 0x04, 0x43); /* enable reverse_control/conf_link */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++#ifdef MAXIM_DUMP ++ client->addr = priv->des_addr; /* MAX9286-CAMx I2C */ ++ maxim_max927x_dump_regs(client); ++ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx I2C new */ ++ maxim_max927x_dump_regs(client); ++#endif +} + -+static int ov10635_set_window(struct v4l2_subdev *sd, int subsampling) ++static int max9286_initialize(struct i2c_client *client) +{ -+ 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); ++ struct max9286_priv *priv = i2c_get_clientdata(client); ++ int idx, ret; + -+ /* 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); ++ 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"); + -+ /* 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 (priv->des_quirk_addr) ++ max9286_preinit(client, priv->des_quirk_addr); + -+#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); ++ max9286_preinit(client, priv->des_addr); ++ max9286_initial_setup(client); + -+ return 0; -+}; ++ for (idx = 0; idx < priv->links; idx++) { ++ if (!IS_ERR(priv->poc_gpio[idx])) { ++ gpiod_direction_output(priv->poc_gpio[idx], 1); /* POC power on */ ++ mdelay(priv->poc_delay); ++ } + -+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); ++ ret = max9286_reverse_channel_setup(client, idx); ++ if (ret) ++ continue; ++ max9286_gmsl_link_setup(client, idx); ++ } + -+ if (format->pad) -+ return -EINVAL; ++ max9286_postinit(client, priv->des_addr); + -+ 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; ++ client->addr = priv->des_addr; + + return 0; +} + -+static int ov10635_set_fmt(struct v4l2_subdev *sd, -+ struct v4l2_subdev_pad_config *cfg, -+ struct v4l2_subdev_format *format) ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int max9286_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) +{ -+ struct v4l2_mbus_framefmt *mf = &format->format; ++ struct max9286_priv *priv = v4l2_get_subdevdata(sd); ++ struct i2c_client *client = priv->client; ++ int ret; ++ u8 val = 0; + -+ mf->code = MEDIA_BUS_FMT_YUYV8_2X8; -+ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; -+ mf->field = V4L2_FIELD_NONE; ++ ret = reg8_read(client, (u8)reg->reg, &val); ++ if (ret < 0) ++ return ret; + -+ if (format->which == V4L2_SUBDEV_FORMAT_TRY) -+ cfg->try_fmt = *mf; ++ reg->val = val; ++ reg->size = sizeof(u8); + + 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) ++static int max9286_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) +{ -+ if (code->pad || code->index > 0) -+ return -EINVAL; -+ -+ code->code = MEDIA_BUS_FMT_YUYV8_2X8; ++ struct max9286_priv *priv = v4l2_get_subdevdata(sd); ++ struct i2c_client *client = priv->client; + -+ return 0; ++ return reg8_write(client, (u8)reg->reg, (u8)reg->val); +} ++#endif + -+static int ov10635_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++static int max9286_s_power(struct v4l2_subdev *sd, int on) +{ -+ struct i2c_client *client = v4l2_get_subdevdata(sd); -+ struct ov10635_priv *priv = to_ov10635(client); ++ struct max9286_priv *priv = v4l2_get_subdevdata(sd); ++ struct i2c_client *client = priv->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; ++ 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 ov10635_set_selection(struct v4l2_subdev *sd, -+ struct v4l2_subdev_pad_config *cfg, -+ struct v4l2_subdev_selection *sel) ++static int max9286_registered_async(struct v4l2_subdev *sd) +{ -+ 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; ++ struct max9286_priv *priv = v4l2_get_subdevdata(sd); ++ struct i2c_client *client = priv->client; ++ int idx, tmp_addr; + -+ rect->left = ALIGN(rect->left, 2); -+ rect->top = ALIGN(rect->top, 2); -+ rect->width = ALIGN(rect->width, 2); -+ rect->height = ALIGN(rect->height, 2); ++ /* switch to GMSL serial_link for streaming video */ ++ tmp_addr = client->addr; ++ idx = sd->grp_id; + -+ if ((rect->left + rect->width > OV10635_MAX_WIDTH) || -+ (rect->top + rect->height > OV10635_MAX_HEIGHT)) -+ *rect = priv->rect; ++ client->addr = priv->des_addr; /* MAX9286 I2C */ ++ reg8_write(client, 0x0a, 0x11 << idx); /* enable reverse/forward control for CAMx */ + -+ if (rect->width == OV10635_MAX_WIDTH / 2 && -+ rect->height == OV10635_MAX_HEIGHT / 2) -+ subsampling = 1; ++ client->addr = priv->max9271_addr_map[idx]; /* MAX9271-CAMx */ ++ reg8_write(client, 0x04, conf_link ? 0x43 : 0x83); /* enable serial_link */ ++ usleep_range(2000, 2500); /* wait 2ms after changing reverse_control */ + -+ priv->rect.left = rect->left; -+ priv->rect.top = rect->top; -+ priv->rect.width = rect->width; -+ priv->rect.height = rect->height; ++ 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 */ + -+ /* change window only for subsampling, crop is done by VIN */ -+ if (subsampling != priv->subsampling) { -+ ov10635_set_window(sd, subsampling); -+ priv->subsampling = subsampling; -+ } ++ client->addr = tmp_addr; + + 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; ++static struct v4l2_subdev_core_ops max9286_subdev_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = max9286_g_register, ++ .s_register = max9286_s_register, ++#endif ++ .s_power = max9286_s_power, ++ .registered_async = max9286_registered_async, ++}; + -+ 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 struct v4l2_subdev_ops max9286_subdev_ops = { ++ .core = &max9286_subdev_core_ops, ++}; + -+static int ov10635_g_mbus_config(struct v4l2_subdev *sd, -+ struct v4l2_mbus_config *cfg) ++static int max9286_parse_dt(struct i2c_client *client) +{ -+ cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | -+ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; -+ cfg->type = V4L2_MBUS_CSI2; ++ struct max9286_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; ++ u8 val = 0; ++ char poc_name[10]; + -+ return 0; -+} ++ if (of_property_read_u32(np, "maxim,links", &priv->links)) ++ priv->links = 4; + -+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 (of_property_read_u32(np, "maxim,lanes", &priv->lanes)) ++ priv->lanes = 4; + -+ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) -+ return -EINVAL; ++ 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); ++ } + -+ memset(cp, 0, sizeof(struct v4l2_captureparm)); -+ cp->capability = V4L2_CAP_TIMEPERFRAME; -+ cp->timeperframe.numerator = 1; -+ cp->timeperframe.denominator = priv->fps_denominator; ++ mdelay(250); + -+ return 0; -+} ++ for (i = 0; i < 4; i++) { ++ sprintf(poc_name, "POC%d", i); ++ priv->poc_gpio[i] = devm_gpiod_get_optional(&client->dev, poc_name, 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; ++ 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 (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) -+ return -EINVAL; -+ if (cp->extendedmode != 0) -+ return -EINVAL; ++ 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 (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; -+ } ++ 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 = 0; ++ else ++ priv->active_low_resetb = 1; ++ } + -+ priv->fps_denominator = cp->timeperframe.denominator; ++ 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; ++ if (of_property_read_u32(np, "maxim,him", &priv->him)) ++ priv->him = 0; ++ if (of_property_read_u32(np, "maxim,hsync", &priv->hsync)) ++ priv->hsync = 0; ++ if (of_property_read_u32(np, "maxim,vsync", &priv->vsync)) ++ priv->vsync = 1; ++ if (of_property_read_u32(np, "maxim,poc-delay", &priv->poc_delay)) ++ priv->poc_delay = 50; ++ ++ /* module params override dts */ ++ if (him) ++ priv->him = him; ++ if (fsync_period) { ++ priv->fsync_period = fsync_period; ++ priv->fsync_mode = fsync_mode_default; + } ++ if (hsync) ++ priv->hsync = hsync; ++ if (!vsync) ++ priv->vsync = vsync; ++ if (gpio_resetb) ++ priv->gpio_resetb = gpio_resetb; ++ if (active_low_resetb) ++ priv->active_low_resetb = active_low_resetb; ++ if (poc_delay) ++ priv->poc_delay = poc_delay; + -+out: -+ return ret; -+} ++ for (i = 0; i < priv->links; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; + -+#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; ++ of_node_put(endpoint); + -+ ret = reg16_read(client, (u16)reg->reg, &val); -+ if (ret < 0) -+ return ret; ++ if (of_property_read_u32(endpoint, "max9271-addr", &priv->max9271_addr_map[i])) { ++ dev_err(&client->dev, "max9271-addr not set\n"); ++ return -EINVAL; ++ } + -+ reg->val = val; -+ reg->size = sizeof(u16); ++ priv->sd_of_node[i] = endpoint; ++ } + + return 0; +} + -+static int ov10635_s_register(struct v4l2_subdev *sd, -+ const struct v4l2_dbg_register *reg) ++static void max9286_setup_remote_endpoint(struct i2c_client *client) +{ -+ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct max9286_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; + -+ return reg16_write(client, (u16)reg->reg, (u8)reg->val); -+} -+#endif ++ for (i = 0; ; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; + -+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 -+}; ++ of_node_put(endpoint); + -+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; ++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); ++ if (!rendpoint) ++ continue; + -+ if (!priv->init_complete) -+ return 0; ++ 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); ++ } + -+ switch (ctrl->id) { -+ case V4L2_CID_BRIGHTNESS: -+ /* AEC/AGC target */ -+ ret = reg16_write(client, 0xc46a, ctrl->val); -+ break; -+ case V4L2_CID_CONTRAST: -+ udelay(100); -+ ret = ov10635_set_regs(client, &ov10635_regs_contrast[ctrl->val][0], 18); -+ break; -+ case V4L2_CID_SATURATION: -+ ret = reg16_write(client, 0xc316, ctrl->val); -+ break; -+ case V4L2_CID_HUE: -+ /* CMX ? */ -+ ret = 0; -+ break; -+ case V4L2_CID_GAMMA: -+ ret = reg16_write(client, 0xc4be, ctrl->val >> 8); -+ ret |= reg16_write(client, 0xc4bf, ctrl->val & 0xff); -+ break; -+ case V4L2_CID_AUTOGAIN: -+ /* automatic gain/exposure */ -+ ret = reg16_write(client, 0x56d0, !ctrl->val); -+ break; -+ case V4L2_CID_GAIN: -+ /* manual gain */ -+ ret = reg16_write(client, 0x3504, 0); -+ ret |= reg16_write(client, 0x56d1, ctrl->val >> 8); -+ ret |= reg16_write(client, 0x56d2, ctrl->val & 0xff); -+ ret |= reg16_write(client, 0x3504, 1); /* validate gain */ -+ break; -+ case V4L2_CID_EXPOSURE: -+ /* manual exposure */ -+ ret = reg16_write(client, 0x3504, 0); -+ ret |= reg16_write(client, 0x56d5, ctrl->val >> 8); -+ ret |= reg16_write(client, 0x56d6, ctrl->val & 0xff); -+ ret |= reg16_write(client, 0x3504, 1); /* validate exposure */ -+ break; -+ case V4L2_CID_HFLIP: -+ ret = reg16_read(client, 0x381d, &val); -+ if (ret < 0) -+ goto out; -+ if (ctrl->val) -+ val |= 0x3; -+ else -+ val &= ~0x3; -+ ret = reg16_write(client, 0x381d, val); -+ break; -+ case V4L2_CID_VFLIP: -+ ret = reg16_read(client, 0x381c, &val); -+ if (ctrl->val) -+ val |= 0xc0; -+ else -+ val &= ~0xc0; -+ ret = reg16_write(client, 0x381c, val); -+ break; -+ case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: -+ ret = 0; -+ break; ++ dvp_order_prop = of_find_property(endpoint, "dvp-order", NULL); ++ if (dvp_order_prop) ++ of_update_property(rendpoint, dvp_order_prop); + } -+ -+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) ++static int max9286_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) +{ -+ 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 */ ++ struct max9286_priv *priv; ++ int err, i; + -+ for (i = 0; i < 6; i++) -+ reg16_read(client, 0x3d00 + i, &priv->id[i]); -+} ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; + -+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); ++ i2c_set_clientdata(client, priv); ++ priv->des_addr = client->addr; ++ priv->client = client; ++ atomic_set(&priv->use_count, 0); ++ priv->csi2_outord = 0xff; + -+ 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]); -+} ++ err = max9286_parse_dt(client); ++ if (err) ++ goto out; + -+static DEVICE_ATTR(otp_id_ov10635, S_IRUGO, ov10635_otp_id_show, NULL); ++ err = max9286_initialize(client); ++ if (err < 0) ++ goto out; + -+static int ov10635_initialize(struct i2c_client *client) -+{ -+ struct ov10635_priv *priv = to_ov10635(client); -+ u8 pid = 0, ver = 0; -+ int ret = 0; ++ max9286_setup_remote_endpoint(client); + -+ ov10635_s_port(client, 1); ++ for (i = 0; i < 4; i++) { ++ v4l2_subdev_init(&priv->sd[i], &max9286_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]; + -+ /* check and show product ID and manufacturer ID */ -+ reg16_read(client, OV10635_PID, &pid); -+ reg16_read(client, OV10635_VER, &ver); ++ 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); + -+ if (OV10635_VERSION(pid, ver) != OV10635_VERSION_REG) { -+ dev_dbg(&client->dev, "Product ID error %x:%x\n", pid, ver); -+ ret = -ENODEV; -+ goto out; ++ err = v4l2_async_register_subdev(&priv->sd[i]); ++ if (err < 0) ++ 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; ++ return err; +} + -+static int ov10635_parse_dt(struct device_node *np, struct ov10635_priv *priv) ++static int max9286_remove(struct i2c_client *client) +{ -+ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); ++ struct max9286_priv *priv = i2c_get_clientdata(client); + 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; ++ for (i = 0; i < 4; i++) { ++ v4l2_async_unregister_subdev(&priv->sd[i]); ++ v4l2_device_unregister_subdev(&priv->sd[i]); ++ } + -+ of_node_put(endpoint); ++ return 0; ++} + -+ of_property_read_u32(endpoint, "dvp-order", &priv->dvp_order); ++static const struct of_device_id max9286_dt_ids[] = { ++ { .compatible = "maxim,max9286" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, max9286_dt_ids); + -+ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); -+ if (!rendpoint) -+ continue; ++static const struct i2c_device_id max9286_id[] = { ++ { "max9286", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, max9286_id); + -+ 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; ++static struct i2c_driver max9286_i2c_driver = { ++ .driver = { ++ .name = "max9286", ++ .of_match_table = of_match_ptr(max9286_dt_ids), ++ }, ++ .probe = max9286_probe, ++ .remove = max9286_remove, ++ .id_table = max9286_id, ++}; + -+ 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; -+ } ++module_i2c_driver(max9286_i2c_driver); + -+ if (!priv->max9286_addr && !priv->ti964_addr && !priv->ti954_addr) { -+ dev_err(&client->dev, "deserializer does not present for OV10635\n"); -+ return -EINVAL; -+ } ++MODULE_DESCRIPTION("GMSL driver for MAX9286"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/i2c/soc_camera/max9286.h b/drivers/media/i2c/soc_camera/max9286.h +new file mode 100644 +index 0000000..6c2a9e0 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/max9286.h +@@ -0,0 +1,244 @@ ++/* ++ * MAXIM max9286-max9271 GMSL driver include file ++ * ++ * Copyright (C) 2015-2017 Cogent Embedded, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ */ + -+ ov10635_s_port(client, 1); ++#ifndef _MAX9286_MAX9271_H ++#define _MAX9286_MAX9271_H + -+ /* setup I2C translator address */ -+ tmp_addr = client->addr; -+ if (priv->max9286_addr) { -+ client->addr = priv->max9271_addr; /* Serializer I2C address */ ++//#define DEBUG ++#ifdef DEBUG ++//#define WRITE_VERIFY ++#define MAXIM_DUMP ++#undef dev_dbg ++#define dev_dbg dev_info ++#endif + -+ 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 */ -+ }; ++#define REG8_NUM_RETRIES 1 /* number of read/write retries */ ++#define REG16_NUM_RETRIES 10 /* number of read/write retries */ ++#define MAX9271_ID 0x9 ++#define MAX96705_ID 0x41 ++#define MAX9286_ID 0x40 ++#define BROADCAST 0x6f + -+ if (priv->ti964_addr) { -+ client->addr = priv->ti964_addr; /* Deserializer I2C address */ ++static inline int reg8_read(struct i2c_client *client, u8 reg, u8 *val) ++{ ++ int ret, retries; + -+ 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 */ ++ for (retries = REG8_NUM_RETRIES; retries; retries--) { ++ ret = i2c_smbus_read_byte_data(client, reg); ++ if (!(ret < 0)) ++ break; ++ } + -+ reg8_write(client, 0x6e, 0xa9); /* GPIO0 - resetb, GPIO1 - fsin */ ++ if (ret < 0) { ++ dev_dbg(&client->dev, ++ "read fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } else { ++ *val = ret; + } + -+ if (priv->ti954_addr) { -+ client->addr = priv->ti954_addr; /* Deserializer I2C address */ ++ return ret < 0 ? ret : 0; ++} + -+ 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 */ ++static inline int reg8_write(struct i2c_client *client, u8 reg, u8 val) ++{ ++ int ret, retries; + -+ reg8_write(client, 0x6e, 0xa9); /* GPIO0 - resetb, GPIO1 - fsin */ ++ for (retries = REG8_NUM_RETRIES; retries; retries--) { ++ ret = i2c_smbus_write_byte_data(client, reg, val); ++ if (!(ret < 0)) ++ break; + } -+ client->addr = tmp_addr; + -+ udelay(100); ++ 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 0; ++ return ret < 0 ? ret : 0; +} + -+static int ov10635_probe(struct i2c_client *client, -+ const struct i2c_device_id *did) ++static inline int reg16_read(struct i2c_client *client, u16 reg, u8 *val) +{ -+ struct ov10635_priv *priv; -+ struct v4l2_ctrl *ctrl; -+ int ret; ++ int ret, retries; ++ u8 buf[2] = {reg >> 8, reg & 0xff}; + -+ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; ++ 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; ++ } ++ } + -+ 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; ++ 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]; ++ } + -+ v4l2_ctrl_handler_init(&priv->hdl, 4); -+ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, -+ V4L2_CID_BRIGHTNESS, 0, 0xff, 1, 0x30); -+ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, -+ V4L2_CID_CONTRAST, 0, 4, 1, 2); -+ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, -+ V4L2_CID_SATURATION, 0, 0xff, 1, 0xff); -+ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, -+ V4L2_CID_HUE, 0, 255, 1, 0); -+ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, -+ V4L2_CID_GAMMA, 0, 0xffff, 1, 0x233); -+ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, -+ V4L2_CID_AUTOGAIN, 0, 1, 1, 1); -+ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, -+ V4L2_CID_GAIN, 0, 0x3ff, 1, 0x10); -+ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, -+ V4L2_CID_EXPOSURE, 0, 0xffff, 1, 0x80); -+ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, -+ V4L2_CID_HFLIP, 0, 1, 1, 0); -+ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, -+ V4L2_CID_VFLIP, 0, 1, 1, 0); -+ ctrl = v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, -+ V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 9); -+ if (ctrl) -+ ctrl->flags &= ~V4L2_CTRL_FLAG_READ_ONLY; -+ priv->sd.ctrl_handler = &priv->hdl; ++ return ret < 0 ? ret : 0; ++} + -+ ret = priv->hdl.error; -+ if (ret) -+ goto cleanup; ++static inline int reg16_write(struct i2c_client *client, u16 reg, u8 val) ++{ ++ int ret, retries; ++ u8 buf[3] = {reg >> 8, reg & 0xff, val}; + -+ v4l2_ctrl_handler_setup(&priv->hdl); ++ for (retries = REG16_NUM_RETRIES; retries; retries--) { ++ ret = i2c_master_send(client, buf, 3); ++ if (ret == 3) ++ break; ++ } + -+ 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; ++ 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 ++ } + -+ ret = ov10635_parse_dt(client->dev.of_node, priv); -+ if (ret) -+ goto cleanup; ++ return ret < 0 ? ret : 0; ++} + -+ ret = ov10635_initialize(client); -+ if (ret < 0) -+ goto cleanup; + -+ ret = v4l2_async_register_subdev(&priv->sd); -+ if (ret) -+ goto cleanup; ++static inline int reg16_read16(struct i2c_client *client, u16 reg, u16 *val) ++{ ++ int ret, retries; ++ u8 buf[2] = {reg >> 8, reg & 0xff}; + -+ 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; ++ for (retries = REG8_NUM_RETRIES; retries; retries--) { ++ ret = i2c_master_send(client, buf, 2); ++ if (ret == 2) { ++ ret = i2c_master_recv(client, buf, 2); ++ if (ret == 2) ++ break; ++ } + } + -+ priv->init_complete = 1; -+ -+ return 0; ++ if (ret < 0) { ++ dev_err(&client->dev, ++ "read fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } else { ++ *val = ((u16)buf[0] << 8) | buf[1]; ++ } + -+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; ++ return ret < 0 ? ret : 0; +} + -+static int ov10635_remove(struct i2c_client *client) ++static inline int reg16_write16(struct i2c_client *client, u16 reg, u16 val) +{ -+ struct ov10635_priv *priv = i2c_get_clientdata(client); ++ int ret, retries; ++ u8 buf[4] = {reg >> 8, reg & 0xff, val >> 8, val & 0xff}; + -+ 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); ++ for (retries = REG8_NUM_RETRIES; retries; retries--) { ++ ret = i2c_master_send(client, buf, 4); ++ if (ret == 4) ++ break; ++ } + -+ return 0; ++ if (ret < 0) { ++ dev_err(&client->dev, ++ "write fail: chip 0x%x register 0x%x: %d\n", ++ client->addr, reg, ret); ++ } ++ ++ return ret < 0 ? ret : 0; +} + -+#ifdef 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); ++#ifdef MAXIM_DUMP ++static void maxim_ovsensor_dump_regs(struct i2c_client *client) ++{ ++ int ret, i; ++ u8 val = 0; ++ u16 regs[] = {0x300a, 0x300b, 0x300c}; + -+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, -+}; ++ dev_dbg(&client->dev, "dump regs 0x%x\n", client->addr); + -+module_i2c_driver(ov10635_i2c_driver); ++ 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); ++ } ++} + -+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 ++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..a0e510d +index 0000000..8c06e59 --- /dev/null -+++ b/drivers/media/i2c/soc_camera/ov10635.h -@@ -0,0 +1,1139 @@ ++++ b/drivers/media/i2c/soc_camera/ov10635.c +@@ -0,0 +1,759 @@ +/* -+ * OmniVision ov10635 sensor camera wizard 1280x800@30/UYVY/BT601/8bit ++ * OmniVision ov10635 sensor camera driver + * + * Copyright (C) 2015-2017 Cogent Embedded, Inc. + * @@ -3837,35 +7451,800 @@ index 0000000..a0e510d + * option) any later version. + */ + -+//#define OV10635_DISPLAY_PATTERN ++#include ++#include ++#include ++#include ++#include + -+#define OV10635_SENSOR_WIDTH 1312 -+#define OV10635_SENSOR_HEIGHT 814 ++#include ++#include ++#include ++#include + -+#define OV10635_MAX_WIDTH 1280 -+#define OV10635_MAX_HEIGHT 800 ++#include "max9286.h" ++#include "ov10635.h" + -+//#define OV10635_PCLK_96MHZ -+#define OV10635_PCLK_88MHZ ++#define OV10635_I2C_ADDR 0x30 + -+#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 ++#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 */ ++ usleep_range(5000, 5500); /* wait 5ms */ ++ 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); + -+struct ov10635_reg { -+ u16 reg; -+ u8 val; ++ return 0; +}; + -+static const struct ov10635_reg ov10635_regs_wizard[] = { ++static int ov10635_get_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10635_priv *priv = to_ov10635(client); ++ ++ if (format->pad) ++ return -EINVAL; ++ ++ mf->width = priv->rect.width; ++ mf->height = priv->rect.height; ++ mf->code = MEDIA_BUS_FMT_YUYV8_2X8; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static int ov10635_set_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ ++ mf->code = MEDIA_BUS_FMT_YUYV8_2X8; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ if (format->which == V4L2_SUBDEV_FORMAT_TRY) ++ cfg->try_fmt = *mf; ++ ++ return 0; ++} ++ ++static int ov10635_enum_mbus_code(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ if (code->pad || code->index > 0) ++ return -EINVAL; ++ ++ code->code = MEDIA_BUS_FMT_YUYV8_2X8; ++ ++ return 0; ++} ++ ++static int ov10635_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10635_priv *priv = to_ov10635(client); ++ ++ memcpy(edid->edid, priv->id, 6); ++ ++ edid->edid[6] = 0xff; ++ edid->edid[7] = client->addr; ++ edid->edid[8] = OV10635_VERSION_REG >> 8; ++ edid->edid[9] = OV10635_VERSION_REG & 0xff; ++ ++ return 0; ++} ++ ++static int ov10635_set_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct v4l2_rect *rect = &sel->r; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10635_priv *priv = to_ov10635(client); ++ int subsampling = 0; ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || ++ sel->target != V4L2_SEL_TGT_CROP) ++ return -EINVAL; ++ ++ rect->left = ALIGN(rect->left, 2); ++ rect->top = ALIGN(rect->top, 2); ++ rect->width = ALIGN(rect->width, 2); ++ rect->height = ALIGN(rect->height, 2); ++ ++ if ((rect->left + rect->width > OV10635_MAX_WIDTH) || ++ (rect->top + rect->height > OV10635_MAX_HEIGHT)) ++ *rect = priv->rect; ++ ++ if (rect->width == OV10635_MAX_WIDTH / 2 && ++ rect->height == OV10635_MAX_HEIGHT / 2) ++ subsampling = 1; ++ ++ priv->rect.left = rect->left; ++ priv->rect.top = rect->top; ++ priv->rect.width = rect->width; ++ priv->rect.height = rect->height; ++ ++ /* change window only for subsampling, crop is done by VIN */ ++ if (subsampling != priv->subsampling) { ++ ov10635_set_window(sd, subsampling); ++ priv->subsampling = subsampling; ++ } ++ ++ return 0; ++} ++ ++static int ov10635_get_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10635_priv *priv = to_ov10635(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) ++ return -EINVAL; ++ ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = OV10635_MAX_WIDTH; ++ sel->r.height = OV10635_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = OV10635_MAX_WIDTH; ++ sel->r.height = OV10635_MAX_HEIGHT; ++ return 0; ++ case V4L2_SEL_TGT_CROP: ++ sel->r = priv->rect; ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int ov10635_g_mbus_config(struct v4l2_subdev *sd, ++ struct v4l2_mbus_config *cfg) ++{ ++ cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | ++ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; ++ cfg->type = V4L2_MBUS_CSI2; ++ ++ return 0; ++} ++ ++static int ov10635_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10635_priv *priv = to_ov10635(client); ++ struct v4l2_captureparm *cp = &parms->parm.capture; ++ ++ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ ++ memset(cp, 0, sizeof(struct v4l2_captureparm)); ++ cp->capability = V4L2_CAP_TIMEPERFRAME; ++ cp->timeperframe.numerator = 1; ++ cp->timeperframe.denominator = priv->fps_denominator; ++ ++ return 0; ++} ++ ++static int ov10635_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10635_priv *priv = to_ov10635(client); ++ struct v4l2_captureparm *cp = &parms->parm.capture; ++ int ret = 0; ++ ++ if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ if (cp->extendedmode != 0) ++ return -EINVAL; ++ ++ if (priv->fps_denominator != cp->timeperframe.denominator) { ++ switch (cp->timeperframe.denominator) { ++ case 5: ++ ret = ov10635_set_regs(client, ov10635_regs_5fps, ++ ARRAY_SIZE(ov10635_regs_5fps)); ++ break; ++ case 10: ++ ret = ov10635_set_regs(client, ov10635_regs_10fps, ++ ARRAY_SIZE(ov10635_regs_10fps)); ++ break; ++ case 15: ++ ret = ov10635_set_regs(client, ov10635_regs_15fps, ++ ARRAY_SIZE(ov10635_regs_15fps)); ++ break; ++ case 30: ++ ret = ov10635_set_regs(client, ov10635_regs_30fps, ++ ARRAY_SIZE(ov10635_regs_30fps)); ++ break; ++ default: ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ priv->fps_denominator = cp->timeperframe.denominator; ++ } ++ ++out: ++ return ret; ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int ov10635_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ int ret; ++ u8 val = 0; ++ ++ ret = reg16_read(client, (u16)reg->reg, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u16); ++ ++ return 0; ++} ++ ++static int ov10635_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ ++ return reg16_write(client, (u16)reg->reg, (u8)reg->val); ++} ++#endif ++ ++static struct v4l2_subdev_core_ops ov10635_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = ov10635_g_register, ++ .s_register = ov10635_s_register, ++#endif ++}; ++ ++static int ov10635_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct v4l2_subdev *sd = to_sd(ctrl); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10635_priv *priv = to_ov10635(client); ++ int ret = -EINVAL; ++ u8 val = 0; ++ ++ if (!priv->init_complete) ++ return 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_BRIGHTNESS: ++ /* AEC/AGC target */ ++ ret = reg16_write(client, 0xc46a, ctrl->val); ++ break; ++ case V4L2_CID_CONTRAST: ++ udelay(100); ++ ret = ov10635_set_regs(client, &ov10635_regs_contrast[ctrl->val][0], 18); ++ break; ++ case V4L2_CID_SATURATION: ++ ret = reg16_write(client, 0xc316, ctrl->val); ++ break; ++ case V4L2_CID_HUE: ++ /* CMX ? */ ++ ret = 0; ++ break; ++ case V4L2_CID_GAMMA: ++ ret = reg16_write(client, 0xc4be, ctrl->val >> 8); ++ ret |= reg16_write(client, 0xc4bf, ctrl->val & 0xff); ++ break; ++ case V4L2_CID_AUTOGAIN: ++ /* automatic gain/exposure */ ++ ret = reg16_write(client, 0x56d0, !ctrl->val); ++ break; ++ case V4L2_CID_GAIN: ++ /* manual gain */ ++ ret = reg16_write(client, 0x3504, 0); ++ ret |= reg16_write(client, 0x56d1, ctrl->val >> 8); ++ ret |= reg16_write(client, 0x56d2, ctrl->val & 0xff); ++ ret |= reg16_write(client, 0x3504, 1); /* validate gain */ ++ break; ++ case V4L2_CID_EXPOSURE: ++ /* manual exposure */ ++ ret = reg16_write(client, 0x3504, 0); ++ ret |= reg16_write(client, 0x56d5, ctrl->val >> 8); ++ ret |= reg16_write(client, 0x56d6, ctrl->val & 0xff); ++ ret |= reg16_write(client, 0x3504, 1); /* validate exposure */ ++ break; ++ case V4L2_CID_HFLIP: ++ ret = reg16_read(client, 0x381d, &val); ++ if (ret < 0) ++ goto out; ++ if (ctrl->val) ++ val |= 0x3; ++ else ++ val &= ~0x3; ++ ret = reg16_write(client, 0x381d, val); ++ break; ++ case V4L2_CID_VFLIP: ++ ret = reg16_read(client, 0x381c, &val); ++ if (ctrl->val) ++ val |= 0xc0; ++ else ++ val &= ~0xc0; ++ ret = reg16_write(client, 0x381c, val); ++ break; ++ case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: ++ ret = 0; ++ break; ++ } ++ ++out: ++ return ret; ++} ++ ++static const struct v4l2_ctrl_ops ov10635_ctrl_ops = { ++ .s_ctrl = ov10635_s_ctrl, ++}; ++ ++static struct v4l2_subdev_video_ops ov10635_video_ops = { ++ .s_stream = ov10635_s_stream, ++ .g_mbus_config = ov10635_g_mbus_config, ++ .g_parm = ov10635_g_parm, ++ .s_parm = ov10635_s_parm, ++}; ++ ++static const struct v4l2_subdev_pad_ops ov10635_subdev_pad_ops = { ++ .get_edid = ov10635_get_edid, ++ .enum_mbus_code = ov10635_enum_mbus_code, ++ .get_selection = ov10635_get_selection, ++ .set_selection = ov10635_set_selection, ++ .get_fmt = ov10635_get_fmt, ++ .set_fmt = ov10635_set_fmt, ++}; ++ ++static struct v4l2_subdev_ops ov10635_subdev_ops = { ++ .core = &ov10635_core_ops, ++ .video = &ov10635_video_ops, ++ .pad = &ov10635_subdev_pad_ops, ++}; ++ ++static void ov10635_otp_id_read(struct i2c_client *client) ++{ ++ struct ov10635_priv *priv = to_ov10635(client); ++ int i; ++ ++ /* read camera id from OTP memory */ ++ reg16_write(client, 0x3d10, 1); ++ ++ usleep_range(15000, 16000); /* wait 15ms */ ++ ++ for (i = 0; i < 6; i++) ++ reg16_read(client, 0x3d00 + i, &priv->id[i]); ++} ++ ++static ssize_t ov10635_otp_id_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(to_i2c_client(dev)); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov10635_priv *priv = to_ov10635(client); ++ ++ return snprintf(buf, 32, "%02x:%02x:%02x:%02x:%02x:%02x\n", ++ priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++} ++ ++static DEVICE_ATTR(otp_id_ov10635, S_IRUGO, ov10635_otp_id_show, NULL); ++ ++static int ov10635_initialize(struct i2c_client *client) ++{ ++ struct ov10635_priv *priv = to_ov10635(client); ++ u8 pid = 0, ver = 0; ++ int ret = 0; ++ ++ ov10635_s_port(client, 1); ++ ++ /* check and show product ID and manufacturer ID */ ++ reg16_read(client, OV10635_PID, &pid); ++ reg16_read(client, OV10635_VER, &ver); ++ ++ if (OV10635_VERSION(pid, ver) != OV10635_VERSION_REG) { ++ dev_dbg(&client->dev, "Product ID error %x:%x\n", pid, ver); ++ ret = -ENODEV; ++ goto out; ++ } ++ ++ /* s/w reset sensor */ ++ reg16_write(client, 0x103, 0x1); ++ udelay(100); ++ /* Program wizard registers */ ++ ov10635_set_regs(client, ov10635_regs_wizard, ARRAY_SIZE(ov10635_regs_wizard)); ++ /* Set DVP bit swap */ ++ reg16_write(client, 0x4709, priv->dvp_order << 4); ++ /* Read OTP IDs */ ++ ov10635_otp_id_read(client); ++ ++ dev_info(&client->dev, "ov10635 Product ID %x Manufacturer ID %x OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, ver, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++out: ++ ov10635_s_port(client, 0); ++ ++ return ret; ++} ++ ++static int ov10635_parse_dt(struct device_node *np, struct ov10635_priv *priv) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); ++ int i; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ int tmp_addr = 0; ++ ++ for (i = 0; ; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; ++ ++ of_node_put(endpoint); ++ ++ of_property_read_u32(endpoint, "dvp-order", &priv->dvp_order); ++ ++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); ++ if (!rendpoint) ++ continue; ++ ++ if (!of_property_read_u32(rendpoint, "max9271-addr", &priv->max9271_addr) && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->max9286_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ ++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti964-ti9x3") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti964_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ ++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti954-ti9x3") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti954_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ } ++ ++ if (!priv->max9286_addr && !priv->ti964_addr && !priv->ti954_addr) { ++ dev_err(&client->dev, "deserializer does not present for OV10635\n"); ++ return -EINVAL; ++ } ++ ++ ov10635_s_port(client, 1); ++ ++ /* setup I2C translator address */ ++ tmp_addr = client->addr; ++ if (priv->max9286_addr) { ++ client->addr = priv->max9271_addr; /* Serializer I2C address */ ++ ++ reg8_write(client, 0x09, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x0A, OV10635_I2C_ADDR << 1); /* Sensor native I2C address */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ }; ++ ++ if (priv->ti964_addr) { ++ client->addr = priv->ti964_addr; /* Deserializer I2C address */ ++ ++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x5d, OV10635_I2C_ADDR << 1); /* Sensor native I2C address */ ++ ++ reg8_write(client, 0x6e, 0xa9); /* GPIO0 - resetb, GPIO1 - fsin */ ++ } ++ ++ if (priv->ti954_addr) { ++ client->addr = priv->ti954_addr; /* Deserializer I2C address */ ++ ++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x5d, OV10635_I2C_ADDR << 1); /* Sensor native I2C address */ ++ ++ reg8_write(client, 0x6e, 0xa9); /* GPIO0 - resetb, GPIO1 - fsin */ ++ } ++ client->addr = tmp_addr; ++ ++ udelay(100); ++ ++ return 0; ++} ++ ++static int ov10635_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct ov10635_priv *priv; ++ struct v4l2_ctrl *ctrl; ++ int ret; ++ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ v4l2_i2c_subdev_init(&priv->sd, client, &ov10635_subdev_ops); ++ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; ++ priv->rect.left = 0; ++ priv->rect.top = 0; ++ priv->rect.width = OV10635_MAX_WIDTH; ++ priv->rect.height = OV10635_MAX_HEIGHT; ++ priv->fps_denominator = 30; ++ ++ v4l2_ctrl_handler_init(&priv->hdl, 4); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_BRIGHTNESS, 0, 0xff, 1, 0x30); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_CONTRAST, 0, 4, 1, 2); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_SATURATION, 0, 0xff, 1, 0xff); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_HUE, 0, 255, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_GAMMA, 0, 0xffff, 1, 0x233); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_AUTOGAIN, 0, 1, 1, 1); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_GAIN, 0, 0x3ff, 1, 0x10); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_EXPOSURE, 0, 0xffff, 1, 0x80); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ ctrl = v4l2_ctrl_new_std(&priv->hdl, &ov10635_ctrl_ops, ++ V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 9); ++ if (ctrl) ++ ctrl->flags &= ~V4L2_CTRL_FLAG_READ_ONLY; ++ priv->sd.ctrl_handler = &priv->hdl; ++ ++ ret = priv->hdl.error; ++ if (ret) ++ goto cleanup; ++ ++ v4l2_ctrl_handler_setup(&priv->hdl); ++ ++ priv->pad.flags = MEDIA_PAD_FL_SOURCE; ++ priv->sd.entity.flags |= MEDIA_ENT_F_CAM_SENSOR; ++ ret = media_entity_pads_init(&priv->sd.entity, 1, &priv->pad); ++ if (ret < 0) ++ goto cleanup; ++ ++ ret = ov10635_parse_dt(client->dev.of_node, priv); ++ if (ret) ++ goto cleanup; ++ ++ ret = ov10635_initialize(client); ++ if (ret < 0) ++ goto cleanup; ++ ++ ret = v4l2_async_register_subdev(&priv->sd); ++ if (ret) ++ goto cleanup; ++ ++ if (device_create_file(&client->dev, &dev_attr_otp_id_ov10635) != 0) { ++ dev_err(&client->dev, "sysfs otp_id entry creation failed\n"); ++ goto cleanup; ++ } ++ ++ priv->init_complete = 1; ++ ++ return 0; ++ ++cleanup: ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++#ifdef CONFIG_SOC_CAMERA_OV10635 ++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", ++ client->addr, client->adapter->name); ++#endif ++ return ret; ++} ++ ++static int ov10635_remove(struct i2c_client *client) ++{ ++ struct ov10635_priv *priv = i2c_get_clientdata(client); ++ ++ device_remove_file(&client->dev, &dev_attr_otp_id_ov10635); ++ v4l2_async_unregister_subdev(&priv->sd); ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_SOC_CAMERA_OV10635 ++static const struct i2c_device_id ov10635_id[] = { ++ { "ov10635", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, ov10635_id); ++ ++static const struct of_device_id ov10635_of_ids[] = { ++ { .compatible = "ovti,ov10635", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ov10635_of_ids); ++ ++static struct i2c_driver ov10635_i2c_driver = { ++ .driver = { ++ .name = "ov10635", ++ .of_match_table = ov10635_of_ids, ++ }, ++ .probe = ov10635_probe, ++ .remove = ov10635_remove, ++ .id_table = ov10635_id, ++}; ++ ++module_i2c_driver(ov10635_i2c_driver); ++ ++MODULE_DESCRIPTION("SoC Camera driver for OV10635"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); ++#endif +diff --git a/drivers/media/i2c/soc_camera/ov10635.h b/drivers/media/i2c/soc_camera/ov10635.h +new file mode 100644 +index 0000000..a0e510d +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov10635.h +@@ -0,0 +1,1139 @@ ++/* ++ * OmniVision ov10635 sensor camera wizard 1280x800@30/UYVY/BT601/8bit ++ * ++ * Copyright (C) 2015-2017 Cogent Embedded, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ */ ++ ++//#define OV10635_DISPLAY_PATTERN ++ ++#define OV10635_SENSOR_WIDTH 1312 ++#define OV10635_SENSOR_HEIGHT 814 ++ ++#define OV10635_MAX_WIDTH 1280 ++#define OV10635_MAX_HEIGHT 800 ++ ++//#define OV10635_PCLK_96MHZ ++#define OV10635_PCLK_88MHZ ++ ++#if defined(OV10635_PCLK_96MHZ) ++/* VTS=PCLK/FPS/HTS/2 (=96MHz/30/1600/2) */ ++ #define OV10635_HTS 1600 ++ #define OV10635_VTS 1000 /* fps=30 */ ++#elif defined(OV10635_PCLK_88MHZ) ++/* VTS=PCLK/FPS/HTS/2 (=88MHz/1572/30/2) */ ++ #define OV10635_HTS 1572 ++ #define OV10635_VTS 933 /* fps=29.9998 */ ++#else ++ #error PCLK not defined ++#endif ++ ++struct ov10635_reg { ++ u16 reg; ++ u8 val; ++}; ++ ++static const struct ov10635_reg ov10635_regs_wizard[] = { +//{0x0103, 0x01}, +{0x300C, 0x61}, +{0x300C, 0x61}, @@ -5027,10 +9406,10 @@ index 0000000..4c3515a +#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..fa775ae +index 0000000..08786ab --- /dev/null +++ b/drivers/media/i2c/soc_camera/ov106xx.c -@@ -0,0 +1,139 @@ +@@ -0,0 +1,161 @@ +/* + * OmniVision ov10635/ov490-ov10640/ov495-ov2775 sensor camera driver + * @@ -5049,6 +9428,8 @@ index 0000000..fa775ae +#include "ar0220.c" +#include "ap0101_ar014x.c" +#include "ov2775.c" ++#include "imx390.c" ++#include "ox03a.c" + +static enum { + ID_OV10635, @@ -5058,6 +9439,8 @@ index 0000000..fa775ae + ID_AR0220, + ID_AP0101_AR014X, + ID_OV2775, ++ ID_IMX390, ++ ID_OX03A, +} chip_id; + +static int ov106xx_probe(struct i2c_client *client, @@ -5108,6 +9491,18 @@ index 0000000..fa775ae + goto out; + } + ++ ret = imx390_probe(client, did); ++ if (!ret) { ++ chip_id = ID_IMX390; ++ goto out; ++ } ++ ++ ret = ox03a_probe(client, did); ++ if (!ret) { ++ chip_id = ID_OX03A; ++ goto out; ++ } ++ + v4l_err(client, "failed to probe @ 0x%02x (%s)\n", + client->addr, client->adapter->name); +out: @@ -5138,6 +9533,12 @@ index 0000000..fa775ae + case ID_OV2775: + ov2775_remove(client); + break; ++ case ID_IMX390: ++ imx390_remove(client); ++ break; ++ case ID_OX03A: ++ ox03a_remove(client); ++ break; + }; + + return 0; @@ -5172,10 +9573,10 @@ index 0000000..fa775ae +MODULE_LICENSE("GPL"); diff --git a/drivers/media/i2c/soc_camera/ov2775.c b/drivers/media/i2c/soc_camera/ov2775.c new file mode 100644 -index 0000000..dac6d60 +index 0000000..f57fc71 --- /dev/null +++ b/drivers/media/i2c/soc_camera/ov2775.c -@@ -0,0 +1,527 @@ +@@ -0,0 +1,538 @@ +/* + * OmniVision OV2775 sensor camera driver + * @@ -5206,7 +9607,7 @@ index 0000000..dac6d60 +#define OV2775_VER 0x300b +#define OV2775_VERSION_REG 0x2770 + -+#define OV2775_MEDIA_BUS_FMT MEDIA_BUS_FMT_SBGGR8_1X8 ++#define OV2775_MEDIA_BUS_FMT MEDIA_BUS_FMT_SBGGR12_1X12 + +struct ov2775_priv { + struct v4l2_subdev sd; @@ -5496,6 +9897,7 @@ index 0000000..dac6d60 + u8 val = 0; + u16 pid; + int ret = 0; ++ int tmp_addr; + + /* check and show model ID */ + reg16_read(client, OV2775_PID, &val); @@ -5509,6 +9911,16 @@ index 0000000..dac6d60 + goto err; + } + ++ /* setup XCLK */ ++ tmp_addr = client->addr; ++ if (priv->ti9x4_addr) { ++ /* CLK_OUT=22.5792*160*M/N/CLKDIV -> CLK_OUT=25MHz: CLKDIV=4, M=7, N=253: 22.5792*160/4*7/253=24.989MHz=CLK_OUT */ ++ client->addr = priv->ti9x3_addr; /* Serializer I2C address */ ++ reg8_write(client, 0x06, 0x47); /* Set CLKDIV and M */ ++ reg8_write(client, 0x07, 0xfd); /* Set N */ ++ } ++ client->addr = tmp_addr; ++ + /* Program wizard registers */ + ov2775_set_regs(client, ov2775_regs_wizard, ARRAY_SIZE(ov2775_regs_wizard)); + /* Read OTP IDs */ @@ -5705,12 +10117,12 @@ index 0000000..dac6d60 +#endif diff --git a/drivers/media/i2c/soc_camera/ov2775.h b/drivers/media/i2c/soc_camera/ov2775.h new file mode 100644 -index 0000000..1cdfb50 +index 0000000..7e1ee31 --- /dev/null +++ b/drivers/media/i2c/soc_camera/ov2775.h @@ -0,0 +1,1841 @@ +/* -+ * OmniVision OV2775 sensor camera wizard 1928x1088@30/RGGB/MIPI ++ * OmniVision OV2775 sensor camera wizard 1920x1080@30/BGGR/MIPI + * + * Copyright (C) 2018 Cogent Embedded, Inc. + * @@ -5720,29 +10132,29 @@ index 0000000..1cdfb50 + * option) any later version. + */ + -+//#define OV2775_DISPLAY_PATTERN_COLOR_BAR ++#define OV2775_DISPLAY_PATTERN_COLOR_BAR + -+#define OV2775_MAX_WIDTH 2880 // (1928*1.5=2892) <- must be multiple of 16 - requred by R-CAR VIN -+#define OV2775_MAX_HEIGHT 1088 ++#define OV2775_MAX_WIDTH 1920 ++#define OV2775_MAX_HEIGHT 1080 + +#define OV2775_DELAY 0xffff -+#define OV2775_DT 0x2c // MIPI Data Type ++#define OV2775_DT 0x2c /* MIPI Data Type RAW12 */ + +struct ov2775_reg { + u16 reg; + u8 val; +}; + -+/* wizard: MIPI 1928x1088 RAW12 Linear 30fps 960Mbps */ ++/* wizard: MIPI 1920x1080 RAW12 Linear 30fps 600Mbps XCLK=25MHz */ +static const struct ov2775_reg ov2775_regs_wizard[] = { +{0x3013, 0x01}, // s/w reset +{OV2775_DELAY, 10}, // Wait 10ms -+{0x3000, 0x02}, -+{0x3001, 0x28}, -+{0x3002, 0x03}, ++{0x3000, 0x03}, ++{0x3001, 0x18}, ++{0x3002, 0x01}, +{0x3003, 0x01}, -+{0x3004, 0x02}, -+{0x3005, 0x26}, ++{0x3004, 0x03}, ++{0x3005, 0x1c}, +{0x3006, 0x00}, +{0x3007, 0x07}, +{0x3008, 0x01}, @@ -5752,7 +10164,7 @@ index 0000000..1cdfb50 +{0x300f, 0x00}, +{0x3012, 0x00}, +{0x3013, 0x00}, -+{0x3014, 0xc4}, ++{0x3014, 0x44}, +{0x3015, 0x00}, +{0x3017, 0x00}, +{0x3018, 0x00}, @@ -6039,7 +10451,7 @@ index 0000000..1cdfb50 +{0x320d, 0x1e}, +{0x320e, 0x30}, +{0x320f, 0x2d}, -+{0x3210, OV2775_DT}, ++{0x3210, 0x2c}, +{0x3211, 0x2b}, +{0x3212, 0x2a}, +{0x3213, 0x24}, @@ -6069,7 +10481,7 @@ index 0000000..1cdfb50 +{0x3251, 0x00}, +{0x3252, 0x20}, +#ifdef OV2775_DISPLAY_PATTERN_COLOR_BAR -+{0x3253, 0x80}, ++{0x3253, 0xC0}, +#else +{0x3253, 0x00}, +#endif @@ -7533,9 +11945,9 @@ index 0000000..1cdfb50 +{0x30a9, 0x04}, +{0x30aa, 0x00}, +{0x30ab, 0x04}, -+{0x30ac, 0x07}, ++{0x30ac, 0x07}, /* OV2775_MAX_WIDTH */ +{0x30ad, 0x88}, -+{0x30ae, 0x04}, ++{0x30ae, 0x04}, /* OV2775_MAX_HEIGHT */ +{0x30af, 0x40}, +{0x30b0, 0x0d}, +{0x30b1, 0xde}, @@ -7550,16 +11962,1263 @@ index 0000000..1cdfb50 +{0x3250, 0xf7}, +{0x3012, 0x01}, +}; -diff --git a/drivers/media/i2c/soc_camera/ov490_ov10640.c b/drivers/media/i2c/soc_camera/ov490_ov10640.c +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..812f367 +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov490_ov10640.c +@@ -0,0 +1,1133 @@ ++/* ++ * OmniVision ov490-ov10640 sensor camera driver ++ * ++ * Copyright (C) 2016-2018 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 ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "max9286.h" ++#include "ov490_ov10640.h" ++ ++#define OV490_I2C_ADDR 0x24 ++ ++#define OV490_PID 0x300a ++#define OV490_VER 0x300b ++#define OV490_VERSION_REG 0x0490 ++#define OV490_VERSION(pid, ver) (((pid) << 8) | ((ver) & 0xff)) ++ ++#define OV490_ISP_HSIZE_LOW 0x60 ++#define OV490_ISP_HSIZE_HIGH 0x61 ++#define OV490_ISP_VSIZE_LOW 0x62 ++#define OV490_ISP_VSIZE_HIGH 0x63 ++ ++struct ov490_priv { ++ struct v4l2_subdev sd; ++ struct v4l2_ctrl_handler hdl; ++ struct media_pad pad; ++ struct v4l2_rect rect; ++ int max_width; ++ int max_height; ++ char is_fixed_sensor; ++ int init_complete; ++ u8 id[6]; ++ int exposure; ++ int gain; ++ int autogain; ++ int red; ++ int green_r; ++ int green_b; ++ int blue; ++ int awb; ++ int dvp_order; ++ /* serializers */ ++ int max9286_addr; ++ int max9271_addr; ++ int ti9x4_addr; ++ int ti9x3_addr; ++ int port; ++ int gpio_resetb; ++ int active_low_resetb; ++ int gpio_fsin; ++}; ++ ++static int conf_link; ++module_param(conf_link, int, 0644); ++MODULE_PARM_DESC(conf_link, " Force configuration link. Used only if robust firmware flashing required (f.e. recovery)"); ++ ++static int dvp_order; ++module_param(dvp_order, int, 0644); ++MODULE_PARM_DESC(dvp_order, " DVP bus bits order"); ++ ++static int max_width; ++module_param(max_width, int, 0644); ++MODULE_PARM_DESC(max_width, " Fixed sensor width"); ++ ++static int max_height; ++module_param(max_height, int, 0644); ++MODULE_PARM_DESC(max_height, " Fixed sensor height"); ++ ++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(5000, 5500); /* wait 5ms */ ++ client->addr = tmp_addr; ++ }; ++} ++ ++static void ov490_reset(struct i2c_client *client) ++{ ++ struct ov490_priv *priv = to_ov490(client); ++ int tmp_addr; ++ ++ if (priv->max9286_addr) { ++ if (priv->gpio_resetb < 1 || priv->gpio_resetb > 5) ++ return; ++ ++ tmp_addr = client->addr; ++ /* get out from sensor reset */ ++ client->addr = priv->max9271_addr; /* MAX9271 I2C address */ ++ reg8_write(client, 0x0f, (0xfe & ~BIT(priv->gpio_resetb)) | ++ (priv->active_low_resetb ? 0 : BIT(priv->gpio_resetb))); /* set GPIOn value to reset */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x0f, (0xfe & ~BIT(priv->gpio_resetb)) | ++ (priv->active_low_resetb ? BIT(priv->gpio_resetb) : 0)); /* set GPIOn value to un-reset */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ client->addr = tmp_addr; ++ } ++ ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x4_addr; /* TI9x4 I2C address */ ++ ++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x6e, 0x8a); /* set GPIO1 value to reset */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x6e, 0x9a); /* set GPIO1 value to un-reset */ ++ } ++} ++ ++static int ov490_set_regs(struct i2c_client *client, ++ const struct ov490_reg *regs, int nr_regs) ++{ ++ int i; ++ ++ for (i = 0; i < nr_regs; i++) { ++ if (reg16_write(client, regs[i].reg, regs[i].val)) { ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, regs[i].reg, regs[i].val); ++ } ++ } ++ ++ return 0; ++} ++ ++static u8 ov490_ov10640_read(struct i2c_client *client, u16 addr) ++{ ++ u8 reg_val = 0; ++ ++ reg16_write(client, 0xFFFD, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x5000, 0x01); /* read operation */ ++ reg16_write(client, 0x5001, addr >> 8); ++ reg16_write(client, 0x5002, addr & 0xff); ++ reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x00C0, 0xc1); ++ reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(1000, 1500); /* wait 1 ms */ ++ reg16_read(client, 0x5000, ®_val); ++ ++ return reg_val; ++} ++ ++static void ov490_ov10640_write(struct i2c_client *client, u16 addr, u8 val) ++{ ++ reg16_write(client, 0xFFFD, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x5000, 0x00); /* write operation */ ++ reg16_write(client, 0x5001, addr >> 8); ++ reg16_write(client, 0x5002, addr & 0xff); ++ reg16_write(client, 0x5003, val); ++ reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x00C0, 0xc1); ++} ++ ++static int ov490_s_stream(struct v4l2_subdev *sd, int enable) ++{ ++ return 0; ++} ++ ++static int ov490_get_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov490_priv *priv = to_ov490(client); ++ ++ if (format->pad) ++ return -EINVAL; ++ ++ mf->width = priv->rect.width; ++ mf->height = priv->rect.height; ++ mf->code = MEDIA_BUS_FMT_YUYV8_2X8; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static int ov490_set_fmt(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *mf = &format->format; ++ ++ mf->code = MEDIA_BUS_FMT_YUYV8_2X8; ++ mf->colorspace = V4L2_COLORSPACE_SMPTE170M; ++ mf->field = V4L2_FIELD_NONE; ++ ++ if (format->which == V4L2_SUBDEV_FORMAT_TRY) ++ cfg->try_fmt = *mf; ++ ++ return 0; ++} ++ ++static int ov490_enum_mbus_code(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ if (code->pad || code->index > 0) ++ return -EINVAL; ++ ++ code->code = MEDIA_BUS_FMT_YUYV8_2X8; ++ ++ return 0; ++} ++ ++static int ov490_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov490_priv *priv = to_ov490(client); ++ ++ memcpy(edid->edid, priv->id, 6); ++ ++ edid->edid[6] = 0xff; ++ edid->edid[7] = client->addr; ++ edid->edid[8] = OV490_VERSION_REG >> 8; ++ edid->edid[9] = OV490_VERSION_REG & 0xff; ++ ++ return 0; ++} ++ ++static int ov490_set_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct v4l2_rect *rect = &sel->r; ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov490_priv *priv = to_ov490(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || ++ sel->target != V4L2_SEL_TGT_CROP) ++ return -EINVAL; ++ ++ rect->left = ALIGN(rect->left, 2); ++ rect->top = ALIGN(rect->top, 2); ++ rect->width = ALIGN(rect->width, 2); ++ rect->height = ALIGN(rect->height, 2); ++ ++ if ((rect->left + rect->width > priv->max_width) || ++ (rect->top + rect->height > priv->max_height)) ++ *rect = priv->rect; ++ ++ priv->rect.left = rect->left; ++ priv->rect.top = rect->top; ++ priv->rect.width = rect->width; ++ priv->rect.height = rect->height; ++ ++ return 0; ++} ++ ++static int ov490_get_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov490_priv *priv = to_ov490(client); ++ ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) ++ return -EINVAL; ++ ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = priv->max_width; ++ sel->r.height = priv->max_height; ++ return 0; ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ sel->r.left = 0; ++ sel->r.top = 0; ++ sel->r.width = priv->max_width; ++ sel->r.height = priv->max_height; ++ return 0; ++ case V4L2_SEL_TGT_CROP: ++ sel->r = priv->rect; ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int ov490_g_mbus_config(struct v4l2_subdev *sd, ++ struct v4l2_mbus_config *cfg) ++{ ++ cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | ++ V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; ++ cfg->type = V4L2_MBUS_CSI2; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int ov490_g_register(struct v4l2_subdev *sd, ++ struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ int ret; ++ u8 val = 0; ++ ++ ret = reg16_read(client, (u16)reg->reg, &val); ++ if (ret < 0) ++ return ret; ++ ++ reg->val = val; ++ reg->size = sizeof(u16); ++ ++ return 0; ++} ++ ++static int ov490_s_register(struct v4l2_subdev *sd, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ int ret; ++ ++ ret = reg16_write(client, (u16)reg->reg, (u8)reg->val); ++ if ((u8)reg->reg == 0xFFFD) ++ usleep_range(100, 150); /* wait 100 us */ ++ if ((u8)reg->reg == 0xFFFE) ++ usleep_range(100, 150); /* wait 100 us */ ++ return ret; ++} ++#endif ++ ++static struct v4l2_subdev_core_ops ov490_core_ops = { ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .g_register = ov490_g_register, ++ .s_register = ov490_s_register, ++#endif ++}; ++ ++static int ov490_s_gamma(int a, int ref) ++{ ++ if ((a + ref) > 0xff) ++ return 0xff; ++ ++ if ((a + ref) < 0) ++ return 0; ++ ++ return a + ref; ++} ++ ++static int ov490_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct v4l2_subdev *sd = to_sd(ctrl); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov490_priv *priv = to_ov490(client); ++ int ret = -EINVAL; ++ ++ if (!priv->init_complete) ++ return 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_BRIGHTNESS: ++ /* SDE (rough) brightness */ ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x00); ++ ret |= reg16_write(client, 0x5001, ctrl->val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xf1); ++ break; ++ case V4L2_CID_CONTRAST: ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, ctrl->val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xfd); ++ break; ++ case V4L2_CID_SATURATION: ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, ctrl->val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xf3); ++ break; ++ case V4L2_CID_HUE: ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, ctrl->val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xf5); ++ break; ++ case V4L2_CID_GAMMA: ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, ov490_s_gamma(ctrl->val, 0x12)); ++ ret |= reg16_write(client, 0x5001, ov490_s_gamma(ctrl->val, 0x20)); ++ ret |= reg16_write(client, 0x5002, ov490_s_gamma(ctrl->val, 0x3b)); ++ ret |= reg16_write(client, 0x5003, ov490_s_gamma(ctrl->val, 0x5d)); ++ ret |= reg16_write(client, 0x5004, ov490_s_gamma(ctrl->val, 0x6a)); ++ ret |= reg16_write(client, 0x5005, ov490_s_gamma(ctrl->val, 0x76)); ++ ret |= reg16_write(client, 0x5006, ov490_s_gamma(ctrl->val, 0x81)); ++ ret |= reg16_write(client, 0x5007, ov490_s_gamma(ctrl->val, 0x8b)); ++ ret |= reg16_write(client, 0x5008, ov490_s_gamma(ctrl->val, 0x96)); ++ ret |= reg16_write(client, 0x5009, ov490_s_gamma(ctrl->val, 0x9e)); ++ ret |= reg16_write(client, 0x500a, ov490_s_gamma(ctrl->val, 0xae)); ++ ret |= reg16_write(client, 0x500b, ov490_s_gamma(ctrl->val, 0xbc)); ++ ret |= reg16_write(client, 0x500c, ov490_s_gamma(ctrl->val, 0xcf)); ++ ret |= reg16_write(client, 0x500d, ov490_s_gamma(ctrl->val, 0xde)); ++ ret |= reg16_write(client, 0x500e, ov490_s_gamma(ctrl->val, 0xec)); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xf9); ++ break; ++ case V4L2_CID_SHARPNESS: ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, ctrl->val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xfb); ++ break; ++ case V4L2_CID_AUTOGAIN: ++ case V4L2_CID_GAIN: ++ case V4L2_CID_EXPOSURE: ++ if (ctrl->id == V4L2_CID_AUTOGAIN) ++ priv->autogain = ctrl->val; ++ if (ctrl->id == V4L2_CID_GAIN) ++ priv->gain = ctrl->val; ++ if (ctrl->id == V4L2_CID_EXPOSURE) ++ priv->exposure = ctrl->val; ++ ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, !priv->autogain); ++ ret |= reg16_write(client, 0x5001, priv->exposure >> 8); ++ ret |= reg16_write(client, 0x5002, priv->exposure & 0xff); ++ ret |= reg16_write(client, 0x5003, priv->exposure >> 8); ++ ret |= reg16_write(client, 0x5004, priv->exposure & 0xff); ++ ret |= reg16_write(client, 0x5005, priv->exposure >> 8); ++ ret |= reg16_write(client, 0x5006, priv->exposure & 0xff); ++ ret |= reg16_write(client, 0x5007, priv->gain >> 8); ++ ret |= reg16_write(client, 0x5008, priv->gain & 0xff); ++ ret |= reg16_write(client, 0x5009, priv->gain >> 8); ++ ret |= reg16_write(client, 0x500a, priv->gain & 0xff); ++ ret |= reg16_write(client, 0x500b, priv->gain >> 8); ++ ret |= reg16_write(client, 0x500c, priv->gain & 0xff); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xea); ++ break; ++ case V4L2_CID_AUTO_WHITE_BALANCE: ++ case V4L2_CID_RED_BALANCE: ++ case V4L2_CID_BLUE_BALANCE: ++ if (ctrl->id == V4L2_CID_AUTO_WHITE_BALANCE) ++ priv->awb = ctrl->val; ++ if (ctrl->id == V4L2_CID_RED_BALANCE) { ++ priv->red = ctrl->val; ++ priv->red <<= 8; ++ priv->green_r = priv->red / 2; ++ } ++ if (ctrl->id == V4L2_CID_BLUE_BALANCE) { ++ priv->blue = ctrl->val; ++ priv->blue <<= 8; ++ priv->green_b = priv->blue / 2; ++ } ++ ++ 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->awb); ++ ret |= reg16_write(client, 0x5001, priv->red >> 8); ++ ret |= reg16_write(client, 0x5002, priv->red & 0xff); ++ ret |= reg16_write(client, 0x5003, priv->green_r >> 8); ++ ret |= reg16_write(client, 0x5004, priv->green_r & 0xff); ++ ret |= reg16_write(client, 0x5005, priv->green_b >> 8); ++ ret |= reg16_write(client, 0x5006, priv->green_b & 0xff); ++ ret |= reg16_write(client, 0x5007, priv->blue >> 8); ++ ret |= reg16_write(client, 0x5008, priv->blue & 0xff); ++ ret |= reg16_write(client, 0x5009, priv->red >> 8); ++ ret |= reg16_write(client, 0x500a, priv->red & 0xff); ++ ret |= reg16_write(client, 0x500b, priv->green_r >> 8); ++ ret |= reg16_write(client, 0x500c, priv->green_r & 0xff); ++ ret |= reg16_write(client, 0x500d, priv->green_b >> 8); ++ ret |= reg16_write(client, 0x500e, priv->green_b & 0xff); ++ ret |= reg16_write(client, 0x500f, priv->blue >> 8); ++ ret |= reg16_write(client, 0x5010, priv->blue & 0xff); ++ ret |= reg16_write(client, 0x5011, priv->red >> 8); ++ ret |= reg16_write(client, 0x5012, priv->red & 0xff); ++ ret |= reg16_write(client, 0x5013, priv->green_r >> 8); ++ ret |= reg16_write(client, 0x5014, priv->green_r & 0xff); ++ ret |= reg16_write(client, 0x5015, priv->green_b >> 8); ++ ret |= reg16_write(client, 0x5016, priv->green_b & 0xff); ++ ret |= reg16_write(client, 0x5017, priv->blue >> 8); ++ ret |= reg16_write(client, 0x5018, priv->blue & 0xff); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xeb); ++ break; ++ case V4L2_CID_HFLIP: ++#if 1 ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, ctrl->val); ++ ret |= reg16_write(client, 0x5001, 0x00); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xdc); ++#else ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x01); // read 0x3128 ++ ret |= reg16_write(client, 0x5001, 0x31); ++ ret |= reg16_write(client, 0x5002, 0x28); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_read(client, 0x5000, &val); ++ val &= ~(0x1 << 0); ++ val |= (ctrl->val << 0); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x00); // write 0x3128 ++ ret |= reg16_write(client, 0x5001, 0x31); ++ ret |= reg16_write(client, 0x5002, 0x28); ++ ret |= reg16_write(client, 0x5003, val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x01); // read 0x3291 ++ ret |= reg16_write(client, 0x5001, 0x32); ++ ret |= reg16_write(client, 0x5002, 0x91); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_read(client, 0x5000, &val); ++ val &= ~(0x1 << 1); ++ val |= (ctrl->val << 1); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x00); // write 0x3291 ++ ret |= reg16_write(client, 0x5001, 0x32); ++ ret |= reg16_write(client, 0x5002, 0x91); ++ ret |= reg16_write(client, 0x5003, val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x01); // read 0x3090 ++ ret |= reg16_write(client, 0x5001, 0x30); ++ ret |= reg16_write(client, 0x5002, 0x90); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_read(client, 0x5000, &val); ++ val &= ~(0x1 << 2); ++ val |= (ctrl->val << 2); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x00); // write 0x3090 ++ ret |= reg16_write(client, 0x5001, 0x30); ++ ret |= reg16_write(client, 0x5002, 0x90); ++ ret |= reg16_write(client, 0x5003, val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++#endif ++ break; ++ case V4L2_CID_VFLIP: ++#if 1 ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, ctrl->val); ++ ret |= reg16_write(client, 0x5001, 0x01); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xdc); ++#else ++ ret = reg16_write(client, 0xFFFD, 0x80); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x01); // read 0x3128 ++ ret |= reg16_write(client, 0x5001, 0x31); ++ ret |= reg16_write(client, 0x5002, 0x28); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_read(client, 0x5000, &val); ++ val &= ~(0x1 << 1); ++ val |= (ctrl->val << 1); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x00); // write 0x3128 ++ ret |= reg16_write(client, 0x5001, 0x31); ++ ret |= reg16_write(client, 0x5002, 0x28); ++ ret |= reg16_write(client, 0x5003, val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x01); // read 0x3291 ++ ret |= reg16_write(client, 0x5001, 0x32); ++ ret |= reg16_write(client, 0x5002, 0x91); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_read(client, 0x5000, &val); ++ val &= ~(0x1 << 2); ++ val |= (ctrl->val << 2); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x00); // write 0x3291 ++ ret |= reg16_write(client, 0x5001, 0x32); ++ ret |= reg16_write(client, 0x5002, 0x91); ++ ret |= reg16_write(client, 0x5003, val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x01); // read 0x3090 ++ ret |= reg16_write(client, 0x5001, 0x30); ++ ret |= reg16_write(client, 0x5002, 0x90); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_read(client, 0x5000, &val); ++ val &= ~(0x1 << 3); ++ val |= (ctrl->val << 3); ++ ret |= reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x5000, 0x00); // write 0x3090 ++ ret |= reg16_write(client, 0x5001, 0x30); ++ ret |= reg16_write(client, 0x5002, 0x90); ++ ret |= reg16_write(client, 0x5003, val); ++ ret |= reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ ret |= reg16_write(client, 0x00C0, 0xc1); ++#endif ++ break; ++ case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: ++ ret = 0; ++ break; ++ } ++ ++ return ret; ++} ++ ++static const struct v4l2_ctrl_ops ov490_ctrl_ops = { ++ .s_ctrl = ov490_s_ctrl, ++}; ++ ++static struct v4l2_subdev_video_ops ov490_video_ops = { ++ .s_stream = ov490_s_stream, ++ .g_mbus_config = ov490_g_mbus_config, ++}; ++ ++static const struct v4l2_subdev_pad_ops ov490_subdev_pad_ops = { ++ .get_edid = ov490_get_edid, ++ .enum_mbus_code = ov490_enum_mbus_code, ++ .get_selection = ov490_get_selection, ++ .set_selection = ov490_set_selection, ++ .get_fmt = ov490_get_fmt, ++ .set_fmt = ov490_set_fmt, ++}; ++ ++static struct v4l2_subdev_ops ov490_subdev_ops = { ++ .core = &ov490_core_ops, ++ .video = &ov490_video_ops, ++ .pad = &ov490_subdev_pad_ops, ++}; ++ ++static void ov490_otp_id_read(struct i2c_client *client) ++{ ++ struct ov490_priv *priv = to_ov490(client); ++ int i; ++ int otp_bank0_allzero = 1; ++ ++#if 0 ++ /* read camera id from ov490 OTP memory */ ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x28); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0xE084, 0x40); /* manual mode, bank#0 */ ++ reg16_write(client, 0xE081, 1); /* start OTP read */ ++ ++ usleep_range(25000, 26000); /* wait 25 ms */ ++ ++ for (i = 0; i < 6; i++) ++ reg16_read(client, 0xe000 + i + 4, &priv->id[i]); ++#else ++ /* read camera id from ov10640 OTP memory */ ++ ov490_ov10640_write(client, 0x349C, 1); ++ usleep_range(25000, 25500); /* wait 25 ms */ ++ ++ for (i = 0; i < 6; i++) { ++ /* first 6 bytes are equal on all ov10640 */ ++ priv->id[i] = ov490_ov10640_read(client, 0x349e + i + 6); ++ if (priv->id[i]) ++ otp_bank0_allzero = 0; ++ } ++ ++ if (otp_bank0_allzero) { ++ ov490_ov10640_write(client, 0x3495, 0x41); /* bank#1 */ ++ ov490_ov10640_write(client, 0x349C, 1); ++ usleep_range(25000, 25500); /* wait 25 ms */ ++ ++ for (i = 0; i < 6; i++) ++ priv->id[i] = ov490_ov10640_read(client, 0x34ae + i); ++ } ++#endif ++} ++ ++static ssize_t ov490_otp_id_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct v4l2_subdev *sd = i2c_get_clientdata(to_i2c_client(dev)); ++ struct i2c_client *client = v4l2_get_subdevdata(sd); ++ struct ov490_priv *priv = to_ov490(client); ++ ++ return snprintf(buf, 32, "%02x:%02x:%02x:%02x:%02x:%02x\n", ++ priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++} ++ ++static DEVICE_ATTR(otp_id_ov490, S_IRUGO, ov490_otp_id_show, NULL); ++ ++static int ov490_initialize(struct i2c_client *client) ++{ ++ struct ov490_priv *priv = to_ov490(client); ++ u8 val = 0; ++ u8 pid = 0, ver = 0; ++ int ret = 0, timeout, retry_timeout = 3; ++ ++ if (priv->is_fixed_sensor) { ++ dev_info(&client->dev, "ov490/ov10640 fixed-sensor res %dx%d\n", priv->max_width, priv->max_height); ++ return 0; ++ } ++ ++ ov490_s_port(client, 1); ++ ++ /* check and show product ID and manufacturer ID */ ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_read(client, OV490_PID, &pid); ++ reg16_read(client, OV490_VER, &ver); ++ ++ if (OV490_VERSION(pid, ver) != OV490_VERSION_REG) { ++ dev_dbg(&client->dev, "Product ID error %x:%x\n", pid, ver); ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ if (unlikely(conf_link)) ++ goto out; ++ ++again: ++ /* Check if firmware booted by reading stream-on status */ ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x29); ++ usleep_range(100, 150); /* wait 100 us */ ++ for (timeout = 300; timeout > 0; timeout--) { ++ reg16_read(client, 0xd000, &val); ++ if (val == 0x0c) ++ break; ++ mdelay(1); ++ } ++ ++ /* wait firmware apps started by reading OV10640 ID */ ++ for (;timeout > 0; timeout--) { ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x5000, 0x01); ++ reg16_write(client, 0x5001, 0x30); ++ reg16_write(client, 0x5002, 0x0a); ++ reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0xC0, 0xc1); ++ reg16_write(client, 0xFFFE, 0x19); ++ usleep_range(1000, 1500); /* wait 1 ms */ ++ reg16_read(client, 0x5000, &val); ++ if (val == 0xa6) ++ break; ++ mdelay(1); ++ } ++ ++ if (!timeout) { ++ dev_err(&client->dev, "Timeout firmware boot wait, retrying\n"); ++ /* reset OV10640 using RESETB pin controlled by OV490 GPIO0 */ ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x80); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x0050, 0x01); ++ reg16_write(client, 0x0054, 0x01); ++ reg16_write(client, 0x0058, 0x00); ++ mdelay(10); ++ reg16_write(client, 0x0058, 0x01); ++ /* reset OV490 using RESETB pin controlled by serializer */ ++ ov490_reset(client); ++ if (retry_timeout--) ++ goto again; ++ } ++ ++ /* read resolution used by current firmware */ ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x82); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_read(client, OV490_ISP_HSIZE_HIGH, &val); ++ priv->max_width = val; ++ reg16_read(client, OV490_ISP_HSIZE_LOW, &val); ++ priv->max_width = (priv->max_width << 8) | val; ++ reg16_read(client, OV490_ISP_VSIZE_HIGH, &val); ++ priv->max_height = val; ++ reg16_read(client, OV490_ISP_VSIZE_LOW, &val); ++ priv->max_height = (priv->max_height << 8) | val; ++ /* Program wizard registers */ ++ ov490_set_regs(client, ov490_regs_wizard, ARRAY_SIZE(ov490_regs_wizard)); ++ /* Set DVP bit swap */ ++ reg16_write(client, 0xFFFD, 0x80); ++ reg16_write(client, 0xFFFE, 0x28); ++ usleep_range(100, 150); /* wait 100 us */ ++ reg16_write(client, 0x6009, priv->dvp_order << 4); ++ /* Read OTP IDs */ ++ ov490_otp_id_read(client); ++ ++out: ++ dev_info(&client->dev, "ov490/ov10640 PID %x%x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, ver, priv->max_width, priv->max_height, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++err: ++ ov490_s_port(client, 0); ++ ++ return ret; ++} ++ ++static int ov490_parse_dt(struct device_node *np, struct ov490_priv *priv) ++{ ++ struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); ++ int i; ++ const char *fixed_sensor; ++ struct device_node *endpoint = NULL, *rendpoint = NULL; ++ int tmp_addr = 0; ++ ++ for (i = 0; ; i++) { ++ endpoint = of_graph_get_next_endpoint(np, endpoint); ++ if (!endpoint) ++ break; ++ ++ of_node_put(endpoint); ++ ++ of_property_read_u32(endpoint, "dvp-order", &priv->dvp_order); ++ ++ rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); ++ if (!rendpoint) ++ continue; ++ ++ if (!of_property_read_u32(rendpoint, "max9271-addr", &priv->max9271_addr) && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->max9286_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) { ++ if (of_property_read_u32(rendpoint->parent->parent, "maxim,resetb-gpio", &priv->gpio_resetb)) { ++ priv->gpio_resetb = -1; ++ } else { ++ if (of_property_read_bool(rendpoint->parent->parent, "maxim,resetb-active-high")) ++ priv->active_low_resetb = false; ++ else ++ priv->active_low_resetb = true; ++ } ++ break; ++ } ++ ++ if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && ++ !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti9x4") && ++ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti9x4_addr) && ++ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) ++ break; ++ } ++ ++ if (!priv->max9286_addr && !priv->ti9x4_addr) { ++ dev_err(&client->dev, "deserializer does not present for OV490\n"); ++ return -EINVAL; ++ } ++ ++ ov490_s_port(client, 1); ++ ++ /* setup I2C translator address */ ++ tmp_addr = client->addr; ++ if (priv->max9286_addr) { ++ client->addr = priv->max9271_addr; /* Serializer I2C address */ ++ ++ reg8_write(client, 0x09, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x0A, OV490_I2C_ADDR << 1); /* Sensor native I2C address */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ }; ++ if (priv->ti9x4_addr) { ++ client->addr = priv->ti9x4_addr; /* Deserializer I2C address */ ++ ++ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ ++ usleep_range(2000, 2500); /* wait 2ms */ ++ reg8_write(client, 0x65, tmp_addr << 1); /* Sensor translated I2C address */ ++ reg8_write(client, 0x5d, OV490_I2C_ADDR << 1); /* Sensor native I2C address */ ++ ++ reg8_write(client, 0x6e, 0x9a); /* GPIO0 - fsin, GPIO1 - resetb */ ++ } ++ client->addr = tmp_addr; ++ ++ if (!of_property_read_string(np, "maxim,fixed-sensor", &fixed_sensor) && ++ strcmp(fixed_sensor, "ov490") == 0) { ++ if (of_property_read_u32(np, "maxim,width", &priv->max_width)) ++ priv->max_width = 1280; ++ ++ if (of_property_read_u32(np, "maxim,height", &priv->max_height)) ++ priv->max_height = 966; ++ ++ priv->is_fixed_sensor = true; ++ } ++ ++ /* module params override dts */ ++ if (dvp_order) ++ priv->dvp_order = dvp_order; ++ if (max_width && max_height) { ++ priv->max_width = max_width; ++ priv->max_height = max_height; ++ priv->is_fixed_sensor = true; ++ } ++ ++ return 0; ++} ++ ++static int ov490_probe(struct i2c_client *client, ++ const struct i2c_device_id *did) ++{ ++ struct ov490_priv *priv; ++ struct v4l2_ctrl *ctrl; ++ int ret; ++ ++ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ v4l2_i2c_subdev_init(&priv->sd, client, &ov490_subdev_ops); ++ priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; ++ ++ priv->exposure = 0x100; ++ priv->gain = 0x100; ++ priv->autogain = 1; ++ priv->red = 0x400; ++ priv->blue = 0x400; ++ priv->green_r = priv->red / 2; ++ priv->green_b = priv->blue / 2; ++ priv->awb = 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_AUTO_WHITE_BALANCE, 0, 1, 1, priv->autogain); ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_RED_BALANCE, 2, 0xf, 1, priv->red >> 8); ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_BLUE_BALANCE, 2, 0xf, 1, priv->blue >> 8); ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 1); ++ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ ctrl = v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 9); ++ if (ctrl) ++ ctrl->flags &= ~V4L2_CTRL_FLAG_READ_ONLY; ++ priv->sd.ctrl_handler = &priv->hdl; ++ ++ ret = priv->hdl.error; ++ if (ret) ++ goto cleanup; ++ ++ v4l2_ctrl_handler_setup(&priv->hdl); ++ ++ priv->pad.flags = MEDIA_PAD_FL_SOURCE; ++ priv->sd.entity.flags |= MEDIA_ENT_F_CAM_SENSOR; ++ ret = media_entity_pads_init(&priv->sd.entity, 1, &priv->pad); ++ if (ret < 0) ++ goto cleanup; ++ ++ ret = ov490_parse_dt(client->dev.of_node, priv); ++ if (ret) ++ goto cleanup; ++ ++ ret = ov490_initialize(client); ++ if (ret < 0) ++ goto cleanup; ++ ++ priv->rect.left = 0; ++ priv->rect.top = 0; ++ priv->rect.width = priv->max_width; ++ priv->rect.height = priv->max_height; ++ ++ ret = v4l2_async_register_subdev(&priv->sd); ++ if (ret) ++ goto cleanup; ++ ++ if (device_create_file(&client->dev, &dev_attr_otp_id_ov490) != 0) { ++ dev_err(&client->dev, "sysfs otp_id entry creation failed\n"); ++ goto cleanup; ++ } ++ ++ priv->init_complete = 1; ++ ++ return 0; ++ ++cleanup: ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++#ifdef CONFIG_SOC_CAMERA_OV490_OV10640 ++ v4l_err(client, "failed to probe @ 0x%02x (%s)\n", ++ client->addr, client->adapter->name); ++#endif ++ return ret; ++} ++ ++static int ov490_remove(struct i2c_client *client) ++{ ++ struct ov490_priv *priv = i2c_get_clientdata(client); ++ ++ device_remove_file(&client->dev, &dev_attr_otp_id_ov490); ++ v4l2_async_unregister_subdev(&priv->sd); ++ media_entity_cleanup(&priv->sd.entity); ++ v4l2_ctrl_handler_free(&priv->hdl); ++ v4l2_device_unregister_subdev(&priv->sd); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_SOC_CAMERA_OV490_OV10640 ++static const struct i2c_device_id ov490_id[] = { ++ { "ov490-ov10640", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, ov490_id); ++ ++static const struct of_device_id ov490_of_ids[] = { ++ { .compatible = "ovti,ov490-ov10640", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ov490_of_ids); ++ ++static struct i2c_driver ov490_i2c_driver = { ++ .driver = { ++ .name = "ov490-ov10640", ++ .of_match_table = ov490_of_ids, ++ }, ++ .probe = ov490_probe, ++ .remove = ov490_remove, ++ .id_table = ov490_id, ++}; ++ ++module_i2c_driver(ov490_i2c_driver); ++ ++MODULE_DESCRIPTION("SoC Camera driver for OV490-OV10640"); ++MODULE_AUTHOR("Vladimir Barinov"); ++MODULE_LICENSE("GPL"); ++#endif +diff --git a/drivers/media/i2c/soc_camera/ov490_ov10640.h b/drivers/media/i2c/soc_camera/ov490_ov10640.h +new file mode 100644 +index 0000000..b22e93e +--- /dev/null ++++ b/drivers/media/i2c/soc_camera/ov490_ov10640.h +@@ -0,0 +1,102 @@ ++/* ++ * 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. ++ */ ++ ++//#define OV490_DISPLAY_PATTERN ++ ++struct ov490_reg { ++ u16 reg; ++ u8 val; ++}; ++ ++static const struct ov490_reg ov490_regs_wizard[] = { ++/* The following registers should match firmware */ ++{0xfffd, 0x80}, ++{0xfffe, 0x82}, ++{0x0071, 0x11}, ++{0x0075, 0x11}, ++{0xfffe, 0x29}, ++{0x6010, 0x01}, ++/* ov490 EMB line disable in YUV and RAW data, NOTE: EMB line is still used in ISP and sensor */ ++{0xe000, 0x14}, ++#if 0 /* do not disable EMB line in ISP! */ ++{0x4017, 0x00}, ++#endif ++{0xfffe, 0x28}, ++{0x6000, 0x04}, ++{0x6004, 0x00}, ++{0x6008, 0x00}, // PCLK polarity - useless due to silicon bug -> use 0x808000bb register ++{0xfffe, 0x80}, ++{0x0091, 0x00}, ++{0x00bb, 0x1d}, // bit[3]=0 - PCLK polarity workaround ++/* ov10640 EMB line disable */ ++#if 0 /* do not disable EMB line in sensor! */ ++{0xfffe, 0x19}, ++{0x5000, 0x00}, ++{0x5001, 0x30}, ++{0x5002, 0x91}, ++{0x5003, 0x08}, ++{0xfffe, 0x80}, ++{0x00c0, 0xc1}, ++#endif ++/* Ov490 FSIN: app_fsin_from_fsync */ ++{0xfffe, 0x85}, ++{0x0008, 0x00}, ++{0x0009, 0x01}, ++{0x000A, 0x05}, // fsin0 src ++{0x000B, 0x00}, ++{0x0030, 0x02}, // fsin0_delay ++{0x0031, 0x00}, ++{0x0032, 0x00}, ++{0x0033, 0x00}, ++{0x0038, 0x02}, // fsin1_delay ++{0x0039, 0x00}, ++{0x003A, 0x00}, ++{0x003B, 0x00}, ++{0x0070, 0x2C}, // fsin0_length ++{0x0071, 0x01}, ++{0x0072, 0x00}, ++{0x0073, 0x00}, ++{0x0074, 0x64}, // fsin1_length ++{0x0075, 0x00}, ++{0x0076, 0x00}, ++{0x0077, 0x00}, ++{0x0000, 0x14}, ++{0x0001, 0x00}, ++{0x0002, 0x00}, ++{0x0003, 0x00}, ++{0x0004, 0x32}, // load fsin0,load fsin1,load other, it will be cleared automatically. ++{0x0005, 0x00}, ++{0x0006, 0x00}, ++{0x0007, 0x00}, ++{0xfffe, 0x80}, ++{0x0081, 0x00}, // 03;SENSOR FSIN ++/* ov10640 FSIN */ ++{0xfffe, 0x19}, ++{0x5000, 0x00}, ++{0x5001, 0x30}, ++{0x5002, 0x8c}, ++{0x5003, 0xb2}, ++{0xfffe, 0x80}, ++{0x00c0, 0xc1}, ++/* ov10640 HFLIP=1 by default */ ++{0xfffe, 0x19}, ++{0x5000, 0x01}, ++{0x5001, 0x00}, ++{0xfffe, 0x80}, ++{0x00c0, 0xdc}, ++#ifdef OV490_DISPLAY_PATTERN ++{0xfffd, 0x80}, ++{0xfffe, 0x19}, ++{0x5000, 0x02}, ++{0xfffe, 0x80}, ++{0x00c0, 0xd6}, ++#endif ++}; +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..812f367 +index 0000000..a371e22 --- /dev/null -+++ b/drivers/media/i2c/soc_camera/ov490_ov10640.c -@@ -0,0 +1,1133 @@ ++++ b/drivers/media/i2c/soc_camera/ov495_ov2775.c +@@ -0,0 +1,650 @@ +/* -+ * OmniVision ov490-ov10640 sensor camera driver ++ * OmniVision ov495-ov2775 sensor camera driver + * -+ * Copyright (C) 2016-2018 Cogent Embedded, Inc. ++ * 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 @@ -7578,40 +13237,32 @@ index 0000000..812f367 +#include +#include + -+#include "max9286.h" -+#include "ov490_ov10640.h" ++#include "ov495_ov2775.h" + -+#define OV490_I2C_ADDR 0x24 ++#define OV495_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 OV495_PID 0x300a ++#define OV495_VER 0x300b ++#define OV495_VERSION_REG 0x0495 ++#define OV495_VERSION(pid, ver) (((pid) << 8) | ((ver) & 0xff)) + -+#define OV490_ISP_HSIZE_LOW 0x60 -+#define OV490_ISP_HSIZE_HIGH 0x61 -+#define OV490_ISP_VSIZE_LOW 0x62 -+#define OV490_ISP_VSIZE_HIGH 0x63 ++#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 ov490_priv { ++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; -+ char is_fixed_sensor; + int init_complete; + u8 id[6]; + int exposure; + int gain; + int autogain; -+ int red; -+ int green_r; -+ int green_b; -+ int blue; -+ int awb; -+ int dvp_order; + /* serializers */ + int max9286_addr; + int max9271_addr; @@ -7619,79 +13270,28 @@ index 0000000..812f367 + int ti9x3_addr; + int port; + int gpio_resetb; -+ int active_low_resetb; + int gpio_fsin; -+}; -+ -+static int conf_link; -+module_param(conf_link, int, 0644); -+MODULE_PARM_DESC(conf_link, " Force configuration link. Used only if robust firmware flashing required (f.e. recovery)"); -+ -+static int dvp_order; -+module_param(dvp_order, int, 0644); -+MODULE_PARM_DESC(dvp_order, " DVP bus bits order"); -+ -+static int max_width; -+module_param(max_width, int, 0644); -+MODULE_PARM_DESC(max_width, " Fixed sensor width"); + -+static int max_height; -+module_param(max_height, int, 0644); -+MODULE_PARM_DESC(max_height, " Fixed sensor height"); ++}; + -+static inline struct ov490_priv *to_ov490(const struct i2c_client *client) -+{ -+ return container_of(i2c_get_clientdata(client), struct ov490_priv, sd); -+} ++static int force_conf_link; + -+static void ov490_s_port(struct i2c_client *client, int fwd_en) ++static __init int ov495_force_conf_link(char *str) +{ -+ 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(5000, 5500); /* wait 5ms */ -+ client->addr = tmp_addr; -+ }; ++ /* 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 void ov490_reset(struct i2c_client *client) ++static inline struct ov495_priv *to_ov495(const struct i2c_client *client) +{ -+ struct ov490_priv *priv = to_ov490(client); -+ int tmp_addr; -+ -+ if (priv->max9286_addr) { -+ if (priv->gpio_resetb < 1 || priv->gpio_resetb > 5) -+ return; -+ -+ tmp_addr = client->addr; -+ /* get out from sensor reset */ -+ client->addr = priv->max9271_addr; /* MAX9271 I2C address */ -+ reg8_write(client, 0x0f, (0xfe & ~BIT(priv->gpio_resetb)) | -+ (priv->active_low_resetb ? 0 : BIT(priv->gpio_resetb))); /* set GPIOn value to reset */ -+ usleep_range(2000, 2500); /* wait 2ms */ -+ reg8_write(client, 0x0f, (0xfe & ~BIT(priv->gpio_resetb)) | -+ (priv->active_low_resetb ? BIT(priv->gpio_resetb) : 0)); /* set GPIOn value to un-reset */ -+ usleep_range(2000, 2500); /* wait 2ms */ -+ client->addr = tmp_addr; -+ } -+ -+ if (priv->ti9x4_addr) { -+ client->addr = priv->ti9x4_addr; /* TI9x4 I2C address */ -+ -+ reg8_write(client, 0x4c, (priv->port << 4) | (1 << priv->port)); /* Select RX port number */ -+ usleep_range(2000, 2500); /* wait 2ms */ -+ reg8_write(client, 0x6e, 0x8a); /* set GPIO1 value to reset */ -+ usleep_range(2000, 2500); /* wait 2ms */ -+ reg8_write(client, 0x6e, 0x9a); /* set GPIO1 value to un-reset */ -+ } ++ return container_of(i2c_get_clientdata(client), struct ov495_priv, sd); +} + -+static int ov490_set_regs(struct i2c_client *client, -+ const struct ov490_reg *regs, int nr_regs) ++static int ov495_set_regs(struct i2c_client *client, ++ const struct ov495_reg *regs, int nr_regs) +{ + int i; + @@ -7705,54 +13305,18 @@ index 0000000..812f367 + return 0; +} + -+static u8 ov490_ov10640_read(struct i2c_client *client, u16 addr) -+{ -+ u8 reg_val = 0; -+ -+ reg16_write(client, 0xFFFD, 0x80); -+ usleep_range(100, 150); /* wait 100 us */ -+ reg16_write(client, 0xFFFE, 0x19); -+ usleep_range(100, 150); /* wait 100 us */ -+ reg16_write(client, 0x5000, 0x01); /* read operation */ -+ reg16_write(client, 0x5001, addr >> 8); -+ reg16_write(client, 0x5002, addr & 0xff); -+ reg16_write(client, 0xFFFE, 0x80); -+ usleep_range(100, 150); /* wait 100 us */ -+ reg16_write(client, 0x00C0, 0xc1); -+ reg16_write(client, 0xFFFE, 0x19); -+ usleep_range(1000, 1500); /* wait 1 ms */ -+ reg16_read(client, 0x5000, ®_val); -+ -+ return reg_val; -+} -+ -+static void ov490_ov10640_write(struct i2c_client *client, u16 addr, u8 val) -+{ -+ reg16_write(client, 0xFFFD, 0x80); -+ usleep_range(100, 150); /* wait 100 us */ -+ reg16_write(client, 0xFFFE, 0x19); -+ usleep_range(100, 150); /* wait 100 us */ -+ reg16_write(client, 0x5000, 0x00); /* write operation */ -+ reg16_write(client, 0x5001, addr >> 8); -+ reg16_write(client, 0x5002, addr & 0xff); -+ reg16_write(client, 0x5003, val); -+ reg16_write(client, 0xFFFE, 0x80); -+ usleep_range(100, 150); /* wait 100 us */ -+ reg16_write(client, 0x00C0, 0xc1); -+} -+ -+static int ov490_s_stream(struct v4l2_subdev *sd, int enable) ++static int ov495_s_stream(struct v4l2_subdev *sd, int enable) +{ + return 0; +} + -+static int ov490_get_fmt(struct v4l2_subdev *sd, ++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 ov490_priv *priv = to_ov490(client); ++ struct ov495_priv *priv = to_ov495(client); + + if (format->pad) + return -EINVAL; @@ -7766,7 +13330,7 @@ index 0000000..812f367 + return 0; +} + -+static int ov490_set_fmt(struct v4l2_subdev *sd, ++static int ov495_set_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_format *format) +{ @@ -7782,7 +13346,7 @@ index 0000000..812f367 + return 0; +} + -+static int ov490_enum_mbus_code(struct v4l2_subdev *sd, ++static int ov495_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_mbus_code_enum *code) +{ @@ -7794,464 +13358,175 @@ index 0000000..812f367 + 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) ++static int ov495_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); -+ int ret; -+ u8 val = 0; ++ struct ov495_priv *priv = to_ov495(client); + -+ ret = reg16_read(client, (u16)reg->reg, &val); -+ if (ret < 0) -+ return ret; ++ memcpy(edid->edid, priv->id, 6); + -+ reg->val = val; -+ reg->size = sizeof(u16); ++ 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 ov490_s_register(struct v4l2_subdev *sd, -+ const struct v4l2_dbg_register *reg) ++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); -+ int ret; ++ struct ov495_priv *priv = to_ov495(client); + -+ 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 ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || ++ sel->target != V4L2_SEL_TGT_CROP) ++ return -EINVAL; + -+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 -+}; ++ rect->left = ALIGN(rect->left, 2); ++ rect->top = ALIGN(rect->top, 2); ++ rect->width = ALIGN(rect->width, 2); ++ rect->height = ALIGN(rect->height, 2); + -+static int ov490_s_gamma(int a, int ref) -+{ -+ if ((a + ref) > 0xff) -+ return 0xff; ++ if ((rect->left + rect->width > priv->max_width) || ++ (rect->top + rect->height > priv->max_height)) ++ *rect = priv->rect; + -+ if ((a + ref) < 0) -+ return 0; ++ priv->rect.left = rect->left; ++ priv->rect.top = rect->top; ++ priv->rect.width = rect->width; ++ priv->rect.height = rect->height; + -+ return a + ref; ++ return 0; +} + -+static int ov490_s_ctrl(struct v4l2_ctrl *ctrl) ++static int ov495_get_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_pad_config *cfg, ++ struct v4l2_subdev_selection *sel) +{ -+ 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; ++ struct ov495_priv *priv = to_ov495(client); + -+ 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_AUTO_WHITE_BALANCE: -+ case V4L2_CID_RED_BALANCE: -+ case V4L2_CID_BLUE_BALANCE: -+ if (ctrl->id == V4L2_CID_AUTO_WHITE_BALANCE) -+ priv->awb = ctrl->val; -+ if (ctrl->id == V4L2_CID_RED_BALANCE) { -+ priv->red = ctrl->val; -+ priv->red <<= 8; -+ priv->green_r = priv->red / 2; -+ } -+ if (ctrl->id == V4L2_CID_BLUE_BALANCE) { -+ priv->blue = ctrl->val; -+ priv->blue <<= 8; -+ priv->green_b = priv->blue / 2; -+ } ++ if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) ++ return -EINVAL; + -+ 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->awb); -+ ret |= reg16_write(client, 0x5001, priv->red >> 8); -+ ret |= reg16_write(client, 0x5002, priv->red & 0xff); -+ ret |= reg16_write(client, 0x5003, priv->green_r >> 8); -+ ret |= reg16_write(client, 0x5004, priv->green_r & 0xff); -+ ret |= reg16_write(client, 0x5005, priv->green_b >> 8); -+ ret |= reg16_write(client, 0x5006, priv->green_b & 0xff); -+ ret |= reg16_write(client, 0x5007, priv->blue >> 8); -+ ret |= reg16_write(client, 0x5008, priv->blue & 0xff); -+ ret |= reg16_write(client, 0x5009, priv->red >> 8); -+ ret |= reg16_write(client, 0x500a, priv->red & 0xff); -+ ret |= reg16_write(client, 0x500b, priv->green_r >> 8); -+ ret |= reg16_write(client, 0x500c, priv->green_r & 0xff); -+ ret |= reg16_write(client, 0x500d, priv->green_b >> 8); -+ ret |= reg16_write(client, 0x500e, priv->green_b & 0xff); -+ ret |= reg16_write(client, 0x500f, priv->blue >> 8); -+ ret |= reg16_write(client, 0x5010, priv->blue & 0xff); -+ ret |= reg16_write(client, 0x5011, priv->red >> 8); -+ ret |= reg16_write(client, 0x5012, priv->red & 0xff); -+ ret |= reg16_write(client, 0x5013, priv->green_r >> 8); -+ ret |= reg16_write(client, 0x5014, priv->green_r & 0xff); -+ ret |= reg16_write(client, 0x5015, priv->green_b >> 8); -+ ret |= reg16_write(client, 0x5016, priv->green_b & 0xff); -+ ret |= reg16_write(client, 0x5017, priv->blue >> 8); -+ ret |= reg16_write(client, 0x5018, priv->blue & 0xff); -+ ret |= reg16_write(client, 0xFFFE, 0x80); -+ usleep_range(100, 150); /* wait 100 us */ -+ ret |= reg16_write(client, 0x00C0, 0xeb); -+ 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); ++ 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; ++ } ++} + -+ 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); ++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; + -+ 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); ++ 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 */ -+ 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); ++ if ((u8)reg->reg == 0xFFFE) + usleep_range(100, 150); /* wait 100 us */ -+ ret |= reg16_write(client, 0x00C0, 0xc1); ++ return ret; ++} +#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); ++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 ++}; + -+ 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); ++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, 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); ++ 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, 0x00C0, 0xc1); -+#endif ++ ret |= reg16_write(client, 0x30C0, 0xdc); ++ ret |= reg16_write(client, 0x3516, 0x01); + break; + case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: + ret = 0; @@ -8261,198 +13536,153 @@ index 0000000..812f367 + return ret; +} + -+static const struct v4l2_ctrl_ops ov490_ctrl_ops = { -+ .s_ctrl = ov490_s_ctrl, ++static const struct v4l2_ctrl_ops ov495_ctrl_ops = { ++ .s_ctrl = ov495_s_ctrl, +}; + -+static struct v4l2_subdev_video_ops ov490_video_ops = { -+ .s_stream = ov490_s_stream, -+ .g_mbus_config = ov490_g_mbus_config, ++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 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 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 ov490_subdev_ops = { -+ .core = &ov490_core_ops, -+ .video = &ov490_video_ops, -+ .pad = &ov490_subdev_pad_ops, ++static struct v4l2_subdev_ops ov495_subdev_ops = { ++ .core = &ov495_core_ops, ++ .video = &ov495_video_ops, ++ .pad = &ov495_subdev_pad_ops, +}; + -+static void ov490_otp_id_read(struct i2c_client *client) ++static void ov495_otp_id_read(struct i2c_client *client) +{ -+ struct ov490_priv *priv = to_ov490(client); ++ struct ov495_priv *priv = to_ov495(client); + int i; -+ int otp_bank0_allzero = 1; + +#if 0 -+ /* read camera id from ov490 OTP memory */ ++ /* read camera id from ov495 OTP memory */ + reg16_write(client, 0xFFFD, 0x80); -+ reg16_write(client, 0xFFFE, 0x28); ++ reg16_write(client, 0xFFFE, 0x20); + usleep_range(100, 150); /* wait 100 us */ -+ reg16_write(client, 0xE084, 0x40); /* manual mode, bank#0 */ -+ reg16_write(client, 0xE081, 1); /* start OTP read */ ++ reg16_write(client, 0x7384, 0x40); /* manual mode, bank#0 */ ++ reg16_write(client, 0x7381, 1); /* start OTP read */ + + usleep_range(25000, 26000); /* wait 25 ms */ + + for (i = 0; i < 6; i++) -+ reg16_read(client, 0xe000 + i + 4, &priv->id[i]); ++ reg16_read(client, 0x7300 + i + 4, &priv->id[i]); +#else -+ /* read camera id from ov10640 OTP memory */ -+ ov490_ov10640_write(client, 0x349C, 1); ++ /* read camera id from ov2775 OTP memory */ ++ reg16_write(client, 0x3516, 0x00); /* unlock write */ ++ reg16_write(client, 0x0FFC, 0); ++ reg16_write(client, 0x0500, 0x00); /* write 0x34a1 -> 1 */ ++ reg16_write(client, 0x0501, 0x34); ++ reg16_write(client, 0x0502, 0xa1); ++ reg16_write(client, 0x0503, 1); ++ reg16_write(client, 0x30C0, 0xc1); ++ + usleep_range(25000, 25500); /* wait 25 ms */ + + for (i = 0; i < 6; i++) { -+ /* first 6 bytes are equal on all ov10640 */ -+ priv->id[i] = ov490_ov10640_read(client, 0x349e + i + 6); -+ if (priv->id[i]) -+ otp_bank0_allzero = 0; -+ } -+ -+ if (otp_bank0_allzero) { -+ ov490_ov10640_write(client, 0x3495, 0x41); /* bank#1 */ -+ ov490_ov10640_write(client, 0x349C, 1); -+ usleep_range(25000, 25500); /* wait 25 ms */ -+ -+ for (i = 0; i < 6; i++) -+ priv->id[i] = ov490_ov10640_read(client, 0x34ae + i); ++ reg16_write(client, 0x3516, 0x00); /* unlock write */ ++ reg16_write(client, 0x0500, 0x01); /* read (0x7a00 + i) */ ++ reg16_write(client, 0x0501, 0x7a); ++ reg16_write(client, 0x0502, 0x00 + i + (i < 3 ? 11 : 3)); /* take bytes 11,12,13,6,7,8 */ ++ reg16_write(client, 0x30C0, 0xc1); ++ usleep_range(1000, 1500); /* wait 1 ms */ ++ reg16_read(client, 0x0500, &priv->id[i]); + } +#endif +} + -+static ssize_t ov490_otp_id_show(struct device *dev, ++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 ov490_priv *priv = to_ov490(client); ++ 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_ov490, S_IRUGO, ov490_otp_id_show, NULL); ++static DEVICE_ATTR(otp_id_ov495, S_IRUGO, ov495_otp_id_show, NULL); + -+static int ov490_initialize(struct i2c_client *client) ++static int ov495_initialize(struct i2c_client *client) +{ -+ struct ov490_priv *priv = to_ov490(client); -+ u8 val = 0; ++ struct ov495_priv *priv = to_ov495(client); + u8 pid = 0, ver = 0; -+ int ret = 0, timeout, retry_timeout = 3; -+ -+ if (priv->is_fixed_sensor) { -+ dev_info(&client->dev, "ov490/ov10640 fixed-sensor res %dx%d\n", priv->max_width, priv->max_height); -+ return 0; -+ } -+ -+ ov490_s_port(client, 1); ++ int ret = 0; ++ int tmp_addr; + + /* 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, OV495_PID, &pid); ++ reg16_read(client, OV495_VER, &ver); + -+ if (OV490_VERSION(pid, ver) != OV490_VERSION_REG) { -+ dev_dbg(&client->dev, "Product ID error %x:%x\n", pid, ver); ++ if (OV495_VERSION(pid, ver) != OV495_VERSION_REG) { ++ dev_err(&client->dev, "Product ID error %x:%x\n", pid, ver); + ret = -ENODEV; + goto err; + } + -+ if (unlikely(conf_link)) -+ goto out; -+ -+again: -+ /* Check if firmware booted by reading stream-on status */ -+ reg16_write(client, 0xFFFD, 0x80); -+ reg16_write(client, 0xFFFE, 0x29); -+ usleep_range(100, 150); /* wait 100 us */ -+ for (timeout = 300; timeout > 0; timeout--) { -+ reg16_read(client, 0xd000, &val); -+ if (val == 0x0c) -+ break; -+ mdelay(1); -+ } -+ -+ /* wait firmware apps started by reading OV10640 ID */ -+ for (;timeout > 0; timeout--) { -+ reg16_write(client, 0xFFFD, 0x80); -+ reg16_write(client, 0xFFFE, 0x19); -+ usleep_range(100, 150); /* wait 100 us */ -+ reg16_write(client, 0x5000, 0x01); -+ reg16_write(client, 0x5001, 0x30); -+ reg16_write(client, 0x5002, 0x0a); -+ reg16_write(client, 0xFFFE, 0x80); -+ usleep_range(100, 150); /* wait 100 us */ -+ reg16_write(client, 0xC0, 0xc1); -+ reg16_write(client, 0xFFFE, 0x19); -+ usleep_range(1000, 1500); /* wait 1 ms */ -+ reg16_read(client, 0x5000, &val); -+ if (val == 0xa6) -+ break; -+ mdelay(1); ++ /* setup XCLK */ ++ tmp_addr = client->addr; ++ if (priv->ti9x4_addr) { ++ /* CLK_OUT=22.5792*160*M/N/CLKDIV -> CLK_OUT=25MHz: CLKDIV=4, M=7, N=253: 22.5792*160/4*7/253=24.989MHz=CLK_OUT */ ++ client->addr = priv->ti9x3_addr; /* Serializer I2C address */ ++ reg8_write(client, 0x06, 0x47); /* Set CLKDIV and M */ ++ reg8_write(client, 0x07, 0xfd); /* Set N */ + } ++ client->addr = tmp_addr; + -+ if (!timeout) { -+ dev_err(&client->dev, "Timeout firmware boot wait, retrying\n"); -+ /* reset OV10640 using RESETB pin controlled by OV490 GPIO0 */ -+ reg16_write(client, 0xFFFD, 0x80); -+ reg16_write(client, 0xFFFE, 0x80); -+ usleep_range(100, 150); /* wait 100 us */ -+ reg16_write(client, 0x0050, 0x01); -+ reg16_write(client, 0x0054, 0x01); -+ reg16_write(client, 0x0058, 0x00); -+ mdelay(10); -+ reg16_write(client, 0x0058, 0x01); -+ /* reset OV490 using RESETB pin controlled by serializer */ -+ ov490_reset(client); -+ if (retry_timeout--) -+ goto again; -+ } ++ 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, OV490_ISP_HSIZE_HIGH, &val); ++ reg16_read(client, OV495_ISP_HSIZE_HIGH, &val); + priv->max_width = val; -+ reg16_read(client, OV490_ISP_HSIZE_LOW, &val); ++ reg16_read(client, OV495_ISP_HSIZE_LOW, &val); + priv->max_width = (priv->max_width << 8) | val; -+ reg16_read(client, OV490_ISP_VSIZE_HIGH, &val); ++ reg16_read(client, OV495_ISP_VSIZE_HIGH, &val); + priv->max_height = val; -+ reg16_read(client, OV490_ISP_VSIZE_LOW, &val); ++ reg16_read(client, OV495_ISP_VSIZE_LOW, &val); + priv->max_height = (priv->max_height << 8) | val; ++#else ++ priv->max_width = 1920; ++ priv->max_height = 1080; ++#endif ++ ++ /* set virtual channel */ ++ ov495_regs_wizard[3].val = 0x1e | (priv->port << 6); + /* Program wizard registers */ -+ 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); ++ ov495_set_regs(client, ov495_regs_wizard, ARRAY_SIZE(ov495_regs_wizard)); + /* Read OTP IDs */ -+ ov490_otp_id_read(client); ++ ov495_otp_id_read(client); + +out: -+ dev_info(&client->dev, "ov490/ov10640 PID %x%x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ dev_info(&client->dev, "ov495/ov2775 PID %x%x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", + pid, ver, priv->max_width, priv->max_height, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); +err: -+ ov490_s_port(client, 0); -+ + return ret; +} + -+static int ov490_parse_dt(struct device_node *np, struct ov490_priv *priv) ++static int ov495_parse_dt(struct device_node *np, struct ov495_priv *priv) +{ + struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); + int i; -+ const char *fixed_sensor; + struct device_node *endpoint = NULL, *rendpoint = NULL; + int tmp_addr = 0; + @@ -8463,26 +13693,10 @@ index 0000000..812f367 + + of_node_put(endpoint); + -+ of_property_read_u32(endpoint, "dvp-order", &priv->dvp_order); -+ + rendpoint = of_parse_phandle(endpoint, "remote-endpoint", 0); + if (!rendpoint) + continue; + -+ if (!of_property_read_u32(rendpoint, "max9271-addr", &priv->max9271_addr) && -+ !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->max9286_addr) && -+ !kstrtouint(strrchr(rendpoint->full_name, '@') + 1, 0, &priv->port)) { -+ if (of_property_read_u32(rendpoint->parent->parent, "maxim,resetb-gpio", &priv->gpio_resetb)) { -+ priv->gpio_resetb = -1; -+ } else { -+ if (of_property_read_bool(rendpoint->parent->parent, "maxim,resetb-active-high")) -+ priv->active_low_resetb = false; -+ else -+ priv->active_low_resetb = true; -+ } -+ break; -+ } -+ + if (!of_property_read_u32(rendpoint, "ti9x3-addr", &priv->ti9x3_addr) && + !of_property_match_string(rendpoint->parent->parent, "compatible", "ti,ti9x4") && + !of_property_read_u32(rendpoint->parent->parent, "reg", &priv->ti9x4_addr) && @@ -8490,61 +13704,34 @@ index 0000000..812f367 + break; + } + -+ if (!priv->max9286_addr && !priv->ti9x4_addr) { -+ dev_err(&client->dev, "deserializer does not present for OV490\n"); ++ if (!priv->ti9x4_addr) { ++ dev_err(&client->dev, "deserializer does not present for OV495\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->ti9x4_addr) { + client->addr = priv->ti9x4_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, 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; + -+ if (!of_property_read_string(np, "maxim,fixed-sensor", &fixed_sensor) && -+ strcmp(fixed_sensor, "ov490") == 0) { -+ if (of_property_read_u32(np, "maxim,width", &priv->max_width)) -+ priv->max_width = 1280; -+ -+ if (of_property_read_u32(np, "maxim,height", &priv->max_height)) -+ priv->max_height = 966; -+ -+ priv->is_fixed_sensor = true; -+ } -+ -+ /* module params override dts */ -+ if (dvp_order) -+ priv->dvp_order = dvp_order; -+ if (max_width && max_height) { -+ priv->max_width = max_width; -+ priv->max_height = max_height; -+ priv->is_fixed_sensor = true; -+ } -+ + return 0; +} + -+static int ov490_probe(struct i2c_client *client, ++static int ov495_probe(struct i2c_client *client, + const struct i2c_device_id *did) +{ -+ struct ov490_priv *priv; ++ struct ov495_priv *priv; + struct v4l2_ctrl *ctrl; + int ret; + @@ -8552,47 +13739,36 @@ index 0000000..812f367 + if (!priv) + return -ENOMEM; + -+ v4l2_i2c_subdev_init(&priv->sd, client, &ov490_subdev_ops); ++ 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; -+ priv->red = 0x400; -+ priv->blue = 0x400; -+ priv->green_r = priv->red / 2; -+ priv->green_b = priv->blue / 2; -+ priv->awb = 1; + v4l2_ctrl_handler_init(&priv->hdl, 4); -+ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, + V4L2_CID_BRIGHTNESS, 0, 16, 1, 7); -+ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, + V4L2_CID_CONTRAST, 0, 16, 1, 7); -+ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, + V4L2_CID_SATURATION, 0, 7, 1, 2); -+ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, + V4L2_CID_HUE, 0, 23, 1, 12); -+ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, + V4L2_CID_GAMMA, -128, 128, 1, 0); -+ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, + V4L2_CID_SHARPNESS, 0, 10, 1, 3); -+ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, + V4L2_CID_AUTOGAIN, 0, 1, 1, priv->autogain); -+ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, + V4L2_CID_GAIN, 0, 0xffff, 1, priv->gain); -+ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, + V4L2_CID_EXPOSURE, 0, 0xffff, 1, priv->exposure); -+ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, -+ V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, priv->autogain); -+ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, -+ V4L2_CID_RED_BALANCE, 2, 0xf, 1, priv->red >> 8); -+ v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, -+ V4L2_CID_BLUE_BALANCE, 2, 0xf, 1, priv->blue >> 8); -+ 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_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 0); ++ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, + V4L2_CID_VFLIP, 0, 1, 1, 0); -+ ctrl = v4l2_ctrl_new_std(&priv->hdl, &ov490_ctrl_ops, ++ ctrl = v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, + V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 9); + if (ctrl) + ctrl->flags &= ~V4L2_CTRL_FLAG_READ_ONLY; @@ -8610,11 +13786,11 @@ index 0000000..812f367 + if (ret < 0) + goto cleanup; + -+ ret = ov490_parse_dt(client->dev.of_node, priv); ++ ret = ov495_parse_dt(client->dev.of_node, priv); + if (ret) + goto cleanup; + -+ ret = ov490_initialize(client); ++ ret = ov495_initialize(client); + if (ret < 0) + goto cleanup; + @@ -8627,7 +13803,7 @@ index 0000000..812f367 + if (ret) + goto cleanup; + -+ if (device_create_file(&client->dev, &dev_attr_otp_id_ov490) != 0) { ++ 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; + } @@ -8640,18 +13816,18 @@ index 0000000..812f367 + media_entity_cleanup(&priv->sd.entity); + v4l2_ctrl_handler_free(&priv->hdl); + v4l2_device_unregister_subdev(&priv->sd); -+#ifdef CONFIG_SOC_CAMERA_OV490_OV10640 ++#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 ov490_remove(struct i2c_client *client) ++static int ov495_remove(struct i2c_client *client) +{ -+ struct ov490_priv *priv = i2c_get_clientdata(client); ++ struct ov495_priv *priv = i2c_get_clientdata(client); + -+ device_remove_file(&client->dev, &dev_attr_otp_id_ov490); ++ 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); @@ -8660,45 +13836,45 @@ index 0000000..812f367 + return 0; +} + -+#ifdef CONFIG_SOC_CAMERA_OV490_OV10640 -+static const struct i2c_device_id ov490_id[] = { -+ { "ov490-ov10640", 0 }, ++#ifdef CONFIG_SOC_CAMERA_OV495_OV2775 ++static const struct i2c_device_id ov495_id[] = { ++ { "ov495-ov2775", 0 }, + { } +}; -+MODULE_DEVICE_TABLE(i2c, ov490_id); ++MODULE_DEVICE_TABLE(i2c, ov495_id); + -+static const struct of_device_id ov490_of_ids[] = { -+ { .compatible = "ovti,ov490-ov10640", }, ++static const struct of_device_id ov495_of_ids[] = { ++ { .compatible = "ovti,ov495-ov2775", }, + { } +}; -+MODULE_DEVICE_TABLE(of, ov490_of_ids); ++MODULE_DEVICE_TABLE(of, ov495_of_ids); + -+static struct i2c_driver ov490_i2c_driver = { ++static struct i2c_driver ov495_i2c_driver = { + .driver = { -+ .name = "ov490-ov10640", -+ .of_match_table = ov490_of_ids, ++ .name = "ov495-ov2775", ++ .of_match_table = ov495_of_ids, + }, -+ .probe = ov490_probe, -+ .remove = ov490_remove, -+ .id_table = ov490_id, ++ .probe = ov495_probe, ++ .remove = ov495_remove, ++ .id_table = ov495_id, +}; + -+module_i2c_driver(ov490_i2c_driver); ++module_i2c_driver(ov495_i2c_driver); + -+MODULE_DESCRIPTION("SoC Camera driver for OV490-OV10640"); ++MODULE_DESCRIPTION("SoC Camera driver for OV495-OV2775"); +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 +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..b22e93e +index 0000000..17c94ae --- /dev/null -+++ b/drivers/media/i2c/soc_camera/ov490_ov10640.h -@@ -0,0 +1,102 @@ ++++ b/drivers/media/i2c/soc_camera/ov495_ov2775.h +@@ -0,0 +1,23 @@ +/* -+ * OmniVision ov490-ov10640 sensor camera wizard 1280x1080@30/UYVY/BT601/8bit ++ * OmniVision ov495-ov2775 sensor camera wizard 1920x1080@30/UYVY/MIPI + * -+ * Copyright (C) 2016-2017 Cogent Embedded, Inc. ++ * 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 @@ -8706,107 +13882,28 @@ index 0000000..b22e93e + * option) any later version. + */ + -+//#define OV490_DISPLAY_PATTERN -+ -+struct ov490_reg { ++struct ov495_reg { + u16 reg; + u8 val; +}; + -+static const struct ov490_reg ov490_regs_wizard[] = { -+/* The following registers should match firmware */ -+{0xfffd, 0x80}, -+{0xfffe, 0x82}, -+{0x0071, 0x11}, -+{0x0075, 0x11}, -+{0xfffe, 0x29}, -+{0x6010, 0x01}, -+/* ov490 EMB line disable in YUV and RAW data, NOTE: EMB line is still used in ISP and sensor */ -+{0xe000, 0x14}, -+#if 0 /* do not disable EMB line in ISP! */ -+{0x4017, 0x00}, -+#endif -+{0xfffe, 0x28}, -+{0x6000, 0x04}, -+{0x6004, 0x00}, -+{0x6008, 0x00}, // PCLK polarity - useless due to silicon bug -> use 0x808000bb register -+{0xfffe, 0x80}, -+{0x0091, 0x00}, -+{0x00bb, 0x1d}, // bit[3]=0 - PCLK polarity workaround -+/* ov10640 EMB line disable */ -+#if 0 /* do not disable EMB line in sensor! */ -+{0xfffe, 0x19}, -+{0x5000, 0x00}, -+{0x5001, 0x30}, -+{0x5002, 0x91}, -+{0x5003, 0x08}, -+{0xfffe, 0x80}, -+{0x00c0, 0xc1}, -+#endif -+/* Ov490 FSIN: app_fsin_from_fsync */ -+{0xfffe, 0x85}, -+{0x0008, 0x00}, -+{0x0009, 0x01}, -+{0x000A, 0x05}, // fsin0 src -+{0x000B, 0x00}, -+{0x0030, 0x02}, // fsin0_delay -+{0x0031, 0x00}, -+{0x0032, 0x00}, -+{0x0033, 0x00}, -+{0x0038, 0x02}, // fsin1_delay -+{0x0039, 0x00}, -+{0x003A, 0x00}, -+{0x003B, 0x00}, -+{0x0070, 0x2C}, // fsin0_length -+{0x0071, 0x01}, -+{0x0072, 0x00}, -+{0x0073, 0x00}, -+{0x0074, 0x64}, // fsin1_length -+{0x0075, 0x00}, -+{0x0076, 0x00}, -+{0x0077, 0x00}, -+{0x0000, 0x14}, -+{0x0001, 0x00}, -+{0x0002, 0x00}, -+{0x0003, 0x00}, -+{0x0004, 0x32}, // load fsin0,load fsin1,load other, it will be cleared automatically. -+{0x0005, 0x00}, -+{0x0006, 0x00}, -+{0x0007, 0x00}, -+{0xfffe, 0x80}, -+{0x0081, 0x00}, // 03;SENSOR FSIN -+/* ov10640 FSIN */ -+{0xfffe, 0x19}, -+{0x5000, 0x00}, -+{0x5001, 0x30}, -+{0x5002, 0x8c}, -+{0x5003, 0xb2}, -+{0xfffe, 0x80}, -+{0x00c0, 0xc1}, -+/* ov10640 HFLIP=1 by default */ -+{0xfffe, 0x19}, -+{0x5000, 0x01}, -+{0x5001, 0x00}, -+{0xfffe, 0x80}, -+{0x00c0, 0xdc}, -+#ifdef OV490_DISPLAY_PATTERN -+{0xfffd, 0x80}, -+{0xfffe, 0x19}, -+{0x5000, 0x02}, -+{0xfffe, 0x80}, -+{0x00c0, 0xd6}, -+#endif ++static struct ov495_reg ov495_regs_wizard[] = { ++{0x3516, 0x00}, /* unlock write */ ++{0xFFFD, 0x80}, ++{0xFFFE, 0x20}, ++{0x8017, 0x1e | (0 << 6)}, ++{0x7c10, 0x01}, /* UYVY */ +}; -diff --git a/drivers/media/i2c/soc_camera/ov495_ov2775.c b/drivers/media/i2c/soc_camera/ov495_ov2775.c +diff --git a/drivers/media/i2c/soc_camera/ox03a.c b/drivers/media/i2c/soc_camera/ox03a.c new file mode 100644 -index 0000000..e53c482 +index 0000000..d51512b9 --- /dev/null -+++ b/drivers/media/i2c/soc_camera/ov495_ov2775.c -@@ -0,0 +1,639 @@ ++++ b/drivers/media/i2c/soc_camera/ox03a.c +@@ -0,0 +1,526 @@ +/* -+ * OmniVision ov495-ov2775 sensor camera driver ++ * OmniVision OX03A sensor camera driver + * -+ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * Copyright (C) 2018 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 @@ -8825,106 +13922,88 @@ index 0000000..e53c482 +#include +#include + -+#include "ov495_ov2775.h" ++#include "ox03a.h" + -+#define OV495_I2C_ADDR 0x24 ++#define OX03A_I2C_ADDR 0x36 + -+#define OV495_PID 0x300a -+#define OV495_VER 0x300b -+#define OV495_VERSION_REG 0x0495 -+#define OV495_VERSION(pid, ver) (((pid) << 8) | ((ver) & 0xff)) ++#define OX03A_PID 0x300A ++#define OX03A_VER 0x300B ++#define OX03A_VERSION_REG 0x5803 + -+#define OV495_ISP_HSIZE_LOW 0x60 -+#define OV495_ISP_HSIZE_HIGH 0x61 -+#define OV495_ISP_VSIZE_LOW 0x62 -+#define OV495_ISP_VSIZE_HIGH 0x63 ++#define OX03A_MEDIA_BUS_FMT MEDIA_BUS_FMT_SBGGR12_1X12 + -+struct ov495_priv { ++struct ox03a_priv { + struct v4l2_subdev sd; + struct v4l2_ctrl_handler hdl; + struct media_pad pad; + struct v4l2_rect rect; -+ int max_width; -+ int max_height; + int init_complete; + u8 id[6]; + int exposure; + int gain; + int autogain; + /* serializers */ -+ int max9286_addr; -+ int max9271_addr; + int ti9x4_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) ++static inline struct ox03a_priv *to_ox03a(const struct i2c_client *client) +{ -+ return container_of(i2c_get_clientdata(client), struct ov495_priv, sd); ++ return container_of(i2c_get_clientdata(client), struct ox03a_priv, sd); +} + -+static int ov495_set_regs(struct i2c_client *client, -+ const struct ov495_reg *regs, int nr_regs) ++static int ox03a_set_regs(struct i2c_client *client, ++ const struct ox03a_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); ++ if (regs[i].reg == OX03A_DELAY) { ++ mdelay(regs[i].val); ++ continue; + } ++ ++ reg16_write(client, regs[i].reg, regs[i].val); + } + + return 0; +} + -+static int ov495_s_stream(struct v4l2_subdev *sd, int enable) ++static int ox03a_s_stream(struct v4l2_subdev *sd, int enable) +{ + return 0; +} + -+static int ov495_get_fmt(struct v4l2_subdev *sd, ++static int ox03a_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); ++ struct ox03a_priv *priv = to_ox03a(client); + + if (format->pad) + return -EINVAL; + + mf->width = priv->rect.width; + mf->height = priv->rect.height; -+ mf->code = MEDIA_BUS_FMT_YUYV8_2X8; ++ mf->code = OX03A_MEDIA_BUS_FMT; + mf->colorspace = V4L2_COLORSPACE_SMPTE170M; + mf->field = V4L2_FIELD_NONE; + + return 0; +} + -+static int ov495_set_fmt(struct v4l2_subdev *sd, ++static int ox03a_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->code = OX03A_MEDIA_BUS_FMT; + mf->colorspace = V4L2_COLORSPACE_SMPTE170M; + mf->field = V4L2_FIELD_NONE; + @@ -8934,40 +14013,40 @@ index 0000000..e53c482 + return 0; +} + -+static int ov495_enum_mbus_code(struct v4l2_subdev *sd, ++static int ox03a_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; ++ code->code = OX03A_MEDIA_BUS_FMT; + + return 0; +} + -+static int ov495_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) ++static int ox03a_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); ++ struct ox03a_priv *priv = to_ox03a(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; ++ edid->edid[8] = OX03A_VERSION_REG >> 8; ++ edid->edid[9] = OX03A_VERSION_REG & 0xff; + + return 0; +} + -+static int ov495_set_selection(struct v4l2_subdev *sd, ++static int ox03a_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); ++ struct ox03a_priv *priv = to_ox03a(client); + + if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE || + sel->target != V4L2_SEL_TGT_CROP) @@ -8978,8 +14057,8 @@ index 0000000..e53c482 + 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)) ++ if ((rect->left + rect->width > OX03A_MAX_WIDTH) || ++ (rect->top + rect->height > OX03A_MAX_HEIGHT)) + *rect = priv->rect; + + priv->rect.left = rect->left; @@ -8990,12 +14069,12 @@ index 0000000..e53c482 + return 0; +} + -+static int ov495_get_selection(struct v4l2_subdev *sd, ++static int ox03a_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); ++ struct ox03a_priv *priv = to_ox03a(client); + + if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; @@ -9004,14 +14083,14 @@ index 0000000..e53c482 + 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; ++ sel->r.width = OX03A_MAX_WIDTH; ++ sel->r.height = OX03A_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; ++ sel->r.width = OX03A_MAX_WIDTH; ++ sel->r.height = OX03A_MAX_HEIGHT; + return 0; + case V4L2_SEL_TGT_CROP: + sel->r = priv->rect; @@ -9021,7 +14100,7 @@ index 0000000..e53c482 + } +} + -+static int ov495_g_mbus_config(struct v4l2_subdev *sd, ++static int ox03a_g_mbus_config(struct v4l2_subdev *sd, + struct v4l2_mbus_config *cfg) +{ + cfg->flags = V4L2_MBUS_CSI2_1_LANE | V4L2_MBUS_CSI2_CHANNEL_0 | @@ -9032,7 +14111,7 @@ index 0000000..e53c482 +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG -+static int ov495_g_register(struct v4l2_subdev *sd, ++static int ox03a_g_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +{ + struct i2c_client *client = v4l2_get_subdevdata(sd); @@ -9044,38 +14123,32 @@ index 0000000..e53c482 + return ret; + + reg->val = val; -+ reg->size = sizeof(u16); ++ reg->size = sizeof(u8); + + return 0; +} + -+static int ov495_s_register(struct v4l2_subdev *sd, ++static int ox03a_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; ++ return reg16_write(client, (u16)reg->reg, (u8)reg->val); +} +#endif + -+static struct v4l2_subdev_core_ops ov495_core_ops = { ++static struct v4l2_subdev_core_ops ox03a_core_ops = { +#ifdef CONFIG_VIDEO_ADV_DEBUG -+ .g_register = ov495_g_register, -+ .s_register = ov495_s_register, ++ .g_register = ox03a_g_register, ++ .s_register = ox03a_s_register, +#endif +}; + -+static int ov495_s_ctrl(struct v4l2_ctrl *ctrl) ++static int ox03a_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); ++ struct ox03a_priv *priv = to_ox03a(client); + int ret = -EINVAL; + + if (!priv->init_complete) @@ -9083,180 +14156,94 @@ index 0000000..e53c482 + + switch (ctrl->id) { + case V4L2_CID_BRIGHTNESS: -+ break; + case V4L2_CID_CONTRAST: -+ break; + case V4L2_CID_SATURATION: -+ break; + case V4L2_CID_HUE: -+ break; + case V4L2_CID_GAMMA: -+ break; + case V4L2_CID_SHARPNESS: -+ break; + case V4L2_CID_AUTOGAIN: + case V4L2_CID_GAIN: -+ case V4L2_CID_EXPOSURE: -+ break; -+ case V4L2_CID_HFLIP: -+ ret = reg16_write(client, 0x3516, 0x00); -+ ret |= reg16_write(client, 0x0ffc, 0x00); -+ ret |= reg16_write(client, 0x0500, ctrl->val); -+ ret |= reg16_write(client, 0x0501, 0x00); -+ usleep_range(100, 150); /* wait 100 us */ -+ ret |= reg16_write(client, 0x30C0, 0xdc); -+ ret |= reg16_write(client, 0x3516, 0x01); -+ break; -+ case V4L2_CID_VFLIP: -+ ret = reg16_write(client, 0x3516, 0x00); -+ ret |= reg16_write(client, 0x0ffc, 0x00); -+ ret |= reg16_write(client, 0x0500, ctrl->val); -+ ret |= reg16_write(client, 0x0501, 0x01); -+ usleep_range(100, 150); /* wait 100 us */ -+ ret |= reg16_write(client, 0x30C0, 0xdc); -+ ret |= reg16_write(client, 0x3516, 0x01); -+ break; -+ case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: -+ ret = 0; ++ case V4L2_CID_EXPOSURE: ++ case V4L2_CID_HFLIP: ++ case V4L2_CID_VFLIP: + break; + } + + return ret; +} + -+static const struct v4l2_ctrl_ops ov495_ctrl_ops = { -+ .s_ctrl = ov495_s_ctrl, ++static const struct v4l2_ctrl_ops ox03a_ctrl_ops = { ++ .s_ctrl = ox03a_s_ctrl, +}; + -+static struct v4l2_subdev_video_ops ov495_video_ops = { -+ .s_stream = ov495_s_stream, -+ .g_mbus_config = ov495_g_mbus_config, ++static struct v4l2_subdev_video_ops ox03a_video_ops = { ++ .s_stream = ox03a_s_stream, ++ .g_mbus_config = ox03a_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 const struct v4l2_subdev_pad_ops ox03a_subdev_pad_ops = { ++ .get_edid = ox03a_get_edid, ++ .enum_mbus_code = ox03a_enum_mbus_code, ++ .get_selection = ox03a_get_selection, ++ .set_selection = ox03a_set_selection, ++ .get_fmt = ox03a_get_fmt, ++ .set_fmt = ox03a_set_fmt, +}; + -+static struct v4l2_subdev_ops ov495_subdev_ops = { -+ .core = &ov495_core_ops, -+ .video = &ov495_video_ops, -+ .pad = &ov495_subdev_pad_ops, ++static struct v4l2_subdev_ops ox03a_subdev_ops = { ++ .core = &ox03a_core_ops, ++ .video = &ox03a_video_ops, ++ .pad = &ox03a_subdev_pad_ops, +}; + -+static void ov495_otp_id_read(struct i2c_client *client) ++static void ox03a_otp_id_read(struct i2c_client *client) +{ -+ struct ov495_priv *priv = to_ov495(client); -+ int i; -+ -+#if 0 -+ /* read camera id from ov495 OTP memory */ -+ reg16_write(client, 0xFFFD, 0x80); -+ reg16_write(client, 0xFFFE, 0x20); -+ usleep_range(100, 150); /* wait 100 us */ -+ reg16_write(client, 0x7384, 0x40); /* manual mode, bank#0 */ -+ reg16_write(client, 0x7381, 1); /* start OTP read */ -+ -+ usleep_range(25000, 26000); /* wait 25 ms */ -+ -+ for (i = 0; i < 6; i++) -+ reg16_read(client, 0x7300 + i + 4, &priv->id[i]); -+#else -+ /* read camera id from ov2775 OTP memory */ -+ reg16_write(client, 0x3516, 0x00); /* unlock write */ -+ reg16_write(client, 0x0FFC, 0); -+ reg16_write(client, 0x0500, 0x00); /* write 0x34a1 -> 1 */ -+ reg16_write(client, 0x0501, 0x34); -+ reg16_write(client, 0x0502, 0xa1); -+ reg16_write(client, 0x0503, 1); -+ reg16_write(client, 0x30C0, 0xc1); -+ -+ usleep_range(25000, 25500); /* wait 25 ms */ -+ -+ for (i = 0; i < 6; i++) { -+ reg16_write(client, 0x3516, 0x00); /* unlock write */ -+ reg16_write(client, 0x0500, 0x01); /* read (0x7a00 + i) */ -+ reg16_write(client, 0x0501, 0x7a); -+ reg16_write(client, 0x0502, 0x00 + i + (i < 3 ? 11 : 3)); /* take bytes 11,12,13,6,7,8 */ -+ reg16_write(client, 0x30C0, 0xc1); -+ usleep_range(1000, 1500); /* wait 1 ms */ -+ reg16_read(client, 0x0500, &priv->id[i]); -+ } -+#endif +} + -+static ssize_t ov495_otp_id_show(struct device *dev, ++static ssize_t ox03a_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); ++ struct ox03a_priv *priv = to_ox03a(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 DEVICE_ATTR(otp_id_ox03a, S_IRUGO, ox03a_otp_id_show, NULL); + -+static int ov495_initialize(struct i2c_client *client) ++static int ox03a_initialize(struct i2c_client *client) +{ -+ struct ov495_priv *priv = to_ov495(client); -+ u8 pid = 0, ver = 0; ++ struct ox03a_priv *priv = to_ox03a(client); ++ u8 val = 0; ++ u16 pid; + 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); ++ /* check and show model ID */ ++ reg16_read(client, OX03A_PID, &val); ++ pid = val; ++ reg16_read(client, OX03A_VER, &val); ++ pid = (pid << 8) | val; + -+ if (OV495_VERSION(pid, ver) != OV495_VERSION_REG) { -+ dev_err(&client->dev, "Product ID error %x:%x\n", pid, ver); ++ if (pid != OX03A_VERSION_REG) { ++ dev_dbg(&client->dev, "Product ID error %x\n", pid); + ret = -ENODEV; + goto err; + } + -+ if (unlikely(force_conf_link)) -+ goto out; -+ -+#if 0 -+ /* read resolution used by current firmware */ -+ reg16_write(client, 0xFFFD, 0x80); -+ reg16_write(client, 0xFFFE, 0x82); -+ usleep_range(100, 150); /* wait 100 us */ -+ reg16_read(client, OV495_ISP_HSIZE_HIGH, &val); -+ priv->max_width = val; -+ reg16_read(client, OV495_ISP_HSIZE_LOW, &val); -+ priv->max_width = (priv->max_width << 8) | val; -+ reg16_read(client, OV495_ISP_VSIZE_HIGH, &val); -+ priv->max_height = val; -+ reg16_read(client, OV495_ISP_VSIZE_LOW, &val); -+ priv->max_height = (priv->max_height << 8) | val; -+#else -+ priv->max_width = 1920; -+ priv->max_height = 1080; -+#endif -+ -+ /* set virtual channel */ -+ ov495_regs_wizard[3].val = 0x1e | (priv->port << 6); + /* Program wizard registers */ -+ ov495_set_regs(client, ov495_regs_wizard, ARRAY_SIZE(ov495_regs_wizard)); ++ ox03a_set_regs(client, ox03a_regs_wizard, ARRAY_SIZE(ox03a_regs_wizard)); + /* Read OTP IDs */ -+ ov495_otp_id_read(client); ++ ox03a_otp_id_read(client); + -+out: -+ dev_info(&client->dev, "ov495/ov2775 PID %x%x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", -+ pid, ver, priv->max_width, priv->max_height, priv->id[0], priv->id[1], priv->id[2], priv->id[3], priv->id[4], priv->id[5]); ++ dev_info(&client->dev, "ox03a PID %x, res %dx%d, OTP_ID %02x:%02x:%02x:%02x:%02x:%02x\n", ++ pid, OX03A_MAX_WIDTH, OX03A_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) ++static int ox03a_parse_dt(struct device_node *np, struct ox03a_priv *priv) +{ + struct i2c_client *client = v4l2_get_subdevdata(&priv->sd); + int i; @@ -9282,7 +14269,7 @@ index 0000000..e53c482 + } + + if (!priv->ti9x4_addr) { -+ dev_err(&client->dev, "deserializer does not present for OV495\n"); ++ dev_err(&client->dev, "deserializer does not present\n"); + return -EINVAL; + } + @@ -9290,65 +14277,62 @@ index 0000000..e53c482 + tmp_addr = client->addr; + if (priv->ti9x4_addr) { + client->addr = priv->ti9x4_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, 0x5d, OX03A_I2C_ADDR << 1); /* Sensor native I2C address */ ++// reg8_write(client, 0x6e, 0xa9); /* GPIO0 - reset, GPIO1 - fsin */ + -+ 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 = priv->ti9x3_addr; /* Serializer I2C address */ ++// reg8_write(client, 0x0d, 0x03); /* unreset gpios */ ++// reg8_write(client, 0x0e, 0xf0); /* unreset gpios */ + } + client->addr = tmp_addr; + ++ mdelay(10); ++ + return 0; +} + -+static int ov495_probe(struct i2c_client *client, ++static int ox03a_probe(struct i2c_client *client, + const struct i2c_device_id *did) +{ -+ struct ov495_priv *priv; -+ struct v4l2_ctrl *ctrl; ++ struct ox03a_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); ++ v4l2_i2c_subdev_init(&priv->sd, client, &ox03a_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_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops, + V4L2_CID_BRIGHTNESS, 0, 16, 1, 7); -+ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops, + V4L2_CID_CONTRAST, 0, 16, 1, 7); -+ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops, + V4L2_CID_SATURATION, 0, 7, 1, 2); -+ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops, + V4L2_CID_HUE, 0, 23, 1, 12); -+ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops, + V4L2_CID_GAMMA, -128, 128, 1, 0); -+ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops, + V4L2_CID_SHARPNESS, 0, 10, 1, 3); -+ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops, + V4L2_CID_AUTOGAIN, 0, 1, 1, priv->autogain); -+ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops, + V4L2_CID_GAIN, 0, 0xffff, 1, priv->gain); -+ v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, ++ v4l2_ctrl_new_std(&priv->hdl, &ox03a_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_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 1); ++ v4l2_ctrl_new_std(&priv->hdl, &ox03a_ctrl_ops, + V4L2_CID_VFLIP, 0, 1, 1, 0); -+ ctrl = v4l2_ctrl_new_std(&priv->hdl, &ov495_ctrl_ops, -+ V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 9); -+ if (ctrl) -+ ctrl->flags &= ~V4L2_CTRL_FLAG_READ_ONLY; + priv->sd.ctrl_handler = &priv->hdl; + + ret = priv->hdl.error; @@ -9363,24 +14347,24 @@ index 0000000..e53c482 + if (ret < 0) + goto cleanup; + -+ ret = ov495_parse_dt(client->dev.of_node, priv); ++ ret = ox03a_parse_dt(client->dev.of_node, priv); + if (ret) + goto cleanup; + -+ ret = ov495_initialize(client); ++ ret = ox03a_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; ++ priv->rect.width = OX03A_MAX_WIDTH; ++ priv->rect.height = OX03A_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) { ++ if (device_create_file(&client->dev, &dev_attr_otp_id_ox03a) != 0) { + dev_err(&client->dev, "sysfs otp_id entry creation failed\n"); + goto cleanup; + } @@ -9393,18 +14377,18 @@ index 0000000..e53c482 + media_entity_cleanup(&priv->sd.entity); + v4l2_ctrl_handler_free(&priv->hdl); + v4l2_device_unregister_subdev(&priv->sd); -+#ifdef CONFIG_SOC_CAMERA_OV495_OV2775 ++#ifdef CONFIG_SOC_CAMERA_OX03A + 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) ++static int ox03a_remove(struct i2c_client *client) +{ -+ struct ov495_priv *priv = i2c_get_clientdata(client); ++ struct ox03a_priv *priv = i2c_get_clientdata(client); + -+ device_remove_file(&client->dev, &dev_attr_otp_id_ov495); ++ device_remove_file(&client->dev, &dev_attr_otp_id_ox03a); + v4l2_async_unregister_subdev(&priv->sd); + media_entity_cleanup(&priv->sd.entity); + v4l2_ctrl_handler_free(&priv->hdl); @@ -9413,45 +14397,45 @@ index 0000000..e53c482 + return 0; +} + -+#ifdef CONFIG_SOC_CAMERA_OV495_OV2775 -+static const struct i2c_device_id ov495_id[] = { -+ { "ov495-ov2775", 0 }, ++#ifdef CONFIG_SOC_CAMERA_OX03A ++static const struct i2c_device_id ox03a_id[] = { ++ { "ox03a", 0 }, + { } +}; -+MODULE_DEVICE_TABLE(i2c, ov495_id); ++MODULE_DEVICE_TABLE(i2c, ox03a_id); + -+static const struct of_device_id ov495_of_ids[] = { -+ { .compatible = "ovti,ov495-ov2775", }, ++static const struct of_device_id ox03a_of_ids[] = { ++ { .compatible = "ovti,ox03a", }, + { } +}; -+MODULE_DEVICE_TABLE(of, ov495_of_ids); ++MODULE_DEVICE_TABLE(of, ox03a_of_ids); + -+static struct i2c_driver ov495_i2c_driver = { ++static struct i2c_driver ox03a_i2c_driver = { + .driver = { -+ .name = "ov495-ov2775", -+ .of_match_table = ov495_of_ids, ++ .name = "ox03a", ++ .of_match_table = ox03a_of_ids, + }, -+ .probe = ov495_probe, -+ .remove = ov495_remove, -+ .id_table = ov495_id, ++ .probe = ox03a_probe, ++ .remove = ox03a_remove, ++ .id_table = ox03a_id, +}; + -+module_i2c_driver(ov495_i2c_driver); ++module_i2c_driver(ox03a_i2c_driver); + -+MODULE_DESCRIPTION("SoC Camera driver for OV495-OV2775"); ++MODULE_DESCRIPTION("SoC Camera driver for OX03A"); +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 +diff --git a/drivers/media/i2c/soc_camera/ox03a.h b/drivers/media/i2c/soc_camera/ox03a.h new file mode 100644 -index 0000000..17c94ae +index 0000000..b69273a --- /dev/null -+++ b/drivers/media/i2c/soc_camera/ov495_ov2775.h -@@ -0,0 +1,23 @@ ++++ b/drivers/media/i2c/soc_camera/ox03a.h +@@ -0,0 +1,1724 @@ +/* -+ * OmniVision ov495-ov2775 sensor camera wizard 1920x1080@30/UYVY/MIPI ++ * OmniVision OX03A sensor camera wizard 1920x1080@30/BGGR/MIPI + * -+ * Copyright (C) 2017 Cogent Embedded, Inc. ++ * Copyright (C) 2018 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 @@ -9459,21 +14443,1722 @@ index 0000000..17c94ae + * option) any later version. + */ + -+struct ov495_reg { ++#define OX03A_DISPLAY_PATTERN_COLOR_BAR ++ ++#define OX03A_MAX_WIDTH 1920 ++#define OX03A_MAX_HEIGHT 1080 ++ ++#define OX03A_DELAY 0xffff ++#define OX03A_DT 0x2c /* MIPI Data Type RAW12 */ ++ ++struct ox03a_reg { + u16 reg; + u8 val; +}; + -+static struct ov495_reg ov495_regs_wizard[] = { -+{0x3516, 0x00}, /* unlock write */ -+{0xFFFD, 0x80}, -+{0xFFFE, 0x20}, -+{0x8017, 0x1e | (0 << 6)}, -+{0x7c10, 0x01}, /* UYVY */ ++/* wizard: MIPI 1920x1280 3x12 30fps 750MBPS */ ++static const struct ox03a_reg ox03a_regs_wizard[] = { ++{0x0103, 0x01}, // s/w reset ++{OX03A_DELAY, 10}, // Wait 10ms ++{0x0100, 0x00}, ++{0x0102, 0x00}, ++{0x0103, 0x00}, ++{0x0104, 0x04}, ++{0x0105, 0x00}, ++{0x0106, 0x00}, ++{0x0107, 0x00}, ++{0x0109, 0x00}, ++{0x0300, 0x00}, ++{0x0301, 0x01}, ++{0x0302, 0x00}, ++{0x0303, 0x02}, ++{0x0304, 0x00}, ++{0x0305, 0x3c}, ++{0x0306, 0x00}, ++{0x0307, 0x00}, ++{0x0308, 0x04}, ++{0x0309, 0x02}, ++{0x030a, 0x00}, ++{0x030c, 0x00}, ++{0x030d, 0x00}, ++{0x0310, 0x00}, ++{0x0311, 0x00}, ++{0x0312, 0x00}, ++{0x0313, 0x00}, ++{0x0314, 0x00}, ++{0x0315, 0x00}, ++{0x0316, 0x00}, ++{0x0317, 0x12}, ++{0x0318, 0x01}, ++{0x0320, 0x00}, ++{0x0321, 0x01}, ++{0x0322, 0x00}, ++{0x0323, 0x02}, ++{0x0324, 0x00}, ++{0x0325, 0x6c}, ++{0x0326, 0x00}, ++{0x0327, 0x05}, ++{0x0328, 0x05}, ++{0x0329, 0x01}, ++{0x032a, 0x02}, ++{0x032b, 0x00}, ++{0x032c, 0x00}, ++{0x0400, 0xe7}, ++{0x0401, 0xff}, ++{0x0404, 0x2b}, ++{0x0405, 0x32}, ++{0x0406, 0x33}, ++{0x0407, 0x8f}, ++{0x0408, 0x0c}, ++{0x040a, 0x00}, ++{0x0410, 0xe7}, ++{0x0411, 0xff}, ++{0x0414, 0x2b}, ++{0x0415, 0x32}, ++{0x0416, 0x33}, ++{0x0417, 0x8f}, ++{0x0418, 0x0c}, ++{0x041a, 0x00}, ++{0x2803, 0x00}, ++{0x3000, 0x00}, ++{0x3001, 0x03}, ++{0x3002, 0x03}, ++{0x3003, 0x00}, ++{0x3004, 0x04}, ++{0x3005, 0x00}, ++{0x3006, 0x00}, ++{0x3007, 0x04}, ++{0x3008, 0x00}, ++{0x3009, 0x06}, ++{0x300d, 0x11}, ++{0x300e, 0x11}, ++{0x300f, 0x11}, ++{0x3012, 0x41}, ++{0x3016, 0xf0}, ++{0x3017, 0xf0}, ++{0x3018, 0xf0}, ++{0x3019, 0xf0}, ++{0x301a, 0xf0}, ++{0x301b, 0xb4}, ++{0x301c, 0x01}, ++{0x301d, 0x02}, ++{0x301e, 0xb8}, ++{0x301f, 0xe1}, ++{0x3020, 0x01}, ++{0x3021, 0x00}, ++{0x3022, 0xf8}, ++{0x3023, 0xf0}, ++{0x3024, 0xf0}, ++{0x3025, 0x02}, ++{0x3026, 0x00}, ++{0x3027, 0x00}, ++{0x3028, 0xf0}, ++{0x3029, 0x80}, ++{0x3035, 0x6c}, ++{0x3036, 0x42}, ++{0x3037, 0x20}, ++{0x3038, 0x00}, ++{0x3700, 0x26}, ++{0x3701, 0x1e}, ++{0x3702, 0x25}, ++{0x3703, 0x28}, ++{0x3704, 0x0f}, ++{0x3705, 0x00}, ++{0x3706, 0x39}, ++{0x3707, 0x0a}, ++{0x3708, 0x36}, ++{0x3709, 0x41}, ++{0x370a, 0x00}, ++{0x370b, 0xa3}, ++{0x370c, 0x0f}, ++{0x370d, 0x00}, ++{0x370e, 0xa6}, ++{0x370f, 0x95}, ++{0x3710, 0x15}, ++{0x3711, 0x72}, ++{0x3712, 0x12}, ++{0x3713, 0x00}, ++{0x3714, 0x22}, ++{0x3715, 0x00}, ++{0x3716, 0x04}, ++{0x3717, 0x02}, ++{0x3718, 0x09}, ++{0x3719, 0x1f}, ++{0x371a, 0x0c}, ++{0x371b, 0x16}, ++{0x371c, 0x00}, ++{0x371d, 0x08}, ++{0x371e, 0x00}, ++{0x371f, 0x02}, ++{0x3720, 0x03}, ++{0x3721, 0x1c}, ++{0x3722, 0x87}, ++{0x3723, 0x08}, ++{0x3724, 0x0d}, ++{0x3725, 0x08}, ++{0x3726, 0x0d}, ++{0x3727, 0x08}, ++{0x3728, 0x04}, ++{0x3729, 0x0c}, ++{0x372a, 0x01}, ++{0x372b, 0x01}, ++{0x372c, 0x17}, ++{0x372d, 0x01}, ++{0x372e, 0x35}, ++{0x372f, 0x43}, ++{0x3730, 0x04}, ++{0x3731, 0x06}, ++{0x3732, 0x01}, ++{0x3733, 0x41}, ++{0x3734, 0x0a}, ++{0x3735, 0x11}, ++{0x3736, 0x11}, ++{0x3737, 0x00}, ++{0x3738, 0x54}, ++{0x3739, 0x54}, ++{0x373a, 0x54}, ++{0x373b, 0x54}, ++{0x373c, 0x11}, ++{0x373d, 0x11}, ++{0x373e, 0x00}, ++{0x373f, 0x4c}, ++{0x3740, 0x4c}, ++{0x3741, 0x4c}, ++{0x3742, 0x23}, ++{0x3743, 0x01}, ++{0x3744, 0x16}, ++{0x3745, 0x08}, ++{0x3746, 0x03}, ++{0x3747, 0x01}, ++{0x3748, 0x07}, ++{0x3749, 0x01}, ++{0x374a, 0x07}, ++{0x374b, 0x03}, ++{0x374c, 0xb1}, ++{0x374d, 0x01}, ++{0x374e, 0x01}, ++{0x374f, 0x01}, ++{0x3750, 0x07}, ++{0x3751, 0x02}, ++{0x3752, 0x03}, ++{0x3753, 0xd0}, ++{0x3754, 0x08}, ++{0x3755, 0x00}, ++{0x3758, 0xdd}, ++{0x3759, 0x50}, ++{0x375a, 0x49}, ++{0x375b, 0x02}, ++{0x375c, 0x2f}, ++{0x375d, 0x00}, ++{0x375e, 0x0f}, ++{0x375f, 0x03}, ++{0x3760, 0x13}, ++{0x3761, 0x12}, ++{0x3762, 0x1c}, ++{0x3763, 0x03}, ++{0x3764, 0x0d}, ++{0x3765, 0x25}, ++{0x3766, 0x08}, ++{0x3767, 0x08}, ++{0x3768, 0x21}, ++{0x3769, 0x01}, ++{0x376a, 0x01}, ++{0x376b, 0x00}, ++{0x376c, 0x15}, ++{0x376d, 0x08}, ++{0x376e, 0x08}, ++{0x376f, 0x08}, ++{0x3770, 0x91}, ++{0x3771, 0x00}, ++{0x3772, 0x00}, ++{0x3773, 0x00}, ++{0x3774, 0x02}, ++{0x3775, 0x00}, ++{0x3776, 0x00}, ++{0x3777, 0x00}, ++{0x3778, 0x00}, ++{0x3779, 0x22}, ++{0x377a, 0x00}, ++{0x377b, 0x00}, ++{0x377c, 0x48}, ++{0x377d, 0x00}, ++{0x377e, 0x00}, ++{0x377f, 0x07}, ++{0x3780, 0x00}, ++{0x3781, 0x02}, ++{0x3782, 0x04}, ++{0x3783, 0x02}, ++{0x3784, 0x08}, ++{0x3785, 0x08}, ++{0x3786, 0x00}, ++{0x3787, 0x04}, ++{0x3788, 0x02}, ++{0x3789, 0x02}, ++{0x378a, 0x04}, ++{0x378b, 0x00}, ++{0x378c, 0x00}, ++{0x378d, 0x00}, ++{0x378e, 0x00}, ++{0x378f, 0x00}, ++{0x3790, 0x10}, ++{0x3791, 0x05}, ++{0x3792, 0x31}, ++{0x3793, 0x00}, ++{0x3795, 0x00}, ++{0x3796, 0x00}, ++{0x3797, 0x00}, ++{0x3798, 0x00}, ++{0x3799, 0x00}, ++{0x379a, 0x00}, ++{0x379b, 0x10}, ++{0x379c, 0x01}, ++{0x379d, 0x00}, ++{0x379e, 0x0d}, ++{0x379f, 0x03}, ++{0x37a0, 0x08}, ++{0x37a1, 0x80}, ++{0x37a2, 0x03}, ++{0x37a3, 0x05}, ++{0x37a4, 0x04}, ++{0x37a5, 0x14}, ++{0x37a6, 0x17}, ++{0x37a7, 0x14}, ++{0x37a8, 0x05}, ++{0x37a9, 0x08}, ++{0x37aa, 0x05}, ++{0x37ab, 0x06}, ++{0x37ac, 0x05}, ++{0x37ad, 0x0d}, ++{0x37ae, 0x0d}, ++{0x37af, 0x01}, ++{0x37b0, 0x0c}, ++{0x37b1, 0x05}, ++{0x37b2, 0x08}, ++{0x37b3, 0x0a}, ++{0x37b4, 0x08}, ++{0x37b5, 0x08}, ++{0x37b6, 0x08}, ++{0x37b7, 0x08}, ++{0x37b8, 0xff}, ++{0x37b9, 0x01}, ++{0x37ba, 0x08}, ++{0x37bb, 0x08}, ++{0x37bd, 0x01}, ++{0x37be, 0x01}, ++{0x37bf, 0x01}, ++{0x37c0, 0x01}, ++{0x37c1, 0x11}, ++{0x37c2, 0x11}, ++{0x37c3, 0x00}, ++{0x37c4, 0x63}, ++{0x37c5, 0x63}, ++{0x37c6, 0x63}, ++{0x37c7, 0x34}, ++{0x37c8, 0x21}, ++{0x37c9, 0x00}, ++{0x37ca, 0x08}, ++{0x37cb, 0x00}, ++{0x37cc, 0x40}, ++{0x37cd, 0x00}, ++{0x37ce, 0x01}, ++{0x37cf, 0x08}, ++{0x37d0, 0x00}, ++{0x37d1, 0x39}, ++{0x37d2, 0x00}, ++{0x37d3, 0xa3}, ++{0x37d4, 0x00}, ++{0x37d5, 0x39}, ++{0x37d6, 0x00}, ++{0x37d7, 0xa3}, ++{0x37da, 0x00}, ++{0x37db, 0x00}, ++{0x37dc, 0x00}, ++{0x37dd, 0x00}, ++{0x37de, 0x00}, ++{0x37df, 0x00}, ++{0x37e0, 0x00}, ++{0x37e1, 0x00}, ++{0x37e2, 0x00}, ++{0x37e3, 0x00}, ++{0x37e4, 0x00}, ++{0x37e5, 0x00}, ++{0x37e6, 0x00}, ++{0x37e7, 0x00}, ++{0x37e8, 0x00}, ++{0x37e9, 0x00}, ++{0x37ea, 0x00}, ++{0x37eb, 0x00}, ++{0x37ec, 0x00}, ++{0x37ed, 0x00}, ++{0x37ee, 0x00}, ++{0x37ef, 0x00}, ++{0x37f0, 0x00}, ++{0x37f1, 0x00}, ++{0x37f2, 0x00}, ++{0x37f3, 0x00}, ++{0x37f4, 0x00}, ++{0x37f5, 0x00}, ++{0x37f6, 0x00}, ++{0x37f7, 0x00}, ++{0x37f8, 0x00}, ++{0x37f9, 0x00}, ++{0x37fa, 0x00}, ++{0x37fb, 0x00}, ++{0x37fc, 0x00}, ++{0x37fd, 0x00}, ++{0x37fe, 0x00}, ++{0x37ff, 0x00}, ++{0x3c00, 0x00}, ++{0x3c01, 0x11}, ++{0x3c02, 0x20}, ++{0x3c03, 0x04}, ++{0x3c04, 0x04}, ++{0x3c05, 0x00}, ++{0x3c06, 0x29}, ++{0x3c07, 0x01}, ++{0x3c08, 0x05}, ++{0x3c09, 0x0c}, ++{0x3c0a, 0x04}, ++{0x3c0b, 0xa8}, ++{0x3c0c, 0x11}, ++{0x3c0d, 0x08}, ++{0x3c0e, 0x03}, ++{0x3c0f, 0x02}, ++{0x3c10, 0x01}, ++{0x3c11, 0x08}, ++{0x3c12, 0x89}, ++{0x3c13, 0x21}, ++{0x3c14, 0x81}, ++{0x3c15, 0x21}, ++{0x3c16, 0x11}, ++{0x3c17, 0x01}, ++{0x3c18, 0x0c}, ++{0x3c19, 0x00}, ++{0x3c1a, 0x16}, ++{0x3c1b, 0x81}, ++{0x3c1c, 0x04}, ++{0x3c1d, 0x16}, ++{0x3c1e, 0x11}, ++{0x3c1f, 0x3a}, ++{0x3c20, 0x20}, ++{0x3c21, 0x00}, ++{0x3c22, 0x17}, ++{0x3c23, 0x07}, ++{0x3c24, 0x1a}, ++{0x3c25, 0x1e}, ++{0x3c26, 0x24}, ++{0x3c27, 0x37}, ++{0x3c28, 0x0a}, ++{0x3c29, 0x14}, ++{0x3c2a, 0xd1}, ++{0x3c2b, 0x27}, ++{0x3c2c, 0x33}, ++{0x3c2d, 0x0c}, ++{0x3c2e, 0x12}, ++{0x3c2f, 0x08}, ++{0x3c30, 0x16}, ++{0x3c31, 0x24}, ++{0x3c32, 0x35}, ++{0x3c33, 0x29}, ++{0x3c34, 0x31}, ++{0x3c35, 0x21}, ++{0x3c36, 0x11}, ++{0x3c37, 0x12}, ++{0x3c38, 0x11}, ++{0x3c39, 0x11}, ++{0x3c3a, 0x08}, ++{0x3c3b, 0x38}, ++{0x3c3c, 0x03}, ++{0x3c3d, 0x23}, ++{0x3c3e, 0x05}, ++{0x3c3f, 0x0a}, ++{0x3c40, 0xc1}, ++{0x3c41, 0x04}, ++{0x3c42, 0x01}, ++{0x3c43, 0x18}, ++{0x3c44, 0x21}, ++{0x3c45, 0x20}, ++{0x3c46, 0x0b}, ++{0x3c47, 0x11}, ++{0x3c48, 0x11}, ++{0x3c4a, 0x02}, ++{0x3c4b, 0x63}, ++{0x3c4c, 0x02}, ++{0x3c4d, 0x63}, ++{0x3c4e, 0x00}, ++{0x3c4f, 0x2a}, ++{0x3c50, 0x2a}, ++{0x3c51, 0x2a}, ++{0x3c52, 0x2a}, ++{0x3c53, 0x08}, ++{0x3c54, 0x1d}, ++{0x3c55, 0xeb}, ++{0x3c56, 0x24}, ++{0x3c57, 0x10}, ++{0x3c58, 0x10}, ++{0x3c59, 0x16}, ++{0x3c5a, 0x55}, ++{0x3c5b, 0x25}, ++{0x3c5c, 0x8e}, ++{0x3ce0, 0x00}, ++{0x3ce1, 0x00}, ++{0x3ce2, 0x00}, ++{0x3ce3, 0x00}, ++{0x3ce4, 0x00}, ++{0x3ce5, 0x00}, ++{0x3ce6, 0x00}, ++{0x3ce7, 0x00}, ++{0x3ce8, 0x00}, ++{0x3ce9, 0x00}, ++{0x3cea, 0x00}, ++{0x3ceb, 0x00}, ++{0x3cec, 0x00}, ++{0x3ced, 0x00}, ++{0x3cee, 0x00}, ++{0x3cef, 0x00}, ++{0x3cf0, 0x00}, ++{0x3cf1, 0x00}, ++{0x3cf2, 0x00}, ++{0x3cf3, 0x00}, ++{0x3cf4, 0x00}, ++{0x3cf5, 0x00}, ++{0x3cf6, 0x00}, ++{0x3cf7, 0x00}, ++{0x3cf8, 0x00}, ++{0x3cf9, 0x00}, ++{0x3cfa, 0x00}, ++{0x3cfb, 0x00}, ++{0x3cfc, 0x00}, ++{0x3cfd, 0x00}, ++{0x3cfe, 0x00}, ++{0x3cff, 0x00}, ++{0x3100, 0x00}, ++{0x3101, 0x32}, ++{0x3102, 0x00}, ++{0x3103, 0x25}, ++{0x3104, 0x01}, ++{0x3105, 0x11}, ++{0x3106, 0x10}, ++{0x3107, 0x01}, ++{0x3108, 0x01}, ++{0x3109, 0x00}, ++{0x3182, 0x10}, ++{0x3183, 0xff}, ++{0x3184, 0xff}, ++{0x3187, 0xff}, ++{0x3189, 0x00}, ++{0x318a, 0x00}, ++{0x318b, 0x00}, ++{0x318c, 0x00}, ++{0x318d, 0x00}, ++{0x318e, 0x00}, ++{0x318f, 0x00}, ++{0x3190, 0x00}, ++{0x3191, 0x00}, ++{0x3192, 0x00}, ++{0x3193, 0x00}, ++{0x3194, 0x00}, ++{0x3200, 0x00}, ++{0x3201, 0x08}, ++{0x3202, 0x10}, ++{0x3203, 0x18}, ++{0x3204, 0x20}, ++{0x3205, 0x30}, ++{0x3206, 0x00}, ++{0x3209, 0x00}, ++{0x320a, 0x00}, ++{0x320b, 0x00}, ++{0x320c, 0x00}, ++{0x320d, 0x01}, ++{0x3216, 0x01}, ++{0x3217, 0x00}, ++{0x3218, 0xf7}, ++{0x3219, 0x55}, ++{0x321b, 0x00}, ++{0x3220, 0x1c}, ++{0x3221, 0x00}, ++{0x3304, 0x04}, ++{0x3305, 0x00}, ++{0x3306, 0x03}, ++{0x3307, 0x00}, ++{0x3308, 0x00}, ++{0x3309, 0x00}, ++{0x330a, 0x00}, ++{0x330b, 0x00}, ++{0x330c, 0x00}, ++{0x330d, 0x00}, ++{0x330e, 0x00}, ++{0x330f, 0x00}, ++{0x3310, 0x06}, ++{0x3311, 0x05}, ++{0x3312, 0x55}, ++{0x3313, 0x0a}, ++{0x3314, 0xaa}, ++{0x3315, 0x0f}, ++{0x3316, 0xf0}, ++{0x3317, 0x00}, ++{0x3400, 0x08}, ++{0x3401, 0x00}, ++{0x3402, 0x00}, ++{0x3403, 0xb1}, ++{0x3404, 0x00}, ++{0x3405, 0x0f}, ++{0x3406, 0x08}, ++{0x3407, 0x08}, ++{0x3408, 0x01}, ++{0x3409, 0x02}, ++{0x340a, 0x02}, ++{0x340c, 0x10}, ++{0x340d, 0x00}, ++{0x3410, 0x00}, ++{0x3412, 0x00}, ++{0x3413, 0x00}, ++{0x3414, 0x00}, ++{0x3415, 0x00}, ++{0x3416, 0x00}, ++{0x3417, 0x00}, ++{0x3420, 0x00}, ++{0x3421, 0x00}, ++{0x3422, 0x00}, ++{0x3423, 0x00}, ++{0x3424, 0x00}, ++{0x3425, 0x00}, ++{0x3426, 0x00}, ++{0x3427, 0x00}, ++{0x3428, 0x00}, ++{0x3429, 0x00}, ++{0x342a, 0x00}, ++{0x342b, 0x00}, ++{0x3501, 0x00}, ++{0x3502, 0x24}, ++{0x3503, 0xa8}, ++{0x3504, 0x08}, ++{0x3506, 0x00}, ++{0x3507, 0x00}, ++{0x3508, 0x01}, ++{0x3509, 0x00}, ++{0x350a, 0x01}, ++{0x350b, 0x00}, ++{0x350c, 0x00}, ++{0x350d, 0x00}, ++{0x3541, 0x00}, ++{0x3542, 0x40}, ++{0x3543, 0xa8}, ++{0x3544, 0x08}, ++{0x3546, 0x00}, ++{0x3547, 0x00}, ++{0x3548, 0x01}, ++{0x3549, 0x00}, ++{0x354a, 0x01}, ++{0x354b, 0x00}, ++{0x354c, 0x00}, ++{0x354d, 0x00}, ++{0x3581, 0x00}, ++{0x3582, 0x24}, ++{0x3583, 0xa8}, ++{0x3584, 0x08}, ++{0x3586, 0x00}, ++{0x3587, 0x00}, ++{0x3588, 0x01}, ++{0x3589, 0x00}, ++{0x358a, 0x01}, ++{0x358b, 0x00}, ++{0x358c, 0x00}, ++{0x358d, 0x00}, ++{0x3600, 0x00}, ++{0x3601, 0x70}, ++{0x3602, 0x42}, ++{0x3603, 0xe3}, ++{0x3604, 0x93}, ++{0x3605, 0x40}, ++{0x3606, 0x80}, ++{0x3607, 0x4a}, ++{0x3608, 0x98}, ++{0x3609, 0x70}, ++{0x360a, 0x90}, ++{0x360b, 0x0a}, ++{0x360c, 0x40}, ++{0x360d, 0x88}, ++{0x360e, 0x88}, ++{0x360f, 0x88}, ++{0x3610, 0x89}, ++{0x3611, 0x4f}, ++{0x3612, 0x4f}, ++{0x3613, 0xba}, ++{0x3614, 0x99}, ++{0x3615, 0x99}, ++{0x3616, 0x00}, ++{0x3617, 0x00}, ++{0x3618, 0x18}, ++{0x3619, 0x00}, ++{0x3620, 0x02}, ++{0x3621, 0x80}, ++{0x3622, 0x00}, ++{0x3623, 0x00}, ++{0x3624, 0x00}, ++{0x3625, 0x00}, ++{0x3626, 0x0e}, ++{0x3627, 0x0f}, ++{0x3628, 0x0a}, ++{0x3629, 0x0a}, ++{0x362a, 0x0e}, ++{0x362b, 0x0e}, ++{0x362c, 0x0e}, ++{0x362d, 0x0e}, ++{0x362e, 0x00}, ++{0x362f, 0x00}, ++{0x3630, 0x00}, ++{0x3631, 0x00}, ++{0x3632, 0x99}, ++{0x3633, 0x99}, ++{0x3634, 0x30}, ++{0x3635, 0x30}, ++{0x3636, 0x30}, ++{0x3637, 0x30}, ++{0x3638, 0x00}, ++{0x3639, 0x00}, ++{0x363a, 0x00}, ++{0x363b, 0x0f}, ++{0x363c, 0x0f}, ++{0x363d, 0x0a}, ++{0x363e, 0x0a}, ++{0x363f, 0x0a}, ++{0x3640, 0x0a}, ++{0x3641, 0x0a}, ++{0x3642, 0x0a}, ++{0x3643, 0x10}, ++{0x3644, 0x00}, ++{0x3645, 0x10}, ++{0x3646, 0x16}, ++{0x3647, 0x10}, ++{0x3648, 0x00}, ++{0x3649, 0x13}, ++{0x364a, 0x1d}, ++{0x364b, 0x00}, ++{0x364c, 0x0e}, ++{0x364d, 0x0e}, ++{0x364e, 0x0e}, ++{0x364f, 0x0e}, ++{0x3650, 0x00}, ++{0x3651, 0x00}, ++{0x3652, 0xc5}, ++{0x3653, 0x00}, ++{0x3654, 0x40}, ++{0x3655, 0x00}, ++{0x3656, 0xcf}, ++{0x3657, 0x2b}, ++{0x3658, 0x09}, ++{0x3659, 0x00}, ++{0x365a, 0x00}, ++{0x365b, 0x00}, ++{0x365c, 0x00}, ++{0x365d, 0x00}, ++{0x3660, 0x01}, ++{0x3661, 0x07}, ++{0x3662, 0x00}, ++{0x3663, 0x20}, ++{0x3664, 0x00}, ++{0x3665, 0x12}, ++{0x3666, 0x13}, ++{0x3667, 0x14}, ++{0x3668, 0x95}, ++{0x3669, 0x16}, ++{0x366a, 0x00}, ++{0x366b, 0x00}, ++{0x366c, 0x00}, ++{0x366d, 0x00}, ++{0x366e, 0x00}, ++{0x366f, 0xc4}, ++{0x3670, 0x6f}, ++{0x3671, 0x0b}, ++{0x3672, 0x1d}, ++{0x3673, 0x6a}, ++{0x3674, 0x6f}, ++{0x3675, 0x1d}, ++{0x3676, 0x6f}, ++{0x3677, 0x1d}, ++{0x3678, 0x80}, ++{0x3679, 0x04}, ++{0x367a, 0x00}, ++{0x367b, 0x04}, ++{0x367c, 0x00}, ++{0x367d, 0x00}, ++{0x367e, 0x00}, ++{0x367f, 0x00}, ++{0x3680, 0x00}, ++{0x3800, 0x00}, ++{0x3801, 0x00}, ++{0x3802, 0x00}, ++{0x3803, 0x04}, ++{0x3804, 0x07}, ++{0x3805, 0x8f}, ++{0x3806, 0x05}, ++{0x3807, 0x0b}, ++{0x3808, 0x07}, ++{0x3809, 0x80}, ++{0x380a, 0x05}, ++{0x380b, 0x00}, ++{0x380c, 0x02}, ++{0x380d, 0x14}, ++{0x380e, 0x05}, ++{0x380f, 0x40}, ++{0x3810, 0x00}, ++{0x3811, 0x08}, ++{0x3812, 0x00}, ++{0x3813, 0x04}, ++{0x3814, 0x01}, ++{0x3815, 0x01}, ++{0x3816, 0x01}, ++{0x3817, 0x01}, ++{0x3818, 0x00}, ++{0x3819, 0x00}, ++{0x381a, 0x00}, ++{0x381b, 0x01}, ++{0x381c, 0x08}, ++{0x381d, 0x00}, ++{0x3820, 0x00}, ++{0x3821, 0x20}, ++{0x3822, 0x04}, ++{0x3823, 0x08}, ++{0x3824, 0x00}, ++{0x3825, 0x20}, ++{0x3826, 0x00}, ++{0x3827, 0x08}, ++{0x3828, 0x38}, ++{0x382a, 0x00}, ++{0x382b, 0x00}, ++{0x382c, 0x00}, ++{0x382d, 0x00}, ++{0x3832, 0x00}, ++{0x3833, 0x00}, ++{0x3834, 0x00}, ++{0x3838, 0x00}, ++{0x3839, 0x00}, ++{0x383a, 0x00}, ++{0x383b, 0x00}, ++{0x383c, 0x48}, ++{0x383d, 0x20}, ++{0x383e, 0x00}, ++{0x3842, 0x00}, ++{0x3843, 0x00}, ++{0x3844, 0x00}, ++{0x384c, 0x02}, ++{0x384d, 0x14}, ++{0x384e, 0x00}, ++{0x384f, 0x40}, ++{0x3850, 0x01}, ++{0x3851, 0x02}, ++{0x3852, 0x01}, ++{0x3853, 0x00}, ++{0x3854, 0x00}, ++{0x3855, 0x05}, ++{0x3856, 0x05}, ++{0x3857, 0x33}, ++{0x3858, 0x7c}, ++{0x3859, 0x00}, ++{0x385a, 0x03}, ++{0x385b, 0x05}, ++{0x385c, 0x32}, ++{0x385d, 0x00}, ++{0x385e, 0x12}, ++{0x385f, 0x00}, ++{0x3860, 0x10}, ++{0x3861, 0x00}, ++{0x3862, 0x40}, ++{0x3863, 0x00}, ++{0x3864, 0x40}, ++{0x3865, 0x00}, ++{0x3866, 0x40}, ++{0x3881, 0x02}, ++{0x3882, 0x00}, ++{0x3883, 0x08}, ++{0x3b40, 0x3e}, ++{0x3b41, 0x00}, ++{0x3b42, 0x02}, ++{0x3b43, 0x00}, ++{0x3b44, 0x03}, ++{0x3b45, 0x00}, ++{0x3b46, 0x03}, ++{0x3b47, 0x00}, ++{0x3b80, 0x00}, ++{0x3b81, 0x00}, ++{0x3b82, 0x07}, ++{0x3b83, 0x87}, ++{0x3b84, 0x36}, ++{0x3b85, 0x00}, ++{0x3b86, 0x00}, ++{0x3b87, 0x04}, ++{0x3b88, 0x00}, ++{0x3b89, 0x04}, ++{0x3b8a, 0x00}, ++{0x3b8b, 0x0a}, ++{0x3b8c, 0x00}, ++{0x3b8d, 0x01}, ++{0x3b8e, 0x03}, ++{0x3b8f, 0xe8}, ++{0x3d82, 0xbc}, ++{0x3d83, 0x08}, ++{0x3d84, 0x00}, ++{0x3d85, 0x1b}, ++{0x3d86, 0x02}, ++{0x3d87, 0x0a}, ++{0x3d88, 0x00}, ++{0x3d89, 0x00}, ++{0x3d8a, 0x03}, ++{0x3d8b, 0xff}, ++{0x3d8c, 0x00}, ++{0x3d8d, 0x00}, ++{0x3d90, 0x00}, ++{0x3d91, 0x00}, ++{0x3d92, 0xe2}, ++{0x3d93, 0x46}, ++{0x3d94, 0x14}, ++{0x3d95, 0x06}, ++{0x3d96, 0x01}, ++{0x3d97, 0x00}, ++{0x3d98, 0x00}, ++{0x3d99, 0x00}, ++{0x3d9a, 0x00}, ++{0x3d9b, 0x00}, ++{0x3d9c, 0x00}, ++{0x3d9d, 0x00}, ++{0x3d9e, 0x00}, ++{0x3d9f, 0x00}, ++{0x3da0, 0x00}, ++{0x3da1, 0x00}, ++{0x3da2, 0x00}, ++{0x3da4, 0x00}, ++{0x3e00, 0x00}, ++{0x3e01, 0x00}, ++{0x3e02, 0x0f}, ++{0x3e03, 0xdb}, ++{0x3e04, 0x14}, ++{0x3e05, 0x00}, ++{0x3e06, 0x03}, ++{0x3e07, 0x40}, ++{0x3e08, 0x00}, ++{0x3e09, 0x00}, ++{0x3e0a, 0x00}, ++{0x3e0b, 0x00}, ++{0x3e0c, 0x00}, ++{0x3e0d, 0x00}, ++{0x3e0e, 0x00}, ++{0x3f00, 0x04}, ++{0x3f01, 0x00}, ++{0x3f02, 0x00}, ++{0x3f03, 0x01}, ++{0x4000, 0xf8}, ++{0x4001, 0xeb}, ++{0x4004, 0x00}, ++{0x4005, 0x40}, ++{0x4006, 0x00}, ++{0x4007, 0x10}, ++{0x4008, 0x00}, ++{0x4009, 0x05}, ++{0x400a, 0x02}, ++{0x400b, 0x00}, ++{0x400c, 0x00}, ++{0x400d, 0x10}, ++{0x400e, 0x00}, ++{0x400f, 0xa0}, ++{0x4010, 0x10}, ++{0x4011, 0xff}, ++{0x4012, 0x08}, ++{0x4013, 0x02}, ++{0x4014, 0x02}, ++{0x4015, 0x02}, ++{0x4016, 0x00}, ++{0x4017, 0x04}, ++{0x4018, 0x18}, ++{0x4019, 0x04}, ++{0x401a, 0x58}, ++{0x4020, 0x00}, ++{0x4021, 0x00}, ++{0x4022, 0x00}, ++{0x4023, 0x00}, ++{0x4024, 0x00}, ++{0x4025, 0x00}, ++{0x4026, 0x00}, ++{0x4027, 0x00}, ++{0x4028, 0x4f}, ++{0x4029, 0x01}, ++{0x402a, 0x00}, ++{0x402b, 0x00}, ++{0x402c, 0x00}, ++{0x402d, 0x00}, ++{0x402e, 0x00}, ++{0x402f, 0x40}, ++{0x4030, 0x00}, ++{0x4031, 0x40}, ++{0x4032, 0x9e}, ++{0x4033, 0x80}, ++{0x4034, 0x00}, ++{0x4035, 0x80}, ++{0x4036, 0x00}, ++{0x4037, 0x80}, ++{0x4038, 0x00}, ++{0x4039, 0x80}, ++{0x403a, 0x00}, ++{0x403b, 0x80}, ++{0x403c, 0x00}, ++{0x403d, 0x00}, ++{0x4040, 0x00}, ++{0x4041, 0x00}, ++{0x4042, 0x00}, ++{0x4043, 0x00}, ++{0x4044, 0x00}, ++{0x4045, 0x00}, ++{0x4046, 0x00}, ++{0x4047, 0x00}, ++{0x4048, 0x00}, ++{0x4049, 0x00}, ++{0x404a, 0x00}, ++{0x404b, 0x00}, ++{0x404c, 0x00}, ++{0x404d, 0x00}, ++{0x404e, 0x00}, ++{0x404f, 0x00}, ++{0x4050, 0x00}, ++{0x4051, 0x05}, ++{0x4052, 0x00}, ++{0x4053, 0x80}, ++{0x4054, 0x00}, ++{0x4055, 0x80}, ++{0x4056, 0x00}, ++{0x4057, 0x80}, ++{0x4058, 0x00}, ++{0x4059, 0x80}, ++{0x405a, 0x30}, ++{0x405b, 0x18}, ++{0x405c, 0x00}, ++{0x405d, 0x00}, ++{0x405e, 0x00}, ++{0x405f, 0x00}, ++{0x4060, 0x00}, ++{0x4065, 0x00}, ++{0x4066, 0x02}, ++{0x406d, 0x00}, ++{0x406e, 0x00}, ++{0x406f, 0x00}, ++{0x40a0, 0x00}, ++{0x40a1, 0x00}, ++{0x40a2, 0x00}, ++{0x40a3, 0x00}, ++{0x40a4, 0x00}, ++{0x40a5, 0x00}, ++{0x40a6, 0x00}, ++{0x40a7, 0x00}, ++{0x40c0, 0x00}, ++{0x40c1, 0x00}, ++{0x40c2, 0x00}, ++{0x40c3, 0x00}, ++{0x40c4, 0x00}, ++{0x40c5, 0x00}, ++{0x40c6, 0x00}, ++{0x40c7, 0x00}, ++{0x40c8, 0x00}, ++{0x40c9, 0x00}, ++{0x40ca, 0x00}, ++{0x40cb, 0x00}, ++{0x40cc, 0x00}, ++{0x40cd, 0x00}, ++{0x40ce, 0x00}, ++{0x40cf, 0x00}, ++{0x4200, 0x00}, ++{0x4201, 0x00}, ++{0x4202, 0x00}, ++{0x4203, 0x00}, ++{0x4204, 0x00}, ++{0x4205, 0x00}, ++{0x4206, 0x00}, ++{0x4207, 0x00}, ++{0x4208, 0x00}, ++{0x4300, 0x00}, ++{0x4301, 0x00}, ++{0x4302, 0x00}, ++{0x4303, 0x00}, ++{0x4304, 0x00}, ++{0x4305, 0x00}, ++{0x4306, 0x00}, ++{0x4307, 0x00}, ++{0x4308, 0x00}, ++{0x4309, 0x00}, ++{0x430a, 0x00}, ++{0x430b, 0xff}, ++{0x430c, 0xff}, ++{0x430d, 0x00}, ++{0x430e, 0x00}, ++{0x430f, 0x02}, ++{0x4500, 0x16}, ++{0x4501, 0x18}, ++{0x4502, 0x00}, ++{0x4503, 0x00}, ++{0x4504, 0x01}, ++{0x4505, 0x00}, ++{0x4506, 0x32}, ++{0x4507, 0x07}, ++{0x4508, 0x1a}, ++{0x4580, 0x68}, ++{0x4581, 0xc7}, ++{0x4582, 0x07}, ++{0x4583, 0x07}, ++{0x4584, 0xec}, ++{0x4585, 0x09}, ++{0x4586, 0xae}, ++{0x4587, 0x04}, ++{0x4588, 0x52}, ++{0x4589, 0x05}, ++{0x458a, 0x47}, ++{0x458b, 0x02}, ++{0x458c, 0xe2}, ++{0x458d, 0x03}, ++{0x458e, 0x85}, ++{0x458f, 0x00}, ++{0x4590, 0x20}, ++{0x4591, 0x09}, ++{0x4592, 0x60}, ++{0x45a6, 0x18}, ++{0x4600, 0x00}, ++{0x4601, 0x30}, ++{0x4602, 0x00}, ++{0x4603, 0x01}, ++{0x4604, 0x00}, ++{0x4605, 0x03}, ++{0x4609, 0x00}, ++{0x460a, 0x30}, ++{0x460b, 0x00}, ++{0x460c, 0x30}, ++{0x460d, 0x01}, ++{0x460e, 0x00}, ++{0x4700, 0x2a}, ++{0x4702, 0x00}, ++{0x4703, 0x80}, ++{0x4704, 0x00}, ++{0x4705, 0x10}, ++{0x4706, 0xaa}, ++{0x4707, 0x55}, ++{0x4708, 0x99}, ++{0x4709, 0x66}, ++{0x470a, 0x08}, ++{0x470b, 0x88}, ++{0x470c, 0x00}, ++{0x470d, 0x02}, ++{0x470e, 0x00}, ++{0x470f, 0x00}, ++{0x4710, 0x00}, ++{0x4711, 0x00}, ++{0x4712, 0x00}, ++{0x4713, 0x00}, ++{0x4800, 0x04}, ++{0x4802, 0x00}, ++{0x4803, 0x00}, ++{0x4804, 0x08}, ++{0x4805, 0x00}, ++{0x4806, 0x00}, ++{0x4807, 0x03}, ++{0x4808, 0x18}, ++{0x480e, 0x04}, ++{0x4810, 0xff}, ++{0x4811, 0xff}, ++{0x4813, 0xe4}, // VC ++{0x4814, 0x2a}, ++{0x4815, 0x2b}, ++{0x4816, 0x2b}, ++{0x4818, 0x00}, ++{0x4819, 0x70}, ++{0x481a, 0x00}, ++{0x481b, 0x3c}, ++{0x481c, 0x01}, ++{0x481d, 0x2c}, ++{0x481e, 0x5f}, ++{0x481f, 0x26}, ++{0x4820, 0x00}, ++{0x4821, 0x3c}, ++{0x4822, 0x00}, ++{0x4823, 0x3c}, ++{0x4824, 0x00}, ++{0x4825, 0x32}, ++{0x4826, 0x32}, ++{0x4827, 0x55}, ++{0x4828, 0x00}, ++{0x4829, 0x64}, ++{0x482a, 0x06}, ++{0x482b, 0x04}, ++{0x482c, 0x00}, ++{0x482d, 0x00}, ++{0x482e, 0x34}, ++{0x482f, 0x00}, ++{0x4830, 0x00}, ++{0x4831, 0x64}, ++{0x4832, 0x00}, ++{0x4833, 0x10}, ++{0x4837, 0x15}, ++{0x4838, 0x00}, ++{0x4839, 0x00}, ++{0x483c, 0x10}, ++{0x483d, 0x00}, ++{0x484a, 0x3f}, ++{0x484b, 0x67}, ++{0x484c, 0x00}, ++{0x484e, 0x10}, ++{0x4850, 0x40}, ++{0x4851, 0xaa}, ++{0x4852, 0xff}, ++{0x4853, 0x8a}, ++{0x4854, 0x08}, ++{0x4855, 0x30}, ++{0x4856, 0x01}, ++{0x4860, 0x00}, ++{0x4861, 0xa0}, ++{0x4862, 0x01}, ++{0x4863, 0x01}, ++{0x4864, 0x02}, ++{0x4865, 0x66}, ++{0x4866, 0x99}, ++{0x4867, 0x88}, ++{0x4868, 0xaa}, ++{0x4869, 0xff}, ++{0x486a, 0x3f}, ++{0x486b, 0x84}, ++{0x486c, 0x36}, ++{0x486d, 0x00}, ++{0x486e, 0x84}, ++{0x486f, 0x36}, ++{0x4870, 0x00}, ++{0x4880, 0x00}, ++{0x4881, 0x00}, ++{0x4882, 0x00}, ++{0x4883, 0x00}, ++{0x4884, 0x08}, ++{0x4885, 0x00}, ++{0x4886, 0x00}, ++{0x4900, 0x08}, ++{0x4901, 0x00}, ++{0x4902, 0x00}, ++{0x4903, 0x80}, ++{0x4f00, 0xff}, ++{0x4f01, 0xff}, ++{0x4f04, 0x00}, ++{0x4f05, 0x01}, ++{0x5180, 0x04}, ++{0x5181, 0x00}, ++{0x5182, 0x04}, ++{0x5183, 0x00}, ++{0x5184, 0x04}, ++{0x5185, 0x00}, ++{0x5186, 0x04}, ++{0x5187, 0x00}, ++{0x5188, 0x00}, ++{0x5189, 0x00}, ++{0x518a, 0x00}, ++{0x518b, 0x10}, ++{0x51a0, 0x04}, ++{0x51a1, 0x00}, ++{0x51a2, 0x04}, ++{0x51a3, 0x00}, ++{0x51a4, 0x04}, ++{0x51a5, 0x00}, ++{0x51a6, 0x04}, ++{0x51a7, 0x00}, ++{0x51a8, 0x00}, ++{0x51a9, 0x00}, ++{0x51aa, 0x00}, ++{0x51ab, 0x10}, ++{0x51c0, 0x04}, ++{0x51c1, 0x00}, ++{0x51c2, 0x04}, ++{0x51c3, 0x00}, ++{0x51c4, 0x04}, ++{0x51c5, 0x00}, ++{0x51c6, 0x04}, ++{0x51c7, 0x00}, ++{0x51c8, 0x00}, ++{0x51c9, 0x00}, ++{0x51ca, 0x00}, ++{0x51cb, 0x10}, ++{0x5380, 0x19}, ++{0x5381, 0x94}, ++{0x5382, 0x2e}, ++{0x5383, 0x24}, ++{0x5384, 0x12}, ++{0x5385, 0x41}, ++{0x5386, 0x48}, ++{0x5387, 0x84}, ++{0x5388, 0x40}, ++{0x5389, 0x00}, ++{0x538a, 0x00}, ++{0x538b, 0x03}, ++{0x538c, 0x00}, ++{0x538d, 0x0f}, ++{0x538e, 0x00}, ++{0x538f, 0x3f}, ++{0x5390, 0x0f}, ++{0x5391, 0xfd}, ++{0x5392, 0xf5}, ++{0x5393, 0xf5}, ++{0x5394, 0x02}, ++{0x5395, 0xff}, ++{0x5396, 0x00}, ++{0x5397, 0x00}, ++{0x53a0, 0x41}, ++{0x53a2, 0x04}, ++{0x53a3, 0x00}, ++{0x53a4, 0x04}, ++{0x53a5, 0x00}, ++{0x53a6, 0x04}, ++{0x53a7, 0x00}, ++{0x53ac, 0x04}, ++{0x53ad, 0x00}, ++{0x53ae, 0x04}, ++{0x53af, 0x00}, ++{0x53b0, 0x04}, ++{0x53b1, 0x00}, ++{0x5400, 0x19}, ++{0x5401, 0x94}, ++{0x5402, 0x2e}, ++{0x5403, 0x24}, ++{0x5404, 0x12}, ++{0x5405, 0x41}, ++{0x5406, 0x48}, ++{0x5407, 0x84}, ++{0x5408, 0x40}, ++{0x5409, 0x00}, ++{0x540a, 0x00}, ++{0x540b, 0x03}, ++{0x540c, 0x00}, ++{0x540d, 0x0f}, ++{0x540e, 0x00}, ++{0x540f, 0x3f}, ++{0x5410, 0x0f}, ++{0x5411, 0xfd}, ++{0x5412, 0xf5}, ++{0x5413, 0xf5}, ++{0x5414, 0x02}, ++{0x5415, 0xff}, ++{0x5416, 0x00}, ++{0x5417, 0x00}, ++{0x5420, 0x41}, ++{0x5422, 0x04}, ++{0x5423, 0x00}, ++{0x5424, 0x04}, ++{0x5425, 0x00}, ++{0x5426, 0x04}, ++{0x5427, 0x00}, ++{0x542c, 0x04}, ++{0x542d, 0x00}, ++{0x542e, 0x04}, ++{0x542f, 0x00}, ++{0x5430, 0x04}, ++{0x5431, 0x00}, ++{0x5480, 0x19}, ++{0x5481, 0x94}, ++{0x5482, 0x2e}, ++{0x5483, 0x24}, ++{0x5484, 0x12}, ++{0x5485, 0x41}, ++{0x5486, 0x48}, ++{0x5487, 0x84}, ++{0x5488, 0x40}, ++{0x5489, 0x00}, ++{0x548a, 0x00}, ++{0x548b, 0x03}, ++{0x548c, 0x00}, ++{0x548d, 0x0f}, ++{0x548e, 0x00}, ++{0x548f, 0x3f}, ++{0x5490, 0x0f}, ++{0x5491, 0xfd}, ++{0x5492, 0xf5}, ++{0x5493, 0xf5}, ++{0x5494, 0x02}, ++{0x5495, 0xff}, ++{0x5496, 0x00}, ++{0x5497, 0x00}, ++{0x54a0, 0x41}, ++{0x54a2, 0x04}, ++{0x54a3, 0x00}, ++{0x54a4, 0x04}, ++{0x54a5, 0x00}, ++{0x54a6, 0x04}, ++{0x54a7, 0x00}, ++{0x54ac, 0x04}, ++{0x54ad, 0x00}, ++{0x54ae, 0x04}, ++{0x54af, 0x00}, ++{0x54b0, 0x04}, ++{0x54b1, 0x00}, ++{0x5800, 0x19}, ++{0x5801, 0x03}, ++{0x5802, 0x60}, ++{0x5803, 0xf0}, ++{0x5804, 0x00}, ++{0x5805, 0x40}, ++{0x5806, 0x01}, ++{0x5807, 0x00}, ++{0x5808, 0x60}, ++{0x5809, 0xf0}, ++{0x580a, 0x33}, ++{0x580b, 0x10}, ++{0x580c, 0x04}, ++{0x580d, 0x00}, ++{0x580e, 0x10}, ++{0x580f, 0x10}, ++{0x5810, 0x02}, ++{0x5811, 0x08}, ++{0x5812, 0x38}, ++{0x5813, 0x00}, ++{0x5814, 0x00}, ++{0x5815, 0x00}, ++{0x5816, 0x00}, ++{0x5000, 0x81}, ++{0x5001, 0x42}, ++{0x5002, 0x19}, ++{0x5003, 0x16}, ++{0x5004, 0x02}, ++{0x5005, 0x00}, ++{0x5006, 0x01}, ++{0x5007, 0x00}, ++{0x5008, 0x00}, ++{0x5009, 0x40}, ++{0x500a, 0x00}, ++{0x500b, 0x00}, ++{0x500c, 0x00}, ++{0x500d, 0x00}, ++{0x500e, 0x00}, ++{0x500f, 0x00}, ++{0x5010, 0x07}, ++{0x5011, 0x8f}, ++{0x5012, 0x05}, ++{0x5013, 0x0f}, ++{0x5014, 0x01}, ++{0x5015, 0x01}, ++{0x5016, 0x01}, ++{0x5017, 0x01}, ++{0x5018, 0x00}, ++{0x5019, 0x00}, ++{0x501a, 0x00}, ++{0x501b, 0x10}, ++{0x501c, 0x00}, ++{0x501d, 0x10}, ++{0x501e, 0x00}, ++{0x501f, 0x10}, ++{0x5020, 0x04}, ++{0x5021, 0x00}, ++{0x5022, 0x04}, ++{0x5023, 0x00}, ++{0x5024, 0x04}, ++{0x5025, 0x00}, ++{0x5026, 0x00}, ++{0x5027, 0x10}, ++{0x5028, 0x00}, ++{0x5029, 0x10}, ++{0x502a, 0x00}, ++{0x502b, 0x10}, ++{0x502c, 0x00}, ++{0x502d, 0x10}, ++{0x502e, 0x00}, ++{0x502f, 0x10}, ++{0x5030, 0x00}, ++{0x5031, 0x10}, ++{0x5032, 0x04}, ++{0x5033, 0x00}, ++{0x5034, 0x04}, ++{0x5035, 0x00}, ++{0x5036, 0x04}, ++{0x5037, 0x00}, ++{0x5038, 0x00}, ++{0x5039, 0x10}, ++{0x503a, 0x00}, ++{0x503b, 0x10}, ++{0x503c, 0x00}, ++{0x503d, 0x10}, ++{0x503e, 0x00}, ++{0x503f, 0x00}, ++{0x5040, 0x00}, ++{0x5041, 0x01}, ++{0x5042, 0x00}, ++{0x5043, 0x00}, ++{0x5600, 0x0f}, ++{0x5601, 0xab}, ++{0x5602, 0x02}, ++{0x5603, 0x58}, ++{0x5604, 0x03}, ++{0x5605, 0x20}, ++{0x5606, 0x02}, ++{0x5607, 0x58}, ++{0x5608, 0x03}, ++{0x5609, 0x20}, ++{0x560a, 0x02}, ++{0x560b, 0x58}, ++{0x560c, 0x03}, ++{0x560d, 0x20}, ++{0x560e, 0x02}, ++{0x560f, 0x58}, ++{0x5610, 0x03}, ++{0x5611, 0x20}, ++{0x5612, 0x02}, ++{0x5613, 0x58}, ++{0x5614, 0x03}, ++{0x5615, 0x20}, ++{0x5616, 0x02}, ++{0x5617, 0x58}, ++{0x5618, 0x03}, ++{0x5619, 0x20}, ++{0x5640, 0x0f}, ++{0x5641, 0xab}, ++{0x5642, 0x02}, ++{0x5643, 0x58}, ++{0x5644, 0x03}, ++{0x5645, 0x20}, ++{0x5646, 0x02}, ++{0x5647, 0x58}, ++{0x5648, 0x03}, ++{0x5649, 0x20}, ++{0x564a, 0x02}, ++{0x564b, 0x58}, ++{0x564c, 0x03}, ++{0x564d, 0x20}, ++{0x564e, 0x02}, ++{0x564f, 0x58}, ++{0x5650, 0x03}, ++{0x5651, 0x20}, ++{0x5652, 0x02}, ++{0x5653, 0x58}, ++{0x5654, 0x03}, ++{0x5655, 0x20}, ++{0x5656, 0x02}, ++{0x5657, 0x58}, ++{0x5658, 0x03}, ++{0x5659, 0x20}, ++{0x5680, 0x0f}, ++{0x5681, 0xab}, ++{0x5682, 0x02}, ++{0x5683, 0x58}, ++{0x5684, 0x03}, ++{0x5685, 0x20}, ++{0x5686, 0x02}, ++{0x5687, 0x58}, ++{0x5688, 0x03}, ++{0x5689, 0x20}, ++{0x568a, 0x02}, ++{0x568b, 0x58}, ++{0x568c, 0x03}, ++{0x568d, 0x20}, ++{0x568e, 0x02}, ++{0x568f, 0x58}, ++{0x5690, 0x03}, ++{0x5691, 0x20}, ++{0x5692, 0x02}, ++{0x5693, 0x58}, ++{0x5694, 0x03}, ++{0x5695, 0x20}, ++{0x5696, 0x02}, ++{0x5697, 0x58}, ++{0x5698, 0x03}, ++{0x5699, 0x20}, ++{0x5700, 0x00}, ++{0x5701, 0x00}, ++{0x5702, 0x00}, ++{0x5703, 0x00}, ++{0x5704, 0x02}, ++{0x5705, 0x80}, ++{0x5706, 0x01}, ++{0x5707, 0xe0}, ++{0x5708, 0x00}, ++{0x5709, 0x0e}, ++{0x5740, 0x00}, ++{0x5741, 0x00}, ++{0x5742, 0x00}, ++{0x5743, 0x00}, ++{0x5744, 0x02}, ++{0x5745, 0x80}, ++{0x5746, 0x01}, ++{0x5747, 0xe0}, ++{0x5748, 0x00}, ++{0x5749, 0x0e}, ++{0x5780, 0x00}, ++{0x5781, 0x00}, ++{0x5782, 0x00}, ++{0x5783, 0x00}, ++{0x5784, 0x02}, ++{0x5785, 0x80}, ++{0x5786, 0x01}, ++{0x5787, 0xe0}, ++{0x5788, 0x00}, ++{0x5789, 0x0e}, ++{0x5200, 0x70}, ++{0x5201, 0x80}, ++{0x5202, 0x73}, ++{0x5203, 0xff}, ++{0x5204, 0x02}, ++{0x5205, 0x6c}, ++{0x5206, 0x00}, ++{0x5207, 0x00}, ++{0x5209, 0x08}, ++{0x520a, 0x00}, ++{0x520b, 0x07}, ++{0x520c, 0x01}, ++{0x520d, 0x01}, ++{0x520e, 0x01}, ++{0x520f, 0x01}, ++{0x5210, 0x00}, ++{0x5211, 0x00}, ++{0x5212, 0x00}, ++{0x5213, 0x00}, ++{0x5214, 0x00}, ++{0x5215, 0x00}, ++{0x5216, 0x07}, ++{0x5217, 0x8b}, ++{0x5218, 0x00}, ++{0x5219, 0x00}, ++{0x5280, 0x00}, ++{0x5281, 0x00}, ++{0x5282, 0xff}, ++{0x5283, 0xff}, ++{0x5284, 0x02}, ++{0x5285, 0x6c}, ++{0x5286, 0x00}, ++{0x5287, 0x00}, ++{0x5289, 0x08}, ++{0x528a, 0x00}, ++{0x528b, 0x07}, ++{0x528c, 0x01}, ++{0x528d, 0x01}, ++{0x528e, 0x01}, ++{0x528f, 0x01}, ++{0x5290, 0x00}, ++{0x5291, 0x00}, ++{0x5292, 0x00}, ++{0x5293, 0x00}, ++{0x5294, 0x00}, ++{0x5295, 0x00}, ++{0x5296, 0x07}, ++{0x5297, 0x8b}, ++{0x5298, 0x00}, ++{0x5299, 0x00}, ++{0x5300, 0x00}, ++{0x5301, 0x00}, ++{0x5302, 0xff}, ++{0x5303, 0xff}, ++{0x5304, 0x02}, ++{0x5305, 0x6c}, ++{0x5306, 0x00}, ++{0x5307, 0x00}, ++{0x5309, 0x08}, ++{0x530a, 0x00}, ++{0x530b, 0x07}, ++{0x530c, 0x01}, ++{0x530d, 0x01}, ++{0x530e, 0x01}, ++{0x530f, 0x01}, ++{0x5310, 0x00}, ++{0x5311, 0x00}, ++{0x5312, 0x00}, ++{0x5313, 0x00}, ++{0x5314, 0x00}, ++{0x5315, 0x00}, ++{0x5316, 0x07}, ++{0x5317, 0x8b}, ++{0x5318, 0x00}, ++{0x5319, 0x00}, ++#ifdef OX03A_DISPLAY_PATTERN_COLOR_BAR ++{0x5080, 0x80}, /* Rolling test pattern for HCG */ ++#else ++{0x5080, 0x00}, ++#endif ++{0x5081, 0x01}, ++{0x5082, 0xb0}, ++{0x5083, 0x0f}, ++{0x5084, 0x00}, ++{0x5085, 0x00}, ++{0x5086, 0x00}, ++{0x5087, 0x01}, ++{0x5088, 0x00}, ++{0x5089, 0x00}, ++{0x508a, 0x00}, ++{0x508b, 0x00}, ++{0x508c, 0x00}, ++{0x508d, 0x00}, ++{0x508e, 0x00}, ++{0x508f, 0x00}, ++{0x5090, 0x00}, ++{0x5091, 0x00}, ++{0x5092, 0x00}, ++{0x5093, 0x00}, ++{0x5094, 0x00}, ++{0x5095, 0x00}, ++{0x5096, 0x00}, ++{0x5097, 0x00}, ++#ifdef OX03A_DISPLAY_PATTERN_COLOR_BAR ++{0x50c0, 0x80}, /* Rolling test pattern for LCG */ ++#else ++{0x50c0, 0x00}, ++#endif ++{0x50c1, 0x01}, ++{0x50c2, 0xb0}, ++{0x50c3, 0x0f}, ++{0x50c4, 0x00}, ++{0x50c5, 0x00}, ++{0x50c6, 0x00}, ++{0x50c7, 0x01}, ++{0x50c8, 0x00}, ++{0x50c9, 0x00}, ++{0x50ca, 0x00}, ++{0x50cb, 0x00}, ++{0x50cc, 0x00}, ++{0x50cd, 0x00}, ++{0x50ce, 0x00}, ++{0x50cf, 0x00}, ++{0x50d0, 0x00}, ++{0x50d1, 0x00}, ++{0x50d2, 0x00}, ++{0x50d3, 0x00}, ++{0x50d4, 0x00}, ++{0x50d5, 0x00}, ++{0x50d6, 0x00}, ++{0x50d7, 0x00}, ++#ifdef OX03A_DISPLAY_PATTERN_COLOR_BAR ++{0x5100, 0x80}, /* Rolling test pattern for VS */ ++#else ++{0x5100, 0x00}, ++#endif ++{0x5101, 0x01}, ++{0x5102, 0xb0}, ++{0x5103, 0x0f}, ++{0x5104, 0x00}, ++{0x5105, 0x00}, ++{0x5106, 0x00}, ++{0x5107, 0x01}, ++{0x5108, 0x00}, ++{0x5109, 0x00}, ++{0x510a, 0x00}, ++{0x510b, 0x00}, ++{0x510c, 0x00}, ++{0x510d, 0x00}, ++{0x510e, 0x00}, ++{0x510f, 0x00}, ++{0x5110, 0x00}, ++{0x5111, 0x00}, ++{0x5112, 0x00}, ++{0x5113, 0x00}, ++{0x5114, 0x00}, ++{0x5115, 0x00}, ++{0x5116, 0x00}, ++{0x5117, 0x00}, ++{0x380e, 0x05}, ++{0x380f, 0x34}, ++{0x380c, 0x06}, ++{0x380d, 0xcc}, ++{0x384c, 0x03}, ++{0x384d, 0xc0}, ++{0x4603, 0x01}, ++{0x4601, 0x00}, ++{0x3501, 0x01}, ++{0x0100, 0x01}, +}; diff --git a/drivers/media/i2c/soc_camera/ti9x4.c b/drivers/media/i2c/soc_camera/ti9x4.c new file mode 100644 -index 0000000..a4c7b3f +index 0000000..222db9b --- /dev/null +++ b/drivers/media/i2c/soc_camera/ti9x4.c @@ -0,0 +1,518 @@ @@ -9698,7 +16383,7 @@ index 0000000..a4c7b3f + reg8_write(client, 0x6d, port_config); + reg8_write(client, 0x7c, port_config2); + reg8_write(client, 0x70, (idx << 6) | 0x1e); /* CSI data type: yuv422 8-bit, assign VC */ -+ reg8_write(client, 0x71, (idx << 6) | 0x2a); /* CSI data type: RAW8, assign VC */ ++ reg8_write(client, 0x71, (idx << 6) | 0x2c); /* CSI data type: RAW12, assign VC */ + reg8_write(client, 0xbc, 0x00); /* Setup minimal time between FV and LV to 3 PCLKs */ + reg8_write(client, 0x6e, 0x88); /* Sensor reset: backchannel GPIO0/GPIO1 set low */ +} @@ -10158,7 +16843,7 @@ index 0000000..b53b4c6 +} +#endif /* _TI9X4_H */ diff --git a/drivers/media/platform/soc_camera/rcar_csi2.c b/drivers/media/platform/soc_camera/rcar_csi2.c -index 4d95da6..2ef27e8 100644 +index 4d95da6..53fc644 100644 --- a/drivers/media/platform/soc_camera/rcar_csi2.c +++ b/drivers/media/platform/soc_camera/rcar_csi2.c @@ -37,8 +37,9 @@ @@ -10191,6 +16876,15 @@ index 4d95da6..2ef27e8 100644 #define RCAR_CSI2_PHYCNT_SHUTDOWNZ (1 << 17) #define RCAR_CSI2_PHYCNT_RSTZ (1 << 16) #define RCAR_CSI2_PHYCNT_ENABLECLK (1 << 4) +@@ -80,7 +86,7 @@ + + #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_ON (0 << 6) + #define RCAR_CSI2_VCDT_SEL_DTN (1 << 0) + + #define RCAR_CSI2_LINKCNT_MONITOR_EN (1 << 31) @@ -106,6 +112,9 @@ #define RCAR_CSI2_LSWAP_L0SEL_PLANE2 (2 << 0) #define RCAR_CSI2_LSWAP_L0SEL_PLANE3 (3 << 0) @@ -10524,7 +17218,7 @@ index 4d95da6..2ef27e8 100644 } return ret; -@@ -543,18 +642,19 @@ static int rcar_csi2_parse_dt(struct device_node *np, +@@ -543,39 +642,30 @@ static int rcar_csi2_parse_dt(struct device_node *np, return -EINVAL; v4l2_of_parse_endpoint(endpoint, &bus_cfg); @@ -10550,25 +17244,42 @@ index 4d95da6..2ef27e8 100644 for (i = 0; i < VC_MAX_CHANNEL; i++) { sprintf(csi_name, "csi2_vc%d", i); -@@ -573,6 +673,8 @@ static int rcar_csi2_parse_dt(struct device_node *np, - config->vcdt |= (0x24 << (i * 16)); - else if (!strcmp(str, "ycbcr422")) - config->vcdt |= (0x1e << (i * 16)); -+ else if (!strcmp(str, "raw8")) -+ config->vcdt |= (0x2a << (i * 16)); - else - config->vcdt |= 0; + 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; -@@ -587,6 +689,8 @@ static int rcar_csi2_parse_dt(struct device_node *np, - config->vcdt2 |= (0x24 << (j * 16)); - else if (!strcmp(str, "ycbcr422")) - config->vcdt2 |= (0x1e << (j * 16)); -+ else if (!strcmp(str, "raw8")) -+ config->vcdt2 |= (0x2a << (j * 16)); - else - config->vcdt2 |= 0; + 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)); +@@ -583,13 +673,6 @@ static int rcar_csi2_parse_dt(struct device_node *np, + if (i >= 2) { + int j = (i - 2); -@@ -608,6 +712,7 @@ static int rcar_csi2_probe(struct platform_device *pdev) +- 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)); +@@ -608,6 +691,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; @@ -10576,7 +17287,7 @@ index 4d95da6..2ef27e8 100644 dev_dbg(&pdev->dev, "CSI2 probed.\n"); -@@ -618,12 +723,7 @@ static int rcar_csi2_probe(struct platform_device *pdev) +@@ -618,12 +702,7 @@ static int rcar_csi2_probe(struct platform_device *pdev) if (ret) return ret; @@ -10590,7 +17301,7 @@ index 4d95da6..2ef27e8 100644 } else { pdata = pdev->dev.platform_data; if (!pdata) -@@ -655,23 +755,27 @@ static int rcar_csi2_probe(struct platform_device *pdev) +@@ -655,23 +734,27 @@ static int rcar_csi2_probe(struct platform_device *pdev) return ret; priv->pdev = pdev; @@ -10628,7 +17339,7 @@ index 4d95da6..2ef27e8 100644 spin_lock_init(&priv->lock); -@@ -684,10 +788,11 @@ static int rcar_csi2_probe(struct platform_device *pdev) +@@ -684,10 +767,11 @@ static int rcar_csi2_probe(struct platform_device *pdev) static int rcar_csi2_remove(struct platform_device *pdev) { @@ -11082,7 +17793,7 @@ index 74fb005..f6119e5 100644 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 +index edd1c1d..ae04c6e 100644 --- a/drivers/media/platform/soc_camera/soc_camera.c +++ b/drivers/media/platform/soc_camera/soc_camera.c @@ -49,7 +49,7 @@ @@ -11094,7 +17805,7 @@ index edd1c1d..54f4c9d 100644 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, +@@ -1106,6 +1106,44 @@ static int soc_camera_s_parm(struct file *file, void *fh, return -ENOIOCTLCMD; } @@ -11109,11 +17820,37 @@ index edd1c1d..54f4c9d 100644 + + return -ENOIOCTLCMD; +} ++ ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++static int soc_camera_g_register(struct file *file, void *priv, ++ struct v4l2_dbg_register *reg) ++{ ++ struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ ++ if (ici->ops->get_register) ++ return ici->ops->get_register(icd, reg); ++ ++ return -ENOIOCTLCMD; ++} ++ ++static int soc_camera_s_register(struct file *file, void *priv, ++ const struct v4l2_dbg_register *reg) ++{ ++ struct soc_camera_device *icd = file->private_data; ++ struct soc_camera_host *ici = to_soc_camera_host(icd->parent); ++ ++ if (ici->ops->set_register) ++ return ici->ops->set_register(icd, reg); ++ ++ return -ENOIOCTLCMD; ++} ++#endif + 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) +@@ -1664,7 +1702,7 @@ static void scan_of_host(struct soc_camera_host *ici) of_node_put(ren); if (i) { @@ -11122,16 +17859,20 @@ index edd1c1d..54f4c9d 100644 break; } } -@@ -2077,6 +2089,7 @@ static int soc_camera_device_register(struct soc_camera_device *icd) +@@ -2077,6 +2115,11 @@ 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, ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ .vidioc_g_register = soc_camera_g_register, ++ .vidioc_s_register = soc_camera_s_register, ++#endif }; 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 +index e3e665e..b47d515 100644 --- a/drivers/media/platform/soc_camera/soc_mediabus.c +++ b/drivers/media/platform/soc_camera/soc_mediabus.c @@ -57,6 +57,16 @@ @@ -11151,7 +17892,24 @@ index e3e665e..84754a4 100644 .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, +@@ -382,6 +392,16 @@ + .order = SOC_MBUS_ORDER_LE, + .layout = SOC_MBUS_LAYOUT_PACKED, + }, ++}, { ++ .code = MEDIA_BUS_FMT_SBGGR16_1X16, ++ .fmt = { ++ .fourcc = V4L2_PIX_FMT_SBGGR16, ++ .name = "Bayer 16 RGGB", ++ .bits_per_sample = 16, ++ .packing = SOC_MBUS_PACKING_NONE, ++ .order = SOC_MBUS_ORDER_LE, ++ .layout = SOC_MBUS_LAYOUT_PACKED, ++ }, + }, + }; + +@@ -403,6 +423,10 @@ int soc_mbus_samples_per_pixel(const struct soc_mbus_pixelfmt *mf, *numerator = 2; *denominator = 1; return 0; @@ -11162,7 +17920,7 @@ index e3e665e..84754a4 100644 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) +@@ -428,6 +452,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; @@ -11193,14 +17951,18 @@ index 2ff7737..e5f3f53 100644 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 +index 1a15c3e..76e90be 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h -@@ -125,6 +125,7 @@ struct soc_camera_host_ops { +@@ -125,6 +125,11 @@ 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 *); ++#ifdef CONFIG_VIDEO_ADV_DEBUG ++ int (*get_register)(struct soc_camera_device *, struct v4l2_dbg_register *reg); ++ int (*set_register)(struct soc_camera_device *, const struct v4l2_dbg_register *reg); ++#endif }; #define SOCAM_SENSOR_INVERT_PCLK (1 << 0) -- cgit 1.2.3-korg From cda041377d8f94b08db2a96215a5689c40b9467b Mon Sep 17 00:00:00 2001 From: Andrey Dolnikov Date: Fri, 13 Apr 2018 17:09:51 +0300 Subject: linux-renesas: rcar_vin: Add RAW sensors MBUS formats --- .../0130-Add-RAW-sensors-MBUS-formats.patch | 36 ++++++++++++++++++++++ .../linux/linux-renesas_4.9.bbappend | 1 + 2 files changed, 37 insertions(+) create mode 100644 meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0130-Add-RAW-sensors-MBUS-formats.patch (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0130-Add-RAW-sensors-MBUS-formats.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0130-Add-RAW-sensors-MBUS-formats.patch new file mode 100644 index 0000000..3278fc2 --- /dev/null +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0130-Add-RAW-sensors-MBUS-formats.patch @@ -0,0 +1,36 @@ +From f977b84f5899093208f64b31731ea991579d6f8f Mon Sep 17 00:00:00 2001 +From: Vladimir Barinov +Date: Fri, 13 Apr 2018 16:51:15 +0300 +Subject: [PATCH] Add RAW sensors MBUS formats. + +--- + drivers/media/platform/soc_camera/rcar_vin.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c +index 37f1a11..b4ea2de 100644 +--- a/drivers/media/platform/soc_camera/rcar_vin.c ++++ b/drivers/media/platform/soc_camera/rcar_vin.c +@@ -1074,6 +1074,9 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) + break; + case MEDIA_BUS_FMT_SBGGR8_1X8: + case MEDIA_BUS_FMT_SBGGR12_1X12: ++ case MEDIA_BUS_FMT_SRGGB12_1X12: ++ case MEDIA_BUS_FMT_SGRBG12_1X12: ++ case MEDIA_BUS_FMT_SGRBG14_1X14: + vnmc |= VNMC_INF_RAW8 | VNMC_BPS; + break; + default: +@@ -2213,6 +2216,9 @@ static int rcar_vin_get_formats(struct soc_camera_device *icd, unsigned int idx, + case MEDIA_BUS_FMT_RGB888_1X24: + case MEDIA_BUS_FMT_SBGGR8_1X8: + case MEDIA_BUS_FMT_SBGGR12_1X12: ++ case MEDIA_BUS_FMT_SRGGB12_1X12: ++ case MEDIA_BUS_FMT_SGRBG12_1X12: ++ case MEDIA_BUS_FMT_SGRBG14_1X14: + if (cam->extra_fmt) + break; + +-- +2.7.4 + 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 index 6c8337b..5f7f64a 100644 --- 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 @@ -109,6 +109,7 @@ SRC_URI_append = " \ file://0127-IMR-UIO-Driver-initial-version.patch \ file://0128-rcar_imr-v4l2-driver-Fix-module-support.patch \ file://0129-Add-cropping-handling-to-VSP-alpha-planes.patch \ + file://0130-Add-RAW-sensors-MBUS-formats.patch \ " SRC_URI_append_h3ulcb = " file://ulcb.cfg" -- cgit 1.2.3-korg From 4ae3ea734b05c22620e7108885f4d28305ceaae7 Mon Sep 17 00:00:00 2001 From: Andrey Dolnikov Date: Fri, 13 Apr 2018 20:05:26 +0300 Subject: Fix ISP devicetree nodes to be compatiable with UIO driver --- .../0018-arm64-renesas-r8a7797-Add-Renesas-R8A7797-SoC-suppor.patch | 2 +- .../0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas') 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 index 0b67bc1..42b8f23 100644 --- 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 @@ -1239,7 +1239,7 @@ index 0000000..faefe8a + isp0: isp@fec00000 { + compatible = "renesas,isp-r8a7797"; + reg = <0 0xfec00000 0 0x20000>, -+ <0 0xfed00000 0 0x4000>; ++ <0 0xfed00000 0 0x10000>; + interrupts = , + ; + clocks = <&cpg CPG_MOD 817>; diff --git a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch index 321258f..d9eb2fa 100644 --- a/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch +++ b/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0051-arm64-renesas-r8a7798-Add-Renesas-R8A7798-SoC-suppor.patch @@ -1784,7 +1784,7 @@ index 0000000..00bd4d6 + isp0: isp@fec00000 { + compatible = "renesas,isp-r8a7798"; + reg = <0 0xfec00000 0 0x20000>, -+ <0 0xfed00000 0 0x4000>; ++ <0 0xfed00000 0 0x10000>; + interrupts = , + ; + clocks = <&cpg CPG_MOD 817>; @@ -1794,7 +1794,7 @@ index 0000000..00bd4d6 + isp1: isp@fee00000 { + compatible = "renesas,isp-r8a7798"; + reg = <0 0xfee00000 0 0x20000>, -+ <0 0xfed20000 0 0x4000>; ++ <0 0xfed20000 0 0x10000>; + interrupts = , + ; + clocks = <&cpg CPG_MOD 814>; -- cgit 1.2.3-korg