aboutsummaryrefslogtreecommitdiffstats
path: root/meta-rcar-gen2/recipes-kernel/linux/linux-renesas
diff options
context:
space:
mode:
authorNobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>2015-03-25 10:47:45 +0900
committerNobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>2015-03-25 10:47:45 +0900
commit1c35920d85e424b3f65aa6df1dbde689dd6ec007 (patch)
tree58b2cacb3674111aad5a4ded694db0cef5cf55f3 /meta-rcar-gen2/recipes-kernel/linux/linux-renesas
commit BSP v1.8.0
Signed-off-by: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
Diffstat (limited to 'meta-rcar-gen2/recipes-kernel/linux/linux-renesas')
-rw-r--r--meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0001-arm-alt-Add-vmalloc-384M-to-bootargs-of-DTS.patch26
-rw-r--r--meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0001-arm-gose-Add-vmalloc-384M-to-bootargs-of-DTS.patch26
-rw-r--r--meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0001-arm-koelsch-Add-vmalloc-384M-to-bootargs-of-DTS.patch26
-rw-r--r--meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0001-arm-lager-Add-vmalloc-384M-to-bootargs-of-DTS.patch26
-rw-r--r--meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0001-kernel-Silk-board-support.patch1456
-rw-r--r--meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0002-kernel-silk-fix-ethernet-phy-irq.patch25
-rw-r--r--meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0003-kernel-silk-fix-sd-detect.patch25
-rw-r--r--meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0004-kernel-Revert-i2c-rcar-Support-ACK-by-HW-auto-restart-after-NACK.patch66
-rw-r--r--meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0006-Rcar-DU-add-RGB-connector.patch276
-rw-r--r--meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0007-SILK-add-i2c0.patch45
-rw-r--r--meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0008-Porter-board-support.patch1426
-rw-r--r--meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0009-shmobile-add-atag-dtb-compat.patch26
-rw-r--r--meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0010-Silk-Add-missing-pins-handle-to-Eth.patch43
-rw-r--r--meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0011-Silk-Add-missing-DU-pins.patch49
-rw-r--r--meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0012-can-add-Renesas-R-Car-CAN-driver.patch958
-rw-r--r--meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0013-sh-pfc-r8a7791-add-CAN-pin-groups.patch216
-rw-r--r--meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0014-sh-pfc-r8a7791-fix-CAN-pin-groups.patch52
-rw-r--r--meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0015-can-rcar_can-support-all-input-clocks.patch139
-rw-r--r--meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0016-can-rcar_can-document-device-tree-bindings.patch66
-rw-r--r--meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0017-can-rcar_can-add-device-tree-support.patch77
-rw-r--r--meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0018-porter-can-support.patch63
-rw-r--r--meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0019-i2c-busses-rcar-Workaround-arbitration-loss-error.patch31
-rw-r--r--meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0020-Silk-Remove-I2C1-clock-from-clk_enables.patch30
23 files changed, 5173 insertions, 0 deletions
diff --git a/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0001-arm-alt-Add-vmalloc-384M-to-bootargs-of-DTS.patch b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0001-arm-alt-Add-vmalloc-384M-to-bootargs-of-DTS.patch
new file mode 100644
index 0000000..b7d23b2
--- /dev/null
+++ b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0001-arm-alt-Add-vmalloc-384M-to-bootargs-of-DTS.patch
@@ -0,0 +1,26 @@
+From 7baf674a7c54d3241d796adf3249b304aa2aeaaf Mon Sep 17 00:00:00 2001
+From: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
+Date: Mon, 14 Jul 2014 11:44:41 +0900
+Subject: [PATCH] arm: shmobile: alt: Add 'vmalloc=384M' to bootargs of DTS
+
+Signed-off-by: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
+---
+ arch/arm/boot/dts/r8a7794-alt.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm/boot/dts/r8a7794-alt.dts b/arch/arm/boot/dts/r8a7794-alt.dts
+index 3e1afef..c85edda8 100644
+--- a/arch/arm/boot/dts/r8a7794-alt.dts
++++ b/arch/arm/boot/dts/r8a7794-alt.dts
+@@ -31,7 +31,7 @@
+ compatible = "renesas,alt", "renesas,r8a7794";
+
+ chosen {
+- bootargs = "console=ttySC10,38400 ignore_loglevel rw root=/dev/nfs ip=dhcp";
++ bootargs = "console=ttySC10,38400 ignore_loglevel rw root=/dev/nfs ip=dhcp vmalloc=384M";
+ };
+
+ memory@40000000 {
+--
+1.7.9.5
+
diff --git a/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0001-arm-gose-Add-vmalloc-384M-to-bootargs-of-DTS.patch b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0001-arm-gose-Add-vmalloc-384M-to-bootargs-of-DTS.patch
new file mode 100644
index 0000000..5c282c8
--- /dev/null
+++ b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0001-arm-gose-Add-vmalloc-384M-to-bootargs-of-DTS.patch
@@ -0,0 +1,26 @@
+From f1b6ab8592afda486b6c4c513f39dfbe2a4e8334 Mon Sep 17 00:00:00 2001
+From: Dien Pham <dien.pham.ry@rvc.renesas.com>
+Date: Fri, 15 Aug 2014 14:59:45 +0700
+Subject: [PATCH] arm gose Add vmalloc 384M to bootargs of DTS
+
+Signed-off-by: Dien Pham <dien.pham.ry@rvc.renesas.com>
+---
+ arch/arm/boot/dts/r8a7793-gose.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm/boot/dts/r8a7793-gose.dts b/arch/arm/boot/dts/r8a7793-gose.dts
+index 9c0108b..fbe3566 100644
+--- a/arch/arm/boot/dts/r8a7793-gose.dts
++++ b/arch/arm/boot/dts/r8a7793-gose.dts
+@@ -36,7 +36,7 @@
+ };
+
+ chosen {
+- bootargs = "console=ttySC6,38400 ignore_loglevel rw root=/dev/nfs ip=dhcp";
++ bootargs = "console=ttySC6,38400 ignore_loglevel rw root=/dev/nfs ip=dhcp vmalloc=384M";
+ };
+
+ memory@40000000 {
+--
+1.8.0.1
+
diff --git a/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0001-arm-koelsch-Add-vmalloc-384M-to-bootargs-of-DTS.patch b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0001-arm-koelsch-Add-vmalloc-384M-to-bootargs-of-DTS.patch
new file mode 100644
index 0000000..d32019f
--- /dev/null
+++ b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0001-arm-koelsch-Add-vmalloc-384M-to-bootargs-of-DTS.patch
@@ -0,0 +1,26 @@
+From 6f5df111b2cf5d4cb01922da7076a7ab238f5650 Mon Sep 17 00:00:00 2001
+From: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
+Date: Mon, 14 Jul 2014 11:43:03 +0900
+Subject: [PATCH 1/3] arm: shmobile: koelsch: Add 'vmalloc=384M' to bootargs of DTS
+
+Signed-off-by: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
+---
+ arch/arm/boot/dts/r8a7791-koelsch.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm/boot/dts/r8a7791-koelsch.dts b/arch/arm/boot/dts/r8a7791-koelsch.dts
+index 5dc4f7d..d3619fc 100644
+--- a/arch/arm/boot/dts/r8a7791-koelsch.dts
++++ b/arch/arm/boot/dts/r8a7791-koelsch.dts
+@@ -39,7 +39,7 @@
+ };
+
+ chosen {
+- bootargs = "console=ttySC6,38400 ignore_loglevel rw root=/dev/nfs ip=dhcp";
++ bootargs = "console=ttySC6,38400 ignore_loglevel rw root=/dev/nfs ip=dhcp vmalloc=384M";
+ };
+
+ memory@40000000 {
+--
+1.7.9.5
+
diff --git a/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0001-arm-lager-Add-vmalloc-384M-to-bootargs-of-DTS.patch b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0001-arm-lager-Add-vmalloc-384M-to-bootargs-of-DTS.patch
new file mode 100644
index 0000000..8d19c6d
--- /dev/null
+++ b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0001-arm-lager-Add-vmalloc-384M-to-bootargs-of-DTS.patch
@@ -0,0 +1,26 @@
+From 7a6b38f46db215055017a3288bd0d0bc6cfd5e8d Mon Sep 17 00:00:00 2001
+From: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
+Date: Mon, 14 Jul 2014 11:43:33 +0900
+Subject: [PATCH] arm: shmobile: lager: Add 'vmalloc=384M' to bootargs of DTS
+
+Signed-off-by: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
+---
+ arch/arm/boot/dts/r8a7790-lager.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm/boot/dts/r8a7790-lager.dts b/arch/arm/boot/dts/r8a7790-lager.dts
+index 58b30a2..e0ac607 100644
+--- a/arch/arm/boot/dts/r8a7790-lager.dts
++++ b/arch/arm/boot/dts/r8a7790-lager.dts
+@@ -38,7 +38,7 @@
+ };
+
+ chosen {
+- bootargs = "console=ttySC6,38400 ignore_loglevel rw root=/dev/nfs ip=dhcp";
++ bootargs = "console=ttySC6,38400 ignore_loglevel rw root=/dev/nfs ip=dhcp vmalloc=384M";
+ };
+
+ memory@40000000 {
+--
+1.7.9.5
+
diff --git a/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0001-kernel-Silk-board-support.patch b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0001-kernel-Silk-board-support.patch
new file mode 100644
index 0000000..12fb76c
--- /dev/null
+++ b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0001-kernel-Silk-board-support.patch
@@ -0,0 +1,1456 @@
+From f04a201ce9bfc04ca4b8b017116ca1cf9a313c9a Mon Sep 17 00:00:00 2001
+From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+Date: Sat, 6 Dec 2014 03:29:15 +0300
+Subject: [linux-kernel][PATCH] arm: rmobile: Add SILK board support
+
+SILK is an entry level development board based on R-Car E2 SoC (R8A7794)
+
+Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+
+---
+ arch/arm/boot/dts/Makefile | 1 +
+ arch/arm/boot/dts/r8a7794-silk.dts | 360 ++++++++++
+ arch/arm/configs/shmobile_defconfig | 1 +
+ arch/arm/mach-shmobile/Kconfig | 6 +
+ arch/arm/mach-shmobile/Makefile | 1 +
+ arch/arm/mach-shmobile/Makefile.boot | 1 +
+ arch/arm/mach-shmobile/board-silk-reference.c | 995 ++++++++++++++++++++++++++
+ 7 files changed, 1365 insertions(+)
+ create mode 100644 arch/arm/boot/dts/r8a7794-silk.dts
+ create mode 100644 arch/arm/mach-shmobile/board-silk-reference.c
+
+diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
+index 2a7b49b..f2b99db 100644
+--- a/arch/arm/boot/dts/Makefile
++++ b/arch/arm/boot/dts/Makefile
+@@ -178,6 +178,7 @@ dtb-$(CONFIG_ARCH_SHMOBILE_MULTI) += emev2-kzm9d.dtb \
+ r8a7791-koelsch.dtb \
+ r8a7790-lager.dtb \
+ r8a7794-alt.dtb \
++ r8a7794-silk.dtb \
+ r8a7793-gose.dtb \
+ r8a7779-marzen.dtb
+ dtb-$(CONFIG_ARCH_SOCFPGA) += socfpga_cyclone5.dtb \
+diff --git a/arch/arm/boot/dts/r8a7794-silk.dts b/arch/arm/boot/dts/r8a7794-silk.dts
+new file mode 100644
+index 0000000..cb69f6b
+--- /dev/null
++++ b/arch/arm/boot/dts/r8a7794-silk.dts
+@@ -0,0 +1,360 @@
++/*
++ * Device Tree Source for the Silk board
++ *
++ * Copyright (C) 2014 Renesas Electronics Corporation
++ * Copyright (C) 2014 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.
++ */
++
++/*
++ * SSI-AK4643
++ *
++ * SW1: 1: AK4643
++ * 3: ADV7511
++ *
++ * this command is required when playback.
++ *
++ * # amixer set "LINEOUT Mixer DACL" on
++ * # amixer set "Digital" 200
++ * # amixer set "DVC Out" 50
++ */
++
++/dts-v1/;
++#include "r8a7794.dtsi"
++#include <dt-bindings/gpio/gpio.h>
++#include <dt-bindings/input/input.h>
++
++/ {
++ model = "Silk";
++ compatible = "renesas,silk", "renesas,r8a7794";
++
++ aliases {
++ serial10 = &scif2;
++ };
++
++ chosen {
++ bootargs = "console=ttySC10,38400 ignore_loglevel rw root=/dev/nfs ip=dhcp vmalloc=384M";
++ };
++
++ memory@40000000 {
++ device_type = "memory";
++ reg = <0 0x40000000 0 0x40000000>;
++ };
++
++ lbsc {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ };
++
++ gpio-keys {
++ compatible = "gpio-keys";
++
++ key-1 {
++ gpios = <&gpio3 9 GPIO_ACTIVE_LOW>;
++ linux,code = <KEY_1>;
++ label = "SW12";
++ gpio-key,wakeup;
++ debounce-interval = <20>;
++ };
++ key-2 {
++ gpios = <&gpio3 10 GPIO_ACTIVE_LOW>;
++ linux,code = <KEY_2>;
++ label = "SW12";
++ gpio-key,wakeup;
++ debounce-interval = <20>;
++ };
++ key-3 {
++ gpios = <&gpio3 11 GPIO_ACTIVE_LOW>;
++ linux,code = <KEY_3>;
++ label = "SW12";
++ gpio-key,wakeup;
++ debounce-interval = <20>;
++ };
++ key-4 {
++ gpios = <&gpio3 12 GPIO_ACTIVE_LOW>;
++ linux,code = <KEY_4>;
++ label = "SW12";
++ gpio-key,wakeup;
++ debounce-interval = <20>;
++ };
++ key-a {
++ gpios = <&gpio5 10 GPIO_ACTIVE_LOW>;
++ linux,code = <KEY_A>;
++ label = "SW3";
++ gpio-key,wakeup;
++ debounce-interval = <20>;
++ };
++ key-b {
++ gpios = <&gpio5 11 GPIO_ACTIVE_LOW>;
++ linux,code = <KEY_B>;
++ label = "SW4";
++ gpio-key,wakeup;
++ debounce-interval = <20>;
++ };
++ key-c {
++ gpios = <&gpio5 12 GPIO_ACTIVE_LOW>;
++ linux,code = <KEY_C>;
++ label = "SW6";
++ gpio-key,wakeup;
++ debounce-interval = <20>;
++ };
++ };
++
++ vcc_sdhi0: regulator@0 {
++ compatible = "regulator-fixed";
++
++ regulator-name = "SDHI0 Vcc";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++
++ gpio = <&gpio2 26 GPIO_ACTIVE_HIGH>;
++ enable-active-high;
++ };
++
++ vccq_sdhi0: regulator@1 {
++ compatible = "regulator-gpio";
++
++ regulator-name = "SDHI0 VccQ";
++ regulator-min-microvolt = <1800000>;
++ regulator-max-microvolt = <3300000>;
++
++ gpios = <&gpio2 29 GPIO_ACTIVE_HIGH>;
++ gpios-states = <1>;
++ states = <3300000 1
++ 1800000 0>;
++ };
++
++ vcc_sdhi1: regulator@2 {
++ compatible = "regulator-fixed";
++
++ regulator-name = "SDHI1 Vcc";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++
++ gpio = <&gpio4 26 GPIO_ACTIVE_HIGH>;
++ enable-active-high;
++ };
++
++ vccq_sdhi1: regulator@3 {
++ compatible = "regulator-gpio";
++
++ regulator-name = "SDHI1 VccQ";
++ regulator-min-microvolt = <1800000>;
++ regulator-max-microvolt = <3300000>;
++
++ gpios = <&gpio4 29 GPIO_ACTIVE_HIGH>;
++ gpios-states = <1>;
++ states = <3300000 1
++ 1800000 0>;
++ };
++
++ fixedregulator3v3: fixedregulator@0 {
++ compatible = "regulator-fixed";
++ regulator-name = "fixed-3.3V";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ regulator-boot-on;
++ regulator-always-on;
++ };
++
++ hdmi_transmitter: adv7511 {
++ compatible = "adi,adv7511";
++ gpios = <&gpio5 23 GPIO_ACTIVE_LOW>;
++
++ adi,input-style = <0x02>;
++ adi,input-id = <0x00>;
++ adi,input-color-depth = <0x03>;
++ adi,sync-pulse = <0x03>;
++ adi,bit-justification = <0x01>;
++ adi,up-conversion = <0x00>;
++ adi,timing-generation-sequence = <0x00>;
++ adi,vsync-polarity = <0x02>;
++ adi,hsync-polarity = <0x02>;
++ adi,clock-delay = <0x03>;
++ };
++};
++
++&extal_clk {
++ clock-frequency = <20000000>;
++};
++
++&i2c1 {
++ pinctrl-0 = <&i2c1_pins>;
++ pinctrl-names = "default";
++
++ status = "okay";
++ clock-frequency = <400000>;
++
++ snd_codec: ak4643 {
++ #sound-dai-cells = <0>;
++ compatible = "asahi-kasei,ak4643";
++ reg = <0x12>;
++ };
++};
++
++&i2c8 {
++ status = "okay";
++ clock-frequency = <100000>;
++};
++
++&pfc {
++ pinctrl-0 = <&du_pins &usb0_pins &usb1_pins &sound_pins &sound_clk_pins
++ &vin0_pins>;
++ pinctrl-names = "default";
++
++ du_pins: du {
++ renesas,groups = "du0_rgb888", "du0_sync", "du0_clk_out",
++ "du1_rgb666", "du1_sync", "du1_clk_out";
++ renesas,function = "du";
++ };
++
++ i2c1_pins: i2c1 {
++ renesas,groups = "i2c1";
++ renesas,function = "i2c1";
++ };
++
++ scif2_pins: serial2 {
++ renesas,groups = "scif2_data";
++ renesas,function = "scif2";
++ };
++
++ ether_pins: ether {
++ renesas,groups = "eth_link", "eth_mdio", "eth_rmii";
++ renesas,function = "eth";
++ };
++
++ qspi_pins: spi0 {
++ renesas,groups = "qspi_ctrl", "qspi_data4";
++ renesas,function = "qspi";
++ };
++
++ sdhi0_pins: sd0 {
++ renesas,groups = "sdhi0_data4", "sdhi0_ctrl";
++ renesas,function = "sdhi0";
++ };
++
++ sdhi1_pins: sd1 {
++ renesas,groups = "sdhi1_data4", "sdhi1_ctrl";
++ renesas,function = "sdhi1";
++ };
++
++ mmc0_pins: mmc0 {
++ renesas,groups = "mmc_data8", "mmc_ctrl";
++ renesas,function = "mmc";
++ };
++
++ usb0_pins: usb0 {
++ renesas,groups = "usb0";
++ renesas,function = "usb0";
++ };
++
++ usb1_pins: usb1 {
++ renesas,groups = "usb1";
++ renesas,function = "usb1";
++ };
++
++ vin0_pins: vin0 {
++ renesas,groups = "vin0_data8", "vin0_sync", "vin0_field",
++ "vin0_clkenb", "vin0_clk";
++ renesas,function = "vin0";
++ };
++
++ sound_pins: sound {
++ renesas,groups = "ssi0129_ctrl", "ssi0_data", "ssi1_data";
++ renesas,function = "ssi";
++ };
++ sound_clk_pins: sound_clk {
++ renesas,groups = "audio_clk_c";
++ renesas,function = "audio_clk";
++ };
++};
++
++&ether {
++ phy-handle = <&phy1>;
++ renesas,ether-link-active-low;
++ status = "ok";
++
++ phy1: ethernet-phy@1 {
++ reg = <1>;
++ interrupt-parent = <&irqc0>;
++ interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
++ micrel,led-mode = <1>;
++ };
++};
++
++&scif2 {
++ pinctrl-0 = <&scif2_pins>;
++ pinctrl-names = "default";
++
++ status = "okay";
++};
++
++&qspi {
++ pinctrl-0 = <&qspi_pins>;
++ pinctrl-names = "default";
++
++ status = "okay";
++
++ flash: flash@0 {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ compatible = "spansion,s25fl512s";
++ reg = <0>;
++ spi-max-frequency = <30000000>;
++ spi-tx-bus-width = <4>;
++ spi-rx-bus-width = <4>;
++ m25p,fast-read;
++ spi-cpol;
++ spi-cpha;
++
++ partition@0 {
++ label = "loader";
++ reg = <0x00000000 0x00040000>;
++ read-only;
++ };
++ partition@40000 {
++ label = "user";
++ reg = <0x00040000 0x00400000>;
++ read-only;
++ };
++ partition@440000 {
++ label = "flash";
++ reg = <0x00440000 0x03bc0000>;
++ };
++ };
++};
++
++&sdhi0 {
++ pinctrl-0 = <&sdhi0_pins>;
++ pinctrl-names = "default";
++
++ vmmc-supply = <&vcc_sdhi0>;
++ vqmmc-supply = <&vccq_sdhi0>;
++ cd-gpios = <&gpio6 6 GPIO_ACTIVE_LOW>;
++ wp-gpios = <&gpio6 7 GPIO_ACTIVE_HIGH>;
++ status = "okay";
++};
++
++&sdhi1 {
++ pinctrl-0 = <&sdhi1_pins>;
++ pinctrl-names = "default";
++
++ vmmc-supply = <&vcc_sdhi1>;
++ vqmmc-supply = <&vccq_sdhi1>;
++ cd-gpios = <&gpio6 14 GPIO_ACTIVE_LOW>;
++ wp-gpios = <&gpio6 15 GPIO_ACTIVE_HIGH>;
++ status = "okay";
++};
++
++&mmcif0 {
++ pinctrl-0 = <&mmc0_pins>;
++ pinctrl-names = "default";
++
++ vmmc-supply = <&fixedregulator3v3>;
++ bus-width = <8>;
++ non-removable;
++ status = "okay";
++};
+diff --git a/arch/arm/configs/shmobile_defconfig b/arch/arm/configs/shmobile_defconfig
+index efdc321..11237db 100644
+--- a/arch/arm/configs/shmobile_defconfig
++++ b/arch/arm/configs/shmobile_defconfig
+@@ -24,6 +24,7 @@ CONFIG_MACH_KOELSCH=y
+ CONFIG_MACH_LAGER=y
+ CONFIG_MACH_GOSE=y
+ CONFIG_MACH_ALT=y
++CONFIG_MACH_SILK=y
+ CONFIG_MACH_MARZEN=y
+ CONFIG_SHMOBILE_TIMER_HZ=100
+ CONFIG_ARM_LPAE=y
+diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
+index bb1b599..e2e00a9 100644
+--- a/arch/arm/mach-shmobile/Kconfig
++++ b/arch/arm/mach-shmobile/Kconfig
+@@ -82,6 +82,12 @@ config MACH_ALT
+ select MICREL_PHY if SH_ETH
+ select SND_SOC_AK4642 if SND_SIMPLE_CARD
+
++config MACH_SILK
++ bool "Silk board"
++ depends on ARCH_R8A7794
++ select MICREL_PHY if SH_ETH
++ select SND_SOC_AK4642 if SND_SIMPLE_CARD
++
+ config MACH_MARZEN
+ bool "MARZEN board"
+ depends on ARCH_R8A7779
+diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
+index 8d997e2..139f31c 100644
+--- a/arch/arm/mach-shmobile/Makefile
++++ b/arch/arm/mach-shmobile/Makefile
+@@ -76,6 +76,7 @@ obj-$(CONFIG_MACH_KOELSCH) += board-koelsch-reference.o
+ obj-$(CONFIG_MACH_LAGER) += board-lager-reference.o
+ obj-$(CONFIG_MACH_GOSE) += board-gose-reference.o
+ obj-$(CONFIG_MACH_ALT) += board-alt-reference.o
++obj-$(CONFIG_MACH_SILK) += board-silk-reference.o
+ obj-$(CONFIG_MACH_MARZEN) += board-marzen-reference.o
+ else
+ obj-$(CONFIG_MACH_APE6EVM) += board-ape6evm.o
+diff --git a/arch/arm/mach-shmobile/Makefile.boot b/arch/arm/mach-shmobile/Makefile.boot
+index 58c2623..25105b2 100644
+--- a/arch/arm/mach-shmobile/Makefile.boot
++++ b/arch/arm/mach-shmobile/Makefile.boot
+@@ -15,6 +15,7 @@ loadaddr-$(CONFIG_MACH_MACKEREL) += 0x40008000
+ loadaddr-$(CONFIG_MACH_MARZEN) += 0x60008000
+ loadaddr-$(CONFIG_MACH_GOSE) += 0x40008000
+ loadaddr-$(CONFIG_MACH_ALT) += 0x40008000
++loadaddr-$(CONFIG_MACH_SILK) += 0x40008000
+
+ __ZRELADDR := $(sort $(loadaddr-y))
+ zreladdr-y += $(__ZRELADDR)
+diff --git a/arch/arm/mach-shmobile/board-silk-reference.c b/arch/arm/mach-shmobile/board-silk-reference.c
+new file mode 100644
+index 0000000..090a4df
+--- /dev/null
++++ b/arch/arm/mach-shmobile/board-silk-reference.c
+@@ -0,0 +1,995 @@
++/*
++ * Silk board support - Reference DT implementation
++ *
++ * Copyright (C) 2014 Renesas Electronics Corporation
++ * Copyright (C) 2014 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.
++ *
++ * 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
++ */
++
++#include <linux/dma-mapping.h>
++#include <linux/gpio.h>
++#include <linux/i2c.h>
++#include <linux/kernel.h>
++#include <linux/mfd/tmio.h>
++#include <linux/mmc/host.h>
++#include <linux/mmc/sh_mmcif.h>
++#include <linux/mmc/sh_mobile_sdhi.h>
++#include <linux/of_gpio.h>
++#include <linux/of_platform.h>
++#include <linux/platform_data/camera-rcar.h>
++#include <linux/platform_data/rcar-du.h>
++#include <linux/platform_data/usb-rcar-gen2-phy.h>
++#if IS_ENABLED(CONFIG_VIDEO_RENESAS_VSP1)
++#include <linux/platform_data/vsp1.h>
++#endif
++#include <linux/serial_sci.h>
++#include <linux/sh_dma.h>
++#include <linux/spi/flash.h>
++#include <linux/spi/sh_msiof.h>
++#include <linux/spi/spi.h>
++#include <linux/usb/phy.h>
++#if IS_ENABLED(CONFIG_USB_RENESAS_USBHS_UDC)
++#include <linux/usb/renesas_usbhs.h>
++#endif
++#include <media/soc_camera.h>
++#include <asm/mach/arch.h>
++#include <sound/rcar_snd.h>
++#include <sound/simple_card.h>
++
++#include "clock.h"
++#include "common.h"
++#include "dma-register.h"
++#include "irqs.h"
++#include "r8a7794.h"
++#include "rcar-gen2.h"
++
++/* DU */
++static struct rcar_du_encoder_data silk_du_encoders[] = {
++ {
++ .type = RCAR_DU_ENCODER_HDMI,
++ .output = RCAR_DU_OUTPUT_DPAD0,
++ },
++ {
++ .type = RCAR_DU_ENCODER_NONE,
++ .output = RCAR_DU_OUTPUT_LVDS0,
++ .connector.lvds.panel = {
++ .width_mm = 210,
++ .height_mm = 158,
++ .mode = {
++ .clock = 65000,
++ .hdisplay = 1024,
++ .hsync_start = 1048,
++ .hsync_end = 1184,
++ .htotal = 1344,
++ .vdisplay = 768,
++ .vsync_start = 771,
++ .vsync_end = 777,
++ .vtotal = 806,
++ .flags = 0,
++ },
++ },
++ },
++ {
++ .type = RCAR_DU_ENCODER_VGA,
++ .output = RCAR_DU_OUTPUT_DPAD1,
++ },
++};
++
++static struct rcar_du_crtc_data silk_du_crtcs[] = {
++ {
++ .exclk = 148500000,
++ .init_conn_type = DRM_MODE_CONNECTOR_HDMIA,
++ },
++ {
++ .exclk = 74250000,
++ .init_conn_type = DRM_MODE_CONNECTOR_VGA,
++ },
++};
++
++static int silk_lvds_backlight_on(void)
++{
++ return 0;
++}
++
++static int silk_lvds_backlight_off(void)
++{
++ return 0;
++}
++
++static struct rcar_du_platform_data silk_du_pdata = {
++ .encoders = silk_du_encoders,
++ .num_encoders = ARRAY_SIZE(silk_du_encoders),
++ .crtcs = silk_du_crtcs,
++ .num_crtcs = ARRAY_SIZE(silk_du_crtcs),
++#ifdef CONFIG_DRM_FBDEV_CRTC
++ .fbdev_crtc = 0,
++#endif
++ .backlight_on = silk_lvds_backlight_on,
++ .backlight_off = silk_lvds_backlight_off,
++ .i2c_ch = 1,
++};
++
++static const struct resource du_resources[] __initconst = {
++ DEFINE_RES_MEM(0xfeb00000, 0x40000),
++ DEFINE_RES_IRQ(gic_spi(256)),
++ DEFINE_RES_IRQ(gic_spi(268)),
++};
++
++static void __init silk_add_du_device(void)
++{
++ struct platform_device_info info = {
++ .name = "rcar-du-r8a7794",
++ .id = -1,
++ .res = du_resources,
++ .num_res = ARRAY_SIZE(du_resources),
++ .data = &silk_du_pdata,
++ .size_data = sizeof(silk_du_pdata),
++ .dma_mask = DMA_BIT_MASK(32),
++ };
++
++ platform_device_register_full(&info);
++}
++
++/* Sound */
++static struct rsnd_ssi_platform_info rsnd_ssi[] = {
++ RSND_SSI(AUDIOPP_DMAC_SLAVE_CMD0_TO_SSI0, gic_spi(370), 0),
++ RSND_SSI(AUDIOPP_DMAC_SLAVE_SSI1_TO_SCU2, gic_spi(371), RSND_SSI_CLK_PIN_SHARE),
++};
++
++static struct rsnd_src_platform_info rsnd_src[3] = {
++ RSND_SRC_UNUSED,
++ RSND_SRC(0, AUDIO_DMAC_SLAVE_SCU1_TX, gic_spi(353)),
++ RSND_SRC(0, AUDIO_DMAC_SLAVE_CMD1_TO_MEM, gic_spi(354)),
++};
++
++static struct rsnd_dvc_platform_info rsnd_dvc[2] = {
++};
++
++static struct rsnd_dai_platform_info rsnd_dai = {
++ .playback = { .ssi = &rsnd_ssi[0], .src = &rsnd_src[1], .dvc = &rsnd_dvc[0], },
++ .capture = { .ssi = &rsnd_ssi[1], .src = &rsnd_src[2], .dvc = &rsnd_dvc[1], },
++};
++
++static struct rcar_snd_info rsnd_info = {
++ .flags = RSND_GEN2,
++ .ssi_info = rsnd_ssi,
++ .ssi_info_nr = ARRAY_SIZE(rsnd_ssi),
++ .src_info = rsnd_src,
++ .src_info_nr = ARRAY_SIZE(rsnd_src),
++ .dvc_info = rsnd_dvc,
++ .dvc_info_nr = ARRAY_SIZE(rsnd_dvc),
++ .dai_info = &rsnd_dai,
++ .dai_info_nr = 1,
++};
++
++static struct asoc_simple_card_info rsnd_card_info = {
++ .name = "SSI01-AK4643",
++ .codec = "ak4642-codec.1-0012",
++ .platform = "rcar_sound",
++ .daifmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS,
++ .cpu_dai = {
++ .name = "rcar_sound",
++ },
++ .codec_dai = {
++ .name = "ak4642-hifi",
++ .sysclk = 12288000,
++ },
++};
++
++static void __init silk_add_rsnd_device(void)
++{
++ struct resource rsnd_resources[] = {
++ [RSND_GEN2_SCU] = DEFINE_RES_MEM(0xec500000, 0x1000),
++ [RSND_GEN2_ADG] = DEFINE_RES_MEM(0xec5a0000, 0x100),
++ [RSND_GEN2_SSIU] = DEFINE_RES_MEM(0xec540000, 0x1000),
++ [RSND_GEN2_SSI] = DEFINE_RES_MEM(0xec541000, 0x1280),
++ };
++
++ struct platform_device_info cardinfo = {
++ .parent = &platform_bus,
++ .name = "asoc-simple-card",
++ .id = -1,
++ .data = &rsnd_card_info,
++ .size_data = sizeof(struct asoc_simple_card_info),
++ .dma_mask = DMA_BIT_MASK(32),
++ };
++
++ platform_device_register_resndata(
++ &platform_bus, "rcar_sound", -1,
++ rsnd_resources, ARRAY_SIZE(rsnd_resources),
++ &rsnd_info, sizeof(rsnd_info));
++
++ platform_device_register_full(&cardinfo);
++}
++
++
++/*
++ * This is a really crude hack to provide clkdev support to platform
++ * devices until they get moved to DT.
++ */
++static const struct clk_name clk_names[] __initconst = {
++ { "cmt0", NULL, "sh_cmt.0" },
++ { "scifa0", NULL, "sh-sci.0" },
++ { "scifa1", NULL, "sh-sci.1" },
++ { "scifb0", NULL, "sh-sci.2" },
++ { "scifb1", NULL, "sh-sci.3" },
++ { "scifb2", NULL, "sh-sci.4" },
++ { "scifa2", NULL, "sh-sci.5" },
++ { "scif0", NULL, "sh-sci.6" },
++ { "scif1", NULL, "sh-sci.7" },
++ { "hscif0", NULL, "sh-sci.8" },
++ { "hscif1", NULL, "sh-sci.9" },
++ { "scif2", NULL, "sh-sci.10" },
++ { "scif3", NULL, "sh-sci.11" },
++ { "scif4", NULL, "sh-sci.12" },
++ { "scif5", NULL, "sh-sci.13" },
++ { "scifa3", NULL, "sh-sci.14" },
++ { "scifa4", NULL, "sh-sci.15" },
++ { "scifa5", NULL, "sh-sci.16" },
++ { "hscif2", NULL, "sh-sci.17" },
++ { "du0", "du.0", "rcar-du-r8a7794" },
++ { "du1", "du.1", "rcar-du-r8a7794" },
++ { "hsusb", NULL, "usb_phy_rcar_gen2" },
++ { "ssi0", "ssi.0", "rcar_sound" },
++ { "ssi1", "ssi.1", "rcar_sound" },
++ { "src1", "src.1", "rcar_sound" },
++ { "src2", "src.2", "rcar_sound" },
++ { "dvc0", "dvc.0", "rcar_sound" },
++ { "dvc1", "dvc.1", "rcar_sound" },
++ { "vin0", NULL, "r8a7794-vin.0" },
++ { "vsps", NULL, NULL },
++#if IS_ENABLED(CONFIG_VIDEO_RENESAS_VSP1)
++ { "vsp1-du0", NULL, "vsp1.2" },
++#else
++ { "vsp1-du0", NULL, NULL },
++#endif
++ { "vpc0", NULL, "vpc1" },
++ { "2ddmac", NULL, "tddmac" },
++ { "fdp0", NULL, "fdp0" },
++ { "pvrsrvkm", NULL, "pvrsrvkm" },
++#if IS_ENABLED(CONFIG_USB_RENESAS_USBHS_UDC)
++ { "hsusb", NULL, "renesas_usbhs" },
++#else
++ { "ehci", NULL, "pci-rcar-gen2.0" },
++#endif
++};
++
++/*
++ * This is a really crude hack to work around core platform clock issues
++ */
++static const struct clk_name clk_enables[] __initconst = {
++ { "ether", NULL, "ee700000.ethernet" },
++ { "i2c1", NULL, "e6518000.i2c" },
++ { "mmcif0", NULL, "ee200000.mmc" },
++ { "sdhi0", NULL, "ee100000.sd" },
++ { "sdhi1", NULL, "ee140000.sd" },
++ { "ehci", NULL, "pci-rcar-gen2.1" },
++ { "vcp0", NULL, "vcp1" },
++ { "dmal", NULL, "sh-dma-engine.0" },
++ { "sys-dmac1", NULL, "sh-dma-engine.2" },
++ { "sys-dmac0", NULL, "sh-dma-engine.3" },
++#if IS_ENABLED(CONFIG_USB_RENESAS_USBHS_UDC)
++ { "usbdmac0", NULL, "sh-dma-engine.4" },
++#endif
++ { "ipmmu_gp", NULL, "ipmmu_gp" },
++};
++
++#define DMAE_CHANNEL(a, b) \
++{ \
++ .offset = (a) - 0x20, \
++ .dmars = (a) - 0x20 + 0x40, \
++ .chclr_bit = (b), \
++ .chclr_offset = 0x80 - 0x20, \
++}
++
++/* Sys-DMAC */
++#define SYS_DMAC_SLAVE(_id, _bit, _addr, toffset, roffset, t, r) \
++{ \
++ .slave_id = SYS_DMAC_SLAVE_## _id ##_TX, \
++ .addr = _addr + toffset, \
++ .chcr = CHCR_TX(XMIT_SZ_## _bit ##BIT), \
++ .mid_rid = t, \
++}, { \
++ .slave_id = SYS_DMAC_SLAVE_## _id ##_RX, \
++ .addr = _addr + roffset, \
++ .chcr = CHCR_RX(XMIT_SZ_## _bit ##BIT), \
++ .mid_rid = r, \
++}
++
++#define SYS_DMAC_SLAVE_TX(_id, _bit, _addr, toffset, roffset, t, r) \
++{ \
++ .slave_id = SYS_DMAC_SLAVE_## _id ##_TX, \
++ .addr = _addr + toffset, \
++ .chcr = CHCR_TX(XMIT_SZ_## _bit ##BIT), \
++ .mid_rid = t, \
++}
++
++static const struct sh_dmae_slave_config r8a7794_sys_dmac_slaves[] = {
++ SYS_DMAC_SLAVE(MMCIF0, 32, 0xee200000, 0x34, 0x34, 0xd1, 0xd2),
++ SYS_DMAC_SLAVE(SDHI0, 256, 0xee100000, 0x60, 0x2060, 0xcd, 0xce),
++ SYS_DMAC_SLAVE(SDHI1, 256, 0xee140000, 0x30, 0x2030, 0xc1, 0xc2),
++ SYS_DMAC_SLAVE(SCIF0, 8, 0xe6e60000, 0xc, 0x14, 0x29, 0x2a),
++ SYS_DMAC_SLAVE(SCIF1, 8, 0xe6e68000, 0xc, 0x14, 0x2d, 0x2e),
++ SYS_DMAC_SLAVE(SCIF2, 8, 0xe6e58000, 0xc, 0x14, 0x2b, 0x2c),
++ SYS_DMAC_SLAVE(SCIF3, 8, 0xe6ea8000, 0xc, 0x14, 0x2f, 0x30),
++ SYS_DMAC_SLAVE(SCIF4, 8, 0xe6ee0000, 0xc, 0x14, 0xfb, 0xfc),
++ SYS_DMAC_SLAVE(SCIF5, 8, 0xe6ee8000, 0xc, 0x14, 0xfd, 0xfe),
++ SYS_DMAC_SLAVE(SCIFA0, 8, 0xe6c40000, 0x20, 0x24, 0x21, 0x22),
++ SYS_DMAC_SLAVE(SCIFA1, 8, 0xe6c50000, 0x20, 0x24, 0x25, 0x26),
++ SYS_DMAC_SLAVE(SCIFA2, 8, 0xe6c60000, 0x20, 0x24, 0x27, 0x28),
++ SYS_DMAC_SLAVE(SCIFA3, 8, 0xe6c70000, 0x20, 0x24, 0x1b, 0x1c),
++ SYS_DMAC_SLAVE(SCIFA4, 8, 0xe6c78000, 0x20, 0x24, 0x1f, 0x20),
++ SYS_DMAC_SLAVE(SCIFA5, 8, 0xe6c80000, 0x20, 0x24, 0x23, 0x24),
++ SYS_DMAC_SLAVE(SCIFB0, 8, 0xe6c20000, 0x40, 0x60, 0x3d, 0x3e),
++ SYS_DMAC_SLAVE(SCIFB1, 8, 0xe6c30000, 0x40, 0x60, 0x19, 0x1a),
++ SYS_DMAC_SLAVE(SCIFB2, 8, 0xe6ce0000, 0x40, 0x60, 0x1d, 0x1e),
++ SYS_DMAC_SLAVE(HSCIF0, 8, 0xe62c0000, 0xc, 0x14, 0x39, 0x3a),
++ SYS_DMAC_SLAVE(HSCIF1, 8, 0xe62c8000, 0xc, 0x14, 0x4d, 0x4e),
++ SYS_DMAC_SLAVE(HSCIF2, 8, 0xe62d0000, 0xc, 0x14, 0x3b, 0x3c),
++ SYS_DMAC_SLAVE(MSIOF0, 32, 0xe7e20000, 0x50, 0x60, 0x51, 0x52),
++ SYS_DMAC_SLAVE(MSIOF1, 32, 0xe7e10000, 0x50, 0x60, 0x55, 0x56),
++ SYS_DMAC_SLAVE(MSIOF2, 32, 0xe7e00000, 0x50, 0x60, 0x41, 0x42),
++};
++
++static const struct sh_dmae_channel r8a7794_sys_dmac_channels[] = {
++ DMAE_CHANNEL(0x8000, 0),
++ DMAE_CHANNEL(0x8080, 1),
++ DMAE_CHANNEL(0x8100, 2),
++ DMAE_CHANNEL(0x8180, 3),
++ DMAE_CHANNEL(0x8200, 4),
++ DMAE_CHANNEL(0x8280, 5),
++ DMAE_CHANNEL(0x8300, 6),
++ DMAE_CHANNEL(0x8380, 7),
++ DMAE_CHANNEL(0x8400, 8),
++ DMAE_CHANNEL(0x8480, 9),
++ DMAE_CHANNEL(0x8500, 10),
++ DMAE_CHANNEL(0x8580, 11),
++ DMAE_CHANNEL(0x8600, 12),
++ DMAE_CHANNEL(0x8680, 13),
++ DMAE_CHANNEL(0x8700, 14),
++};
++
++static struct sh_dmae_pdata r8a7794_sys_dmac_platform_data = {
++ .slave = r8a7794_sys_dmac_slaves,
++ .slave_num = ARRAY_SIZE(r8a7794_sys_dmac_slaves),
++ .channel = r8a7794_sys_dmac_channels,
++ .channel_num = ARRAY_SIZE(r8a7794_sys_dmac_channels),
++ .ts_low_shift = TS_LOW_SHIFT,
++ .ts_low_mask = TS_LOW_BIT << TS_LOW_SHIFT,
++ .ts_high_shift = TS_HI_SHIFT,
++ .ts_high_mask = TS_HI_BIT << TS_HI_SHIFT,
++ .ts_shift = dma_ts_shift,
++ .ts_shift_num = ARRAY_SIZE(dma_ts_shift),
++ .dmaor_init = DMAOR_DME,
++ .chclr_present = 1,
++ .chclr_bitwise = 1,
++ .fourty_bits_addr = 1,
++};
++
++static struct resource r8a7794_sys_dmac_resources[] = {
++ /* Channel registers and DMAOR for low */
++ DEFINE_RES_MEM(0xe6700020, 0x8763 - 0x20),
++ DEFINE_RES_IRQ(gic_spi(197)),
++ DEFINE_RES_NAMED(gic_spi(200), 15, NULL, IORESOURCE_IRQ),
++
++ /* Channel registers and DMAOR for high */
++ DEFINE_RES_MEM(0xe6720020, 0x8763 - 0x20),
++ DEFINE_RES_IRQ(gic_spi(220)),
++ DEFINE_RES_NAMED(gic_spi(216), 4, NULL, IORESOURCE_IRQ),
++ DEFINE_RES_NAMED(gic_spi(308), 11, NULL, IORESOURCE_IRQ),
++};
++
++#define r8a7794_register_sys_dmac(id) \
++ platform_device_register_resndata( \
++ &platform_bus, "sh-dma-engine", 2 + id, \
++ &r8a7794_sys_dmac_resources[id * 3], id * 1 + 3, \
++ &r8a7794_sys_dmac_platform_data, \
++ sizeof(r8a7794_sys_dmac_platform_data))
++
++static void __init silk_add_dmac_prototype(void)
++{
++ r8a7794_register_sys_dmac(0);
++ r8a7794_register_sys_dmac(1);
++}
++
++static struct sh_mmcif_plat_data mmcif0_pdata = {
++ .caps = MMC_CAP_4_BIT_DATA |
++ MMC_CAP_8_BIT_DATA |
++ MMC_CAP_NONREMOVABLE,
++ .ccs_unsupported = true,
++ .clk_ctrl2_present = true,
++ .slave_id_tx = SYS_DMAC_SLAVE_MMCIF0_TX,
++ .slave_id_rx = SYS_DMAC_SLAVE_MMCIF0_RX,
++};
++
++static struct sh_mobile_sdhi_info sdhi0_info __initdata = {
++ .dma_slave_tx = SYS_DMAC_SLAVE_SDHI0_TX,
++ .dma_slave_rx = SYS_DMAC_SLAVE_SDHI0_RX,
++ .dma_rx_offset = 0x2000,
++
++ .tmio_caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
++ MMC_CAP_POWER_OFF_CARD,
++ .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT,
++};
++
++static struct sh_mobile_sdhi_info sdhi1_info __initdata = {
++ .dma_slave_tx = SYS_DMAC_SLAVE_SDHI1_TX,
++ .dma_slave_rx = SYS_DMAC_SLAVE_SDHI1_RX,
++ .dma_rx_offset = 0x2000,
++
++ .tmio_caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
++ MMC_CAP_POWER_OFF_CARD,
++ .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT,
++};
++
++/* SCIF */
++#define SCIF_PD(scif_type, index, scif_index) \
++static struct plat_sci_port scif##index##_platform_data = { \
++ .type = PORT_##scif_type, \
++ .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, \
++ .scscr = SCSCR_RE | SCSCR_TE, \
++ .dma_slave_tx = SYS_DMAC_SLAVE_##scif_type##scif_index##_TX, \
++ .dma_slave_rx = SYS_DMAC_SLAVE_##scif_type##scif_index##_RX, \
++}
++
++#define PDATA_SCIF(index, baseaddr, irq, i) SCIF_PD(SCIF, index, i)
++#define PDATA_SCIFA(index, baseaddr, irq, i) SCIF_PD(SCIFA, index, i)
++#define PDATA_SCIFB(index, baseaddr, irq, i) SCIF_PD(SCIFB, index, i)
++#define PDATA_HSCIF(index, baseaddr, irq, i) SCIF_PD(HSCIF, index, i)
++
++PDATA_SCIFA(0, 0xe6c40000, gic_spi(144), 0); /* SCIFA0 */
++PDATA_SCIFA(1, 0xe6c50000, gic_spi(145), 1); /* SCIFA1 */
++PDATA_SCIFB(2, 0xe6c20000, gic_spi(148), 0); /* SCIFB0 */
++PDATA_SCIFB(3, 0xe6c30000, gic_spi(149), 1); /* SCIFB1 */
++PDATA_SCIFB(4, 0xe6ce0000, gic_spi(150), 2); /* SCIFB2 */
++PDATA_SCIFA(5, 0xe6c60000, gic_spi(151), 2); /* SCIFA2 */
++PDATA_SCIF(6, 0xe6e60000, gic_spi(152), 0); /* SCIF0 */
++PDATA_SCIF(7, 0xe6e68000, gic_spi(153), 1); /* SCIF1 */
++PDATA_HSCIF(8, 0xe62c0000, gic_spi(154), 0); /* HSCIF0 */
++PDATA_HSCIF(9, 0xe62c8000, gic_spi(155), 1); /* HSCIF1 */
++PDATA_SCIF(10, 0xe6e58000, gic_spi(22), 2); /* SCIF2 */
++PDATA_SCIF(11, 0xe6ea8000, gic_spi(23), 3); /* SCIF3 */
++PDATA_SCIF(12, 0xe6ee0000, gic_spi(24), 4); /* SCIF4 */
++PDATA_SCIF(13, 0xe6ee8000, gic_spi(25), 5); /* SCIF5 */
++PDATA_SCIFA(14, 0xe6c70000, gic_spi(29), 3); /* SCIFA3 */
++PDATA_SCIFA(15, 0xe6c78000, gic_spi(30), 4); /* SCIFA4 */
++PDATA_SCIFA(16, 0xe6c80000, gic_spi(31), 5); /* SCIFA5 */
++PDATA_HSCIF(17, 0xe6cd0000, gic_spi(21), 2); /* HSCIF2 */
++
++#define SCIF_AD(scif_type, index, baseaddr) \
++ OF_DEV_AUXDATA("renesas," scif_type "-r8a7794", baseaddr, \
++ "sh-sci." # index, &scif##index##_platform_data)
++
++#define AUXDATA_SCIF(index, baseaddr, irq) SCIF_AD("scif", index, baseaddr)
++#define AUXDATA_SCIFA(index, baseaddr, irq) SCIF_AD("scifa", index, baseaddr)
++#define AUXDATA_SCIFB(index, baseaddr, irq) SCIF_AD("scifb", index, baseaddr)
++#define AUXDATA_HSCIF(index, baseaddr, irq) SCIF_AD("hscif", index, baseaddr)
++
++#if IS_ENABLED(CONFIG_USB_RENESAS_USBHS_UDC)
++/* USB-DMAC */
++static const struct sh_dmae_channel usb_dmac_channels[] = {
++ {
++ .offset = 0,
++ }, {
++ .offset = 0x20,
++ },
++};
++
++static const struct sh_dmae_slave_config usb_dmac_slaves[] = {
++ {
++ .slave_id = USB_DMAC_SLAVE_USBHS_TX,
++ .chcr = USBTS_INDEX2VAL(USBTS_XMIT_SZ_32BYTE),
++ }, {
++ .slave_id = USB_DMAC_SLAVE_USBHS_RX,
++ .chcr = USBTS_INDEX2VAL(USBTS_XMIT_SZ_32BYTE),
++ },
++};
++
++static struct sh_dmae_pdata usb_dmac_platform_data = {
++ .slave = usb_dmac_slaves,
++ .slave_num = ARRAY_SIZE(usb_dmac_slaves),
++ .channel = usb_dmac_channels,
++ .channel_num = ARRAY_SIZE(usb_dmac_channels),
++ .ts_low_shift = USBTS_LOW_SHIFT,
++ .ts_low_mask = USBTS_LOW_BIT << USBTS_LOW_SHIFT,
++ .ts_high_shift = USBTS_HI_SHIFT,
++ .ts_high_mask = USBTS_HI_BIT << USBTS_HI_SHIFT,
++ .ts_shift = dma_usbts_shift,
++ .ts_shift_num = ARRAY_SIZE(dma_usbts_shift),
++ .dmaor_init = DMAOR_DME,
++ .chcr_offset = 0x14,
++ .chcr_ie_bit = 1 << 5,
++ .dmaor_is_32bit = 1,
++ .needs_tend_set = 1,
++ .no_dmars = 1,
++ .slave_only = 1,
++};
++
++static struct resource usb_dmac_resources[] = {
++ DEFINE_RES_MEM(0xe65a0020, 0x44), /* Channel registers and DMAOR */
++ DEFINE_RES_MEM(0xe65a0000, 0x14), /* VCR/SWR/DMICR */
++ DEFINE_RES_IRQ(gic_spi(109)),
++};
++
++static void __init silk_add_usb_dmac_prototype(void)
++{
++ platform_device_register_resndata(&platform_bus, "sh-dma-engine",
++ 4,
++ usb_dmac_resources,
++ ARRAY_SIZE(usb_dmac_resources),
++ &usb_dmac_platform_data,
++ sizeof(usb_dmac_platform_data));
++}
++
++/* USBHS */
++static const struct resource usbhs_resources[] __initconst = {
++ DEFINE_RES_MEM(0xe6590000, 0x100),
++ DEFINE_RES_IRQ(gic_spi(107)),
++};
++
++struct usbhs_private {
++ struct renesas_usbhs_platform_info info;
++ struct usb_phy *phy;
++ int pwen_gpio;
++};
++
++#define usbhs_get_priv(pdev) \
++ container_of(renesas_usbhs_get_info(pdev), struct usbhs_private, info)
++
++static int usbhs_power_ctrl(struct platform_device *pdev,
++ void __iomem *base, int enable)
++{
++ struct usbhs_private *priv = usbhs_get_priv(pdev);
++
++ if (!priv->phy)
++ return -ENODEV;
++
++ if (enable) {
++ int retval = usb_phy_init(priv->phy);
++
++ if (!retval)
++ retval = usb_phy_set_suspend(priv->phy, 0);
++ return retval;
++ }
++
++ usb_phy_set_suspend(priv->phy, 1);
++ usb_phy_shutdown(priv->phy);
++ return 0;
++}
++
++static int usbhs_hardware_init(struct platform_device *pdev)
++{
++ struct usbhs_private *priv = usbhs_get_priv(pdev);
++ struct usb_phy *phy;
++ int ret;
++ struct device_node *np;
++
++ np = of_find_node_by_path("/gpio@e6055000");
++ if (np) {
++ priv->pwen_gpio = of_get_gpio(np, 24);
++ of_node_put(np);
++ } else {
++ pr_warn("Error: Unable to get PWEN GPIO line\n");
++ ret = -ENOTSUPP;
++ goto error2;
++ }
++
++ phy = usb_get_phy_dev(&pdev->dev, 0);
++ if (IS_ERR(phy)) {
++ ret = PTR_ERR(phy);
++ goto error;
++ }
++
++ priv->phy = phy;
++ return 0;
++ error:
++ gpio_free(priv->pwen_gpio);
++ error2:
++ return ret;
++}
++
++static int usbhs_hardware_exit(struct platform_device *pdev)
++{
++ struct usbhs_private *priv = usbhs_get_priv(pdev);
++
++ if (!priv->phy)
++ return 0;
++
++ usb_put_phy(priv->phy);
++ priv->phy = NULL;
++ gpio_free(priv->pwen_gpio);
++ return 0;
++}
++
++static int usbhs_get_id(struct platform_device *pdev)
++{
++ return USBHS_GADGET;
++}
++
++static int usbhs_get_vbus(struct platform_device *pdev)
++{
++ return 0;
++}
++
++static u32 lager_usbhs_pipe_type[] = {
++ USB_ENDPOINT_XFER_CONTROL,
++ USB_ENDPOINT_XFER_ISOC,
++ USB_ENDPOINT_XFER_ISOC,
++ USB_ENDPOINT_XFER_BULK,
++ USB_ENDPOINT_XFER_BULK,
++ USB_ENDPOINT_XFER_BULK,
++ USB_ENDPOINT_XFER_INT,
++ USB_ENDPOINT_XFER_INT,
++ USB_ENDPOINT_XFER_INT,
++ USB_ENDPOINT_XFER_BULK,
++ USB_ENDPOINT_XFER_BULK,
++ USB_ENDPOINT_XFER_BULK,
++ USB_ENDPOINT_XFER_BULK,
++ USB_ENDPOINT_XFER_BULK,
++ USB_ENDPOINT_XFER_BULK,
++ USB_ENDPOINT_XFER_BULK,
++};
++
++static struct usbhs_private usbhs_priv __initdata = {
++ .info = {
++ .platform_callback = {
++ .power_ctrl = usbhs_power_ctrl,
++ .hardware_init = usbhs_hardware_init,
++ .hardware_exit = usbhs_hardware_exit,
++ .get_id = usbhs_get_id,
++ .get_vbus = usbhs_get_vbus,
++ },
++ .driver_param = {
++ .buswait_bwait = 4,
++ .pipe_type = lager_usbhs_pipe_type,
++ .pipe_size = ARRAY_SIZE(lager_usbhs_pipe_type),
++ .d0_rx_id = USB_DMAC_SLAVE_USBHS_RX,
++ .d1_tx_id = USB_DMAC_SLAVE_USBHS_TX,
++ .usb_dmac_xfer_size = 32,
++ },
++ }
++};
++
++static void __init silk_register_usbhs(void)
++{
++ usb_bind_phy("renesas_usbhs", 0, "usb_phy_rcar_gen2");
++ platform_device_register_resndata(&platform_bus,
++ "renesas_usbhs", -1,
++ usbhs_resources,
++ ARRAY_SIZE(usbhs_resources),
++ &usbhs_priv.info,
++ sizeof(usbhs_priv.info));
++}
++
++#else
++/* Internal PCI0 */
++static const struct resource pci0_resources[] __initconst = {
++ DEFINE_RES_MEM(0xee090000, 0x10000), /* CFG */
++ DEFINE_RES_MEM(0xee080000, 0x10000), /* MEM */
++ DEFINE_RES_IRQ(gic_spi(108)),
++};
++
++static const struct platform_device_info pci0_info __initconst = {
++ .parent = &platform_bus,
++ .name = "pci-rcar-gen2",
++ .id = 0,
++ .res = pci0_resources,
++ .num_res = ARRAY_SIZE(pci0_resources),
++ .dma_mask = DMA_BIT_MASK(32),
++};
++
++static void __init silk_add_usb0_device(void)
++{
++ usb_bind_phy("pci-rcar-gen2.0", 0, "usb_phy_rcar_gen2");
++ platform_device_register_full(&pci0_info);
++}
++#endif
++/* USBHS PHY */
++static const struct rcar_gen2_phy_platform_data usbhs_phy_pdata __initconst = {
++#if IS_ENABLED(CONFIG_USB_RENESAS_USBHS_UDC)
++ .chan0_pci = 0, /* Channel 0 is USBHS */
++#else
++ .chan0_pci = 1, /* Channel 0 is PCI USB */
++#endif
++ .chan2_pci = 1, /* Channel 2 is PCI USB */
++ .gpio_vbus = 857,
++ .wakeup = true,
++};
++
++static const struct resource usbhs_phy_resources[] __initconst = {
++ DEFINE_RES_MEM(0xe6590100, 0x100),
++};
++
++/* Internal PCI1 */
++static const struct resource pci1_resources[] __initconst = {
++ DEFINE_RES_MEM(0xee0d0000, 0x10000), /* CFG */
++ DEFINE_RES_MEM(0xee0c0000, 0x10000), /* MEM */
++ DEFINE_RES_IRQ(gic_spi(113)),
++};
++
++static const struct platform_device_info pci1_info __initconst = {
++ .parent = &platform_bus,
++ .name = "pci-rcar-gen2",
++ .id = 1,
++ .res = pci1_resources,
++ .num_res = ARRAY_SIZE(pci1_resources),
++ .dma_mask = DMA_BIT_MASK(32),
++};
++
++static void __init silk_add_usb1_device(void)
++{
++ usb_bind_phy("pci-rcar-gen2.1", 0, "usb_phy_rcar_gen2");
++ platform_device_register_full(&pci1_info);
++}
++
++/* POWER IC */
++static struct i2c_board_info poweric_i2c[] = {
++ { I2C_BOARD_INFO("da9063", 0x58), },
++};
++
++static void silk_restart(char mode, const char *cmd)
++{
++ struct i2c_adapter *adap;
++ struct i2c_client *client;
++ u8 val;
++ int busnum = 8;
++
++ adap = i2c_get_adapter(busnum);
++ if (!adap) {
++ pr_err("failed to get adapter i2c%d\n", busnum);
++ return;
++ }
++
++ client = i2c_new_device(adap, &poweric_i2c[0]);
++ if (!client)
++ pr_err("failed to register %s to i2c%d\n",
++ poweric_i2c[0].type, busnum);
++
++ i2c_put_adapter(adap);
++
++ val = i2c_smbus_read_byte_data(client, 0x13);
++
++ if (val < 0)
++ pr_err("couldn't access da9063\n");
++
++ val |= 0x02;
++
++ i2c_smbus_write_byte_data(client, 0x13, val);
++}
++
++/* VIN */
++static const struct resource vin_resources[] __initconst = {
++ /* VIN0 */
++ DEFINE_RES_MEM(0xe6ef0000, 0x1000),
++ DEFINE_RES_IRQ(gic_spi(188)),
++};
++
++static void __init silk_add_vin_device(unsigned idx,
++ struct rcar_vin_platform_data *pdata)
++{
++ struct platform_device_info vin_info = {
++ .parent = &platform_bus,
++ .name = "r8a7794-vin",
++ .id = idx,
++ .res = &vin_resources[idx * 2],
++ .num_res = 2,
++ .dma_mask = DMA_BIT_MASK(32),
++ .data = pdata,
++ .size_data = sizeof(*pdata),
++ };
++
++ BUG_ON(idx > 1);
++
++ platform_device_register_full(&vin_info);
++}
++
++#define SILK_CAMERA(idx, name, addr, pdata, flag) \
++static struct i2c_board_info i2c_cam##idx##_device = { \
++ I2C_BOARD_INFO(name, addr), \
++}; \
++ \
++static struct rcar_vin_platform_data vin##idx##_pdata = { \
++ .flags = flag, \
++}; \
++ \
++static struct soc_camera_link cam##idx##_link = { \
++ .bus_id = idx, \
++ .board_info = &i2c_cam##idx##_device, \
++ .i2c_adapter_id = 1, \
++ .module_name = name, \
++ .priv = pdata, \
++}
++
++SILK_CAMERA(0, "adv7180", 0x20, NULL, RCAR_VIN_BT656);
++
++static void __init silk_add_camera0_device(void)
++{
++ platform_device_register_data(&platform_bus, "soc-camera-pdrv", 0,
++ &cam0_link, sizeof(cam0_link));
++ silk_add_vin_device(0, &vin0_pdata);
++}
++
++/* VSP1 */
++#if IS_ENABLED(CONFIG_VIDEO_RENESAS_VSP1)
++static const struct vsp1_platform_data silk_vsps_pdata __initconst = {
++ .features = 0,
++ .rpf_count = 5,
++ .uds_count = 3,
++ .wpf_count = 4,
++};
++
++static const struct vsp1_platform_data silk_vspd0_pdata __initconst = {
++ .features = VSP1_HAS_LIF,
++ .rpf_count = 4,
++ .uds_count = 1,
++ .wpf_count = 4,
++};
++
++static const struct vsp1_platform_data * const silk_vsp1_pdata[] __initconst
++ = {
++ &silk_vsps_pdata,
++ &silk_vspd0_pdata,
++};
++
++static const struct resource vsp1_1_resources[] __initconst = {
++ DEFINE_RES_MEM(0xfe928000, 0x8000),
++ DEFINE_RES_IRQ(gic_spi(267)),
++};
++
++static const struct resource vsp1_2_resources[] __initconst = {
++ DEFINE_RES_MEM(0xfe930000, 0x8000),
++ DEFINE_RES_IRQ(gic_spi(246)),
++};
++
++static const struct resource * const vsp1_resources[] __initconst = {
++ vsp1_1_resources,
++ vsp1_2_resources,
++};
++
++static void __init silk_add_vsp1_devices(void)
++{
++ struct platform_device_info info = {
++ .name = "vsp1",
++ .size_data = sizeof(*silk_vsp1_pdata[0]),
++ .num_res = 2,
++ .dma_mask = DMA_BIT_MASK(32),
++ };
++ unsigned int i;
++
++ for (i = 1; i < ARRAY_SIZE(vsp1_resources); ++i) {
++ info.id = i + 1;
++ info.data = silk_vsp1_pdata[i];
++ info.res = vsp1_resources[i];
++
++ platform_device_register_full(&info);
++ }
++}
++#endif
++
++/* MSIOF */
++static struct sh_msiof_spi_info msiof0_info = {
++ .rx_fifo_override = 256,
++ .num_chipselect = 1,
++ .dma_tx_id = SYS_DMAC_SLAVE_MSIOF0_TX,
++ .dma_rx_id = SYS_DMAC_SLAVE_MSIOF0_RX,
++};
++
++static struct sh_msiof_spi_info msiof1_info = {
++ .rx_fifo_override = 256,
++ .num_chipselect = 1,
++ .dma_tx_id = SYS_DMAC_SLAVE_MSIOF1_TX,
++ .dma_rx_id = SYS_DMAC_SLAVE_MSIOF1_RX,
++};
++
++/* MSIOF spidev */
++static const struct spi_board_info spi_bus[] __initconst = {
++ {
++ .modalias = "spidev",
++ .max_speed_hz = 6000000,
++ .mode = SPI_MODE_3,
++ .bus_num = 1,
++ .chip_select = 0,
++ },
++ {
++ .modalias = "spidev",
++ .max_speed_hz = 6000000,
++ .mode = SPI_MODE_3,
++ .bus_num = 2,
++ .chip_select = 0,
++ },
++};
++
++#define silk_add_msiof_device spi_register_board_info
++
++static struct of_dev_auxdata silk_auxdata_lookup[] __initdata = {
++ OF_DEV_AUXDATA("renesas,mmcif-r8a7794", 0xee200000, "sh_mmcif",
++ &mmcif0_pdata),
++ OF_DEV_AUXDATA("renesas,sdhi-r8a7794", 0xee100000, "sdhi0",
++ &sdhi0_info),
++ OF_DEV_AUXDATA("renesas,sdhi-r8a7794", 0xee140000, "sdhi1",
++ &sdhi1_info),
++ AUXDATA_SCIFA(0, 0xe6c40000, gic_spi(144)), /* SCIFA0 */
++ AUXDATA_SCIFA(1, 0xe6c50000, gic_spi(145)), /* SCIFA1 */
++ AUXDATA_SCIFB(2, 0xe6c20000, gic_spi(148)), /* SCIFB0 */
++ AUXDATA_SCIFB(3, 0xe6c30000, gic_spi(149)), /* SCIFB1 */
++ AUXDATA_SCIFB(4, 0xe6ce0000, gic_spi(150)), /* SCIFB2 */
++ AUXDATA_SCIFA(5, 0xe6c60000, gic_spi(151)), /* SCIFA2 */
++ AUXDATA_SCIF(6, 0xe6e60000, gic_spi(152)), /* SCIF0 */
++ AUXDATA_SCIF(7, 0xe6e68000, gic_spi(153)), /* SCIF1 */
++ AUXDATA_HSCIF(8, 0xe62c0000, gic_spi(154)), /* HSCIF0 */
++ AUXDATA_HSCIF(9, 0xe62c8000, gic_spi(155)), /* HSCIF1 */
++ AUXDATA_SCIF(10, 0xe6e58000, gic_spi(22)), /* SCIF2 */
++ AUXDATA_SCIF(11, 0xe6ea8000, gic_spi(23)), /* SCIF3 */
++ AUXDATA_SCIF(12, 0xe6ee0000, gic_spi(24)), /* SCIF4 */
++ AUXDATA_SCIF(13, 0xe6ee8000, gic_spi(25)), /* SCIF5 */
++ AUXDATA_SCIFA(14, 0xe6c70000, gic_spi(29)), /* SCIFA3 */
++ AUXDATA_SCIFA(15, 0xe6c78000, gic_spi(30)), /* SCIFA4 */
++ AUXDATA_SCIFA(16, 0xe6c80000, gic_spi(31)), /* SCIFA5 */
++ AUXDATA_HSCIF(17, 0xe6cd0000, gic_spi(21)), /* HSCIF2 */
++ OF_DEV_AUXDATA("renesas,msiof-r8a7794", 0xe6e20000,
++ "spi_r8a7794_msiof.0", &msiof0_info),
++ OF_DEV_AUXDATA("renesas,msiof-r8a7794", 0xe6e10000,
++ "spi_r8a7794_msiof.1", &msiof1_info),
++ {},
++};
++
++static void __init silk_add_standard_devices(void)
++{
++ shmobile_clk_workaround(clk_names, ARRAY_SIZE(clk_names), false);
++ shmobile_clk_workaround(clk_enables, ARRAY_SIZE(clk_enables), true);
++ r8a7794_add_dt_devices();
++ silk_add_dmac_prototype();
++#if IS_ENABLED(CONFIG_USB_RENESAS_USBHS_UDC)
++ silk_add_usb_dmac_prototype();
++#endif
++ of_platform_populate(NULL, of_default_bus_match_table,
++ silk_auxdata_lookup, NULL);
++ silk_add_du_device();
++
++ platform_device_register_resndata(&platform_bus, "usb_phy_rcar_gen2",
++ -1, usbhs_phy_resources,
++ ARRAY_SIZE(usbhs_phy_resources),
++ &usbhs_phy_pdata,
++ sizeof(usbhs_phy_pdata));
++#if IS_ENABLED(CONFIG_USB_RENESAS_USBHS_UDC)
++ silk_register_usbhs();
++#else
++ silk_add_usb0_device();
++#endif
++ silk_add_usb1_device();
++ silk_add_rsnd_device();
++ silk_add_camera0_device();
++#if IS_ENABLED(CONFIG_VIDEO_RENESAS_VSP1)
++ silk_add_vsp1_devices();
++#endif
++ silk_add_msiof_device(spi_bus, ARRAY_SIZE(spi_bus));
++}
++
++static const char * const silk_boards_compat_dt[] __initconst = {
++ "renesas,silk",
++ "renesas,silk-reference",
++ NULL,
++};
++
++DT_MACHINE_START(SILK_DT, "silk")
++ .smp = smp_ops(r8a7794_smp_ops),
++ .init_early = r8a7794_init_early,
++ .init_time = r8a7794_timer_init,
++ .init_machine = silk_add_standard_devices,
++ .init_late = shmobile_init_late,
++ .reserve = rcar_gen2_reserve,
++ .restart = silk_restart,
++ .dt_compat = silk_boards_compat_dt,
++MACHINE_END
+--
+1.9.1
+
diff --git a/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0002-kernel-silk-fix-ethernet-phy-irq.patch b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0002-kernel-silk-fix-ethernet-phy-irq.patch
new file mode 100644
index 0000000..5e72b82
--- /dev/null
+++ b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0002-kernel-silk-fix-ethernet-phy-irq.patch
@@ -0,0 +1,25 @@
+From f186213b9d9d3942dc403060542796e07d254d52 Mon Sep 17 00:00:00 2001
+From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+Date: Mon, 2 Feb 2015 13:34:25 +0300
+Subject: [PATCH] Silk: Ethernet phy interrupt is connected to IRQ8
+
+---
+ arch/arm/boot/dts/r8a7794-silk.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm/boot/dts/r8a7794-silk.dts b/arch/arm/boot/dts/r8a7794-silk.dts
+index cb69f6b..aa20df8 100644
+--- a/arch/arm/boot/dts/r8a7794-silk.dts
++++ b/arch/arm/boot/dts/r8a7794-silk.dts
+@@ -280,7 +280,7 @@
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ interrupt-parent = <&irqc0>;
+- interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
++ interrupts = <8 IRQ_TYPE_LEVEL_LOW>;
+ micrel,led-mode = <1>;
+ };
+ };
+--
+1.9.1
+
diff --git a/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0003-kernel-silk-fix-sd-detect.patch b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0003-kernel-silk-fix-sd-detect.patch
new file mode 100644
index 0000000..0bb4f75
--- /dev/null
+++ b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0003-kernel-silk-fix-sd-detect.patch
@@ -0,0 +1,25 @@
+From 1a56b82aad68465e69827f1cbe18f53ab886f7df Mon Sep 17 00:00:00 2001
+From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+Date: Mon, 2 Feb 2015 13:35:06 +0300
+Subject: [PATCH] Silk: Fix SDHI1 write protect pin detection
+
+---
+ arch/arm/boot/dts/r8a7794-silk.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm/boot/dts/r8a7794-silk.dts b/arch/arm/boot/dts/r8a7794-silk.dts
+index aa20df8..9438dfa 100644
+--- a/arch/arm/boot/dts/r8a7794-silk.dts
++++ b/arch/arm/boot/dts/r8a7794-silk.dts
+@@ -345,7 +345,7 @@
+ vmmc-supply = <&vcc_sdhi1>;
+ vqmmc-supply = <&vccq_sdhi1>;
+ cd-gpios = <&gpio6 14 GPIO_ACTIVE_LOW>;
+- wp-gpios = <&gpio6 15 GPIO_ACTIVE_HIGH>;
++ wp-gpios = <&gpio6 15 GPIO_ACTIVE_LOW>;
+ status = "okay";
+ };
+
+--
+1.9.1
+
diff --git a/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0004-kernel-Revert-i2c-rcar-Support-ACK-by-HW-auto-restart-after-NACK.patch b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0004-kernel-Revert-i2c-rcar-Support-ACK-by-HW-auto-restart-after-NACK.patch
new file mode 100644
index 0000000..5f23129
--- /dev/null
+++ b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0004-kernel-Revert-i2c-rcar-Support-ACK-by-HW-auto-restart-after-NACK.patch
@@ -0,0 +1,66 @@
+From 4f249ca259008006d972ea76fd2b37a2558ea2f1 Mon Sep 17 00:00:00 2001
+From: Petr Nechaev <petr.nechaev@cogentembedded.com>
+Date: Mon, 2 Feb 2015 13:37:55 +0300
+Subject: [PATCH] Revert "i2c: rcar: Support ACK by HW auto restart after
+ NACK"
+
+This reverts commit 4df6b2af6c0f795d810eb1e2e9411ad1cbbe4245.
+---
+ drivers/i2c/busses/i2c-rcar.c | 20 ++++++++------------
+ 1 file changed, 8 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c
+index 18034cd..0e863f3 100644
+--- a/drivers/i2c/busses/i2c-rcar.c
++++ b/drivers/i2c/busses/i2c-rcar.c
+@@ -522,6 +522,7 @@ static irqreturn_t rcar_i2c_irq(int irq, void *ptr)
+
+ /* go to stop phase */
+ rcar_i2c_bus_phase(priv, RCAR_BUS_PHASE_STOP);
++ rcar_i2c_irq_mask(priv, RCAR_IRQ_OPEN_FOR_STOP);
+ rcar_i2c_flags_set(priv, ID_NACK);
+ rcar_i2c_status_bit_clear(priv, MNR);
+ goto out;
+@@ -532,14 +533,8 @@ static irqreturn_t rcar_i2c_irq(int irq, void *ptr)
+ */
+ if (msr & MST) {
+ dev_dbg(dev, "Stop\n");
+- if (rcar_i2c_flags_has(priv, ID_NACK)) {
+- /* don't set ID_DONE for expecting ACK
+- after auto-restart by HW */
+- rcar_i2c_status_bit_clear(priv, MST);
+- } else {
+- rcar_i2c_flags_set(priv, ID_DONE);
+- rcar_i2c_status_clear(priv);
+- }
++ rcar_i2c_flags_set(priv, ID_DONE);
++ rcar_i2c_status_clear(priv);
+ goto out;
+ }
+
+@@ -616,10 +611,6 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
+ rcar_i2c_flags_has(priv, ID_DONE),
+ 5 * HZ);
+ if (!timeout) {
+- if (rcar_i2c_flags_has(priv, ID_NACK)) {
+- ret = -ENXIO;
+- break;
+- }
+ ret = -ETIMEDOUT;
+ break;
+ }
+@@ -627,6 +618,11 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
+ /*
+ * error handling
+ */
++ if (rcar_i2c_flags_has(priv, ID_NACK)) {
++ ret = -ENXIO;
++ break;
++ }
++
+ if (rcar_i2c_flags_has(priv, ID_ARBLOST)) {
+ ret = -EAGAIN;
+ break;
+--
+1.9.1
+
diff --git a/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0006-Rcar-DU-add-RGB-connector.patch b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0006-Rcar-DU-add-RGB-connector.patch
new file mode 100644
index 0000000..d1c8da8
--- /dev/null
+++ b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0006-Rcar-DU-add-RGB-connector.patch
@@ -0,0 +1,276 @@
+From 488e93a1d8371c6ce8cfd24d7299973c476a1aef Mon Sep 17 00:00:00 2001
+From: Andrey Gusakov <andrey.gusakov@cogentembedded.com>
+Date: Sun, 28 Dec 2014 19:58:58 +0300
+Subject: [PATCH] Rcar-DU: add RGB connector
+
+
+Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com>
+---
+ drivers/gpu/drm/rcar-du/Makefile | 1 +
+ drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 9 ++
+ drivers/gpu/drm/rcar-du/rcar_du_rgbcon.c | 142 +++++++++++++++++++++++++++++
+ drivers/gpu/drm/rcar-du/rcar_du_rgbcon.h | 24 +++++
+ include/linux/platform_data/rcar-du.h | 7 ++
+ 5 files changed, 183 insertions(+)
+ create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_rgbcon.c
+ create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_rgbcon.h
+
+diff --git a/drivers/gpu/drm/rcar-du/Makefile b/drivers/gpu/drm/rcar-du/Makefile
+index a6909f0..744da0f 100644
+--- a/drivers/gpu/drm/rcar-du/Makefile
++++ b/drivers/gpu/drm/rcar-du/Makefile
+@@ -5,6 +5,7 @@ rcar-du-drm-y := rcar_du_crtc.o \
+ rcar_du_hdmicon.o \
+ rcar_du_kms.o \
+ rcar_du_lvdscon.o \
++ rcar_du_rgbcon.o \
+ rcar_du_plane.o \
+ rcar_du_vgacon.o
+
+diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
+index 0edec97..de0ccc1 100644
+--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
++++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
+@@ -24,6 +24,7 @@
+ #include "rcar_du_encoder.h"
+ #include "rcar_du_kms.h"
+ #include "rcar_du_lvdscon.h"
++#include "rcar_du_rgbcon.h"
+ #include "rcar_du_lvdsenc.h"
+ #include "rcar_du_vgacon.h"
+ #include "rcar_du_hdmicon.h"
+@@ -235,6 +236,9 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
+ case RCAR_DU_ENCODER_LVDS:
+ encoder_type = DRM_MODE_ENCODER_LVDS;
+ break;
++ case RCAR_DU_ENCODER_RGB:
++ encoder_type = DRM_MODE_ENCODER_NONE;
++ break;
+ case RCAR_DU_ENCODER_HDMI:
+ encoder_type = DRM_MODE_ENCODER_TMDS;
+ break;
+@@ -277,6 +281,11 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
+ case DRM_MODE_ENCODER_DAC:
+ return rcar_du_vga_connector_init(rcdu, renc);
+
++ case DRM_MODE_ENCODER_NONE:
++ if (type == RCAR_DU_ENCODER_RGB)
++ return rcar_du_rgb_connector_init(rcdu, renc,
++ &data->connector.rgb.panel);
++ /* fallthrough */
+ default:
+ return -EINVAL;
+ }
+diff --git a/drivers/gpu/drm/rcar-du/rcar_du_rgbcon.c b/drivers/gpu/drm/rcar-du/rcar_du_rgbcon.c
+new file mode 100644
+index 0000000..9ee845d
+--- /dev/null
++++ b/drivers/gpu/drm/rcar-du/rcar_du_rgbcon.c
+@@ -0,0 +1,142 @@
++/*
++ * rcar_du_rgbcon.c -- R-Car Display Unit RGB Connector
++ * base on rcar_du_lvdscon.c
++ *
++ * Copyright (C) 2013-2014 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; either version 2 of the License, or
++ * (at your option) any later version.
++ */
++
++#include <drm/drmP.h>
++#include <drm/drm_crtc.h>
++#include <drm/drm_crtc_helper.h>
++#include <drm/drm_encoder_slave.h>
++
++#include "rcar_du_drv.h"
++#include "rcar_du_encoder.h"
++#include "rcar_du_kms.h"
++#include "rcar_du_rgbcon.h"
++
++struct rcar_du_rgb_connector {
++ struct rcar_du_connector connector;
++
++ const struct rcar_du_panel_data *panel;
++};
++
++#define to_rcar_rgb_connector(c) \
++ container_of(c, struct rcar_du_rgb_connector, connector.connector)
++
++static int rcar_du_rgb_connector_get_modes(struct drm_connector *connector)
++{
++ struct rcar_du_rgb_connector *rgbcon =
++ to_rcar_rgb_connector(connector);
++ struct drm_display_mode *mode;
++
++ mode = drm_mode_create(connector->dev);
++ if (mode == NULL)
++ return 0;
++
++ mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
++ mode->clock = rgbcon->panel->mode.clock;
++ mode->hdisplay = rgbcon->panel->mode.hdisplay;
++ mode->hsync_start = rgbcon->panel->mode.hsync_start;
++ mode->hsync_end = rgbcon->panel->mode.hsync_end;
++ mode->htotal = rgbcon->panel->mode.htotal;
++ mode->vdisplay = rgbcon->panel->mode.vdisplay;
++ mode->vsync_start = rgbcon->panel->mode.vsync_start;
++ mode->vsync_end = rgbcon->panel->mode.vsync_end;
++ mode->vtotal = rgbcon->panel->mode.vtotal;
++ mode->flags = rgbcon->panel->mode.flags;
++
++ drm_mode_set_name(mode);
++ drm_mode_probed_add(connector, mode);
++
++ return 1;
++}
++
++static int rcar_du_rgb_connector_mode_valid(struct drm_connector *connector,
++ struct drm_display_mode *mode)
++{
++ return MODE_OK;
++}
++
++static const struct drm_connector_helper_funcs connector_helper_funcs = {
++ .get_modes = rcar_du_rgb_connector_get_modes,
++ .mode_valid = rcar_du_rgb_connector_mode_valid,
++ .best_encoder = rcar_du_connector_best_encoder,
++};
++
++static void rcar_du_rgb_connector_destroy(struct drm_connector *connector)
++{
++ drm_sysfs_connector_remove(connector);
++ drm_connector_cleanup(connector);
++}
++
++static enum drm_connector_status
++rcar_du_rgb_connector_detect(struct drm_connector *connector, bool force)
++{
++ return connector_status_connected;
++}
++
++static const struct drm_connector_funcs connector_funcs = {
++ .dpms = drm_helper_connector_dpms,
++ .detect = rcar_du_rgb_connector_detect,
++ .fill_modes = drm_helper_probe_single_connector_modes,
++ .destroy = rcar_du_rgb_connector_destroy,
++};
++
++int rcar_du_rgb_connector_init(struct rcar_du_device *rcdu,
++ struct rcar_du_encoder *renc,
++ const struct rcar_du_panel_data *panel)
++{
++ struct rcar_du_rgb_connector *rgbcon;
++ struct drm_connector *connector;
++ int ret;
++
++ if (rcdu->pdata->backlight_on) {
++ ret = rcdu->pdata->backlight_on();
++ if (ret < 0)
++ return ret;
++ }
++
++ rgbcon = devm_kzalloc(rcdu->dev, sizeof(*rgbcon), GFP_KERNEL);
++ if (rgbcon == NULL)
++ return -ENOMEM;
++
++ rgbcon->panel = panel;
++
++ connector = &rgbcon->connector.connector;
++ connector->display_info.width_mm = panel->width_mm;
++ connector->display_info.height_mm = panel->height_mm;
++
++ ret = drm_connector_init(rcdu->ddev, connector, &connector_funcs,
++ DRM_MODE_CONNECTOR_Component);
++ if (ret < 0)
++ return ret;
++
++ drm_connector_helper_add(connector, &connector_helper_funcs);
++ ret = drm_sysfs_connector_add(connector);
++ if (ret < 0)
++ return ret;
++
++#if 0
++ drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
++ drm_object_property_set_value(&connector->base,
++ rcdu->ddev->mode_config.dpms_property, DRM_MODE_DPMS_OFF);
++#else
++ drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
++ drm_object_property_set_value(&connector->base,
++ rcdu->ddev->mode_config.dpms_property, DRM_MODE_DPMS_ON);
++#endif
++ ret = drm_mode_connector_attach_encoder(connector, renc->encoder);
++ if (ret < 0)
++ return ret;
++
++ connector->encoder = renc->encoder;
++ rgbcon->connector.encoder = renc;
++
++ return 0;
++}
+diff --git a/drivers/gpu/drm/rcar-du/rcar_du_rgbcon.h b/drivers/gpu/drm/rcar-du/rcar_du_rgbcon.h
+new file mode 100644
+index 0000000..d4d51be
+--- /dev/null
++++ b/drivers/gpu/drm/rcar-du/rcar_du_rgbcon.h
+@@ -0,0 +1,24 @@
++/*
++ * rcar_du_rgbcon.h -- R-Car Display Unit RGB Connector
++ * based on rcar_du_lvdscon.h
++ *
++ * Copyright (C) 2013-2014 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; either version 2 of the License, or
++ * (at your option) any later version.
++ */
++
++#ifndef __RCAR_DU_RGBCON_H__
++#define __RCAR_DU_RGBCON_H__
++
++struct rcar_du_device;
++struct rcar_du_encoder;
++struct rcar_du_panel_data;
++
++int rcar_du_rgb_connector_init(struct rcar_du_device *rcdu,
++ struct rcar_du_encoder *renc,
++ const struct rcar_du_panel_data *panel);
++
++#endif /* __RCAR_DU_RGBCON_H__ */
+diff --git a/include/linux/platform_data/rcar-du.h b/include/linux/platform_data/rcar-du.h
+index 62464de..93c29af 100644
+--- a/include/linux/platform_data/rcar-du.h
++++ b/include/linux/platform_data/rcar-du.h
+@@ -31,6 +31,7 @@ enum rcar_du_encoder_type {
+ RCAR_DU_ENCODER_NONE,
+ RCAR_DU_ENCODER_VGA,
+ RCAR_DU_ENCODER_LVDS,
++ RCAR_DU_ENCODER_RGB,
+ RCAR_DU_ENCODER_HDMI,
+ };
+
+@@ -44,6 +45,11 @@ struct rcar_du_connector_lvds_data {
+ struct rcar_du_panel_data panel;
+ };
+
++struct rcar_du_connector_rgb_data {
++ struct rcar_du_panel_data panel;
++};
++
++
+ struct rcar_du_connector_vga_data {
+ /* TODO: Add DDC information for EDID retrieval */
+ };
+@@ -68,6 +74,7 @@ struct rcar_du_encoder_data {
+
+ union {
+ struct rcar_du_connector_lvds_data lvds;
++ struct rcar_du_connector_rgb_data rgb;
+ struct rcar_du_connector_vga_data vga;
+ struct rcar_du_connector_hdmi_data hdmi;
+ } connector;
+--
+1.7.10.4
+
diff --git a/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0007-SILK-add-i2c0.patch b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0007-SILK-add-i2c0.patch
new file mode 100644
index 0000000..1f02501
--- /dev/null
+++ b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0007-SILK-add-i2c0.patch
@@ -0,0 +1,45 @@
+From 207ad91c8ebbfbd2b862323200071a8c2a816fef Mon Sep 17 00:00:00 2001
+From: Andrey Gusakov <andrey.gusakov@cogentembedded.com>
+Date: Sun, 28 Dec 2014 20:01:53 +0300
+Subject: [PATCH] SILK: add i2c0
+
+
+Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com>
+---
+ arch/arm/boot/dts/r8a7794-silk.dts | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/arch/arm/boot/dts/r8a7794-silk.dts b/arch/arm/boot/dts/r8a7794-silk.dts
+index aa20df8..bd1359d 100644
+--- a/arch/arm/boot/dts/r8a7794-silk.dts
++++ b/arch/arm/boot/dts/r8a7794-silk.dts
+@@ -181,6 +181,14 @@
+ clock-frequency = <20000000>;
+ };
+
++&i2c0 {
++ pinctrl-0 = <&i2c0_pins>;
++ pinctrl-names = "default";
++
++ status = "okay";
++ clock-frequency = <400000>;
++};
++
+ &i2c1 {
+ pinctrl-0 = <&i2c1_pins>;
+ pinctrl-names = "default";
+@@ -211,6 +219,11 @@
+ renesas,function = "du";
+ };
+
++ i2c0_pins: i2c0 {
++ renesas,groups = "i2c0_d";
++ renesas,function = "i2c0";
++ };
++
+ i2c1_pins: i2c1 {
+ renesas,groups = "i2c1";
+ renesas,function = "i2c1";
+--
+1.7.10.4
+
diff --git a/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0008-Porter-board-support.patch b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0008-Porter-board-support.patch
new file mode 100644
index 0000000..13fc68b
--- /dev/null
+++ b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0008-Porter-board-support.patch
@@ -0,0 +1,1426 @@
+From c8c4c6ed85b5f34b8f8178b8ce53c246a67cfa00 Mon Sep 17 00:00:00 2001
+From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+Date: Mon, 2 Feb 2015 14:12:24 +0300
+Subject: [PATCH] Add Porter board support
+
+Porter is an entry level development board based on R-Car M2 SoC
+(R8A7791)
+
+Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+---
+ arch/arm/boot/dts/Makefile | 1 +
+ arch/arm/boot/dts/r8a7791-porter.dts | 385 ++++++++++
+ arch/arm/configs/shmobile_defconfig | 1 +
+ arch/arm/mach-shmobile/Kconfig | 6 +
+ arch/arm/mach-shmobile/Makefile | 1 +
+ arch/arm/mach-shmobile/board-porter-reference.c | 953 ++++++++++++++++++++++++
+ 6 files changed, 1347 insertions(+)
+ create mode 100644 arch/arm/boot/dts/r8a7791-porter.dts
+ create mode 100644 arch/arm/mach-shmobile/board-porter-reference.c
+
+diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
+index f2b99db..a1de751 100644
+--- a/arch/arm/boot/dts/Makefile
++++ b/arch/arm/boot/dts/Makefile
+@@ -176,6 +176,7 @@ dtb-$(CONFIG_ARCH_SHMOBILE_MULTI) += emev2-kzm9d.dtb \
+ r7s72100-genmai.dtb \
+ r8a7791-henninger.dtb \
+ r8a7791-koelsch.dtb \
++ r8a7791-porter.dtb \
+ r8a7790-lager.dtb \
+ r8a7794-alt.dtb \
+ r8a7794-silk.dtb \
+diff --git a/arch/arm/boot/dts/r8a7791-porter.dts b/arch/arm/boot/dts/r8a7791-porter.dts
+new file mode 100644
+index 0000000..6a0ccde
+--- /dev/null
++++ b/arch/arm/boot/dts/r8a7791-porter.dts
+@@ -0,0 +1,385 @@
++/*
++ * Device Tree Source for the Porter board
++ *
++ * Copyright (C) 2015 Renesas Electronics Corporation
++ * Copyright (C) 2015 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.
++ */
++
++/*
++ * SSI-AK4643
++ *
++ * these commands are required when playback.
++ *
++ * # amixer set "LINEOUT Mixer DACL" on
++ * # amixer set "Digital" 200
++ * # amixer set "DVC Out" 50
++ */
++
++/dts-v1/;
++#include "r8a7791.dtsi"
++#include <dt-bindings/gpio/gpio.h>
++
++/ {
++ model = "Porter";
++ compatible = "renesas,porter", "renesas,r8a7791";
++
++ aliases {
++ serial6 = &scif0;
++ };
++
++ chosen {
++ bootargs = "console=ttySC6,38400 ignore_loglevel rw root=/dev/nfs ip=dhcp vmalloc=384M";
++ };
++
++ memory@40000000 {
++ device_type = "memory";
++ reg = <0 0x40000000 0 0x40000000>;
++ };
++
++ memory@200000000 {
++ device_type = "memory";
++ reg = <2 0x00000000 0 0x40000000>;
++ };
++
++ leds {
++ compatible = "gpio-leds";
++ led2 {
++ gpios = <&gpio2 19 GPIO_ACTIVE_HIGH>;
++ };
++ led3 {
++ gpios = <&gpio2 20 GPIO_ACTIVE_HIGH>;
++ };
++ led4 {
++ gpios = <&gpio2 21 GPIO_ACTIVE_HIGH>;
++ };
++ };
++
++ vcc_sdhi0: regulator@0 {
++ compatible = "regulator-fixed";
++
++ regulator-name = "SDHI0 Vcc";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ regulator-always-on;
++ };
++
++ vccq_sdhi0: regulator@1 {
++ compatible = "regulator-gpio";
++
++ regulator-name = "SDHI0 VccQ";
++ regulator-min-microvolt = <1800000>;
++ regulator-max-microvolt = <3300000>;
++
++ gpios = <&gpio2 12 GPIO_ACTIVE_HIGH>;
++ gpios-states = <1>;
++ states = <3300000 1
++ 1800000 0>;
++ };
++
++ vcc_sdhi2: regulator@2 {
++ compatible = "regulator-fixed";
++
++ regulator-name = "SDHI2 Vcc";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ regulator-always-on;
++ };
++
++ vccq_sdhi2: regulator@3 {
++ compatible = "regulator-gpio";
++
++ regulator-name = "SDHI2 VccQ";
++ regulator-min-microvolt = <1800000>;
++ regulator-max-microvolt = <3300000>;
++
++ gpios = <&gpio2 26 GPIO_ACTIVE_HIGH>;
++ gpios-states = <1>;
++ states = <3300000 1
++ 1800000 0>;
++ };
++
++ hdmi_transmitter: adv7511 {
++ compatible = "adi,adv7511";
++ gpios = <&gpio3 29 GPIO_ACTIVE_LOW>;
++
++ adi,input-style = <0x02>;
++ adi,input-id = <0x00>;
++ adi,input-color-depth = <0x03>;
++ adi,sync-pulse = <0x03>;
++ adi,bit-justification = <0x01>;
++ adi,up-conversion = <0x00>;
++ adi,timing-generation-sequence = <0x00>;
++ adi,vsync-polarity = <0x02>;
++ adi,hsync-polarity = <0x02>;
++ adi,clock-delay = <0x03>;
++ };
++
++ usbhs_udc {
++ gpios = <&gpio5 31 GPIO_ACTIVE_HIGH>;
++ };
++};
++
++&extal_clk {
++ clock-frequency = <20000000>;
++};
++
++&pfc {
++ pinctrl-0 = <&du_pins &usb0_pins &usb1_pins &sound_pins &sound_clk_pins &vin0_pins>;
++ pinctrl-names = "default";
++
++ du_pins: du {
++ renesas,groups = "du_rgb666", "du_sync", "du_clk_out_0";
++ renesas,function = "du";
++ };
++
++ scif0_pins: serial6 {
++ renesas,groups = "scif0_data_d";
++ renesas,function = "scif0";
++ };
++
++ i2c1_pins: i2c1 {
++ renesas,groups = "i2c1_e";
++ renesas,function = "i2c1";
++ };
++
++ i2c2_pins: i2c2 {
++ renesas,groups = "i2c2";
++ renesas,function = "i2c2";
++ };
++
++ i2c4_pins: i2c4 {
++ renesas,groups = "i2c4_c";
++ renesas,function = "i2c4";
++ };
++
++ ether_pins: ether {
++ renesas,groups = "eth_link", "eth_mdio", "eth_rmii";
++ renesas,function = "eth";
++ };
++
++ phy1_pins: phy1 {
++ renesas,groups = "intc_irq0";
++ renesas,function = "intc";
++ };
++
++ sdhi0_pins: sd0 {
++ renesas,groups = "sdhi0_data4", "sdhi0_ctrl";
++ renesas,function = "sdhi0";
++ };
++
++ sdhi2_pins: sd2 {
++ renesas,groups = "sdhi2_data4", "sdhi2_ctrl";
++ renesas,function = "sdhi2";
++ };
++
++ qspi_pins: spi0 {
++ renesas,groups = "qspi_ctrl", "qspi_data4";
++ renesas,function = "qspi";
++ };
++
++ msiof0_pins: spi1 {
++ renesas,groups = "msiof0_clk", "msiof0_sync", "msiof0_rx",
++ "msiof0_tx";
++ renesas,function = "msiof0";
++ };
++
++ sound_pins: sound {
++ renesas,groups = "ssi0129_ctrl", "ssi0_data", "ssi1_data";
++ renesas,function = "ssi";
++ };
++
++ sound_clk_pins: sound_clk {
++ renesas,groups = "audio_clk_a";
++ renesas,function = "audio_clk";
++ };
++
++ usb0_pins: usb0 {
++ renesas,groups = "usb0";
++ renesas,function = "usb0";
++ };
++
++ usb1_pins: usb1 {
++ renesas,groups = "usb1";
++ renesas,function = "usb1";
++ };
++
++ vin0_pins: vin0 {
++ renesas,groups = "vin0_data8", "vin0_clk";
++ renesas,function = "vin0";
++ };
++};
++
++&ether {
++ pinctrl-0 = <&ether_pins &phy1_pins>;
++ pinctrl-names = "default";
++
++ phy-handle = <&phy1>;
++ renesas,ether-link-active-low;
++ status = "ok";
++
++ phy1: ethernet-phy@1 {
++ reg = <1>;
++ interrupt-parent = <&irqc0>;
++ interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
++ micrel,led-mode = <1>;
++ };
++};
++
++&sata0 {
++ status = "okay";
++};
++
++&scif0 {
++ pinctrl-0 = <&scif0_pins>;
++ pinctrl-names = "default";
++
++ status = "okay";
++};
++
++&sdhi0 {
++ pinctrl-0 = <&sdhi0_pins>;
++ pinctrl-names = "default";
++
++ vmmc-supply = <&vcc_sdhi0>;
++ vqmmc-supply = <&vccq_sdhi0>;
++ cd-gpios = <&gpio6 6 GPIO_ACTIVE_LOW>;
++ wp-gpios = <&gpio6 7 GPIO_ACTIVE_HIGH>;
++ status = "okay";
++};
++
++&sdhi2 {
++ pinctrl-0 = <&sdhi2_pins>;
++ pinctrl-names = "default";
++
++ vmmc-supply = <&vcc_sdhi2>;
++ vqmmc-supply = <&vccq_sdhi2>;
++ cd-gpios = <&gpio6 22 GPIO_ACTIVE_LOW>;
++ toshiba,mmc-wrprotect-disable;
++ status = "okay";
++};
++
++&qspi {
++ pinctrl-0 = <&qspi_pins>;
++ pinctrl-names = "default";
++
++ status = "okay";
++
++ flash: flash@0 {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ compatible = "spansion,s25fl512s";
++ reg = <0>;
++ spi-max-frequency = <30000000>;
++ spi-tx-bus-width = <4>;
++ spi-rx-bus-width = <4>;
++ m25p,fast-read;
++ spi-cpol;
++ spi-cpha;
++
++ partition@0 {
++ label = "loader";
++ reg = <0x00000000 0x00040000>;
++ read-only;
++ };
++ partition@40000 {
++ label = "user";
++ reg = <0x00040000 0x00400000>;
++ read-only;
++ };
++ partition@440000 {
++ label = "flash";
++ reg = <0x00440000 0x03bc0000>;
++ };
++ };
++};
++
++&msiof0 {
++ pinctrl-0 = <&msiof0_pins>;
++ pinctrl-names = "default";
++
++ status = "okay";
++};
++
++&i2c1 {
++ pinctrl-0 = <&i2c1_pins>;
++ pinctrl-names = "default";
++
++ status = "okay";
++ clock-frequency = <400000>;
++};
++
++&i2c2 {
++ pinctrl-0 = <&i2c2_pins>;
++ pinctrl-names = "default";
++
++ status = "okay";
++ clock-frequency = <400000>;
++
++ eeprom@50 {
++ compatible = "renesas,24c02";
++ reg = <0x50>;
++ pagesize = <16>;
++ };
++
++ snd_codec: ak4643 {
++ #sound-dai-cells = <0>;
++ compatible = "asahi-kasei,ak4643";
++ reg = <0x12>;
++ };
++};
++
++&i2c4 {
++ pinctrl-0 = <&i2c4_pins>;
++ pinctrl-names = "default";
++
++ status = "okay";
++ clock-frequency = <400000>;
++};
++
++&i2c5 {
++ status = "okay";
++ clock-frequency = <400000>;
++};
++
++&i2c6 {
++ status = "okay";
++ clock-frequency = <100000>;
++
++ vdd_dvfs: regulator@68 {
++ compatible = "diasemi,da9210";
++ reg = <0x68>;
++
++ regulator-min-microvolt = <1000000>;
++ regulator-max-microvolt = <1000000>;
++ regulator-boot-on;
++ regulator-always-on;
++ };
++};
++
++&pci0 {
++ status = "okay";
++ pinctrl-0 = <&usb0_pins>;
++ pinctrl-names = "default";
++};
++
++&pci1 {
++ status = "okay";
++ pinctrl-0 = <&usb1_pins>;
++ pinctrl-names = "default";
++};
++
++&pcie_bus_clk {
++ status = "okay";
++};
++
++&pciec {
++ status = "okay";
++};
++
++&cpu0 {
++ cpu0-supply = <&vdd_dvfs>;
++};
+diff --git a/arch/arm/configs/shmobile_defconfig b/arch/arm/configs/shmobile_defconfig
+index 11237db..bb4e0e6 100644
+--- a/arch/arm/configs/shmobile_defconfig
++++ b/arch/arm/configs/shmobile_defconfig
+@@ -26,6 +26,7 @@ CONFIG_MACH_GOSE=y
+ CONFIG_MACH_ALT=y
+ CONFIG_MACH_SILK=y
+ CONFIG_MACH_MARZEN=y
++CONFIG_MACH_PORTER=y
+ CONFIG_SHMOBILE_TIMER_HZ=100
+ CONFIG_ARM_LPAE=y
+ # CONFIG_SWP_EMULATE is not set
+diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
+index e2e00a9..7c15245 100644
+--- a/arch/arm/mach-shmobile/Kconfig
++++ b/arch/arm/mach-shmobile/Kconfig
+@@ -93,6 +93,12 @@ config MACH_MARZEN
+ depends on ARCH_R8A7779
+ select REGULATOR_FIXED_VOLTAGE if REGULATOR
+
++config MACH_PORTER
++ bool "Porter board"
++ depends on ARCH_R8A7791
++ select MICREL_PHY if SH_ETH
++ select SND_SOC_AK4642 if SND_SIMPLE_CARD
++
+ comment "Renesas ARM SoCs System Configuration"
+ endif
+
+diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
+index 139f31c..43b4025 100644
+--- a/arch/arm/mach-shmobile/Makefile
++++ b/arch/arm/mach-shmobile/Makefile
+@@ -78,6 +78,7 @@ obj-$(CONFIG_MACH_GOSE) += board-gose-reference.o
+ obj-$(CONFIG_MACH_ALT) += board-alt-reference.o
+ obj-$(CONFIG_MACH_SILK) += board-silk-reference.o
+ obj-$(CONFIG_MACH_MARZEN) += board-marzen-reference.o
++obj-$(CONFIG_MACH_PORTER) += board-porter-reference.o
+ else
+ obj-$(CONFIG_MACH_APE6EVM) += board-ape6evm.o
+ obj-$(CONFIG_MACH_APE6EVM_REFERENCE) += board-ape6evm-reference.o
+diff --git a/arch/arm/mach-shmobile/board-porter-reference.c b/arch/arm/mach-shmobile/board-porter-reference.c
+new file mode 100644
+index 0000000..d481ecd
+--- /dev/null
++++ b/arch/arm/mach-shmobile/board-porter-reference.c
+@@ -0,0 +1,953 @@
++/*
++ * Porter board support - Reference DT implementation
++ *
++ * Copyright (C) 2013-2015 Renesas Electronics Corporation
++ * Copyright (C) 2013 Renesas Solutions Corp.
++ * Copyright (C) 2013 Magnus Damm
++ * Copyright (C) 2015 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.
++ *
++ * 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
++ */
++
++#include <linux/dma-mapping.h>
++#include <linux/kernel.h>
++#include <linux/mfd/tmio.h>
++#include <linux/mmc/host.h>
++#include <linux/mmc/sh_mobile_sdhi.h>
++#include <linux/of_gpio.h>
++#include <linux/of_platform.h>
++#include <linux/platform_data/camera-rcar.h>
++#include <linux/platform_data/rcar-du.h>
++#include <linux/platform_data/usb-rcar-gen2-phy.h>
++#if IS_ENABLED(CONFIG_VIDEO_RENESAS_VSP1)
++#include <linux/platform_data/vsp1.h>
++#endif
++#include <linux/serial_sci.h>
++#include <linux/sh_dma.h>
++#include <linux/spi/flash.h>
++#include <linux/spi/sh_msiof.h>
++#include <linux/spi/spi.h>
++#include <linux/usb/phy.h>
++#if IS_ENABLED(CONFIG_USB_RENESAS_USBHS_UDC)
++#include <linux/usb/renesas_usbhs.h>
++#endif
++#include <media/soc_camera.h>
++#include <asm/mach/arch.h>
++#include <sound/rcar_snd.h>
++#include <sound/simple_card.h>
++
++#include "clock.h"
++#include "common.h"
++#include "dma-register.h"
++#include "irqs.h"
++#include "r8a7791.h"
++#include "rcar-gen2.h"
++
++/* DU */
++static struct rcar_du_encoder_data porter_du_encoders[] = {
++ {
++ .type = RCAR_DU_ENCODER_HDMI,
++ .output = RCAR_DU_OUTPUT_DPAD0,
++ },
++ {
++ .type = RCAR_DU_ENCODER_NONE,
++ .output = RCAR_DU_OUTPUT_LVDS0,
++ .connector.lvds.panel = {
++ .width_mm = 229,
++ .height_mm = 149,
++ .mode = {
++ .clock = 69000,
++ .hdisplay = 1280,
++ .hsync_start = 1280 + 48,
++ .hsync_end = 1280 + 48 + 32,
++ .htotal = 1280 + 48 + 32 + 80,
++ .vdisplay = 800,
++ .vsync_start = 800 + 2,
++ .vsync_end = 800 + 2 + 6,
++ .vtotal = 800 + 2 + 6 + 15,
++ .flags = 0,
++ },
++ },
++ },
++};
++
++static struct rcar_du_crtc_data porter_du_crtcs[] = {
++ {
++ .exclk = 0, /* NoP */
++ .init_conn_type = DRM_MODE_CONNECTOR_LVDS,
++ },
++ {
++ .exclk = 0, /* NoP */
++ .init_conn_type = DRM_MODE_CONNECTOR_HDMIA,
++ },
++};
++
++static struct rcar_du_platform_data porter_du_pdata = {
++ .encoders = porter_du_encoders,
++ .num_encoders = ARRAY_SIZE(porter_du_encoders),
++ .crtcs = porter_du_crtcs,
++ .num_crtcs = ARRAY_SIZE(porter_du_crtcs),
++#ifdef CONFIG_DRM_FBDEV_CRTC
++ .fbdev_crtc = 1,
++#endif
++ .i2c_ch = 2,
++};
++
++static const struct resource du_resources[] __initconst = {
++ DEFINE_RES_MEM(0xfeb00000, 0x40000),
++ DEFINE_RES_MEM_NAMED(0xfeb90000, 0x1c, "lvds.0"),
++ DEFINE_RES_IRQ(gic_spi(256)),
++ DEFINE_RES_IRQ(gic_spi(268)),
++};
++
++static void __init porter_add_du_device(void)
++{
++ struct platform_device_info info = {
++ .name = "rcar-du-r8a7791",
++ .id = -1,
++ .res = du_resources,
++ .num_res = ARRAY_SIZE(du_resources),
++ .data = &porter_du_pdata,
++ .size_data = sizeof(porter_du_pdata),
++ .dma_mask = DMA_BIT_MASK(32),
++ };
++
++ platform_device_register_full(&info);
++}
++
++/* Sound */
++static struct rsnd_ssi_platform_info rsnd_ssi[] = {
++ RSND_SSI(AUDIOPP_DMAC_SLAVE_CMD0_TO_SSI0, gic_spi(370), 0),
++ RSND_SSI(AUDIOPP_DMAC_SLAVE_SSI1_TO_SCU1, gic_spi(371), RSND_SSI_CLK_PIN_SHARE),
++};
++
++static struct rsnd_src_platform_info rsnd_src[2] = {
++ RSND_SRC(0, AUDIO_DMAC_SLAVE_SCU0_TX, gic_spi(352)),
++ RSND_SRC(0, AUDIO_DMAC_SLAVE_CMD1_TO_MEM, gic_spi(353)),
++};
++
++static struct rsnd_dvc_platform_info rsnd_dvc[2] = {
++};
++
++static struct rsnd_dai_platform_info rsnd_dai = {
++ .playback = { .ssi = &rsnd_ssi[0], .src = &rsnd_src[0], .dvc = &rsnd_dvc[0], },
++ .capture = { .ssi = &rsnd_ssi[1], .src = &rsnd_src[1], .dvc = &rsnd_dvc[1], },
++};
++
++static struct rcar_snd_info rsnd_info = {
++ .flags = RSND_GEN2,
++ .ssi_info = rsnd_ssi,
++ .ssi_info_nr = ARRAY_SIZE(rsnd_ssi),
++ .src_info = rsnd_src,
++ .src_info_nr = ARRAY_SIZE(rsnd_src),
++ .dvc_info = rsnd_dvc,
++ .dvc_info_nr = ARRAY_SIZE(rsnd_dvc),
++ .dai_info = &rsnd_dai,
++ .dai_info_nr = 1,
++};
++
++static struct asoc_simple_card_info rsnd_card_info = {
++ .name = "SSI01-AK4643",
++ .codec = "ak4642-codec.2-0012",
++ .platform = "rcar_sound",
++ .daifmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS,
++ .cpu_dai = {
++ .name = "rcar_sound",
++ },
++ .codec_dai = {
++ .name = "ak4642-hifi",
++ .sysclk = 11289600,
++ },
++};
++
++static void __init porter_add_rsnd_device(void)
++{
++ struct resource rsnd_resources[] = {
++ [RSND_GEN2_SCU] = DEFINE_RES_MEM(0xec500000, 0x1000),
++ [RSND_GEN2_ADG] = DEFINE_RES_MEM(0xec5a0000, 0x100),
++ [RSND_GEN2_SSIU] = DEFINE_RES_MEM(0xec540000, 0x1000),
++ [RSND_GEN2_SSI] = DEFINE_RES_MEM(0xec541000, 0x1280),
++ };
++
++ struct platform_device_info cardinfo = {
++ .parent = &platform_bus,
++ .name = "asoc-simple-card",
++ .id = -1,
++ .data = &rsnd_card_info,
++ .size_data = sizeof(struct asoc_simple_card_info),
++ .dma_mask = DMA_BIT_MASK(32),
++ };
++
++ platform_device_register_resndata(
++ &platform_bus, "rcar_sound", -1,
++ rsnd_resources, ARRAY_SIZE(rsnd_resources),
++ &rsnd_info, sizeof(rsnd_info));
++
++ platform_device_register_full(&cardinfo);
++}
++
++
++/*
++ * This is a really crude hack to provide clkdev support to platform
++ * devices until they get moved to DT.
++ */
++static const struct clk_name clk_names[] __initconst = {
++ { "cmt0", NULL, "sh_cmt.0" },
++ { "cmt0", "fck", "sh-cmt-48-gen2.0" },
++ { "du0", "du.0", "rcar-du-r8a7791" },
++ { "du1", "du.1", "rcar-du-r8a7791" },
++ { "lvds0", "lvds.0", "rcar-du-r8a7791" },
++ { "hsusb", NULL, "usb_phy_rcar_gen2" },
++ { "ssi0", "ssi.0", "rcar_sound" },
++ { "ssi1", "ssi.1", "rcar_sound" },
++ { "src0", "src.0", "rcar_sound" },
++ { "src1", "src.1", "rcar_sound" },
++ { "dvc0", "dvc.0", "rcar_sound" },
++ { "dvc1", "dvc.1", "rcar_sound" },
++ { "vin0", NULL, "r8a7791-vin.0" },
++ { "vsps", NULL, NULL },
++#if IS_ENABLED(CONFIG_VIDEO_RENESAS_VSP1)
++ { "vsp1-du0", NULL, "vsp1.2" },
++ { "vsp1-du1", NULL, "vsp1.3" },
++#else
++ { "vsp1-du0", NULL, NULL },
++ { "vsp1-du1", NULL, NULL },
++#endif
++ { "vcp0", NULL, NULL },
++ { "vpc0", NULL, NULL },
++ { "tddmac", NULL, NULL },
++ { "fdp1", NULL, NULL },
++ { "fdp0", NULL, NULL },
++ { "pvrsrvkm", NULL, "pvrsrvkm" },
++#if IS_ENABLED(CONFIG_USB_RENESAS_USBHS_UDC)
++ { "hsusb", NULL, "renesas_usbhs" },
++#else
++ { "ehci", NULL, "pci-rcar-gen2.0" },
++#endif
++};
++
++/*
++ * This is a really crude hack to work around core platform clock issues
++ */
++static const struct clk_name clk_enables[] __initconst = {
++ { "ehci", NULL, "pci-rcar-gen2.1" },
++ { "dmal", NULL, "sh-dma-engine.0" },
++ { "dmah", NULL, "sh-dma-engine.1" },
++ { "sys-dmac1", NULL, "sh-dma-engine.2" },
++ { "sys-dmac0", NULL, "sh-dma-engine.3" },
++#if IS_ENABLED(CONFIG_USB_RENESAS_USBHS_UDC)
++ { "usbdmac0", NULL, "sh-dma-engine.4" },
++#endif
++ { "ssp_dev", NULL, "ssp_dev" },
++ { "ipmmu_gp", NULL, "ipmmu_gp" },
++};
++
++#define DMAE_CHANNEL(a, b) \
++{ \
++ .offset = (a) - 0x20, \
++ .dmars = (a) - 0x20 + 0x40, \
++ .chclr_bit = (b), \
++ .chclr_offset = 0x80 - 0x20, \
++}
++
++/* Sys-DMAC */
++#define SYS_DMAC_SLAVE(_id, _bit, _addr, toffset, roffset, t, r) \
++{ \
++ .slave_id = SYS_DMAC_SLAVE_## _id ##_TX, \
++ .addr = _addr + toffset, \
++ .chcr = CHCR_TX(XMIT_SZ_## _bit ##BIT), \
++ .mid_rid = t, \
++}, { \
++ .slave_id = SYS_DMAC_SLAVE_## _id ##_RX, \
++ .addr = _addr + roffset, \
++ .chcr = CHCR_RX(XMIT_SZ_## _bit ##BIT), \
++ .mid_rid = r, \
++}
++
++#define SYS_DMAC_SLAVE_TX(_id, _bit, _addr, toffset, roffset, t, r) \
++{ \
++ .slave_id = SYS_DMAC_SLAVE_## _id ##_TX, \
++ .addr = _addr + toffset, \
++ .chcr = CHCR_TX(XMIT_SZ_## _bit ##BIT), \
++ .mid_rid = t, \
++}
++
++static const struct sh_dmae_slave_config r8a7791_sys_dmac_slaves[] = {
++ SYS_DMAC_SLAVE(SDHI0, 256, 0xee100000, 0x60, 0x2060, 0xcd, 0xce),
++ SYS_DMAC_SLAVE(SDHI1, 256, 0xee140000, 0x30, 0x2030, 0xc1, 0xc2),
++ SYS_DMAC_SLAVE(SDHI2, 256, 0xee160000, 0x30, 0x2030, 0xd3, 0xd4),
++ SYS_DMAC_SLAVE(SCIF0, 8, 0xe6e60000, 0xc, 0x14, 0x29, 0x2a),
++ SYS_DMAC_SLAVE(SCIF1, 8, 0xe6e68000, 0xc, 0x14, 0x2d, 0x2e),
++ SYS_DMAC_SLAVE(SCIF2, 8, 0xe6e58000, 0xc, 0x14, 0x2b, 0x2c),
++ SYS_DMAC_SLAVE(SCIF3, 8, 0xe6ea8000, 0xc, 0x14, 0x2f, 0x30),
++ SYS_DMAC_SLAVE(SCIF4, 8, 0xe6ee0000, 0xc, 0x14, 0xfb, 0xfc),
++ SYS_DMAC_SLAVE(SCIF5, 8, 0xe6ee8000, 0xc, 0x14, 0xfd, 0xfe),
++ SYS_DMAC_SLAVE(SCIFA0, 8, 0xe6c40000, 0x20, 0x24, 0x21, 0x22),
++ SYS_DMAC_SLAVE(SCIFA1, 8, 0xe6c50000, 0x20, 0x24, 0x25, 0x26),
++ SYS_DMAC_SLAVE(SCIFA2, 8, 0xe6c60000, 0x20, 0x24, 0x27, 0x28),
++ SYS_DMAC_SLAVE(SCIFA3, 8, 0xe6c70000, 0x20, 0x24, 0x1b, 0x1c),
++ SYS_DMAC_SLAVE(SCIFA4, 8, 0xe6c78000, 0x20, 0x24, 0x1f, 0x20),
++ SYS_DMAC_SLAVE(SCIFA5, 8, 0xe6c80000, 0x20, 0x24, 0x23, 0x24),
++ SYS_DMAC_SLAVE(SCIFB0, 8, 0xe6c20000, 0x40, 0x60, 0x3d, 0x3e),
++ SYS_DMAC_SLAVE(SCIFB1, 8, 0xe6c30000, 0x40, 0x60, 0x19, 0x1a),
++ SYS_DMAC_SLAVE(SCIFB2, 8, 0xe6ce0000, 0x40, 0x60, 0x1d, 0x1e),
++ SYS_DMAC_SLAVE(HSCIF0, 8, 0xe62c0000, 0xc, 0x14, 0x39, 0x3a),
++ SYS_DMAC_SLAVE(HSCIF1, 8, 0xe62c8000, 0xc, 0x14, 0x4d, 0x4e),
++ SYS_DMAC_SLAVE(HSCIF2, 8, 0xe62d0000, 0xc, 0x14, 0x3b, 0x3c),
++ SYS_DMAC_SLAVE(MSIOF0, 32, 0xe7e20000, 0x50, 0x60, 0x51, 0x52),
++ SYS_DMAC_SLAVE(MSIOF1, 32, 0xe7e10000, 0x50, 0x60, 0x55, 0x56),
++ SYS_DMAC_SLAVE(MSIOF2, 32, 0xe7e00000, 0x50, 0x60, 0x41, 0x42),
++};
++
++static const struct sh_dmae_channel r8a7791_sys_dmac_channels[] = {
++ DMAE_CHANNEL(0x8000, 0),
++ DMAE_CHANNEL(0x8080, 1),
++ DMAE_CHANNEL(0x8100, 2),
++ DMAE_CHANNEL(0x8180, 3),
++ DMAE_CHANNEL(0x8200, 4),
++ DMAE_CHANNEL(0x8280, 5),
++ DMAE_CHANNEL(0x8300, 6),
++ DMAE_CHANNEL(0x8380, 7),
++ DMAE_CHANNEL(0x8400, 8),
++ DMAE_CHANNEL(0x8480, 9),
++ DMAE_CHANNEL(0x8500, 10),
++ DMAE_CHANNEL(0x8580, 11),
++ DMAE_CHANNEL(0x8600, 12),
++ DMAE_CHANNEL(0x8680, 13),
++ DMAE_CHANNEL(0x8700, 14),
++};
++
++static struct sh_dmae_pdata r8a7791_sys_dmac_platform_data = {
++ .slave = r8a7791_sys_dmac_slaves,
++ .slave_num = ARRAY_SIZE(r8a7791_sys_dmac_slaves),
++ .channel = r8a7791_sys_dmac_channels,
++ .channel_num = ARRAY_SIZE(r8a7791_sys_dmac_channels),
++ .ts_low_shift = TS_LOW_SHIFT,
++ .ts_low_mask = TS_LOW_BIT << TS_LOW_SHIFT,
++ .ts_high_shift = TS_HI_SHIFT,
++ .ts_high_mask = TS_HI_BIT << TS_HI_SHIFT,
++ .ts_shift = dma_ts_shift,
++ .ts_shift_num = ARRAY_SIZE(dma_ts_shift),
++ .dmaor_init = DMAOR_DME,
++ .chclr_present = 1,
++ .chclr_bitwise = 1,
++ .fourty_bits_addr = 1,
++};
++
++static struct resource r8a7791_sys_dmac_resources[] = {
++ /* Channel registers and DMAOR for low */
++ DEFINE_RES_MEM(0xe6700020, 0x8763 - 0x20),
++ DEFINE_RES_IRQ(gic_spi(197)),
++ DEFINE_RES_NAMED(gic_spi(200), 15, NULL, IORESOURCE_IRQ),
++
++ /* Channel registers and DMAOR for high */
++ DEFINE_RES_MEM(0xe6720020, 0x8763 - 0x20),
++ DEFINE_RES_IRQ(gic_spi(220)),
++ DEFINE_RES_NAMED(gic_spi(216), 4, NULL, IORESOURCE_IRQ),
++ DEFINE_RES_NAMED(gic_spi(308), 11, NULL, IORESOURCE_IRQ),
++};
++
++#define r8a7791_register_sys_dmac(id) \
++ platform_device_register_resndata( \
++ &platform_bus, "sh-dma-engine", 2 + id, \
++ &r8a7791_sys_dmac_resources[id * 3], id * 1 + 3, \
++ &r8a7791_sys_dmac_platform_data, \
++ sizeof(r8a7791_sys_dmac_platform_data))
++
++static void __init porter_add_dmac_prototype(void)
++{
++ r8a7791_register_sys_dmac(0);
++ r8a7791_register_sys_dmac(1);
++}
++
++static struct sh_mobile_sdhi_info sdhi0_info __initdata = {
++ .dma_slave_tx = SYS_DMAC_SLAVE_SDHI0_TX,
++ .dma_slave_rx = SYS_DMAC_SLAVE_SDHI0_RX,
++ .dma_rx_offset = 0x2000,
++
++ .tmio_caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
++ MMC_CAP_POWER_OFF_CARD,
++ .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT,
++};
++
++static struct sh_mobile_sdhi_info sdhi2_info __initdata = {
++ .dma_slave_tx = SYS_DMAC_SLAVE_SDHI2_TX,
++ .dma_slave_rx = SYS_DMAC_SLAVE_SDHI2_RX,
++ .dma_rx_offset = 0x2000,
++
++ .tmio_caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ |
++ MMC_CAP_POWER_OFF_CARD,
++ .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT |
++ TMIO_MMC_WRPROTECT_DISABLE,
++};
++
++/* SCIF */
++#define SCIF_PD(scif_type, index, scif_index) \
++static struct plat_sci_port scif##index##_platform_data = { \
++ .type = PORT_##scif_type, \
++ .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, \
++ .scscr = SCSCR_RE | SCSCR_TE, \
++ .dma_slave_tx = SYS_DMAC_SLAVE_##scif_type##scif_index##_TX, \
++ .dma_slave_rx = SYS_DMAC_SLAVE_##scif_type##scif_index##_RX, \
++}
++
++#define PDATA_SCIF(index, baseaddr, irq, i) SCIF_PD(SCIF, index, i)
++#define PDATA_SCIFA(index, baseaddr, irq, i) SCIF_PD(SCIFA, index, i)
++#define PDATA_SCIFB(index, baseaddr, irq, i) SCIF_PD(SCIFB, index, i)
++#define PDATA_HSCIF(index, baseaddr, irq, i) SCIF_PD(HSCIF, index, i)
++
++PDATA_SCIFA(0, 0xe6c40000, gic_spi(144), 0); /* SCIFA0 */
++PDATA_SCIFA(1, 0xe6c50000, gic_spi(145), 1); /* SCIFA1 */
++PDATA_SCIFB(2, 0xe6c20000, gic_spi(148), 0); /* SCIFB0 */
++PDATA_SCIFB(3, 0xe6c30000, gic_spi(149), 1); /* SCIFB1 */
++PDATA_SCIFB(4, 0xe6ce0000, gic_spi(150), 2); /* SCIFB2 */
++PDATA_SCIFA(5, 0xe6c60000, gic_spi(151), 2); /* SCIFA2 */
++PDATA_SCIF(6, 0xe6e60000, gic_spi(152), 0); /* SCIF0 */
++PDATA_SCIF(7, 0xe6e68000, gic_spi(153), 1); /* SCIF1 */
++PDATA_HSCIF(8, 0xe62c0000, gic_spi(154), 0); /* HSCIF0 */
++PDATA_HSCIF(9, 0xe62c8000, gic_spi(155), 1); /* HSCIF1 */
++PDATA_SCIF(10, 0xe6e58000, gic_spi(22), 2); /* SCIF2 */
++PDATA_SCIF(11, 0xe6ea8000, gic_spi(23), 3); /* SCIF3 */
++PDATA_SCIF(12, 0xe6ee0000, gic_spi(24), 4); /* SCIF4 */
++PDATA_SCIF(13, 0xe6ee8000, gic_spi(25), 5); /* SCIF5 */
++PDATA_SCIFA(14, 0xe6c70000, gic_spi(29), 3); /* SCIFA3 */
++PDATA_SCIFA(15, 0xe6c78000, gic_spi(30), 4); /* SCIFA4 */
++PDATA_SCIFA(16, 0xe6c80000, gic_spi(31), 5); /* SCIFA5 */
++PDATA_HSCIF(17, 0xe6cd0000, gic_spi(21), 2); /* HSCIF2 */
++
++#define SCIF_AD(scif_type, index, baseaddr) \
++ OF_DEV_AUXDATA("renesas," scif_type "-r8a7791", baseaddr, \
++ "sh-sci." # index, &scif##index##_platform_data)
++
++#define AUXDATA_SCIF(index, baseaddr, irq) SCIF_AD("scif", index, baseaddr)
++#define AUXDATA_SCIFA(index, baseaddr, irq) SCIF_AD("scifa", index, baseaddr)
++#define AUXDATA_SCIFB(index, baseaddr, irq) SCIF_AD("scifb", index, baseaddr)
++#define AUXDATA_HSCIF(index, baseaddr, irq) SCIF_AD("hscif", index, baseaddr)
++
++#if IS_ENABLED(CONFIG_USB_RENESAS_USBHS_UDC)
++/* USB-DMAC */
++static const struct sh_dmae_channel usb_dmac_channels[] = {
++ {
++ .offset = 0,
++ }, {
++ .offset = 0x20,
++ },
++};
++
++static const struct sh_dmae_slave_config usb_dmac_slaves[] = {
++ {
++ .slave_id = USB_DMAC_SLAVE_USBHS_TX,
++ .chcr = USBTS_INDEX2VAL(USBTS_XMIT_SZ_32BYTE),
++ }, {
++ .slave_id = USB_DMAC_SLAVE_USBHS_RX,
++ .chcr = USBTS_INDEX2VAL(USBTS_XMIT_SZ_32BYTE),
++ },
++};
++
++static struct sh_dmae_pdata usb_dmac_platform_data = {
++ .slave = usb_dmac_slaves,
++ .slave_num = ARRAY_SIZE(usb_dmac_slaves),
++ .channel = usb_dmac_channels,
++ .channel_num = ARRAY_SIZE(usb_dmac_channels),
++ .ts_low_shift = USBTS_LOW_SHIFT,
++ .ts_low_mask = USBTS_LOW_BIT << USBTS_LOW_SHIFT,
++ .ts_high_shift = USBTS_HI_SHIFT,
++ .ts_high_mask = USBTS_HI_BIT << USBTS_HI_SHIFT,
++ .ts_shift = dma_usbts_shift,
++ .ts_shift_num = ARRAY_SIZE(dma_usbts_shift),
++ .dmaor_init = DMAOR_DME,
++ .chcr_offset = 0x14,
++ .chcr_ie_bit = 1 << 5,
++ .dmaor_is_32bit = 1,
++ .needs_tend_set = 1,
++ .no_dmars = 1,
++ .slave_only = 1,
++};
++
++static struct resource usb_dmac_resources[] = {
++ DEFINE_RES_MEM(0xe65a0020, 0x44), /* Channel registers and DMAOR */
++ DEFINE_RES_MEM(0xe65a0000, 0x14), /* VCR/SWR/DMICR */
++ DEFINE_RES_IRQ(gic_spi(109)),
++};
++
++static void __init porter_add_usb_dmac_prototype(void)
++{
++ platform_device_register_resndata(&platform_bus, "sh-dma-engine",
++ 4,
++ usb_dmac_resources,
++ ARRAY_SIZE(usb_dmac_resources),
++ &usb_dmac_platform_data,
++ sizeof(usb_dmac_platform_data));
++}
++
++
++/* USBHS */
++static const struct resource usbhs_resources[] __initconst = {
++ DEFINE_RES_MEM(0xe6590000, 0x100),
++ DEFINE_RES_IRQ(gic_spi(107)),
++};
++
++struct usbhs_private {
++ struct renesas_usbhs_platform_info info;
++ struct usb_phy *phy;
++ int id_gpio;
++};
++
++#define usbhs_get_priv(pdev) \
++ container_of(renesas_usbhs_get_info(pdev), struct usbhs_private, info)
++
++static int usbhs_power_ctrl(struct platform_device *pdev,
++ void __iomem *base, int enable)
++{
++ struct usbhs_private *priv = usbhs_get_priv(pdev);
++
++ if (!priv->phy)
++ return -ENODEV;
++
++ if (enable) {
++ int retval = usb_phy_init(priv->phy);
++
++ if (!retval)
++ retval = usb_phy_set_suspend(priv->phy, 0);
++ return retval;
++ }
++
++ usb_phy_set_suspend(priv->phy, 1);
++ usb_phy_shutdown(priv->phy);
++ return 0;
++}
++
++static int usbhs_hardware_init(struct platform_device *pdev)
++{
++ struct usbhs_private *priv = usbhs_get_priv(pdev);
++ struct usb_phy *phy;
++ int ret;
++ struct device_node *np;
++
++ np = of_find_node_by_path("/gpio@e6055000");
++ if (np) {
++ priv->id_gpio = of_get_gpio(np, 31);
++ of_node_put(np);
++ } else {
++ pr_warn("Error: Unable to get MAX3355 ID input\n");
++ ret = -ENOTSUPP;
++ goto error2;
++ }
++
++ /* Check MAX3355E ID pin */
++ gpio_request_one(priv->id_gpio, GPIOF_IN, NULL);
++ if (!gpio_get_value(priv->id_gpio)) {
++ pr_warn("Error: USB0 cable selects host mode\n");
++ ret = -ENOTSUPP;
++ goto error;
++ }
++
++ phy = usb_get_phy_dev(&pdev->dev, 0);
++ if (IS_ERR(phy))
++ return PTR_ERR(phy);
++
++ priv->phy = phy;
++ return 0;
++
++error:
++ gpio_free(priv->id_gpio);
++error2:
++ return ret;
++}
++
++static int usbhs_hardware_exit(struct platform_device *pdev)
++{
++ struct usbhs_private *priv = usbhs_get_priv(pdev);
++
++ if (!priv->phy)
++ return 0;
++
++ usb_put_phy(priv->phy);
++ priv->phy = NULL;
++
++ gpio_free(priv->id_gpio);
++ return 0;
++}
++
++static int usbhs_get_id(struct platform_device *pdev)
++{
++ return USBHS_GADGET;
++}
++
++static int usbhs_get_vbus(struct platform_device *pdev)
++{
++ return 0;
++}
++
++static u32 porter_usbhs_pipe_type[] = {
++ USB_ENDPOINT_XFER_CONTROL,
++ USB_ENDPOINT_XFER_ISOC,
++ USB_ENDPOINT_XFER_ISOC,
++ USB_ENDPOINT_XFER_BULK,
++ USB_ENDPOINT_XFER_BULK,
++ USB_ENDPOINT_XFER_BULK,
++ USB_ENDPOINT_XFER_INT,
++ USB_ENDPOINT_XFER_INT,
++ USB_ENDPOINT_XFER_INT,
++ USB_ENDPOINT_XFER_BULK,
++ USB_ENDPOINT_XFER_BULK,
++ USB_ENDPOINT_XFER_BULK,
++ USB_ENDPOINT_XFER_BULK,
++ USB_ENDPOINT_XFER_BULK,
++ USB_ENDPOINT_XFER_BULK,
++ USB_ENDPOINT_XFER_BULK,
++};
++
++static struct usbhs_private usbhs_priv __initdata = {
++ .info = {
++ .platform_callback = {
++ .power_ctrl = usbhs_power_ctrl,
++ .hardware_init = usbhs_hardware_init,
++ .hardware_exit = usbhs_hardware_exit,
++ .get_id = usbhs_get_id,
++ .get_vbus = usbhs_get_vbus,
++ },
++ .driver_param = {
++ .buswait_bwait = 4,
++ .pipe_type = porter_usbhs_pipe_type,
++ .pipe_size = ARRAY_SIZE(porter_usbhs_pipe_type),
++ .d0_rx_id = USB_DMAC_SLAVE_USBHS_RX,
++ .d1_tx_id = USB_DMAC_SLAVE_USBHS_TX,
++ .usb_dmac_xfer_size = 32,
++ },
++ }
++};
++
++static void __init porter_add_usb0_gadget(void)
++{
++ usb_bind_phy("renesas_usbhs", 0, "usb_phy_rcar_gen2");
++ platform_device_register_resndata(&platform_bus,
++ "renesas_usbhs", -1,
++ usbhs_resources,
++ ARRAY_SIZE(usbhs_resources),
++ &usbhs_priv.info,
++ sizeof(usbhs_priv.info));
++}
++#else
++/* Internal PCI0 */
++static const struct resource pci0_resources[] __initconst = {
++ DEFINE_RES_MEM(0xee090000, 0x10000), /* CFG */
++ DEFINE_RES_MEM(0xee080000, 0x10000), /* MEM */
++ DEFINE_RES_IRQ(gic_spi(108)),
++};
++
++static void __init porter_add_usb0_host(void)
++{
++ usb_bind_phy("pci-rcar-gen2.0", 0, "usb_phy_rcar_gen2");
++ platform_device_register_simple("pci-rcar-gen2",
++ 0, pci0_resources,
++ ARRAY_SIZE(pci0_resources));
++}
++#endif
++
++/* Internal PCI1 */
++static const struct resource pci1_resources[] __initconst = {
++ DEFINE_RES_MEM(0xee0d0000, 0x10000), /* CFG */
++ DEFINE_RES_MEM(0xee0c0000, 0x10000), /* MEM */
++ DEFINE_RES_IRQ(gic_spi(113)),
++};
++
++static void __init porter_add_usb1_host(void)
++{
++ usb_bind_phy("pci-rcar-gen2.1", 0, "usb_phy_rcar_gen2");
++ platform_device_register_simple("pci-rcar-gen2",
++ 1, pci1_resources,
++ ARRAY_SIZE(pci1_resources));
++}
++
++/* USBHS PHY */
++static const struct rcar_gen2_phy_platform_data usbhs_phy_pdata __initconst = {
++#if IS_ENABLED(CONFIG_USB_RENESAS_USBHS_UDC)
++ .chan0_pci = 0, /* Channel 0 is USBHS */
++#else
++ .chan0_pci = 1, /* Channel 0 is PCI USB */
++#endif
++ .chan2_pci = 1, /* Channel 2 is PCI USB host */
++ .gpio_vbus = 798,
++ .wakeup = true,
++};
++
++/* VIN */
++static const struct resource vin_resources[] __initconst = {
++ /* VIN0 */
++ DEFINE_RES_MEM(0xe6ef0000, 0x1000),
++ DEFINE_RES_IRQ(gic_spi(188)),
++ /* VIN1 */
++ DEFINE_RES_MEM(0xe6ef1000, 0x1000),
++ DEFINE_RES_IRQ(gic_spi(189)),
++};
++
++static void __init porter_add_vin_device(unsigned idx,
++ struct rcar_vin_platform_data *pdata)
++{
++ struct platform_device_info vin_info = {
++ .parent = &platform_bus,
++ .name = "r8a7791-vin",
++ .id = idx,
++ .res = &vin_resources[idx * 2],
++ .num_res = 2,
++ .dma_mask = DMA_BIT_MASK(32),
++ .data = pdata,
++ .size_data = sizeof(*pdata),
++ };
++
++ BUG_ON(idx > 1);
++
++ platform_device_register_full(&vin_info);
++}
++
++#define PORTER_CAMERA(idx, name, addr, pdata, flag) \
++static struct i2c_board_info i2c_cam##idx##_device = { \
++ I2C_BOARD_INFO(name, addr), \
++}; \
++ \
++static struct rcar_vin_platform_data vin##idx##_pdata = { \
++ .flags = flag, \
++}; \
++ \
++static struct soc_camera_link cam##idx##_link = { \
++ .bus_id = idx, \
++ .board_info = &i2c_cam##idx##_device, \
++ .i2c_adapter_id = 2, \
++ .module_name = name, \
++ .priv = pdata, \
++}
++
++PORTER_CAMERA(0, "adv7180", 0x20, NULL, RCAR_VIN_BT656);
++
++static void __init porter_add_camera0_device(void)
++{
++ platform_device_register_data(&platform_bus, "soc-camera-pdrv", 0,
++ &cam0_link, sizeof(cam0_link));
++ porter_add_vin_device(0, &vin0_pdata);
++}
++
++/* VSP1 */
++#if IS_ENABLED(CONFIG_VIDEO_RENESAS_VSP1)
++static const struct vsp1_platform_data porter_vsps_pdata __initconst = {
++ .features = 0,
++ .rpf_count = 5,
++ .uds_count = 3,
++ .wpf_count = 4,
++};
++
++static const struct vsp1_platform_data porter_vspd0_pdata __initconst = {
++ .features = VSP1_HAS_LIF,
++ .rpf_count = 4,
++ .uds_count = 1,
++ .wpf_count = 4,
++};
++
++static const struct vsp1_platform_data porter_vspd1_pdata __initconst = {
++ .features = VSP1_HAS_LIF,
++ .rpf_count = 4,
++ .uds_count = 1,
++ .wpf_count = 4,
++};
++
++static const struct vsp1_platform_data * const porter_vsp1_pdata[] __initconst
++ = {
++ &porter_vsps_pdata,
++ &porter_vspd0_pdata,
++ &porter_vspd1_pdata,
++};
++
++static const struct resource vsp1_1_resources[] __initconst = {
++ DEFINE_RES_MEM(0xfe928000, 0x8000),
++ DEFINE_RES_IRQ(gic_spi(267)),
++};
++
++static const struct resource vsp1_2_resources[] __initconst = {
++ DEFINE_RES_MEM(0xfe930000, 0x8000),
++ DEFINE_RES_IRQ(gic_spi(246)),
++};
++
++static const struct resource vsp1_3_resources[] __initconst = {
++ DEFINE_RES_MEM(0xfe938000, 0x8000),
++ DEFINE_RES_IRQ(gic_spi(247)),
++};
++
++static const struct resource * const vsp1_resources[] __initconst = {
++ vsp1_1_resources,
++ vsp1_2_resources,
++ vsp1_3_resources,
++};
++
++static void __init porter_add_vsp1_devices(void)
++{
++ struct platform_device_info info = {
++ .name = "vsp1",
++ .size_data = sizeof(*porter_vsp1_pdata[0]),
++ .num_res = 2,
++ .dma_mask = DMA_BIT_MASK(32),
++ };
++ unsigned int i;
++
++ for (i = 1; i < ARRAY_SIZE(vsp1_resources); ++i) {
++ info.id = i + 1;
++ info.data = porter_vsp1_pdata[i];
++ info.res = vsp1_resources[i];
++
++ platform_device_register_full(&info);
++ }
++}
++#endif
++
++static const struct resource usbhs_phy_resources[] __initconst = {
++ DEFINE_RES_MEM(0xe6590100, 0x100),
++};
++
++/* Add all available USB devices */
++static void __init porter_add_usb_devices(void)
++{
++ platform_device_register_resndata(&platform_bus, "usb_phy_rcar_gen2",
++ -1, usbhs_phy_resources,
++ ARRAY_SIZE(usbhs_phy_resources),
++ &usbhs_phy_pdata,
++ sizeof(usbhs_phy_pdata));
++#if IS_ENABLED(CONFIG_USB_RENESAS_USBHS_UDC)
++ porter_add_usb0_gadget();
++#else
++ porter_add_usb0_host();
++#endif
++ porter_add_usb1_host();
++}
++
++/* MSIOF */
++static struct sh_msiof_spi_info msiof0_info = {
++ .rx_fifo_override = 256,
++ .num_chipselect = 1,
++ .dma_tx_id = SYS_DMAC_SLAVE_MSIOF0_TX,
++ .dma_rx_id = SYS_DMAC_SLAVE_MSIOF0_RX,
++};
++
++/* MSIOF spidev */
++static const struct spi_board_info spi_bus[] __initconst = {
++ {
++ .modalias = "spidev",
++ .max_speed_hz = 6000000,
++ .mode = SPI_MODE_3,
++ .bus_num = 1,
++ .chip_select = 0,
++ },
++};
++
++#define porter_add_msiof_device spi_register_board_info
++
++/* POWER IC */
++static struct i2c_board_info poweric_i2c[] = {
++ { I2C_BOARD_INFO("da9063", 0x58), },
++};
++
++static void porter_restart(char mode, const char *cmd)
++{
++ struct i2c_adapter *adap;
++ struct i2c_client *client;
++ u8 val;
++ int busnum = 6;
++
++ adap = i2c_get_adapter(busnum);
++ if (!adap) {
++ pr_err("failed to get adapter i2c%d\n", busnum);
++ return;
++ }
++
++ client = i2c_new_device(adap, &poweric_i2c[0]);
++ if (!client)
++ pr_err("failed to register %s to i2c%d\n",
++ poweric_i2c[0].type, busnum);
++
++ i2c_put_adapter(adap);
++
++ val = i2c_smbus_read_byte_data(client, 0x13);
++
++ if (val < 0)
++ pr_err("couldn't access da9063\n");
++
++ val |= 0x02;
++
++ i2c_smbus_write_byte_data(client, 0x13, val);
++}
++
++static struct of_dev_auxdata porter_auxdata_lookup[] __initdata = {
++ OF_DEV_AUXDATA("renesas,sdhi-r8a7791", 0xee100000, "sdhi0",
++ &sdhi0_info),
++ OF_DEV_AUXDATA("renesas,sdhi-r8a7791", 0xee160000, "sdhi2",
++ &sdhi2_info),
++ AUXDATA_SCIFA(0, 0xe6c40000, gic_spi(144)), /* SCIFA0 */
++ AUXDATA_SCIFA(1, 0xe6c50000, gic_spi(145)), /* SCIFA1 */
++ AUXDATA_SCIFB(2, 0xe6c20000, gic_spi(148)), /* SCIFB0 */
++ AUXDATA_SCIFB(3, 0xe6c30000, gic_spi(149)), /* SCIFB1 */
++ AUXDATA_SCIFB(4, 0xe6ce0000, gic_spi(150)), /* SCIFB2 */
++ AUXDATA_SCIFA(5, 0xe6c60000, gic_spi(151)), /* SCIFA2 */
++ AUXDATA_SCIF(6, 0xe6e60000, gic_spi(152)), /* SCIF0 */
++ AUXDATA_SCIF(7, 0xe6e68000, gic_spi(153)), /* SCIF1 */
++ AUXDATA_HSCIF(8, 0xe62c0000, gic_spi(154)), /* HSCIF0 */
++ AUXDATA_HSCIF(9, 0xe62c8000, gic_spi(155)), /* HSCIF1 */
++ AUXDATA_SCIF(10, 0xe6e58000, gic_spi(22)), /* SCIF2 */
++ AUXDATA_SCIF(11, 0xe6ea8000, gic_spi(23)), /* SCIF3 */
++ AUXDATA_SCIF(12, 0xe6ee0000, gic_spi(24)), /* SCIF4 */
++ AUXDATA_SCIF(13, 0xe6ee8000, gic_spi(25)), /* SCIF5 */
++ AUXDATA_SCIFA(14, 0xe6c70000, gic_spi(29)), /* SCIFA3 */
++ AUXDATA_SCIFA(15, 0xe6c78000, gic_spi(30)), /* SCIFA4 */
++ AUXDATA_SCIFA(16, 0xe6c80000, gic_spi(31)), /* SCIFA5 */
++ AUXDATA_HSCIF(17, 0xe6cd0000, gic_spi(21)), /* HSCIF2 */
++ OF_DEV_AUXDATA("renesas,msiof-r8a7791", 0xe6e20000,
++ "spi_r8a7791_msiof.0", &msiof0_info),
++ {},
++};
++
++static void __init porter_add_standard_devices(void)
++{
++ shmobile_clk_workaround(clk_names, ARRAY_SIZE(clk_names), false);
++ shmobile_clk_workaround(clk_enables, ARRAY_SIZE(clk_enables), true);
++ r8a7791_add_dt_devices();
++ porter_add_dmac_prototype();
++#if IS_ENABLED(CONFIG_USB_RENESAS_USBHS_UDC)
++ porter_add_usb_dmac_prototype();
++#endif
++ of_platform_populate(NULL, of_default_bus_match_table,
++ porter_auxdata_lookup, NULL);
++
++ porter_add_du_device();
++ porter_add_usb_devices();
++ porter_add_rsnd_device();
++ porter_add_camera0_device();
++#if IS_ENABLED(CONFIG_VIDEO_RENESAS_VSP1)
++ porter_add_vsp1_devices();
++#endif
++ porter_add_msiof_device(spi_bus, ARRAY_SIZE(spi_bus));
++}
++
++static const char * const porter_boards_compat_dt[] __initconst = {
++ "renesas,porter",
++ "renesas,porter-reference",
++ NULL,
++};
++
++DT_MACHINE_START(PORTER_DT, "porter")
++ .smp = smp_ops(r8a7791_smp_ops),
++ .init_early = shmobile_init_delay,
++ .init_time = rcar_gen2_timer_init,
++ .init_machine = porter_add_standard_devices,
++ .init_late = shmobile_init_late,
++ .reserve = rcar_gen2_reserve,
++ .restart = porter_restart,
++ .dt_compat = porter_boards_compat_dt,
++MACHINE_END
+--
+1.9.1
+
diff --git a/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0009-shmobile-add-atag-dtb-compat.patch b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0009-shmobile-add-atag-dtb-compat.patch
new file mode 100644
index 0000000..8b6935f
--- /dev/null
+++ b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0009-shmobile-add-atag-dtb-compat.patch
@@ -0,0 +1,26 @@
+From 80644cc053765ec9ea7c509acad7cfd819ea25f5 Mon Sep 17 00:00:00 2001
+From: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+Date: Wed, 11 Feb 2015 15:19:56 +0300
+Subject: [PATCH] Add ATAG DTB compatibility
+
+This is useful when DTB is static
+
+Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+
+---
+ arch/arm/configs/shmobile_defconfig | 2 ++
+ 1 file changed, 2 insertions(+)
+
+Index: renesas-backport.v0/arch/arm/configs/shmobile_defconfig
+===================================================================
+--- renesas-backport.v0.orig/arch/arm/configs/shmobile_defconfig 2015-01-28 12:21:43.823500578 +0300
++++ renesas-backport.v0/arch/arm/configs/shmobile_defconfig 2015-02-11 14:33:34.864892464 +0300
+@@ -52,6 +52,8 @@
+ CONFIG_ZBOOT_ROM_TEXT=0x0
+ CONFIG_ZBOOT_ROM_BSS=0x0
+ CONFIG_ARM_APPENDED_DTB=y
++CONFIG_ARM_ATAG_DTB_COMPAT=y
++CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER=y
+ CONFIG_KEXEC=y
+ CONFIG_CPU_FREQ=y
+ CONFIG_CPU_FREQ_STAT_DETAILS=y
diff --git a/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0010-Silk-Add-missing-pins-handle-to-Eth.patch b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0010-Silk-Add-missing-pins-handle-to-Eth.patch
new file mode 100644
index 0000000..22742ea
--- /dev/null
+++ b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0010-Silk-Add-missing-pins-handle-to-Eth.patch
@@ -0,0 +1,43 @@
+From 4369d6e8d6c7068f6d570701afd87fb0e3b50495 Mon Sep 17 00:00:00 2001
+From: Valentine Barshak <valentine.barshak@cogentembedded.com>
+Date: Fri, 13 Feb 2015 23:12:41 +0300
+Subject: [PATCH] ARM: dts: r8a7794-silk: Add missing pins handle to
+ Ethernet node
+
+This adds missing pins handle to the Ethernet node.
+
+Signed-off-by: Valentine Barshak <valentine.barshak@cogentembedded.com>
+Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
+---
+ arch/arm/boot/dts/r8a7794-silk.dts | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/arm/boot/dts/r8a7794-silk.dts b/arch/arm/boot/dts/r8a7794-silk.dts
+index dc04673..9775aba 100644
+--- a/arch/arm/boot/dts/r8a7794-silk.dts
++++ b/arch/arm/boot/dts/r8a7794-silk.dts
+@@ -239,6 +239,11 @@
+ renesas,function = "eth";
+ };
+
++ phy1_pins: phy1 {
++ renesas,groups = "intc_irq8";
++ renesas,function = "intc";
++ };
++
+ qspi_pins: spi0 {
+ renesas,groups = "qspi_ctrl", "qspi_data4";
+ renesas,function = "qspi";
+@@ -286,6 +291,9 @@
+ };
+
+ &ether {
++ pinctrl-0 = <&ether_pins &phy1_pins>;
++ pinctrl-names = "default";
++
+ phy-handle = <&phy1>;
+ renesas,ether-link-active-low;
+ status = "ok";
+--
+1.9.3
+
diff --git a/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0011-Silk-Add-missing-DU-pins.patch b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0011-Silk-Add-missing-DU-pins.patch
new file mode 100644
index 0000000..791b1a8
--- /dev/null
+++ b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0011-Silk-Add-missing-DU-pins.patch
@@ -0,0 +1,49 @@
+From 78aac9e8fbd6b5463554990e055302074a7fc485 Mon Sep 17 00:00:00 2001
+From: Valentine Barshak <valentine.barshak@cogentembedded.com>
+Date: Fri, 13 Feb 2015 06:01:51 +0300
+Subject: [PATCH] ARM: dts: r8a7794-silk: Add missing DU pins
+
+This adds missing DU pins to R8A7794 SILK device tree.
+
+Signed-off-by: Valentine Barshak <valentine.barshak@cogentembedded.com>
+---
+ arch/arm/boot/dts/r8a7794-silk.dts | 16 +++++++++++++---
+ 1 file changed, 13 insertions(+), 3 deletions(-)
+
+diff --git a/arch/arm/boot/dts/r8a7794-silk.dts b/arch/arm/boot/dts/r8a7794-silk.dts
+index f6994c9..dc04673 100644
+--- a/arch/arm/boot/dts/r8a7794-silk.dts
++++ b/arch/arm/boot/dts/r8a7794-silk.dts
+@@ -209,16 +209,26 @@
+ };
+
+ &pfc {
+- pinctrl-0 = <&du_pins &usb0_pins &usb1_pins &sound_pins &sound_clk_pins
++ pinctrl-0 = <&du_pins &du0_pins &du1_pins &usb0_pins &usb1_pins &sound_pins &sound_clk_pins
+ &vin0_pins>;
+ pinctrl-names = "default";
+
+ du_pins: du {
+- renesas,groups = "du0_rgb888", "du0_sync", "du0_clk_out",
+- "du1_rgb666", "du1_sync", "du1_clk_out";
++ renesas,groups = "du0_rgb888", "du0_sync", "du0_clk_out", "du0_cde_disp",
++ "du1_rgb666", "du1_sync", "du1_clk_out", "du1_cde_disp";
+ renesas,function = "du";
+ };
+
++ du0_pins: du0 {
++ renesas,groups = "du0_clk_in";
++ renesas,function = "du0";
++ };
++
++ du1_pins: du1 {
++ renesas,groups = "du1_clk_in";
++ renesas,function = "du1";
++ };
++
+ i2c0_pins: i2c0 {
+ renesas,groups = "i2c0_d";
+ renesas,function = "i2c0";
+--
+1.9.3
+
diff --git a/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0012-can-add-Renesas-R-Car-CAN-driver.patch b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0012-can-add-Renesas-R-Car-CAN-driver.patch
new file mode 100644
index 0000000..55450c0
--- /dev/null
+++ b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0012-can-add-Renesas-R-Car-CAN-driver.patch
@@ -0,0 +1,958 @@
+From fd1159318e55e901cf269de90163b19fd62938cb Mon Sep 17 00:00:00 2001
+From: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
+Date: Sat, 17 May 2014 00:03:54 +0400
+Subject: [PATCH] can: add Renesas R-Car CAN driver
+
+Add support for the CAN controller found in Renesas R-Car SoCs.
+
+Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+---
+ drivers/net/can/Kconfig | 10 +
+ drivers/net/can/Makefile | 1 +
+ drivers/net/can/rcar_can.c | 876 ++++++++++++++++++++++++++++++++++
+ include/linux/can/platform/rcar_can.h | 17 +
+ 4 files changed, 904 insertions(+)
+ create mode 100644 drivers/net/can/rcar_can.c
+ create mode 100644 include/linux/can/platform/rcar_can.h
+
+diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
+index ac67afa..714b187 100644
+--- a/drivers/net/can/Kconfig
++++ b/drivers/net/can/Kconfig
+@@ -119,6 +119,16 @@ config CAN_GRCAN
+ endian syntheses of the cores would need some modifications on
+ the hardware level to work.
+
++config CAN_RCAR
++ tristate "Renesas R-Car CAN controller"
++ depends on ARM
++ ---help---
++ Say Y here if you want to use CAN controller found on Renesas R-Car
++ SoCs.
++
++ To compile this driver as a module, choose M here: the module will
++ be called rcar_can.
++
+ source "drivers/net/can/mscan/Kconfig"
+
+ source "drivers/net/can/sja1000/Kconfig"
+diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
+index c420588..90f538c 100644
+--- a/drivers/net/can/Makefile
++++ b/drivers/net/can/Makefile
+@@ -25,5 +25,6 @@ obj-$(CONFIG_CAN_JANZ_ICAN3) += janz-ican3.o
+ obj-$(CONFIG_CAN_FLEXCAN) += flexcan.o
+ obj-$(CONFIG_PCH_CAN) += pch_can.o
+ obj-$(CONFIG_CAN_GRCAN) += grcan.o
++obj-$(CONFIG_CAN_RCAR) += rcar_can.o
+
+ ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
+diff --git a/drivers/net/can/rcar_can.c b/drivers/net/can/rcar_can.c
+new file mode 100644
+index 0000000..5268d21
+--- /dev/null
++++ b/drivers/net/can/rcar_can.c
+@@ -0,0 +1,876 @@
++/* Renesas R-Car CAN device driver
++ *
++ * Copyright (C) 2013 Cogent Embedded, Inc. <source@cogentembedded.com>
++ * Copyright (C) 2013 Renesas Solutions Corp.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/interrupt.h>
++#include <linux/errno.h>
++#include <linux/netdevice.h>
++#include <linux/platform_device.h>
++#include <linux/can/led.h>
++#include <linux/can/dev.h>
++#include <linux/clk.h>
++#include <linux/can/platform/rcar_can.h>
++
++#define RCAR_CAN_DRV_NAME "rcar_can"
++
++/* Mailbox configuration:
++ * mailbox 60 - 63 - Rx FIFO mailboxes
++ * mailbox 56 - 59 - Tx FIFO mailboxes
++ * non-FIFO mailboxes are not used
++ */
++#define RCAR_CAN_N_MBX 64 /* Number of mailboxes in non-FIFO mode */
++#define RCAR_CAN_RX_FIFO_MBX 60 /* Mailbox - window to Rx FIFO */
++#define RCAR_CAN_TX_FIFO_MBX 56 /* Mailbox - window to Tx FIFO */
++#define RCAR_CAN_FIFO_DEPTH 4
++
++/* Mailbox registers structure */
++struct rcar_can_mbox_regs {
++ u32 id; /* IDE and RTR bits, SID and EID */
++ u8 stub; /* Not used */
++ u8 dlc; /* Data Length Code - bits [0..3] */
++ u8 data[8]; /* Data Bytes */
++ u8 tsh; /* Time Stamp Higher Byte */
++ u8 tsl; /* Time Stamp Lower Byte */
++};
++
++struct rcar_can_regs {
++ struct rcar_can_mbox_regs mb[RCAR_CAN_N_MBX]; /* Mailbox registers */
++ u32 mkr_2_9[8]; /* Mask Registers 2-9 */
++ u32 fidcr[2]; /* FIFO Received ID Compare Register */
++ u32 mkivlr1; /* Mask Invalid Register 1 */
++ u32 mier1; /* Mailbox Interrupt Enable Register 1 */
++ u32 mkr_0_1[2]; /* Mask Registers 0-1 */
++ u32 mkivlr0; /* Mask Invalid Register 0*/
++ u32 mier0; /* Mailbox Interrupt Enable Register 0 */
++ u8 pad_440[0x3c0];
++ u8 mctl[64]; /* Message Control Registers */
++ u16 ctlr; /* Control Register */
++ u16 str; /* Status register */
++ u8 bcr[3]; /* Bit Configuration Register */
++ u8 clkr; /* Clock Select Register */
++ u8 rfcr; /* Receive FIFO Control Register */
++ u8 rfpcr; /* Receive FIFO Pointer Control Register */
++ u8 tfcr; /* Transmit FIFO Control Register */
++ u8 tfpcr; /* Transmit FIFO Pointer Control Register */
++ u8 eier; /* Error Interrupt Enable Register */
++ u8 eifr; /* Error Interrupt Factor Judge Register */
++ u8 recr; /* Receive Error Count Register */
++ u8 tecr; /* Transmit Error Count Register */
++ u8 ecsr; /* Error Code Store Register */
++ u8 cssr; /* Channel Search Support Register */
++ u8 mssr; /* Mailbox Search Status Register */
++ u8 msmr; /* Mailbox Search Mode Register */
++ u16 tsr; /* Time Stamp Register */
++ u8 afsr; /* Acceptance Filter Support Register */
++ u8 pad_857;
++ u8 tcr; /* Test Control Register */
++ u8 pad_859[7];
++ u8 ier; /* Interrupt Enable Register */
++ u8 isr; /* Interrupt Status Register */
++ u8 pad_862;
++ u8 mbsmr; /* Mailbox Search Mask Register */
++};
++
++struct rcar_can_priv {
++ struct can_priv can; /* Must be the first member! */
++ struct net_device *ndev;
++ struct napi_struct napi;
++ struct rcar_can_regs __iomem *regs;
++ struct clk *clk;
++ u8 tx_dlc[RCAR_CAN_FIFO_DEPTH];
++ u32 tx_head;
++ u32 tx_tail;
++ u8 clock_select;
++ u8 ier;
++};
++
++static const struct can_bittiming_const rcar_can_bittiming_const = {
++ .name = RCAR_CAN_DRV_NAME,
++ .tseg1_min = 4,
++ .tseg1_max = 16,
++ .tseg2_min = 2,
++ .tseg2_max = 8,
++ .sjw_max = 4,
++ .brp_min = 1,
++ .brp_max = 1024,
++ .brp_inc = 1,
++};
++
++/* Control Register bits */
++#define RCAR_CAN_CTLR_BOM (3 << 11) /* Bus-Off Recovery Mode Bits */
++#define RCAR_CAN_CTLR_BOM_ENT (1 << 11) /* Entry to halt mode */
++ /* at bus-off entry */
++#define RCAR_CAN_CTLR_SLPM (1 << 10)
++#define RCAR_CAN_CTLR_CANM (3 << 8) /* Operating Mode Select Bit */
++#define RCAR_CAN_CTLR_CANM_HALT (1 << 9)
++#define RCAR_CAN_CTLR_CANM_RESET (1 << 8)
++#define RCAR_CAN_CTLR_CANM_FORCE_RESET (3 << 8)
++#define RCAR_CAN_CTLR_MLM (1 << 3) /* Message Lost Mode Select */
++#define RCAR_CAN_CTLR_IDFM (3 << 1) /* ID Format Mode Select Bits */
++#define RCAR_CAN_CTLR_IDFM_MIXED (1 << 2) /* Mixed ID mode */
++#define RCAR_CAN_CTLR_MBM (1 << 0) /* Mailbox Mode select */
++
++/* Status Register bits */
++#define RCAR_CAN_STR_RSTST (1 << 8) /* Reset Status Bit */
++
++/* FIFO Received ID Compare Registers 0 and 1 bits */
++#define RCAR_CAN_FIDCR_IDE (1 << 31) /* ID Extension Bit */
++#define RCAR_CAN_FIDCR_RTR (1 << 30) /* Remote Transmission Request Bit */
++
++/* Receive FIFO Control Register bits */
++#define RCAR_CAN_RFCR_RFEST (1 << 7) /* Receive FIFO Empty Status Flag */
++#define RCAR_CAN_RFCR_RFE (1 << 0) /* Receive FIFO Enable */
++
++/* Transmit FIFO Control Register bits */
++#define RCAR_CAN_TFCR_TFUST (7 << 1) /* Transmit FIFO Unsent Message */
++ /* Number Status Bits */
++#define RCAR_CAN_TFCR_TFUST_SHIFT 1 /* Offset of Transmit FIFO Unsent */
++ /* Message Number Status Bits */
++#define RCAR_CAN_TFCR_TFE (1 << 0) /* Transmit FIFO Enable */
++
++#define RCAR_CAN_N_RX_MKREGS1 2 /* Number of mask registers */
++ /* for Rx mailboxes 0-31 */
++#define RCAR_CAN_N_RX_MKREGS2 8
++
++/* Bit Configuration Register settings */
++#define RCAR_CAN_BCR_TSEG1(x) (((x) & 0x0f) << 20)
++#define RCAR_CAN_BCR_BPR(x) (((x) & 0x3ff) << 8)
++#define RCAR_CAN_BCR_SJW(x) (((x) & 0x3) << 4)
++#define RCAR_CAN_BCR_TSEG2(x) ((x) & 0x07)
++
++/* Mailbox and Mask Registers bits */
++#define RCAR_CAN_IDE (1 << 31)
++#define RCAR_CAN_RTR (1 << 30)
++#define RCAR_CAN_SID_SHIFT 18
++
++/* Mailbox Interrupt Enable Register 1 bits */
++#define RCAR_CAN_MIER1_RXFIE (1 << 28) /* Receive FIFO Interrupt Enable */
++#define RCAR_CAN_MIER1_TXFIE (1 << 24) /* Transmit FIFO Interrupt Enable */
++
++/* Interrupt Enable Register bits */
++#define RCAR_CAN_IER_ERSIE (1 << 5) /* Error (ERS) Interrupt Enable Bit */
++#define RCAR_CAN_IER_RXFIE (1 << 4) /* Reception FIFO Interrupt */
++ /* Enable Bit */
++#define RCAR_CAN_IER_TXFIE (1 << 3) /* Transmission FIFO Interrupt */
++ /* Enable Bit */
++/* Interrupt Status Register bits */
++#define RCAR_CAN_ISR_ERSF (1 << 5) /* Error (ERS) Interrupt Status Bit */
++#define RCAR_CAN_ISR_RXFF (1 << 4) /* Reception FIFO Interrupt */
++ /* Status Bit */
++#define RCAR_CAN_ISR_TXFF (1 << 3) /* Transmission FIFO Interrupt */
++ /* Status Bit */
++
++/* Error Interrupt Enable Register bits */
++#define RCAR_CAN_EIER_BLIE (1 << 7) /* Bus Lock Interrupt Enable */
++#define RCAR_CAN_EIER_OLIE (1 << 6) /* Overload Frame Transmit */
++ /* Interrupt Enable */
++#define RCAR_CAN_EIER_ORIE (1 << 5) /* Receive Overrun Interrupt Enable */
++#define RCAR_CAN_EIER_BORIE (1 << 4) /* Bus-Off Recovery Interrupt Enable */
++#define RCAR_CAN_EIER_BOEIE (1 << 3) /* Bus-Off Entry Interrupt Enable */
++#define RCAR_CAN_EIER_EPIE (1 << 2) /* Error Passive Interrupt Enable */
++#define RCAR_CAN_EIER_EWIE (1 << 1) /* Error Warning Interrupt Enable */
++#define RCAR_CAN_EIER_BEIE (1 << 0) /* Bus Error Interrupt Enable */
++
++/* Error Interrupt Factor Judge Register bits */
++#define RCAR_CAN_EIFR_BLIF (1 << 7) /* Bus Lock Detect Flag */
++#define RCAR_CAN_EIFR_OLIF (1 << 6) /* Overload Frame Transmission */
++ /* Detect Flag */
++#define RCAR_CAN_EIFR_ORIF (1 << 5) /* Receive Overrun Detect Flag */
++#define RCAR_CAN_EIFR_BORIF (1 << 4) /* Bus-Off Recovery Detect Flag */
++#define RCAR_CAN_EIFR_BOEIF (1 << 3) /* Bus-Off Entry Detect Flag */
++#define RCAR_CAN_EIFR_EPIF (1 << 2) /* Error Passive Detect Flag */
++#define RCAR_CAN_EIFR_EWIF (1 << 1) /* Error Warning Detect Flag */
++#define RCAR_CAN_EIFR_BEIF (1 << 0) /* Bus Error Detect Flag */
++
++/* Error Code Store Register bits */
++#define RCAR_CAN_ECSR_EDPM (1 << 7) /* Error Display Mode Select Bit */
++#define RCAR_CAN_ECSR_ADEF (1 << 6) /* ACK Delimiter Error Flag */
++#define RCAR_CAN_ECSR_BE0F (1 << 5) /* Bit Error (dominant) Flag */
++#define RCAR_CAN_ECSR_BE1F (1 << 4) /* Bit Error (recessive) Flag */
++#define RCAR_CAN_ECSR_CEF (1 << 3) /* CRC Error Flag */
++#define RCAR_CAN_ECSR_AEF (1 << 2) /* ACK Error Flag */
++#define RCAR_CAN_ECSR_FEF (1 << 1) /* Form Error Flag */
++#define RCAR_CAN_ECSR_SEF (1 << 0) /* Stuff Error Flag */
++
++#define RCAR_CAN_NAPI_WEIGHT 4
++#define MAX_STR_READS 0x100
++
++static void tx_failure_cleanup(struct net_device *ndev)
++{
++ int i;
++
++ for (i = 0; i < RCAR_CAN_FIFO_DEPTH; i++)
++ can_free_echo_skb(ndev, i);
++}
++
++static void rcar_can_error(struct net_device *ndev)
++{
++ struct rcar_can_priv *priv = netdev_priv(ndev);
++ struct net_device_stats *stats = &ndev->stats;
++ struct can_frame *cf;
++ struct sk_buff *skb;
++ u8 eifr, txerr = 0, rxerr = 0;
++
++ /* Propagate the error condition to the CAN stack */
++ skb = alloc_can_err_skb(ndev, &cf);
++
++ eifr = readb(&priv->regs->eifr);
++ if (eifr & (RCAR_CAN_EIFR_EWIF | RCAR_CAN_EIFR_EPIF)) {
++ txerr = readb(&priv->regs->tecr);
++ rxerr = readb(&priv->regs->recr);
++ if (skb) {
++ cf->can_id |= CAN_ERR_CRTL;
++ cf->data[6] = txerr;
++ cf->data[7] = rxerr;
++ }
++ }
++ if (eifr & RCAR_CAN_EIFR_BEIF) {
++ int rx_errors = 0, tx_errors = 0;
++ u8 ecsr;
++
++ netdev_dbg(priv->ndev, "Bus error interrupt:\n");
++ if (skb) {
++ cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_PROT;
++ cf->data[2] = CAN_ERR_PROT_UNSPEC;
++ }
++ ecsr = readb(&priv->regs->ecsr);
++ if (ecsr & RCAR_CAN_ECSR_ADEF) {
++ netdev_dbg(priv->ndev, "ACK Delimiter Error\n");
++ tx_errors++;
++ writeb(~RCAR_CAN_ECSR_ADEF, &priv->regs->ecsr);
++ if (skb)
++ cf->data[3] |= CAN_ERR_PROT_LOC_ACK_DEL;
++ }
++ if (ecsr & RCAR_CAN_ECSR_BE0F) {
++ netdev_dbg(priv->ndev, "Bit Error (dominant)\n");
++ tx_errors++;
++ writeb(~RCAR_CAN_ECSR_BE0F, &priv->regs->ecsr);
++ if (skb)
++ cf->data[2] |= CAN_ERR_PROT_BIT0;
++ }
++ if (ecsr & RCAR_CAN_ECSR_BE1F) {
++ netdev_dbg(priv->ndev, "Bit Error (recessive)\n");
++ tx_errors++;
++ writeb(~RCAR_CAN_ECSR_BE1F, &priv->regs->ecsr);
++ if (skb)
++ cf->data[2] |= CAN_ERR_PROT_BIT1;
++ }
++ if (ecsr & RCAR_CAN_ECSR_CEF) {
++ netdev_dbg(priv->ndev, "CRC Error\n");
++ rx_errors++;
++ writeb(~RCAR_CAN_ECSR_CEF, &priv->regs->ecsr);
++ if (skb)
++ cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ;
++ }
++ if (ecsr & RCAR_CAN_ECSR_AEF) {
++ netdev_dbg(priv->ndev, "ACK Error\n");
++ tx_errors++;
++ writeb(~RCAR_CAN_ECSR_AEF, &priv->regs->ecsr);
++ if (skb) {
++ cf->can_id |= CAN_ERR_ACK;
++ cf->data[3] |= CAN_ERR_PROT_LOC_ACK;
++ }
++ }
++ if (ecsr & RCAR_CAN_ECSR_FEF) {
++ netdev_dbg(priv->ndev, "Form Error\n");
++ rx_errors++;
++ writeb(~RCAR_CAN_ECSR_FEF, &priv->regs->ecsr);
++ if (skb)
++ cf->data[2] |= CAN_ERR_PROT_FORM;
++ }
++ if (ecsr & RCAR_CAN_ECSR_SEF) {
++ netdev_dbg(priv->ndev, "Stuff Error\n");
++ rx_errors++;
++ writeb(~RCAR_CAN_ECSR_SEF, &priv->regs->ecsr);
++ if (skb)
++ cf->data[2] |= CAN_ERR_PROT_STUFF;
++ }
++
++ priv->can.can_stats.bus_error++;
++ ndev->stats.rx_errors += rx_errors;
++ ndev->stats.tx_errors += tx_errors;
++ writeb(~RCAR_CAN_EIFR_BEIF, &priv->regs->eifr);
++ }
++ if (eifr & RCAR_CAN_EIFR_EWIF) {
++ netdev_dbg(priv->ndev, "Error warning interrupt\n");
++ priv->can.state = CAN_STATE_ERROR_WARNING;
++ priv->can.can_stats.error_warning++;
++ /* Clear interrupt condition */
++ writeb(~RCAR_CAN_EIFR_EWIF, &priv->regs->eifr);
++ if (skb)
++ cf->data[1] = txerr > rxerr ? CAN_ERR_CRTL_TX_WARNING :
++ CAN_ERR_CRTL_RX_WARNING;
++ }
++ if (eifr & RCAR_CAN_EIFR_EPIF) {
++ netdev_dbg(priv->ndev, "Error passive interrupt\n");
++ priv->can.state = CAN_STATE_ERROR_PASSIVE;
++ priv->can.can_stats.error_passive++;
++ /* Clear interrupt condition */
++ writeb(~RCAR_CAN_EIFR_EPIF, &priv->regs->eifr);
++ if (skb)
++ cf->data[1] = txerr > rxerr ? CAN_ERR_CRTL_TX_PASSIVE :
++ CAN_ERR_CRTL_RX_PASSIVE;
++ }
++ if (eifr & RCAR_CAN_EIFR_BOEIF) {
++ netdev_dbg(priv->ndev, "Bus-off entry interrupt\n");
++ tx_failure_cleanup(ndev);
++ priv->ier = RCAR_CAN_IER_ERSIE;
++ writeb(priv->ier, &priv->regs->ier);
++ priv->can.state = CAN_STATE_BUS_OFF;
++ /* Clear interrupt condition */
++ writeb(~RCAR_CAN_EIFR_BOEIF, &priv->regs->eifr);
++ can_bus_off(ndev);
++ if (skb)
++ cf->can_id |= CAN_ERR_BUSOFF;
++ }
++ if (eifr & RCAR_CAN_EIFR_ORIF) {
++ netdev_dbg(priv->ndev, "Receive overrun error interrupt\n");
++ ndev->stats.rx_over_errors++;
++ ndev->stats.rx_errors++;
++ writeb(~RCAR_CAN_EIFR_ORIF, &priv->regs->eifr);
++ if (skb) {
++ cf->can_id |= CAN_ERR_CRTL;
++ cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
++ }
++ }
++ if (eifr & RCAR_CAN_EIFR_OLIF) {
++ netdev_dbg(priv->ndev,
++ "Overload Frame Transmission error interrupt\n");
++ ndev->stats.rx_over_errors++;
++ ndev->stats.rx_errors++;
++ writeb(~RCAR_CAN_EIFR_OLIF, &priv->regs->eifr);
++ if (skb) {
++ cf->can_id |= CAN_ERR_PROT;
++ cf->data[2] |= CAN_ERR_PROT_OVERLOAD;
++ }
++ }
++
++ if (skb) {
++ stats->rx_packets++;
++ stats->rx_bytes += cf->can_dlc;
++ netif_rx(skb);
++ }
++}
++
++static void rcar_can_tx_done(struct net_device *ndev)
++{
++ struct rcar_can_priv *priv = netdev_priv(ndev);
++ struct net_device_stats *stats = &ndev->stats;
++ u8 isr;
++
++ while (1) {
++ u8 unsent = readb(&priv->regs->tfcr);
++
++ unsent = (unsent & RCAR_CAN_TFCR_TFUST) >>
++ RCAR_CAN_TFCR_TFUST_SHIFT;
++ if (priv->tx_head - priv->tx_tail <= unsent)
++ break;
++ stats->tx_packets++;
++ stats->tx_bytes += priv->tx_dlc[priv->tx_tail %
++ RCAR_CAN_FIFO_DEPTH];
++ priv->tx_dlc[priv->tx_tail % RCAR_CAN_FIFO_DEPTH] = 0;
++ can_get_echo_skb(ndev, priv->tx_tail % RCAR_CAN_FIFO_DEPTH);
++ priv->tx_tail++;
++ netif_wake_queue(ndev);
++ }
++ /* Clear interrupt */
++ isr = readb(&priv->regs->isr);
++ writeb(isr & ~RCAR_CAN_ISR_TXFF, &priv->regs->isr);
++ can_led_event(ndev, CAN_LED_EVENT_TX);
++}
++
++static irqreturn_t rcar_can_interrupt(int irq, void *dev_id)
++{
++ struct net_device *ndev = dev_id;
++ struct rcar_can_priv *priv = netdev_priv(ndev);
++ u8 isr;
++
++ isr = readb(&priv->regs->isr);
++ if (!(isr & priv->ier))
++ return IRQ_NONE;
++
++ if (isr & RCAR_CAN_ISR_ERSF)
++ rcar_can_error(ndev);
++
++ if (isr & RCAR_CAN_ISR_TXFF)
++ rcar_can_tx_done(ndev);
++
++ if (isr & RCAR_CAN_ISR_RXFF) {
++ if (napi_schedule_prep(&priv->napi)) {
++ /* Disable Rx FIFO interrupts */
++ priv->ier &= ~RCAR_CAN_IER_RXFIE;
++ writeb(priv->ier, &priv->regs->ier);
++ __napi_schedule(&priv->napi);
++ }
++ }
++
++ return IRQ_HANDLED;
++}
++
++static void rcar_can_set_bittiming(struct net_device *dev)
++{
++ struct rcar_can_priv *priv = netdev_priv(dev);
++ struct can_bittiming *bt = &priv->can.bittiming;
++ u32 bcr;
++
++ bcr = RCAR_CAN_BCR_TSEG1(bt->phase_seg1 + bt->prop_seg - 1) |
++ RCAR_CAN_BCR_BPR(bt->brp - 1) | RCAR_CAN_BCR_SJW(bt->sjw - 1) |
++ RCAR_CAN_BCR_TSEG2(bt->phase_seg2 - 1);
++ /* Don't overwrite CLKR with 32-bit BCR access; CLKR has 8-bit access.
++ * All the registers are big-endian but they get byte-swapped on 32-bit
++ * read/write (but not on 8-bit, contrary to the manuals)...
++ */
++ writel((bcr << 8) | priv->clock_select, &priv->regs->bcr);
++}
++
++static void rcar_can_start(struct net_device *ndev)
++{
++ struct rcar_can_priv *priv = netdev_priv(ndev);
++ u16 ctlr;
++ int i;
++
++ /* Set controller to known mode:
++ * - FIFO mailbox mode
++ * - accept all messages
++ * - overrun mode
++ * CAN is in sleep mode after MCU hardware or software reset.
++ */
++ ctlr = readw(&priv->regs->ctlr);
++ ctlr &= ~RCAR_CAN_CTLR_SLPM;
++ writew(ctlr, &priv->regs->ctlr);
++ /* Go to reset mode */
++ ctlr |= RCAR_CAN_CTLR_CANM_FORCE_RESET;
++ writew(ctlr, &priv->regs->ctlr);
++ for (i = 0; i < MAX_STR_READS; i++) {
++ if (readw(&priv->regs->str) & RCAR_CAN_STR_RSTST)
++ break;
++ }
++ rcar_can_set_bittiming(ndev);
++ ctlr |= RCAR_CAN_CTLR_IDFM_MIXED; /* Select mixed ID mode */
++ ctlr |= RCAR_CAN_CTLR_BOM_ENT; /* Entry to halt mode automatically */
++ /* at bus-off */
++ ctlr |= RCAR_CAN_CTLR_MBM; /* Select FIFO mailbox mode */
++ ctlr |= RCAR_CAN_CTLR_MLM; /* Overrun mode */
++ writew(ctlr, &priv->regs->ctlr);
++
++ /* Accept all SID and EID */
++ writel(0, &priv->regs->mkr_2_9[6]);
++ writel(0, &priv->regs->mkr_2_9[7]);
++ /* In FIFO mailbox mode, write "0" to bits 24 to 31 */
++ writel(0, &priv->regs->mkivlr1);
++ /* Accept all frames */
++ writel(0, &priv->regs->fidcr[0]);
++ writel(RCAR_CAN_FIDCR_IDE | RCAR_CAN_FIDCR_RTR, &priv->regs->fidcr[1]);
++ /* Enable and configure FIFO mailbox interrupts */
++ writel(RCAR_CAN_MIER1_RXFIE | RCAR_CAN_MIER1_TXFIE, &priv->regs->mier1);
++
++ priv->ier = RCAR_CAN_IER_ERSIE | RCAR_CAN_IER_RXFIE |
++ RCAR_CAN_IER_TXFIE;
++ writeb(priv->ier, &priv->regs->ier);
++
++ /* Accumulate error codes */
++ writeb(RCAR_CAN_ECSR_EDPM, &priv->regs->ecsr);
++ /* Enable error interrupts */
++ writeb(RCAR_CAN_EIER_EWIE | RCAR_CAN_EIER_EPIE | RCAR_CAN_EIER_BOEIE |
++ (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING ?
++ RCAR_CAN_EIER_BEIE : 0) | RCAR_CAN_EIER_ORIE |
++ RCAR_CAN_EIER_OLIE, &priv->regs->eier);
++ priv->can.state = CAN_STATE_ERROR_ACTIVE;
++
++ /* Go to operation mode */
++ writew(ctlr & ~RCAR_CAN_CTLR_CANM, &priv->regs->ctlr);
++ for (i = 0; i < MAX_STR_READS; i++) {
++ if (!(readw(&priv->regs->str) & RCAR_CAN_STR_RSTST))
++ break;
++ }
++ /* Enable Rx and Tx FIFO */
++ writeb(RCAR_CAN_RFCR_RFE, &priv->regs->rfcr);
++ writeb(RCAR_CAN_TFCR_TFE, &priv->regs->tfcr);
++}
++
++static int rcar_can_open(struct net_device *ndev)
++{
++ struct rcar_can_priv *priv = netdev_priv(ndev);
++ int err;
++
++ err = clk_prepare_enable(priv->clk);
++ if (err) {
++ netdev_err(ndev, "clk_prepare_enable() failed, error %d\n",
++ err);
++ goto out;
++ }
++ err = open_candev(ndev);
++ if (err) {
++ netdev_err(ndev, "open_candev() failed, error %d\n", err);
++ goto out_clock;
++ }
++ napi_enable(&priv->napi);
++ err = request_irq(ndev->irq, rcar_can_interrupt, 0, ndev->name, ndev);
++ if (err) {
++ netdev_err(ndev, "error requesting interrupt %x\n", ndev->irq);
++ goto out_close;
++ }
++ can_led_event(ndev, CAN_LED_EVENT_OPEN);
++ rcar_can_start(ndev);
++ netif_start_queue(ndev);
++ return 0;
++out_close:
++ napi_disable(&priv->napi);
++ close_candev(ndev);
++out_clock:
++ clk_disable_unprepare(priv->clk);
++out:
++ return err;
++}
++
++static void rcar_can_stop(struct net_device *ndev)
++{
++ struct rcar_can_priv *priv = netdev_priv(ndev);
++ u16 ctlr;
++ int i;
++
++ /* Go to (force) reset mode */
++ ctlr = readw(&priv->regs->ctlr);
++ ctlr |= RCAR_CAN_CTLR_CANM_FORCE_RESET;
++ writew(ctlr, &priv->regs->ctlr);
++ for (i = 0; i < MAX_STR_READS; i++) {
++ if (readw(&priv->regs->str) & RCAR_CAN_STR_RSTST)
++ break;
++ }
++ writel(0, &priv->regs->mier0);
++ writel(0, &priv->regs->mier1);
++ writeb(0, &priv->regs->ier);
++ writeb(0, &priv->regs->eier);
++ /* Go to sleep mode */
++ ctlr |= RCAR_CAN_CTLR_SLPM;
++ writew(ctlr, &priv->regs->ctlr);
++ priv->can.state = CAN_STATE_STOPPED;
++}
++
++static int rcar_can_close(struct net_device *ndev)
++{
++ struct rcar_can_priv *priv = netdev_priv(ndev);
++
++ netif_stop_queue(ndev);
++ rcar_can_stop(ndev);
++ free_irq(ndev->irq, ndev);
++ napi_disable(&priv->napi);
++ clk_disable_unprepare(priv->clk);
++ close_candev(ndev);
++ can_led_event(ndev, CAN_LED_EVENT_STOP);
++ return 0;
++}
++
++static netdev_tx_t rcar_can_start_xmit(struct sk_buff *skb,
++ struct net_device *ndev)
++{
++ struct rcar_can_priv *priv = netdev_priv(ndev);
++ struct can_frame *cf = (struct can_frame *)skb->data;
++ u32 data, i;
++
++ if (can_dropped_invalid_skb(ndev, skb))
++ return NETDEV_TX_OK;
++
++ if (cf->can_id & CAN_EFF_FLAG) /* Extended frame format */
++ data = (cf->can_id & CAN_EFF_MASK) | RCAR_CAN_IDE;
++ else /* Standard frame format */
++ data = (cf->can_id & CAN_SFF_MASK) << RCAR_CAN_SID_SHIFT;
++
++ if (cf->can_id & CAN_RTR_FLAG) { /* Remote transmission request */
++ data |= RCAR_CAN_RTR;
++ } else {
++ for (i = 0; i < cf->can_dlc; i++)
++ writeb(cf->data[i],
++ &priv->regs->mb[RCAR_CAN_TX_FIFO_MBX].data[i]);
++ }
++
++ writel(data, &priv->regs->mb[RCAR_CAN_TX_FIFO_MBX].id);
++
++ writeb(cf->can_dlc, &priv->regs->mb[RCAR_CAN_TX_FIFO_MBX].dlc);
++
++ priv->tx_dlc[priv->tx_head % RCAR_CAN_FIFO_DEPTH] = cf->can_dlc;
++ can_put_echo_skb(skb, ndev, priv->tx_head % RCAR_CAN_FIFO_DEPTH);
++ priv->tx_head++;
++ /* Start Tx: write 0xff to the TFPCR register to increment
++ * the CPU-side pointer for the transmit FIFO to the next
++ * mailbox location
++ */
++ writeb(0xff, &priv->regs->tfpcr);
++ /* Stop the queue if we've filled all FIFO entries */
++ if (priv->tx_head - priv->tx_tail >= RCAR_CAN_FIFO_DEPTH)
++ netif_stop_queue(ndev);
++
++ return NETDEV_TX_OK;
++}
++
++static const struct net_device_ops rcar_can_netdev_ops = {
++ .ndo_open = rcar_can_open,
++ .ndo_stop = rcar_can_close,
++ .ndo_start_xmit = rcar_can_start_xmit,
++};
++
++static void rcar_can_rx_pkt(struct rcar_can_priv *priv)
++{
++ struct net_device_stats *stats = &priv->ndev->stats;
++ struct can_frame *cf;
++ struct sk_buff *skb;
++ u32 data;
++ u8 dlc;
++
++ skb = alloc_can_skb(priv->ndev, &cf);
++ if (!skb) {
++ stats->rx_dropped++;
++ return;
++ }
++
++ data = readl(&priv->regs->mb[RCAR_CAN_RX_FIFO_MBX].id);
++ if (data & RCAR_CAN_IDE)
++ cf->can_id = (data & CAN_EFF_MASK) | CAN_EFF_FLAG;
++ else
++ cf->can_id = (data >> RCAR_CAN_SID_SHIFT) & CAN_SFF_MASK;
++
++ dlc = readb(&priv->regs->mb[RCAR_CAN_RX_FIFO_MBX].dlc);
++ cf->can_dlc = get_can_dlc(dlc);
++ if (data & RCAR_CAN_RTR) {
++ cf->can_id |= CAN_RTR_FLAG;
++ } else {
++ for (dlc = 0; dlc < cf->can_dlc; dlc++)
++ cf->data[dlc] =
++ readb(&priv->regs->mb[RCAR_CAN_RX_FIFO_MBX].data[dlc]);
++ }
++
++ can_led_event(priv->ndev, CAN_LED_EVENT_RX);
++
++ stats->rx_bytes += cf->can_dlc;
++ stats->rx_packets++;
++ netif_receive_skb(skb);
++}
++
++static int rcar_can_rx_poll(struct napi_struct *napi, int quota)
++{
++ struct rcar_can_priv *priv = container_of(napi,
++ struct rcar_can_priv, napi);
++ int num_pkts;
++
++ for (num_pkts = 0; num_pkts < quota; num_pkts++) {
++ u8 rfcr, isr;
++
++ isr = readb(&priv->regs->isr);
++ /* Clear interrupt bit */
++ if (isr & RCAR_CAN_ISR_RXFF)
++ writeb(isr & ~RCAR_CAN_ISR_RXFF, &priv->regs->isr);
++ rfcr = readb(&priv->regs->rfcr);
++ if (rfcr & RCAR_CAN_RFCR_RFEST)
++ break;
++ rcar_can_rx_pkt(priv);
++ /* Write 0xff to the RFPCR register to increment
++ * the CPU-side pointer for the receive FIFO
++ * to the next mailbox location
++ */
++ writeb(0xff, &priv->regs->rfpcr);
++ }
++ /* All packets processed */
++ if (num_pkts < quota) {
++ napi_complete(napi);
++ priv->ier |= RCAR_CAN_IER_RXFIE;
++ writeb(priv->ier, &priv->regs->ier);
++ }
++ return num_pkts;
++}
++
++static int rcar_can_do_set_mode(struct net_device *ndev, enum can_mode mode)
++{
++ switch (mode) {
++ case CAN_MODE_START:
++ rcar_can_start(ndev);
++ netif_wake_queue(ndev);
++ return 0;
++ default:
++ return -EOPNOTSUPP;
++ }
++}
++
++static int rcar_can_get_berr_counter(const struct net_device *dev,
++ struct can_berr_counter *bec)
++{
++ struct rcar_can_priv *priv = netdev_priv(dev);
++ int err;
++
++ err = clk_prepare_enable(priv->clk);
++ if (err)
++ return err;
++ bec->txerr = readb(&priv->regs->tecr);
++ bec->rxerr = readb(&priv->regs->recr);
++ clk_disable_unprepare(priv->clk);
++ return 0;
++}
++
++static int rcar_can_probe(struct platform_device *pdev)
++{
++ struct rcar_can_platform_data *pdata;
++ struct rcar_can_priv *priv;
++ struct net_device *ndev;
++ struct resource *mem;
++ void __iomem *addr;
++ int err = -ENODEV;
++ int irq;
++
++ pdata = dev_get_platdata(&pdev->dev);
++ if (!pdata) {
++ dev_err(&pdev->dev, "No platform data provided!\n");
++ goto fail;
++ }
++
++ irq = platform_get_irq(pdev, 0);
++ if (!irq) {
++ dev_err(&pdev->dev, "No IRQ resource\n");
++ goto fail;
++ }
++
++ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ addr = devm_ioremap_resource(&pdev->dev, mem);
++ if (IS_ERR(addr)) {
++ err = PTR_ERR(addr);
++ goto fail;
++ }
++
++ ndev = alloc_candev(sizeof(struct rcar_can_priv), RCAR_CAN_FIFO_DEPTH);
++ if (!ndev) {
++ dev_err(&pdev->dev, "alloc_candev() failed\n");
++ err = -ENOMEM;
++ goto fail;
++ }
++
++ priv = netdev_priv(ndev);
++
++ priv->clk = devm_clk_get(&pdev->dev, NULL);
++ if (IS_ERR(priv->clk)) {
++ err = PTR_ERR(priv->clk);
++ dev_err(&pdev->dev, "cannot get clock: %d\n", err);
++ goto fail_clk;
++ }
++
++ ndev->netdev_ops = &rcar_can_netdev_ops;
++ ndev->irq = irq;
++ ndev->flags |= IFF_ECHO;
++ priv->ndev = ndev;
++ priv->regs = addr;
++ priv->clock_select = pdata->clock_select;
++ priv->can.clock.freq = clk_get_rate(priv->clk);
++ priv->can.bittiming_const = &rcar_can_bittiming_const;
++ priv->can.do_set_mode = rcar_can_do_set_mode;
++ priv->can.do_get_berr_counter = rcar_can_get_berr_counter;
++ priv->can.ctrlmode_supported = CAN_CTRLMODE_BERR_REPORTING;
++ platform_set_drvdata(pdev, ndev);
++ SET_NETDEV_DEV(ndev, &pdev->dev);
++
++ netif_napi_add(ndev, &priv->napi, rcar_can_rx_poll,
++ RCAR_CAN_NAPI_WEIGHT);
++ err = register_candev(ndev);
++ if (err) {
++ dev_err(&pdev->dev, "register_candev() failed, error %d\n",
++ err);
++ goto fail_candev;
++ }
++
++ devm_can_led_init(ndev);
++
++ dev_info(&pdev->dev, "device registered (reg_base=%p, irq=%u)\n",
++ priv->regs, ndev->irq);
++
++ return 0;
++fail_candev:
++ netif_napi_del(&priv->napi);
++fail_clk:
++ free_candev(ndev);
++fail:
++ return err;
++}
++
++static int rcar_can_remove(struct platform_device *pdev)
++{
++ struct net_device *ndev = platform_get_drvdata(pdev);
++ struct rcar_can_priv *priv = netdev_priv(ndev);
++
++ unregister_candev(ndev);
++ netif_napi_del(&priv->napi);
++ free_candev(ndev);
++ return 0;
++}
++
++static int __maybe_unused rcar_can_suspend(struct device *dev)
++{
++ struct net_device *ndev = dev_get_drvdata(dev);
++ struct rcar_can_priv *priv = netdev_priv(ndev);
++ u16 ctlr;
++
++ if (netif_running(ndev)) {
++ netif_stop_queue(ndev);
++ netif_device_detach(ndev);
++ }
++ ctlr = readw(&priv->regs->ctlr);
++ ctlr |= RCAR_CAN_CTLR_CANM_HALT;
++ writew(ctlr, &priv->regs->ctlr);
++ ctlr |= RCAR_CAN_CTLR_SLPM;
++ writew(ctlr, &priv->regs->ctlr);
++ priv->can.state = CAN_STATE_SLEEPING;
++
++ clk_disable(priv->clk);
++ return 0;
++}
++
++static int __maybe_unused rcar_can_resume(struct device *dev)
++{
++ struct net_device *ndev = dev_get_drvdata(dev);
++ struct rcar_can_priv *priv = netdev_priv(ndev);
++ u16 ctlr;
++ int err;
++
++ err = clk_enable(priv->clk);
++ if (err) {
++ netdev_err(ndev, "clk_enable() failed, error %d\n", err);
++ return err;
++ }
++
++ ctlr = readw(&priv->regs->ctlr);
++ ctlr &= ~RCAR_CAN_CTLR_SLPM;
++ writew(ctlr, &priv->regs->ctlr);
++ ctlr &= ~RCAR_CAN_CTLR_CANM;
++ writew(ctlr, &priv->regs->ctlr);
++ priv->can.state = CAN_STATE_ERROR_ACTIVE;
++
++ if (netif_running(ndev)) {
++ netif_device_attach(ndev);
++ netif_start_queue(ndev);
++ }
++ return 0;
++}
++
++static SIMPLE_DEV_PM_OPS(rcar_can_pm_ops, rcar_can_suspend, rcar_can_resume);
++
++static struct platform_driver rcar_can_driver = {
++ .driver = {
++ .name = RCAR_CAN_DRV_NAME,
++ .owner = THIS_MODULE,
++ .pm = &rcar_can_pm_ops,
++ },
++ .probe = rcar_can_probe,
++ .remove = rcar_can_remove,
++};
++
++module_platform_driver(rcar_can_driver);
++
++MODULE_AUTHOR("Cogent Embedded, Inc.");
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("CAN driver for Renesas R-Car SoC");
++MODULE_ALIAS("platform:" RCAR_CAN_DRV_NAME);
+diff --git a/include/linux/can/platform/rcar_can.h b/include/linux/can/platform/rcar_can.h
+new file mode 100644
+index 0000000..0f4a2f3
+--- /dev/null
++++ b/include/linux/can/platform/rcar_can.h
+@@ -0,0 +1,17 @@
++#ifndef _CAN_PLATFORM_RCAR_CAN_H_
++#define _CAN_PLATFORM_RCAR_CAN_H_
++
++#include <linux/types.h>
++
++/* Clock Select Register settings */
++enum CLKR {
++ CLKR_CLKP1 = 0, /* Peripheral clock (clkp1) */
++ CLKR_CLKP2 = 1, /* Peripheral clock (clkp2) */
++ CLKR_CLKEXT = 3 /* Externally input clock */
++};
++
++struct rcar_can_platform_data {
++ enum CLKR clock_select; /* Clock source select */
++};
++
++#endif /* !_CAN_PLATFORM_RCAR_CAN_H_ */
+--
+1.9.1
+
diff --git a/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0013-sh-pfc-r8a7791-add-CAN-pin-groups.patch b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0013-sh-pfc-r8a7791-add-CAN-pin-groups.patch
new file mode 100644
index 0000000..23e74c7
--- /dev/null
+++ b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0013-sh-pfc-r8a7791-add-CAN-pin-groups.patch
@@ -0,0 +1,216 @@
+From 0e9386752758b74fd42fda7cbdd6ccb5cb31033c Mon Sep 17 00:00:00 2001
+From: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
+Date: Wed, 2 Jul 2014 00:58:16 +0400
+Subject: [PATCH] sh-pfc: r8a7791: add CAN pin groups
+
+Add CAN0/1 data/clock pin groups to R8A7791 PFC driver.
+
+Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
+Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+---
+ drivers/pinctrl/sh-pfc/pfc-r8a7791.c | 167 +++++++++++++++++++++++++++++++++++
+ 1 file changed, 167 insertions(+)
+
+diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c
+index 394b234..576d41b 100644
+--- a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c
++++ b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c
+@@ -1726,6 +1726,133 @@ static const unsigned int audio_clkout_mux[] = {
+ AUDIO_CLKOUT_MARK,
+ };
+
++/* - CAN -------------------------------------------------------------------- */
++
++static const unsigned int can0_data_pins[] = {
++ /* TX, RX */
++ RCAR_GP_PIN(3, 26), RCAR_GP_PIN(3, 29),
++};
++
++static const unsigned int can0_data_mux[] = {
++ CAN0_TX_MARK, CAN0_RX_MARK,
++};
++
++static const unsigned int can0_data_b_pins[] = {
++ /* TX, RX */
++ RCAR_GP_PIN(7, 4), RCAR_GP_PIN(7, 3),
++};
++
++static const unsigned int can0_data_b_mux[] = {
++ CAN0_TX_B_MARK, CAN0_RX_B_MARK,
++};
++
++static const unsigned int can0_data_c_pins[] = {
++ /* TX, RX */
++ RCAR_GP_PIN(5, 17), RCAR_GP_PIN(5, 18),
++};
++
++static const unsigned int can0_data_c_mux[] = {
++ CAN0_TX_C_MARK, CAN0_RX_C_MARK,
++};
++
++static const unsigned int can0_data_d_pins[] = {
++ /* TX, RX */
++ RCAR_GP_PIN(2, 26), RCAR_GP_PIN(2, 27),
++};
++
++static const unsigned int can0_data_d_mux[] = {
++ CAN0_TX_D_MARK, CAN0_RX_D_MARK,
++};
++
++static const unsigned int can0_data_e_pins[] = {
++ /* TX, RX */
++ RCAR_GP_PIN(4, 18), RCAR_GP_PIN(4, 28),
++};
++
++static const unsigned int can0_data_e_mux[] = {
++ CAN0_TX_E_MARK, CAN0_RX_E_MARK,
++};
++
++static const unsigned int can0_data_f_pins[] = {
++ /* TX, RX */
++ RCAR_GP_PIN(6, 7), RCAR_GP_PIN(6, 6),
++};
++
++static const unsigned int can0_data_f_mux[] = {
++ CAN0_TX_F_MARK, CAN0_RX_F_MARK,
++};
++
++static const unsigned int can1_data_pins[] = {
++ /* TX, RX */
++ RCAR_GP_PIN(3, 21), RCAR_GP_PIN(3, 20),
++};
++
++static const unsigned int can1_data_mux[] = {
++ CAN1_TX_MARK, CAN1_RX_MARK,
++};
++
++static const unsigned int can1_data_b_pins[] = {
++ /* TX, RX */
++ RCAR_GP_PIN(7, 8), RCAR_GP_PIN(7, 9),
++};
++
++static const unsigned int can1_data_b_mux[] = {
++ CAN1_TX_B_MARK, CAN1_RX_B_MARK,
++};
++
++static const unsigned int can1_data_c_pins[] = {
++ /* TX, RX */
++ RCAR_GP_PIN(5, 20), RCAR_GP_PIN(5, 19),
++};
++
++static const unsigned int can1_data_c_mux[] = {
++ CAN1_TX_C_MARK, CAN1_RX_C_MARK,
++};
++
++static const unsigned int can1_data_d_pins[] = {
++ /* TX, RX */
++ RCAR_GP_PIN(4, 29), RCAR_GP_PIN(4, 31),
++};
++
++static const unsigned int can1_data_d_mux[] = {
++ CAN1_TX_D_MARK, CAN1_RX_D_MARK,
++};
++
++static const unsigned int can_clk_pins[] = {
++ /* CLK */
++ RCAR_GP_PIN(7, 2),
++};
++
++static const unsigned int can_clk_mux[] = {
++ CAN_CLK_MARK,
++};
++
++static const unsigned int can_clk_b_pins[] = {
++ /* CLK */
++ RCAR_GP_PIN(5, 21),
++};
++
++static const unsigned int can_clk_b_mux[] = {
++ CAN_CLK_B_MARK,
++};
++
++static const unsigned int can_clk_c_pins[] = {
++ /* CLK */
++ RCAR_GP_PIN(4, 30),
++};
++
++static const unsigned int can_clk_c_mux[] = {
++ CAN_CLK_C_MARK,
++};
++
++static const unsigned int can_clk_d_pins[] = {
++ /* CLK */
++ RCAR_GP_PIN(7, 19),
++};
++
++static const unsigned int can_clk_d_mux[] = {
++ CAN_CLK_D_MARK,
++};
+
+ /* - DU --------------------------------------------------------------------- */
+ static const unsigned int du_rgb666_pins[] = {
+@@ -4055,6 +4182,20 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
+ SH_PFC_PIN_GROUP(audio_clk_b_b),
+ SH_PFC_PIN_GROUP(audio_clk_c),
+ SH_PFC_PIN_GROUP(audio_clkout),
++ SH_PFC_PIN_GROUP(can0_data),
++ SH_PFC_PIN_GROUP(can0_data_b),
++ SH_PFC_PIN_GROUP(can0_data_c),
++ SH_PFC_PIN_GROUP(can0_data_d),
++ SH_PFC_PIN_GROUP(can0_data_e),
++ SH_PFC_PIN_GROUP(can0_data_f),
++ SH_PFC_PIN_GROUP(can1_data),
++ SH_PFC_PIN_GROUP(can1_data_b),
++ SH_PFC_PIN_GROUP(can1_data_c),
++ SH_PFC_PIN_GROUP(can1_data_d),
++ SH_PFC_PIN_GROUP(can_clk),
++ SH_PFC_PIN_GROUP(can_clk_b),
++ SH_PFC_PIN_GROUP(can_clk_c),
++ SH_PFC_PIN_GROUP(can_clk_d),
+ SH_PFC_PIN_GROUP(du_rgb666),
+ SH_PFC_PIN_GROUP(du_rgb888),
+ SH_PFC_PIN_GROUP(du_clk_out_0),
+@@ -4367,6 +4508,30 @@ static const char * const audio_clk_groups[] = {
+ "audio_clkout",
+ };
+
++static const char * const can0_groups[] = {
++ "can0_data_a",
++ "can0_data_b",
++ "can0_data_c",
++ "can0_data_d",
++ "can0_data_e",
++ "can0_data_f",
++ "can_clk_a",
++ "can_clk_b",
++ "can_clk_c",
++ "can_clk_d",
++};
++
++static const char * const can1_groups[] = {
++ "can1_data_a",
++ "can1_data_b",
++ "can1_data_c",
++ "can1_data_d",
++ "can_clk_a",
++ "can_clk_b",
++ "can_clk_c",
++ "can_clk_d",
++};
++
+ static const char * const du_groups[] = {
+ "du_rgb666",
+ "du_rgb888",
+@@ -4790,6 +4955,8 @@ static const char * const vin2_groups[] = {
+
+ static const struct sh_pfc_function pinmux_functions[] = {
+ SH_PFC_FUNCTION(audio_clk),
++ SH_PFC_FUNCTION(can0),
++ SH_PFC_FUNCTION(can1),
+ SH_PFC_FUNCTION(du),
+ SH_PFC_FUNCTION(du0),
+ SH_PFC_FUNCTION(du1),
+--
+1.9.1
+
diff --git a/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0014-sh-pfc-r8a7791-fix-CAN-pin-groups.patch b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0014-sh-pfc-r8a7791-fix-CAN-pin-groups.patch
new file mode 100644
index 0000000..65b0fcd
--- /dev/null
+++ b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0014-sh-pfc-r8a7791-fix-CAN-pin-groups.patch
@@ -0,0 +1,52 @@
+From 302fb1781783ded370f515e8e649b8285ee29cdc Mon Sep 17 00:00:00 2001
+From: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
+Date: Tue, 29 Jul 2014 02:12:55 +0400
+Subject: [PATCH] sh-pfc: r8a7791: fix CAN pin groups
+
+I had made last-minute changes before submitting the patch "sh-pfc: r8a7791:
+add CAN pin groups"; now I'm seeing that they weren't complete: I had missed
+update to the pin group names in pin[01]_groups[]. Drop the "_a" suffixes there.
+
+Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
+Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+---
+ drivers/pinctrl/sh-pfc/pfc-r8a7791.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c
+index 576d41b..c6e5deb 100644
+--- a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c
++++ b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c
+@@ -4509,24 +4509,24 @@ static const char * const audio_clk_groups[] = {
+ };
+
+ static const char * const can0_groups[] = {
+- "can0_data_a",
++ "can0_data",
+ "can0_data_b",
+ "can0_data_c",
+ "can0_data_d",
+ "can0_data_e",
+ "can0_data_f",
+- "can_clk_a",
++ "can_clk",
+ "can_clk_b",
+ "can_clk_c",
+ "can_clk_d",
+ };
+
+ static const char * const can1_groups[] = {
+- "can1_data_a",
++ "can1_data",
+ "can1_data_b",
+ "can1_data_c",
+ "can1_data_d",
+- "can_clk_a",
++ "can_clk",
+ "can_clk_b",
+ "can_clk_c",
+ "can_clk_d",
+--
+1.9.1
+
diff --git a/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0015-can-rcar_can-support-all-input-clocks.patch b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0015-can-rcar_can-support-all-input-clocks.patch
new file mode 100644
index 0000000..65f33af
--- /dev/null
+++ b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0015-can-rcar_can-support-all-input-clocks.patch
@@ -0,0 +1,139 @@
+From 862e2b6af9413b43ef044979b934cab07bfd33e5 Mon Sep 17 00:00:00 2001
+From: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
+Date: Fri, 1 Aug 2014 01:23:32 +0400
+Subject: [PATCH] can: rcar_can: support all input clocks
+
+When writing the driver, I didn't give enough attention to the possible sources
+of the CAN clock: although the value of the CLKR register was specified by the
+platform data, the driver only handled one case, that is CAN clock being
+sourced from the clkp1 clock, the same that clocks the whole CAN module. In
+order to fix that overlook, we'll have to handle the CAN clock separately from
+the peripheral clock (however, clkp1 will be specified for a CAN device only
+once)...
+
+Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+---
+ drivers/net/can/rcar_can.c | 42 ++++++++++++++++++++++++++++++++++++------
+ 1 file changed, 36 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/net/can/rcar_can.c b/drivers/net/can/rcar_can.c
+index 5268d21..c02fcf3 100644
+--- a/drivers/net/can/rcar_can.c
++++ b/drivers/net/can/rcar_can.c
+@@ -87,6 +87,7 @@ struct rcar_can_priv {
+ struct napi_struct napi;
+ struct rcar_can_regs __iomem *regs;
+ struct clk *clk;
++ struct clk *can_clk;
+ u8 tx_dlc[RCAR_CAN_FIFO_DEPTH];
+ u32 tx_head;
+ u32 tx_tail;
+@@ -505,14 +506,20 @@ static int rcar_can_open(struct net_device *ndev)
+
+ err = clk_prepare_enable(priv->clk);
+ if (err) {
+- netdev_err(ndev, "clk_prepare_enable() failed, error %d\n",
++ netdev_err(ndev, "failed to enable periperal clock, error %d\n",
+ err);
+ goto out;
+ }
++ err = clk_prepare_enable(priv->can_clk);
++ if (err) {
++ netdev_err(ndev, "failed to enable CAN clock, error %d\n",
++ err);
++ goto out_clock;
++ }
+ err = open_candev(ndev);
+ if (err) {
+ netdev_err(ndev, "open_candev() failed, error %d\n", err);
+- goto out_clock;
++ goto out_can_clock;
+ }
+ napi_enable(&priv->napi);
+ err = request_irq(ndev->irq, rcar_can_interrupt, 0, ndev->name, ndev);
+@@ -527,6 +534,8 @@ static int rcar_can_open(struct net_device *ndev)
+ out_close:
+ napi_disable(&priv->napi);
+ close_candev(ndev);
++out_can_clock:
++ clk_disable_unprepare(priv->can_clk);
+ out_clock:
+ clk_disable_unprepare(priv->clk);
+ out:
+@@ -565,6 +574,7 @@ static int rcar_can_close(struct net_device *ndev)
+ rcar_can_stop(ndev);
+ free_irq(ndev->irq, ndev);
+ napi_disable(&priv->napi);
++ clk_disable_unprepare(priv->can_clk);
+ clk_disable_unprepare(priv->clk);
+ close_candev(ndev);
+ can_led_event(ndev, CAN_LED_EVENT_STOP);
+@@ -715,6 +725,12 @@ static int rcar_can_get_berr_counter(const struct net_device *dev,
+ return 0;
+ }
+
++static const char * const clock_names[] = {
++ [CLKR_CLKP1] = "clkp1",
++ [CLKR_CLKP2] = "clkp2",
++ [CLKR_CLKEXT] = "can_clk",
++};
++
+ static int rcar_can_probe(struct platform_device *pdev)
+ {
+ struct rcar_can_platform_data *pdata;
+@@ -722,6 +738,7 @@ static int rcar_can_probe(struct platform_device *pdev)
+ struct net_device *ndev;
+ struct resource *mem;
+ void __iomem *addr;
++ u32 clock_select;
+ int err = -ENODEV;
+ int irq;
+
+@@ -730,6 +747,7 @@ static int rcar_can_probe(struct platform_device *pdev)
+ dev_err(&pdev->dev, "No platform data provided!\n");
+ goto fail;
+ }
++ clock_select = pdata->clock_select;
+
+ irq = platform_get_irq(pdev, 0);
+ if (!irq) {
+@@ -753,10 +771,22 @@ static int rcar_can_probe(struct platform_device *pdev)
+
+ priv = netdev_priv(ndev);
+
+- priv->clk = devm_clk_get(&pdev->dev, NULL);
++ priv->clk = devm_clk_get(&pdev->dev, "clkp1");
+ if (IS_ERR(priv->clk)) {
+ err = PTR_ERR(priv->clk);
+- dev_err(&pdev->dev, "cannot get clock: %d\n", err);
++ dev_err(&pdev->dev, "cannot get peripheral clock: %d\n", err);
++ goto fail_clk;
++ }
++
++ if (clock_select >= ARRAY_SIZE(clock_names)) {
++ err = -EINVAL;
++ dev_err(&pdev->dev, "invalid CAN clock selected\n");
++ goto fail_clk;
++ }
++ priv->can_clk = devm_clk_get(&pdev->dev, clock_names[clock_select]);
++ if (IS_ERR(priv->can_clk)) {
++ err = PTR_ERR(priv->can_clk);
++ dev_err(&pdev->dev, "cannot get CAN clock: %d\n", err);
+ goto fail_clk;
+ }
+
+@@ -765,8 +795,8 @@ static int rcar_can_probe(struct platform_device *pdev)
+ ndev->flags |= IFF_ECHO;
+ priv->ndev = ndev;
+ priv->regs = addr;
+- priv->clock_select = pdata->clock_select;
+- priv->can.clock.freq = clk_get_rate(priv->clk);
++ priv->clock_select = clock_select;
++ priv->can.clock.freq = clk_get_rate(priv->can_clk);
+ priv->can.bittiming_const = &rcar_can_bittiming_const;
+ priv->can.do_set_mode = rcar_can_do_set_mode;
+ priv->can.do_get_berr_counter = rcar_can_get_berr_counter;
+--
+1.9.1
+
diff --git a/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0016-can-rcar_can-document-device-tree-bindings.patch b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0016-can-rcar_can-document-device-tree-bindings.patch
new file mode 100644
index 0000000..df8137f
--- /dev/null
+++ b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0016-can-rcar_can-document-device-tree-bindings.patch
@@ -0,0 +1,66 @@
+From 632e25ca722e5361a1b40d89e77808f8f1c6799f Mon Sep 17 00:00:00 2001
+From: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
+Date: Fri, 1 Aug 2014 01:24:25 +0400
+Subject: [PATCH] can: rcar_can: document device tree bindings
+
+Document the R-Car CAN device tree bindings.
+
+Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+---
+ .../devicetree/bindings/net/can/rcar_can.txt | 43 ++++++++++++++++++++++
+ 1 file changed, 43 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/net/can/rcar_can.txt
+
+diff --git a/Documentation/devicetree/bindings/net/can/rcar_can.txt b/Documentation/devicetree/bindings/net/can/rcar_can.txt
+new file mode 100644
+index 0000000..002d844
+--- /dev/null
++++ b/Documentation/devicetree/bindings/net/can/rcar_can.txt
+@@ -0,0 +1,43 @@
++Renesas R-Car CAN controller Device Tree Bindings
++-------------------------------------------------
++
++Required properties:
++- compatible: "renesas,can-r8a7778" if CAN controller is a part of R8A7778 SoC.
++ "renesas,can-r8a7779" if CAN controller is a part of R8A7779 SoC.
++ "renesas,can-r8a7790" if CAN controller is a part of R8A7790 SoC.
++ "renesas,can-r8a7791" if CAN controller is a part of R8A7791 SoC.
++- reg: physical base address and size of the R-Car CAN register map.
++- interrupts: interrupt specifier for the sole interrupt.
++- clocks: phandles and clock specifiers for 3 CAN clock inputs.
++- clock-names: 3 clock input name strings: "clkp1", "clkp2", "can_clk".
++- pinctrl-0: pin control group to be used for this controller.
++- pinctrl-names: must be "default".
++
++Optional properties:
++- renesas,can-clock-select: R-Car CAN Clock Source Select. Valid values are:
++ <0x0> (default) : Peripheral clock (clkp1)
++ <0x1> : Peripheral clock (clkp2)
++ <0x3> : Externally input clock
++
++Example
++-------
++
++SoC common .dtsi file:
++
++ can0: can@e6e80000 {
++ compatible = "renesas,can-r8a7791";
++ reg = <0 0xe6e80000 0 0x1000>;
++ interrupts = <0 186 IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&mstp9_clks R8A7791_CLK_RCAN0>,
++ <&cpg_clocks R8A7791_CLK_RCAN>, <&can_clk>;
++ clock-names = "clkp1", "clkp2", "can_clk";
++ status = "disabled";
++ };
++
++Board specific .dts file:
++
++&can0 {
++ pinctrl-0 = <&can0_pins>;
++ pinctrl-names = "default";
++ status = "okay";
++};
+--
+1.9.1
+
diff --git a/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0017-can-rcar_can-add-device-tree-support.patch b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0017-can-rcar_can-add-device-tree-support.patch
new file mode 100644
index 0000000..716bdbc
--- /dev/null
+++ b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0017-can-rcar_can-add-device-tree-support.patch
@@ -0,0 +1,77 @@
+From a268de6c68e4933234e9ac62f2ab7ff8264ce0b4 Mon Sep 17 00:00:00 2001
+From: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
+Date: Fri, 1 Aug 2014 01:25:53 +0400
+Subject: [PATCH] can: rcar_can: add device tree support
+
+Add support of the device tree probing for the Renesas R-Car CAN controllers.
+
+Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+---
+ drivers/net/can/rcar_can.c | 28 ++++++++++++++++++++++------
+ 1 file changed, 22 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/net/can/rcar_can.c b/drivers/net/can/rcar_can.c
+index c02fcf3..1abe133 100644
+--- a/drivers/net/can/rcar_can.c
++++ b/drivers/net/can/rcar_can.c
+@@ -20,6 +20,7 @@
+ #include <linux/can/dev.h>
+ #include <linux/clk.h>
+ #include <linux/can/platform/rcar_can.h>
++#include <linux/of.h>
+
+ #define RCAR_CAN_DRV_NAME "rcar_can"
+
+@@ -738,16 +739,21 @@ static int rcar_can_probe(struct platform_device *pdev)
+ struct net_device *ndev;
+ struct resource *mem;
+ void __iomem *addr;
+- u32 clock_select;
++ u32 clock_select = CLKR_CLKP1;
+ int err = -ENODEV;
+ int irq;
+
+- pdata = dev_get_platdata(&pdev->dev);
+- if (!pdata) {
+- dev_err(&pdev->dev, "No platform data provided!\n");
+- goto fail;
++ if (pdev->dev.of_node) {
++ of_property_read_u32(pdev->dev.of_node,
++ "renesas,can-clock-select", &clock_select);
++ } else {
++ pdata = dev_get_platdata(&pdev->dev);
++ if (!pdata) {
++ dev_err(&pdev->dev, "No platform data provided!\n");
++ goto fail;
++ }
++ clock_select = pdata->clock_select;
+ }
+- clock_select = pdata->clock_select;
+
+ irq = platform_get_irq(pdev, 0);
+ if (!irq) {
+@@ -888,10 +894,20 @@ static int __maybe_unused rcar_can_resume(struct device *dev)
+
+ static SIMPLE_DEV_PM_OPS(rcar_can_pm_ops, rcar_can_suspend, rcar_can_resume);
+
++static const struct of_device_id rcar_can_of_table[] __maybe_unused = {
++ { .compatible = "renesas,can-r8a7778" },
++ { .compatible = "renesas,can-r8a7779" },
++ { .compatible = "renesas,can-r8a7790" },
++ { .compatible = "renesas,can-r8a7791" },
++ { }
++};
++MODULE_DEVICE_TABLE(of, rcar_can_of_table);
++
+ static struct platform_driver rcar_can_driver = {
+ .driver = {
+ .name = RCAR_CAN_DRV_NAME,
+ .owner = THIS_MODULE,
++ .of_match_table = of_match_ptr(rcar_can_of_table),
+ .pm = &rcar_can_pm_ops,
+ },
+ .probe = rcar_can_probe,
+--
+1.9.1
+
diff --git a/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0018-porter-can-support.patch b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0018-porter-can-support.patch
new file mode 100644
index 0000000..e56bda3
--- /dev/null
+++ b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0018-porter-can-support.patch
@@ -0,0 +1,63 @@
+From b73784d861cfff9651936b3d101b1a91ca3550a8 Mon Sep 17 00:00:00 2001
+From: Andrey Dolnikov <andrey.dolnikov@cogentembedded.com>
+Date: Wed, 25 Feb 2015 15:17:46 +0300
+Subject: [PATCH] Porter: Add CAN support.
+
+---
+ arch/arm/boot/dts/r8a7791-porter.dts | 12 ++++++++++++
+ arch/arm/boot/dts/r8a7791.dtsi | 9 +++++++++
+ 2 files changed, 21 insertions(+)
+
+diff --git a/arch/arm/boot/dts/r8a7791-porter.dts b/arch/arm/boot/dts/r8a7791-porter.dts
+index 6a0ccde..4fb5cd5 100644
+--- a/arch/arm/boot/dts/r8a7791-porter.dts
++++ b/arch/arm/boot/dts/r8a7791-porter.dts
+@@ -211,6 +211,11 @@
+ renesas,groups = "vin0_data8", "vin0_clk";
+ renesas,function = "vin0";
+ };
++
++ can0_pins: can0 {
++ renesas,groups = "can0_data_b";
++ renesas,function = "can0";
++ };
+ };
+
+ &ether {
+@@ -229,6 +234,13 @@
+ };
+ };
+
++&can0 {
++ pinctrl-0 = <&can0_pins>;
++ pinctrl-names = "default";
++ renesas,can-clock-select = <0x0>;
++ status = "okay";
++};
++
+ &sata0 {
+ status = "okay";
+ };
+diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi
+index 799d41c..1cad41e 100644
+--- a/arch/arm/boot/dts/r8a7791.dtsi
++++ b/arch/arm/boot/dts/r8a7791.dtsi
+@@ -533,6 +533,15 @@
+ status = "disabled";
+ };
+
++ can0: can@e6e80000 {
++ compatible = "renesas,can-r8a7791";
++ reg = <0 0xe6e80000 0 0x1000>;
++ interrupts = <0 186 IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&mstp9_clks R8A7791_CLK_RCAN0>;
++ clock-names = "clkp1", "clkp2", "can_clk";
++ status = "disabled";
++ };
++
+ sata0: sata@ee300000 {
+ compatible = "renesas,sata-r8a7791";
+ reg = <0 0xee300000 0 0x2000>;
+--
+1.9.1
+
diff --git a/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0019-i2c-busses-rcar-Workaround-arbitration-loss-error.patch b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0019-i2c-busses-rcar-Workaround-arbitration-loss-error.patch
new file mode 100644
index 0000000..209d1b4
--- /dev/null
+++ b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0019-i2c-busses-rcar-Workaround-arbitration-loss-error.patch
@@ -0,0 +1,31 @@
+From 23fa8d125ca1be9c03ac7d2f42530a57d6ca28f2 Mon Sep 17 00:00:00 2001
+From: Valentine Barshak <valentine.barshak@cogentembedded.com>
+Date: Tue, 3 Mar 2015 18:30:16 +0300
+Subject: [PATCH] i2c: busses: rcar: Workaround arbitration loss error
+
+Sometimes I2C master enable/disable at every transmission
+causes arbitration loss errors making the bus unusable.
+Workaround the issue by enabling I2C master
+in the rcar_i2c_init() function.
+
+Signed-off-by: Valentine Barshak <valentine.barshak@cogentembedded.com>
+---
+ drivers/i2c/busses/i2c-rcar.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c
+index 0e863f3..4334006 100644
+--- a/drivers/i2c/busses/i2c-rcar.c
++++ b/drivers/i2c/busses/i2c-rcar.c
+@@ -161,7 +161,7 @@ static void rcar_i2c_init(struct rcar_i2c_priv *priv)
+
+ /* reset master mode */
+ rcar_i2c_write(priv, ICMIER, 0);
+- rcar_i2c_write(priv, ICMCR, 0);
++ rcar_i2c_write(priv, ICMCR, MDBS | MIE);
+ rcar_i2c_write(priv, ICMSR, 0);
+ rcar_i2c_write(priv, ICMAR, 0);
+ }
+--
+1.9.3
+
diff --git a/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0020-Silk-Remove-I2C1-clock-from-clk_enables.patch b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0020-Silk-Remove-I2C1-clock-from-clk_enables.patch
new file mode 100644
index 0000000..78a3a5b
--- /dev/null
+++ b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0020-Silk-Remove-I2C1-clock-from-clk_enables.patch
@@ -0,0 +1,30 @@
+From 6c0691906b3bcce0a9629ca00faa6be88a013aaa Mon Sep 17 00:00:00 2001
+From: Valentine Barshak <valentine.barshak@cogentembedded.com>
+Date: Tue, 3 Mar 2015 18:25:15 +0300
+Subject: [PATCH] ARM: shmobile: silk: Remove I2C1 clock from clk_enables
+ array
+
+Remove I2C1 clock from clk_enables array since it is not needed.
+I2C clocks are handled by the OF driver while shmobile_clk_workaround
+is only needed for platform devices.
+
+Signed-off-by: Valentine Barshak <valentine.barshak@cogentembedded.com>
+---
+ arch/arm/mach-shmobile/board-silk-reference.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/arch/arm/mach-shmobile/board-silk-reference.c b/arch/arm/mach-shmobile/board-silk-reference.c
+index 090a4df..d4c64fa 100644
+--- a/arch/arm/mach-shmobile/board-silk-reference.c
++++ b/arch/arm/mach-shmobile/board-silk-reference.c
+@@ -271,7 +271,6 @@ static const struct clk_name clk_names[] __initconst = {
+ */
+ static const struct clk_name clk_enables[] __initconst = {
+ { "ether", NULL, "ee700000.ethernet" },
+- { "i2c1", NULL, "e6518000.i2c" },
+ { "mmcif0", NULL, "ee200000.mmc" },
+ { "sdhi0", NULL, "ee100000.sd" },
+ { "sdhi1", NULL, "ee140000.sd" },
+--
+1.9.3
+