summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--meta-agl-bsp/conf/include/agl_s4sk.inc5
-rw-r--r--meta-agl-bsp/meta-rcar-gateway/recipes-kernel/linux/linux-renesas/0001-Porting-to-support-device-driver-Canfd-from-Control-.patch1388
-rw-r--r--meta-agl-bsp/meta-rcar-gateway/recipes-kernel/linux/linux-renesas_%.bbappend6
3 files changed, 1399 insertions, 0 deletions
diff --git a/meta-agl-bsp/conf/include/agl_s4sk.inc b/meta-agl-bsp/conf/include/agl_s4sk.inc
index 8f4a91b44..91a65d8b8 100644
--- a/meta-agl-bsp/conf/include/agl_s4sk.inc
+++ b/meta-agl-bsp/conf/include/agl_s4sk.inc
@@ -7,3 +7,8 @@ WKS_FILE = "singlepart-noloader.wks"
IMAGE_INSTALL:append = " \
kernel-devicetree \
"
+
+# For systemd CAN bus configuration
+#MACHINE_FEATURES:append = " canfd"
+CANBUS_NETWORK_CONFIG = "canbus-can-fd.network"
+
diff --git a/meta-agl-bsp/meta-rcar-gateway/recipes-kernel/linux/linux-renesas/0001-Porting-to-support-device-driver-Canfd-from-Control-.patch b/meta-agl-bsp/meta-rcar-gateway/recipes-kernel/linux/linux-renesas/0001-Porting-to-support-device-driver-Canfd-from-Control-.patch
new file mode 100644
index 000000000..69fb1ace2
--- /dev/null
+++ b/meta-agl-bsp/meta-rcar-gateway/recipes-kernel/linux/linux-renesas/0001-Porting-to-support-device-driver-Canfd-from-Control-.patch
@@ -0,0 +1,1388 @@
+From a7e7a8317d5b150a97a08270ddfb711a88168add Mon Sep 17 00:00:00 2001
+From: Phat Pham <phat.pham.zg@renesas.com>
+Date: Wed, 2 Aug 2023 17:12:09 +0700
+Subject: [PATCH] Porting to support device driver Canfd from Control Domain to
+ Application Domain
+
+- Update pinctrl support for 15 canfd channels in file pfc-r8a779f0.c.
+- Update device tree to support GPIO Group 4-7 on CA55 in file r8a779f0.dtsi and r8a779f0-spider.dts,
+r8a779f0-s4sk.dts.
+- Update Canfd device nodes in device tree R9A779F0.
+- Update Source code support canfd device in rcar-canfd.c.
+
+Signed-off-by: Phat Pham <phat.pham.zg@renesas.com>
+Signed-off-by: Duy Dang <duy.dang.yw@renesas.com>
+---
+ arch/arm64/boot/dts/renesas/r8a779f0-s4sk.dts | 28 ++
+ .../boot/dts/renesas/r8a779f0-spider.dts | 160 ++++++++++++
+ arch/arm64/boot/dts/renesas/r8a779f0.dtsi | 170 +++++++++++-
+ drivers/net/can/rcar/rcar_can.c | 28 +-
+ drivers/net/can/rcar/rcar_canfd.c | 211 +++++++++++----
+ drivers/pinctrl/renesas/pfc-r8a779f0.c | 246 ++++++++++++++++++
+ 6 files changed, 780 insertions(+), 63 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/renesas/r8a779f0-s4sk.dts b/arch/arm64/boot/dts/renesas/r8a779f0-s4sk.dts
+index b6c61a20cd0d..1288285b5a9d 100644
+--- a/arch/arm64/boot/dts/renesas/r8a779f0-s4sk.dts
++++ b/arch/arm64/boot/dts/renesas/r8a779f0-s4sk.dts
+@@ -109,6 +109,24 @@ &mmc0 {
+ status = "okay";
+ };
+
++&canfd0 {
++ pinctrl-0 = <&canfd0_pins>, <&canfd1_pins>;
++ pinctrl-names = "default";
++ status = "okay";
++
++ channel0 {
++ status = "okay";
++ };
++
++ channel1 {
++ status = "okay";
++ };
++};
++
++&canfd1 {
++ status = "disabled";
++};
++
+ &pfc {
+ pinctrl-0 = <&scif_clk_pins>;
+ pinctrl-names = "default";
+@@ -203,6 +221,16 @@ pins_mdio {
+ power-source = <3300>;
+ };
+ };
++
++ canfd0_pins: canfd0 {
++ groups = "canfd0_data";
++ function = "canfd0";
++ };
++
++ canfd1_pins: canfd1 {
++ groups = "canfd1_data";
++ function = "canfd1";
++ };
+ };
+
+ &rwdt {
+diff --git a/arch/arm64/boot/dts/renesas/r8a779f0-spider.dts b/arch/arm64/boot/dts/renesas/r8a779f0-spider.dts
+index 538f413fbffd..0d6b21fe0c07 100644
+--- a/arch/arm64/boot/dts/renesas/r8a779f0-spider.dts
++++ b/arch/arm64/boot/dts/renesas/r8a779f0-spider.dts
+@@ -27,6 +27,86 @@ eeprom@51 {
+ };
+ };
+
++&canfd0 {
++ pinctrl-0 = <&canfd0_pins>, <&canfd1_pins>, <&canfd2_pins>,
++ <&canfd3_pins>, <&canfd4_pins>, <&canfd5_pins>,
++ <&canfd6_pins>, <&canfd7_pins>;
++ pinctrl-names = "default";
++ status = "okay";
++
++ channel0 {
++ status = "okay";
++ };
++
++ channel1 {
++ status = "okay";
++ };
++
++ channel2 {
++ status = "okay";
++ };
++
++ channel3 {
++ status = "okay";
++ };
++
++ channel4 {
++ status = "okay";
++ };
++
++ channel5 {
++ status = "okay";
++ };
++
++ channel6 {
++ status = "okay";
++ };
++
++ channel7 {
++ status = "okay";
++ };
++};
++
++&canfd1 {
++ pinctrl-0 = <&canfd8_pins>,<&canfd9_pins>, <&canfd10_pins>,
++ <&canfd11_pins>, <&canfd12_pins>, <&canfd13_pins>,
++ <&canfd14_pins>, <&canfd15_pins>;
++ pinctrl-names = "default";
++ status = "okay";
++
++ channel0 {
++ status = "okay";
++ };
++
++ channel1 {
++ status = "okay";
++ };
++
++ channel2 {
++ status = "okay";
++ };
++
++ channel3 {
++ status = "okay";
++ };
++
++ channel4 {
++ status = "okay";
++ };
++
++ channel5 {
++ status = "okay";
++ };
++
++ channel6 {
++ status = "okay";
++ };
++
++ channel7 {
++ status = "okay";
++ };
++};
++
+ &pfc {
+ tsn0_pins: tsn0 {
+ mux {
+@@ -73,6 +153,86 @@ pins_mdio {
+ };
+ };
+
++ canfd0_pins: canfd0 {
++ groups = "canfd0_data";
++ function = "canfd0";
++ };
++
++ canfd1_pins: canfd1 {
++ groups = "canfd1_data";
++ function = "canfd1";
++ };
++
++ canfd2_pins: canfd2 {
++ groups = "canfd2_data";
++ function = "canfd2";
++ };
++
++ canfd3_pins: canfd3 {
++ groups = "canfd3_data";
++ function = "canfd3";
++ };
++
++ canfd4_pins: canfd4 {
++ groups = "canfd4_data";
++ function = "canfd4";
++ };
++
++ canfd5_pins: canfd5 {
++ groups = "canfd5_data";
++ function = "canfd5";
++ };
++
++ canfd6_pins: canfd6 {
++ groups = "canfd6_data";
++ function = "canfd6";
++ };
++
++ canfd7_pins: canfd7 {
++ groups = "canfd7_data";
++ function = "canfd7";
++ };
++
++ canfd8_pins: canfd8 {
++ groups = "canfd8_data";
++ function = "canfd8";
++ };
++
++ canfd9_pins: canfd9 {
++ groups = "canfd9_data";
++ function = "canfd9";
++ };
++
++ canfd10_pins: canfd10 {
++ groups = "canfd10_data";
++ function = "canfd10";
++ };
++
++ canfd11_pins: canfd11 {
++ groups = "canfd11_data";
++ function = "canfd11";
++ };
++
++ canfd12_pins: canfd12 {
++ groups = "canfd12_data";
++ function = "canfd12";
++ };
++
++ canfd13_pins: canfd13 {
++ groups = "canfd13_data";
++ function = "canfd13";
++ };
++
++ canfd14_pins: canfd14 {
++ groups = "canfd14_data";
++ function = "canfd14";
++ };
++
++ canfd15_pins: canfd15 {
++ groups = "canfd15_data";
++ function = "canfd15";
++ };
++
+ pcie0_pins: pcie0 {
+ groups = "pcie0_clkreq_n";
+ function = "pcie";
+diff --git a/arch/arm64/boot/dts/renesas/r8a779f0.dtsi b/arch/arm64/boot/dts/renesas/r8a779f0.dtsi
+index ddda2fc3acd0..b930b93ab3f7 100644
+--- a/arch/arm64/boot/dts/renesas/r8a779f0.dtsi
++++ b/arch/arm64/boot/dts/renesas/r8a779f0.dtsi
+@@ -23,6 +23,13 @@ aliases {
+ i2c5 = &i2c5;
+ };
+
++ /* External CAN clock - to be overridden by boards that provide it */
++ can_clk: can {
++ compatible = "fixed-clock";
++ #clock-cells = <0>;
++ clock-frequency = <40000000>;
++ };
++
+ cluster1_opp: opp_table10 {
+ compatible = "operating-points-v2";
+ opp-shared;
+@@ -329,7 +336,7 @@ pfc: pin-controller@e6050000 {
+ compatible = "renesas,pfc-r8a779f0";
+ reg = <0 0xe6050000 0 0x16c>, <0 0xe6050800 0 0x16c>,
+ <0 0xe6051000 0 0x16c>, <0 0xe6051800 0 0x16c>,
+- <0 0xdfd90000 0 0x16c>, <0 0xdfd90800 0 0x16c>,
++ <0 0xdfd90000 0 0x16c>, <0 0xdfd90800 0 0x16c>,
+ <0 0xdfd91000 0 0x16c>, <0 0xdfd91800 0 0x16c>;
+ };
+
+@@ -389,6 +396,63 @@ gpio3: gpio@e6051980 {
+ resets = <&cpg 915>;
+ };
+
++ /* Porting GPIO GP 4~7 from Control Domain to Application Domain */
++ gpio4: gpio@dfd90180 {
++ compatible = "renesas,gpio-r8a779f0";
++ reg = <0 0xdfd90180 0 0x54>;
++ interrupts = <GIC_SPI 826 IRQ_TYPE_LEVEL_HIGH>;
++ #gpio-cells = <2>;
++ gpio-controller;
++ gpio-ranges = <&pfc 0 128 31>;
++ #interrupt-cells = <2>;
++ interrupt-controller;
++ clocks = <&cpg CPG_MOD 915>;
++ power-domains = <&sysc R8A779F0_PD_ALWAYS_ON>;
++ resets = <&cpg 915>;
++ };
++
++ gpio5: gpio@dfd90980 {
++ compatible = "renesas,gpio-r8a779f0";
++ reg = <0 0xdfd90980 0 0x54>;
++ interrupts = <GIC_SPI 827 IRQ_TYPE_LEVEL_HIGH>;
++ #gpio-cells = <2>;
++ gpio-controller;
++ gpio-ranges = <&pfc 0 160 20>;
++ #interrupt-cells = <2>;
++ interrupt-controller;
++ clocks = <&cpg CPG_MOD 915>;
++ power-domains = <&sysc R8A779F0_PD_ALWAYS_ON>;
++ resets = <&cpg 915>;
++ };
++
++ gpio6: gpio@dfd91180 {
++ compatible = "renesas,gpio-r8a779f0";
++ reg = <0 0xdfd91180 0 0x54>;
++ interrupts = <GIC_SPI 828 IRQ_TYPE_LEVEL_HIGH>;
++ #gpio-cells = <2>;
++ gpio-controller;
++ gpio-ranges = <&pfc 0 192 24>;
++ #interrupt-cells = <2>;
++ interrupt-controller;
++ clocks = <&cpg CPG_MOD 915>;
++ power-domains = <&sysc R8A779F0_PD_ALWAYS_ON>;
++ resets = <&cpg 915>;
++ };
++
++ gpio7: gpio@dfd91980 {
++ compatible = "renesas,gpio-r8a779f0";
++ reg = <0 0xdfd91980 0 0x54>;
++ interrupts = <GIC_SPI 829 IRQ_TYPE_LEVEL_HIGH>;
++ #gpio-cells = <2>;
++ gpio-controller;
++ gpio-ranges = <&pfc 0 224 32>;
++ #interrupt-cells = <2>;
++ interrupt-controller;
++ clocks = <&cpg CPG_MOD 915>;
++ power-domains = <&sysc R8A779F0_PD_ALWAYS_ON>;
++ resets = <&cpg 915>;
++ };
++
+ cpg: clock-controller@e6150000 {
+ compatible = "renesas,r8a779f0-cpg-mssr";
+ reg = <0 0xe6150000 0 0x4000>;
+@@ -410,6 +474,110 @@ sysc: system-controller@e6180000 {
+ #power-domain-cells = <1>;
+ };
+
++ canfd0: can@dff50000 {
++ compatible = "renesas,r8a779f0-canfd";
++ reg = <0 0xdff50000 0 0x8600>;
++ interrupts = <GIC_SPI 534 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 535 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 536 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 537 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 538 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 539 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 540 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 541 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 542 IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&can_clk>;
++ clock-names = "can_clk";
++ assigned-clocks = <&can_clk>;
++ assigned-clock-rates = <40000000>;
++ power-domains = <&sysc R8A779F0_PD_ALWAYS_ON>;
++ status = "okay";
++
++ channel0 {
++ status = "disabled";
++ };
++
++ channel1 {
++ status = "disabled";
++ };
++
++ channel2 {
++ status = "disabled";
++ };
++
++ channel3 {
++ status = "disabled";
++ };
++
++ channel4 {
++ status = "disabled";
++ };
++
++ channel5 {
++ status = "disabled";
++ };
++
++ channel6 {
++ status = "disabled";
++ };
++
++ channel7 {
++ status = "disabled";
++ };
++ };
++
++ canfd1: can@dfd00000 {
++ compatible = "renesas,r8a779f0-canfd";
++ reg = <0 0xdfd00000 0 0x8600>;
++ interrupts = <GIC_SPI 543 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 544 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 545 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 546 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 547 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 548 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 549 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 550 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 551 IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&can_clk>;
++ clock-names = "can_clk";
++ assigned-clocks = <&can_clk>;
++ assigned-clock-rates = <40000000>;
++ power-domains = <&sysc R8A779F0_PD_ALWAYS_ON>;
++ status = "okay";
++
++ channel0 {
++ status = "disabled";
++ };
++
++ channel1 {
++ status = "disabled";
++ };
++
++ channel2 {
++ status = "disabled";
++ };
++
++ channel3 {
++ status = "disabled";
++ };
++
++ channel4 {
++ status = "disabled";
++ };
++
++ channel5 {
++ status = "disabled";
++ };
++
++ channel6 {
++ status = "disabled";
++ };
++
++ channel7 {
++ status = "disabled";
++ };
++ };
++
+ i2c0: i2c@e6500000 {
+ compatible = "renesas,i2c-r8a779f0",
+ "renesas,rcar-gen4-i2c";
+diff --git a/drivers/net/can/rcar/rcar_can.c b/drivers/net/can/rcar/rcar_can.c
+index 48575900adb7..134eda66f0dc 100644
+--- a/drivers/net/can/rcar/rcar_can.c
++++ b/drivers/net/can/rcar/rcar_can.c
+@@ -235,11 +235,8 @@ static void rcar_can_error(struct net_device *ndev)
+ if (eifr & (RCAR_CAN_EIFR_EWIF | RCAR_CAN_EIFR_EPIF)) {
+ txerr = readb(&priv->regs->tecr);
+ rxerr = readb(&priv->regs->recr);
+- if (skb) {
++ 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;
+@@ -339,6 +336,9 @@ static void rcar_can_error(struct net_device *ndev)
+ can_bus_off(ndev);
+ if (skb)
+ cf->can_id |= CAN_ERR_BUSOFF;
++ } else if (skb) {
++ cf->data[6] = txerr;
++ cf->data[7] = rxerr;
+ }
+ if (eifr & RCAR_CAN_EIFR_ORIF) {
+ netdev_dbg(priv->ndev, "Receive overrun error interrupt\n");
+@@ -846,10 +846,12 @@ static int __maybe_unused rcar_can_suspend(struct device *dev)
+ struct rcar_can_priv *priv = netdev_priv(ndev);
+ u16 ctlr;
+
+- if (netif_running(ndev)) {
+- netif_stop_queue(ndev);
+- netif_device_detach(ndev);
+- }
++ if (!netif_running(ndev))
++ return 0;
++
++ netif_stop_queue(ndev);
++ netif_device_detach(ndev);
++
+ ctlr = readw(&priv->regs->ctlr);
+ ctlr |= RCAR_CAN_CTLR_CANM_HALT;
+ writew(ctlr, &priv->regs->ctlr);
+@@ -868,6 +870,9 @@ static int __maybe_unused rcar_can_resume(struct device *dev)
+ u16 ctlr;
+ int err;
+
++ if (!netif_running(ndev))
++ return 0;
++
+ err = clk_enable(priv->clk);
+ if (err) {
+ netdev_err(ndev, "clk_enable() failed, error %d\n", err);
+@@ -881,10 +886,9 @@ static int __maybe_unused rcar_can_resume(struct device *dev)
+ writew(ctlr, &priv->regs->ctlr);
+ priv->can.state = CAN_STATE_ERROR_ACTIVE;
+
+- if (netif_running(ndev)) {
+- netif_device_attach(ndev);
+- netif_start_queue(ndev);
+- }
++ netif_device_attach(ndev);
++ netif_start_queue(ndev);
++
+ return 0;
+ }
+
+diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c
+index b458b5fd7900..e4f820308954 100644
+--- a/drivers/net/can/rcar/rcar_canfd.c
++++ b/drivers/net/can/rcar/rcar_canfd.c
+@@ -203,7 +203,7 @@
+ #define RCANFD_FDCFG_FDOE BIT(28)
+ #define RCANFD_FDCFG_TDCE BIT(9)
+ #define RCANFD_FDCFG_TDCOC BIT(8)
+-#define RCANFD_FDCFG_TDCO(x) (((x) & 0x7f) >> 16)
++#define RCANFD_FDCFG_TDCO(x) (((x) & 0xff) << 16)
+
+ /* RSCFDnCFDRFCCx */
+ #define RCANFD_RFCC_RFIM BIT(12)
+@@ -506,6 +506,7 @@
+ /* R-Car V3U Classical and CAN FD mode specific register map */
+ #define RCANFD_V3U_CFDCFG (0x1314)
+ #define RCANFD_V3U_DCFG(m) (0x1400 + (0x20 * (m)))
++#define RCANFD_V3U_FDCFG(m) (0x1404 + (0x20 * (m)))
+
+ #define RCANFD_V3U_GAFL_OFFSET (0x1800)
+
+@@ -574,6 +575,7 @@ struct rcar_canfd_channel {
+
+ enum rcar_canfd_chip_id {
+ R8A779G0,
++ R8A779F0,
+ R8A779A0,
+ GEN3,
+ };
+@@ -734,13 +736,17 @@ static int rcar_canfd_reset_controller(struct rcar_canfd_global *gpriv)
+ rcar_canfd_write(gpriv->base, RCANFD_GERFL, 0x0);
+
+ /* Set the controller into appropriate mode */
+- if ((gpriv->chip_id == R8A779A0) || (gpriv->chip_id == R8A779G0)) {
++ if (gpriv->chip_id == R8A779A0 || gpriv->chip_id == R8A779G0 || gpriv->chip_id == R8A779F0) {
+ if (gpriv->fdmode)
+- rcar_canfd_set_bit(gpriv->base, RCANFD_V3U_CFDCFG,
+- RCANFD_FDCFG_FDOE);
++ {
++ for_each_set_bit(ch, &gpriv->channels_mask, gpriv->max_channels)
++ rcar_canfd_set_bit(gpriv->base, RCANFD_V3U_FDCFG(ch),
++ RCANFD_FDCFG_FDOE);
++ }
+ else
+- rcar_canfd_set_bit(gpriv->base, RCANFD_V3U_CFDCFG,
+- RCANFD_FDCFG_CLOE);
++ for_each_set_bit(ch, &gpriv->channels_mask, gpriv->max_channels)
++ rcar_canfd_set_bit(gpriv->base, RCANFD_V3U_FDCFG(ch),
++ RCANFD_FDCFG_CLOE);
+ } else {
+ if (gpriv->fdmode)
+ rcar_canfd_set_bit(gpriv->base, RCANFD_GRMCFG,
+@@ -801,7 +807,7 @@ static void rcar_canfd_configure_controller(struct rcar_canfd_global *gpriv)
+ }
+
+ static void rcar_canfd_configure_afl_rules(struct rcar_canfd_global *gpriv,
+- u32 ch)
++ u32 ch, int num_ch_enabled)
+ {
+ u32 cfg;
+ int offset, start, page, num_rules = RCANFD_CHANNEL_NUMRULES;
+@@ -812,7 +818,7 @@ static void rcar_canfd_configure_afl_rules(struct rcar_canfd_global *gpriv,
+ } else {
+ /* Get number of Channel 0 rules and adjust */
+ cfg = rcar_canfd_read(gpriv->base, RCANFD_V3U_GAFLCFG(ch));
+- if ((gpriv->chip_id == R8A779A0) || (gpriv->chip_id == R8A779G0))
++ if (gpriv->chip_id == R8A779A0 || gpriv->chip_id == R8A779G0 || gpriv->chip_id == R8A779F0)
+ start = ch * num_rules;
+ else
+ start = RCANFD_GAFLCFG_GETRNC(0, cfg);
+@@ -821,24 +827,28 @@ static void rcar_canfd_configure_afl_rules(struct rcar_canfd_global *gpriv,
+ /* Enable write access to entry */
+ page = RCANFD_GAFL_PAGENUM(start);
+
+- if ((gpriv->chip_id == R8A779A0) || (gpriv->chip_id == R8A779G0))
++ if (gpriv->chip_id == R8A779A0 || gpriv->chip_id == R8A779G0 || gpriv->chip_id == R8A779F0)
++ {
+ rcar_canfd_set_bit(gpriv->base, RCANFD_GAFLECTR,
+ (RCANFD_V3U_GAFLECTR_AFLPN(page) |
+ RCANFD_GAFLECTR_AFLDAE));
++ }
+ else
+ rcar_canfd_set_bit(gpriv->base, RCANFD_GAFLECTR,
+ (RCANFD_GAFLECTR_AFLPN(page) |
+ RCANFD_GAFLECTR_AFLDAE));
+
+ /* Write number of rules for channel */
+- if ((gpriv->chip_id == R8A779A0) || (gpriv->chip_id == R8A779G0))
++ if (gpriv->chip_id == R8A779A0 || gpriv->chip_id == R8A779G0 || gpriv->chip_id == R8A779F0)
++ {
+ rcar_canfd_set_bit(gpriv->base, RCANFD_V3U_GAFLCFG(ch),
+ RCANFD_V3U_GAFLCFG_SETRNC(ch, num_rules));
++ }
+ else
+ rcar_canfd_set_bit(gpriv->base, RCANFD_GAFLCFG0,
+ RCANFD_GAFLCFG_SETRNC(ch, num_rules));
+
+- if ((gpriv->chip_id == R8A779A0) || (gpriv->chip_id == R8A779G0)) {
++ if (gpriv->chip_id == R8A779A0 || gpriv->chip_id == R8A779G0 || gpriv->chip_id == R8A779F0) {
+ offset = RCANFD_V3U_GAFL_OFFSET;
+ } else {
+ if (gpriv->fdmode)
+@@ -848,13 +858,13 @@ static void rcar_canfd_configure_afl_rules(struct rcar_canfd_global *gpriv,
+ }
+
+ /* Accept all IDs */
+- rcar_canfd_write(gpriv->base, RCANFD_GAFLID(offset, start), 0);
++ rcar_canfd_write(gpriv->base, RCANFD_GAFLID(offset, num_ch_enabled), 0);
+ /* IDE or RTR is not considered for matching */
+- rcar_canfd_write(gpriv->base, RCANFD_GAFLM(offset, start), 0);
++ rcar_canfd_write(gpriv->base, RCANFD_GAFLM(offset, num_ch_enabled), 0);
+ /* Any data length accepted */
+- rcar_canfd_write(gpriv->base, RCANFD_GAFLP0(offset, start), 0);
++ rcar_canfd_write(gpriv->base, RCANFD_GAFLP0(offset, num_ch_enabled), 0);
+ /* Place the msg in corresponding Rx FIFO entry */
+- rcar_canfd_set_bit(gpriv->base, RCANFD_GAFLP1(offset, start),
++ rcar_canfd_set_bit(gpriv->base, RCANFD_GAFLP1(offset, num_ch_enabled),
+ RCANFD_GAFLP1_GAFLFDP(ridx));
+
+ /* Disable write access to page */
+@@ -879,10 +889,14 @@ static void rcar_canfd_configure_rx(struct rcar_canfd_global *gpriv, u32 ch)
+
+ cfg = (RCANFD_RFCC_RFIM | RCANFD_RFCC_RFDC(rfdc) |
+ RCANFD_RFCC_RFPLS(rfpls) | RCANFD_RFCC_RFIE);
+- if ((gpriv->chip_id == R8A779A0) || (gpriv->chip_id == R8A779G0))
++ if (gpriv->chip_id == R8A779A0 || gpriv->chip_id == R8A779G0 || gpriv->chip_id == R8A779F0)
++ {
+ rcar_canfd_write(gpriv->base, RCANFD_V3U_RFCC(ridx), cfg);
++ }
+ else
++ {
+ rcar_canfd_write(gpriv->base, RCANFD_RFCC(ridx), cfg);
++ }
+ }
+
+ static void rcar_canfd_configure_tx(struct rcar_canfd_global *gpriv, u32 ch)
+@@ -904,7 +918,7 @@ static void rcar_canfd_configure_tx(struct rcar_canfd_global *gpriv, u32 ch)
+ else
+ cfpls = 0; /* b000 - Max 8 bytes payload */
+
+- if ((gpriv->chip_id == R8A779A0) || (gpriv->chip_id == R8A779G0)) {
++ if (gpriv->chip_id == R8A779A0 || gpriv->chip_id == R8A779G0 || gpriv->chip_id == R8A779F0) {
+ cfg = (RCANFD_V3U_CFCC_CFTML(cftml) | RCANFD_V3U_CFCC_CFM(cfm) |
+ RCANFD_V3U_CFCC_CFIM | RCANFD_V3U_CFCC_CFDC(cfdc) |
+ RCANFD_V3U_CFCC_CFPLS(cfpls) | RCANFD_V3U_CFCC_CFTXIE);
+@@ -919,8 +933,10 @@ static void rcar_canfd_configure_tx(struct rcar_canfd_global *gpriv, u32 ch)
+ }
+ if (gpriv->fdmode) {
+ /* Clear FD mode specific control/status register */
+- if ((gpriv->chip_id == R8A779A0) || (gpriv->chip_id == R8A779G0))
++ if (gpriv->chip_id == R8A779A0 || gpriv->chip_id == R8A779G0 || gpriv->chip_id == R8A779F0)
++ {
+ addr = RCANFD_V3U_CFFDCSTS(ch, RCANFD_CFFIFO_IDX);
++ }
+ else
+ addr = RCANFD_F_CFFDCSTS(ch, RCANFD_CFFIFO_IDX);
+
+@@ -938,7 +954,9 @@ static void rcar_canfd_enable_global_interrupts(struct rcar_canfd_global *gpriv)
+ /* Global interrupts setup */
+ ctr = RCANFD_GCTR_MEIE;
+ if (gpriv->fdmode)
++ {
+ ctr |= RCANFD_GCTR_CFMPOFIE;
++ }
+
+ rcar_canfd_set_bit(gpriv->base, RCANFD_GCTR, ctr);
+ }
+@@ -1005,7 +1023,7 @@ static void rcar_canfd_global_error(struct net_device *ndev)
+ stats->tx_dropped++;
+ }
+ if (gerfl & RCANFD_GERFL_MES) {
+- if ((gpriv->chip_id == R8A779A0) || (gpriv->chip_id == R8A779G0))
++ if (gpriv->chip_id == R8A779A0 || gpriv->chip_id == R8A779G0 || gpriv->chip_id == R8A779F0)
+ addr = RCANFD_V3U_CFSTS(ch, RCANFD_CFFIFO_IDX);
+ else
+ addr = RCANFD_CFSTS(ch, RCANFD_CFFIFO_IDX);
+@@ -1018,7 +1036,7 @@ static void rcar_canfd_global_error(struct net_device *ndev)
+ rcar_canfd_write(priv->base, addr,
+ sts & ~RCANFD_CFSTS_CFMLT);
+ }
+- if ((gpriv->chip_id == R8A779A0) || (gpriv->chip_id == R8A779G0))
++ if (gpriv->chip_id == R8A779A0 || gpriv->chip_id == R8A779G0 || gpriv->chip_id == R8A779F0)
+ addr = RCANFD_V3U_RFSTS(ridx);
+ else
+ addr = RCANFD_RFSTS(ridx);
+@@ -1171,8 +1189,10 @@ static void rcar_canfd_tx_done(struct net_device *ndev)
+ u32 ch = priv->channel;
+ struct rcar_canfd_global *gpriv = priv->gpriv;
+
+- if ((gpriv->chip_id == R8A779A0) || (gpriv->chip_id == R8A779G0))
++ if (gpriv->chip_id == R8A779A0 || gpriv->chip_id == R8A779G0 || gpriv->chip_id == R8A779F0)
++ {
+ addr = RCANFD_V3U_CFSTS(ch, RCANFD_CFFIFO_IDX);
++ }
+ else
+ addr = RCANFD_CFSTS(ch, RCANFD_CFFIFO_IDX);
+
+@@ -1227,7 +1247,7 @@ static irqreturn_t rcar_canfd_global_interrupt(int irq, void *dev_id)
+
+ /* Global error interrupts */
+ gerfl = rcar_canfd_read(priv->base, RCANFD_GERFL);
+- if ((gpriv->chip_id == R8A779A0) || (gpriv->chip_id == R8A779G0)) {
++ if (gpriv->chip_id == R8A779A0 || gpriv->chip_id == R8A779G0 || gpriv->chip_id == R8A779F0) {
+ if (unlikely(RCANFD_V3U_GERFL_ERR(gpriv, gerfl)))
+ rcar_canfd_global_error(ndev);
+ } else {
+@@ -1235,7 +1255,7 @@ static irqreturn_t rcar_canfd_global_interrupt(int irq, void *dev_id)
+ rcar_canfd_global_error(ndev);
+ }
+ /* Handle Rx interrupts */
+- if ((gpriv->chip_id == R8A779A0) || (gpriv->chip_id == R8A779G0)) {
++ if (gpriv->chip_id == R8A779A0 || gpriv->chip_id == R8A779G0 || gpriv->chip_id == R8A779F0) {
+ addr1 = RCANFD_V3U_RFSTS(ridx);
+ addr2 = RCANFD_V3U_RFCC(ridx);
+ } else {
+@@ -1307,6 +1327,7 @@ static irqreturn_t rcar_canfd_channel_interrupt(int irq, void *dev_id)
+ sts = rcar_canfd_read(priv->base, RCANFD_CSTS(ch));
+ txerr = RCANFD_CSTS_TECCNT(sts);
+ rxerr = RCANFD_CSTS_RECCNT(sts);
++
+ if (unlikely(RCANFD_CERFL_ERR(cerfl)))
+ rcar_canfd_error(ndev, cerfl, txerr, rxerr);
+
+@@ -1316,19 +1337,57 @@ static irqreturn_t rcar_canfd_channel_interrupt(int irq, void *dev_id)
+ rcar_canfd_state_change(ndev, txerr, rxerr);
+
+ /* Handle Tx interrupts */
+- if ((gpriv->chip_id == R8A779A0) || (gpriv->chip_id == R8A779G0))
++ if (gpriv->chip_id == R8A779A0 || gpriv->chip_id == R8A779G0 || gpriv->chip_id == R8A779F0)
++ {
+ addr = RCANFD_V3U_CFSTS(ch, RCANFD_CFFIFO_IDX);
++ }
+ else
++ {
+ addr = RCANFD_CFSTS(ch, RCANFD_CFFIFO_IDX);
++ }
+
+ sts = rcar_canfd_read(priv->base, addr);
+
+ if (likely(sts & RCANFD_CFSTS_CFTXIF))
++ {
+ rcar_canfd_tx_done(ndev);
++ }
+ }
+ return IRQ_HANDLED;
+ }
+
++static void rcar_canfd_set_samplepoint(struct net_device *dev)
++{
++ struct rcar_canfd_channel *priv = netdev_priv(dev);
++ u32 ch = priv->channel;
++ u16 tdco;
++ u32 cfg;
++ struct rcar_canfd_global *gpriv = priv->gpriv;
++
++ /* Sample point settings */
++ tdco = 2; /* TDCO = 2Tq */
++
++ /* Transceiver Delay Compensation Offset Configuration */
++ if (gpriv->chip_id == R8A779A0 || gpriv->chip_id == R8A779G0 || gpriv->chip_id == R8A779F0) {
++ cfg = (RCANFD_FDCFG_TDCE |
++ RCANFD_FDCFG_TDCO(tdco));
++ rcar_canfd_set_bit(priv->base, RCANFD_V3U_FDCFG(ch), cfg);
++ }
++}
++
++static void rcar_canfd_unset_samplepoint(struct net_device *dev)
++{
++ struct rcar_canfd_channel *priv = netdev_priv(dev);
++ u32 ch = priv->channel;
++ u32 cfg;
++ struct rcar_canfd_global *gpriv = priv->gpriv;
++
++ if (gpriv->chip_id == R8A779A0 || gpriv->chip_id == R8A779G0 || gpriv->chip_id == R8A779F0) {
++ cfg = RCANFD_FDCFG_TDCE; /* Disable TDC */
++ rcar_canfd_clear_bit(priv->base, RCANFD_V3U_FDCFG(ch), cfg);
++ }
++}
++
+ static void rcar_canfd_set_bittiming(struct net_device *dev)
+ {
+ struct rcar_canfd_channel *priv = netdev_priv(dev);
+@@ -1342,12 +1401,12 @@ static void rcar_canfd_set_bittiming(struct net_device *dev)
+ /* Nominal bit timing settings */
+ brp = bt->brp - 1;
+ sjw = bt->sjw - 1;
+- tseg1 = bt->prop_seg + bt->phase_seg1 + 1;
++ tseg1 = bt->prop_seg + bt->phase_seg1 - 1;
+ tseg2 = bt->phase_seg2 - 1;
+
+ if (priv->can.ctrlmode & CAN_CTRLMODE_FD) {
+ /* CAN FD only mode */
+- if ((gpriv->chip_id == R8A779A0) || (gpriv->chip_id == R8A779G0))
++ if (gpriv->chip_id == R8A779A0 || gpriv->chip_id == R8A779G0 || gpriv->chip_id == R8A779F0)
+ cfg = (RCANFD_V3U_NCFG_NTSEG1(tseg1) |
+ RCANFD_V3U_NCFG_NBRP(brp) |
+ RCANFD_V3U_NCFG_NSJW(sjw) |
+@@ -1365,10 +1424,16 @@ static void rcar_canfd_set_bittiming(struct net_device *dev)
+ /* Data bit timing settings */
+ brp = dbt->brp - 1;
+ sjw = dbt->sjw - 1;
+- tseg1 = dbt->prop_seg + dbt->phase_seg1 + 1;
++ tseg1 = dbt->prop_seg + dbt->phase_seg1 - 1;
+ tseg2 = dbt->phase_seg2 - 1;
+
+- if ((gpriv->chip_id == R8A779A0) || (gpriv->chip_id == R8A779G0)) {
++ /* Set Secondary Sample Point for high baud rate */
++ if (brp == 0 && tseg1 <= 5 && tseg2 == 1)
++ rcar_canfd_set_samplepoint(dev);
++ else
++ rcar_canfd_unset_samplepoint(dev);
++
++ if (gpriv->chip_id == R8A779A0 || gpriv->chip_id == R8A779G0 || gpriv->chip_id == R8A779F0) {
+ cfg = (RCANFD_V3U_DCFG_DTSEG1(tseg1) |
+ RCANFD_V3U_DCFG_DBRP(brp) |
+ RCANFD_V3U_DCFG_DSJW(sjw) |
+@@ -1387,7 +1452,7 @@ static void rcar_canfd_set_bittiming(struct net_device *dev)
+ brp, sjw, tseg1, tseg2);
+ } else {
+ /* Classical CAN only mode */
+- if ((gpriv->chip_id == R8A779A0) || (gpriv->chip_id == R8A779G0))
++ if (gpriv->chip_id == R8A779A0 || gpriv->chip_id == R8A779G0 || gpriv->chip_id == R8A779F0)
+ cfg = (RCANFD_V3U_NCFG_NTSEG1(tseg1) |
+ RCANFD_V3U_NCFG_NBRP(brp) |
+ RCANFD_V3U_NCFG_NSJW(sjw) |
+@@ -1430,7 +1495,7 @@ static int rcar_canfd_start(struct net_device *ndev)
+ }
+
+ /* Enable Common & Rx FIFO */
+- if ((gpriv->chip_id == R8A779A0) || (gpriv->chip_id == R8A779G0)) {
++ if (gpriv->chip_id == R8A779A0 || gpriv->chip_id == R8A779G0 || gpriv->chip_id == R8A779F0) {
+ addr1 = RCANFD_V3U_CFCC(ch, RCANFD_CFFIFO_IDX);
+ addr2 = RCANFD_V3U_RFCC(ridx);
+ } else {
+@@ -1505,7 +1570,7 @@ static void rcar_canfd_stop(struct net_device *ndev)
+ rcar_canfd_disable_channel_interrupts(priv);
+
+ /* Disable Common & Rx FIFO */
+- if ((gpriv->chip_id == R8A779A0) || (gpriv->chip_id == R8A779G0)) {
++ if (gpriv->chip_id == R8A779A0 || gpriv->chip_id == R8A779G0 || gpriv->chip_id == R8A779F0) {
+ addr1 = RCANFD_V3U_CFCC(ch, RCANFD_CFFIFO_IDX);
+ addr2 = RCANFD_V3U_RFCC(ridx);
+ } else {
+@@ -1544,7 +1609,9 @@ static netdev_tx_t rcar_canfd_start_xmit(struct sk_buff *skb,
+ struct rcar_canfd_global *gpriv = priv->gpriv;
+
+ if (can_dropped_invalid_skb(ndev, skb))
++ {
+ return NETDEV_TX_OK;
++ }
+
+ if (cf->can_id & CAN_EFF_FLAG) {
+ id = cf->can_id & CAN_EFF_MASK;
+@@ -1554,11 +1621,13 @@ static netdev_tx_t rcar_canfd_start_xmit(struct sk_buff *skb,
+ }
+
+ if (cf->can_id & CAN_RTR_FLAG)
++ {
+ id |= RCANFD_CFID_CFRTR;
++ }
+
+ dlc = RCANFD_CFPTR_CFDLC(can_len2dlc(cf->len));
+
+- if ((gpriv->chip_id == R8A779A0) || (gpriv->chip_id == R8A779G0)) {
++ if (gpriv->chip_id == R8A779A0 || gpriv->chip_id == R8A779G0 || gpriv->chip_id == R8A779F0) {
+ rcar_canfd_write(priv->base,
+ RCANFD_V3U_CFID(ch, RCANFD_CFFIFO_IDX), id);
+ rcar_canfd_write(priv->base,
+@@ -1622,7 +1691,7 @@ static netdev_tx_t rcar_canfd_start_xmit(struct sk_buff *skb,
+ /* Start Tx: Write 0xff to CFPC to increment the CPU-side
+ * pointer for the Common FIFO
+ */
+- if ((gpriv->chip_id == R8A779A0) || (gpriv->chip_id == R8A779G0))
++ if (gpriv->chip_id == R8A779A0 || gpriv->chip_id == R8A779G0 || gpriv->chip_id == R8A779F0)
+ addr = RCANFD_V3U_CFPCTR(ch, RCANFD_CFFIFO_IDX);
+ else
+ addr = RCANFD_CFPCTR(ch, RCANFD_CFFIFO_IDX);
+@@ -1630,6 +1699,7 @@ static netdev_tx_t rcar_canfd_start_xmit(struct sk_buff *skb,
+ rcar_canfd_write(priv->base, addr, 0xff);
+
+ spin_unlock_irqrestore(&priv->tx_lock, flags);
++
+ return NETDEV_TX_OK;
+ }
+
+@@ -1643,7 +1713,7 @@ static void rcar_canfd_rx_pkt(struct rcar_canfd_channel *priv)
+ u32 ridx = ch + RCANFD_RFFIFO_IDX;
+ struct rcar_canfd_global *gpriv = priv->gpriv;
+
+- if ((gpriv->chip_id == R8A779A0) || (gpriv->chip_id == R8A779G0)) {
++ if (gpriv->chip_id == R8A779A0 || gpriv->chip_id == R8A779G0 || gpriv->chip_id == R8A779F0) {
+ id = rcar_canfd_read(priv->base, RCANFD_V3U_RFID(ridx));
+ dlc = rcar_canfd_read(priv->base, RCANFD_V3U_RFPTR(ridx));
+ if (priv->can.ctrlmode & CAN_CTRLMODE_FD) {
+@@ -1707,7 +1777,7 @@ static void rcar_canfd_rx_pkt(struct rcar_canfd_channel *priv)
+ if (sts & RCANFD_RFFDSTS_RFBRS)
+ cf->flags |= CANFD_BRS;
+
+- if ((gpriv->chip_id == R8A779A0) || (gpriv->chip_id == R8A779G0))
++ if (gpriv->chip_id == R8A779A0 || gpriv->chip_id == R8A779G0 || gpriv->chip_id == R8A779F0)
+ rcar_canfd_get_data(priv, cf,
+ RCANFD_V3U_RFDF(ridx, 0));
+ else
+@@ -1719,7 +1789,7 @@ static void rcar_canfd_rx_pkt(struct rcar_canfd_channel *priv)
+ if (id & RCANFD_RFID_RFRTR)
+ cf->can_id |= CAN_RTR_FLAG;
+ else
+- if ((gpriv->chip_id == R8A779A0) || (gpriv->chip_id == R8A779G0))
++ if (gpriv->chip_id == R8A779A0 || gpriv->chip_id == R8A779G0 || gpriv->chip_id == R8A779F0)
+ rcar_canfd_get_data(priv, cf,
+ RCANFD_V3U_RFDF(ridx, 0));
+ else
+@@ -1730,7 +1800,7 @@ static void rcar_canfd_rx_pkt(struct rcar_canfd_channel *priv)
+ /* Write 0xff to RFPC to increment the CPU-side
+ * pointer of the Rx FIFO
+ */
+- if ((gpriv->chip_id == R8A779A0) || (gpriv->chip_id == R8A779G0))
++ if (gpriv->chip_id == R8A779A0 || gpriv->chip_id == R8A779G0 || gpriv->chip_id == R8A779F0)
+ rcar_canfd_write(priv->base, RCANFD_V3U_RFPCTR(ridx), 0xff);
+ else
+ rcar_canfd_write(priv->base, RCANFD_RFPCTR(ridx), 0xff);
+@@ -1752,7 +1822,7 @@ static int rcar_canfd_rx_poll(struct napi_struct *napi, int quota)
+ u32 ridx = ch + RCANFD_RFFIFO_IDX, addr1, addr2;
+ struct rcar_canfd_global *gpriv = priv->gpriv;
+
+- if ((gpriv->chip_id == R8A779A0) || (gpriv->chip_id == R8A779G0)) {
++ if (gpriv->chip_id == R8A779A0 || gpriv->chip_id == R8A779G0 || gpriv->chip_id == R8A779F0) {
+ addr1 = RCANFD_V3U_RFSTS(ridx);
+ addr2 = RCANFD_V3U_RFCC(ridx);
+ } else {
+@@ -1867,15 +1937,15 @@ static int rcar_canfd_channel_probe(struct rcar_canfd_global *gpriv, u32 ch,
+
+ netif_napi_add(ndev, &priv->napi, rcar_canfd_rx_poll,
+ RCANFD_NAPI_WEIGHT);
++ spin_lock_init(&priv->tx_lock);
++ devm_can_led_init(ndev);
++ gpriv->ch[priv->channel] = priv;
+ err = register_candev(ndev);
+ if (err) {
+ dev_err(&pdev->dev,
+ "register_candev() failed, error %d\n", err);
+ goto fail_candev;
+ }
+- spin_lock_init(&priv->tx_lock);
+- devm_can_led_init(ndev);
+- gpriv->ch[priv->channel] = priv;
+ dev_info(&pdev->dev, "device registered (channel %u)\n", priv->channel);
+ return 0;
+
+@@ -1904,7 +1974,8 @@ static int rcar_canfd_probe(struct platform_device *pdev)
+ struct rcar_canfd_global *gpriv;
+ struct device_node *of_child;
+ unsigned long channels_mask = 0;
+- int err, ch_irq, g_irq, i;
++ int err, g_irq, ch_irq, i, num_ch_enabled = 0;
++ int ch_irq_s4[RCANFD_NUM_CHANNELS] = {0, 0, 0, 0, 0, 0, 0, 0};
+ bool fdmode = true; /* CAN FD only mode - default */
+ const struct rcar_canfd_of_data *of_data;
+ char *name[RCANFD_NUM_CHANNELS] = {
+@@ -1925,13 +1996,28 @@ static int rcar_canfd_probe(struct platform_device *pdev)
+ channels_mask |= BIT(i); /* Channel i */
+ }
+
+- ch_irq = platform_get_irq(pdev, 0);
++ /* ch_irq = platform_get_irq(pdev, 0);
+ if (ch_irq < 0) {
+ err = ch_irq;
+ goto fail_dev;
+ }
+
+ g_irq = platform_get_irq(pdev, 1);
++ if (g_irq < 0) {
++ err = g_irq;
++ goto fail_dev;
++ } */
++
++ /* Porting for R8A779F0 */
++ for (i = 0; i < RCANFD_NUM_CHANNELS; i++) {
++ ch_irq_s4[i] = platform_get_irq(pdev, i + 1);
++ if (ch_irq_s4[i] < 0) {
++ err = ch_irq_s4[i];
++ goto fail_dev;
++ }
++ }
++
++ g_irq = platform_get_irq(pdev, 0);
+ if (g_irq < 0) {
+ err = g_irq;
+ goto fail_dev;
+@@ -1950,13 +2036,14 @@ static int rcar_canfd_probe(struct platform_device *pdev)
+ gpriv->max_channels = of_data->max_channels;
+
+ /* Peripheral clock */
+- gpriv->clkp = devm_clk_get(&pdev->dev, "fck");
++ /* Porting for R8A779F0, not use fck */
++ /* gpriv->clkp = devm_clk_get(&pdev->dev, "fck");
+ if (IS_ERR(gpriv->clkp)) {
+ err = PTR_ERR(gpriv->clkp);
+ dev_err(&pdev->dev, "cannot get peripheral clock, error %d\n",
+ err);
+ goto fail_dev;
+- }
++ } */
+
+ /* fCAN clock: Pick External clock. If not available fallback to
+ * CANFD clock
+@@ -1971,15 +2058,16 @@ static int rcar_canfd_probe(struct platform_device *pdev)
+ goto fail_dev;
+ }
+ gpriv->fcan = RCANFD_CANFDCLK;
+-
+ } else {
+ gpriv->fcan = RCANFD_EXTCLK;
+ }
+ fcan_freq = clk_get_rate(gpriv->can_clk);
+
+ if (gpriv->fcan == RCANFD_CANFDCLK)
++ {
+ /* CANFD clock is further divided by (1/2) within the IP */
+ fcan_freq /= 2;
++ }
+
+ addr = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(addr)) {
+@@ -1989,14 +2077,27 @@ static int rcar_canfd_probe(struct platform_device *pdev)
+ gpriv->base = addr;
+
+ /* Request IRQ that's common for both channels */
+- err = devm_request_irq(&pdev->dev, ch_irq,
+- rcar_canfd_channel_interrupt, 0,
+- "canfd.chn", gpriv);
++ /* err = devm_request_irq(&pdev->dev, ch_irq,
++ rcar_canfd_channel_interrupt, 0,
++ "canfd.chn", gpriv);
+ if (err) {
+ dev_err(&pdev->dev, "devm_request_irq(%d) failed, error %d\n",
+ ch_irq, err);
+ goto fail_dev;
++ } */
++
++ /* Porting for R8A779F0 */
++ for (i = 0; i < RCANFD_NUM_CHANNELS; i++) {
++ err = devm_request_irq(&pdev->dev, ch_irq_s4[i],
++ rcar_canfd_channel_interrupt, 0,
++ "canfd.chn", gpriv);
++ if (err) {
++ dev_err(&pdev->dev, "devm_request_irq(%d) failed, error %d\n",
++ ch_irq_s4[i], err);
++ goto fail_dev;
++ }
+ }
++
+ err = devm_request_irq(&pdev->dev, g_irq,
+ rcar_canfd_global_interrupt, 0,
+ "canfd.gbl", gpriv);
+@@ -2032,7 +2133,8 @@ static int rcar_canfd_probe(struct platform_device *pdev)
+ rcar_canfd_configure_tx(gpriv, ch);
+
+ /* Configure receive rules */
+- rcar_canfd_configure_afl_rules(gpriv, ch);
++ rcar_canfd_configure_afl_rules(gpriv, ch, num_ch_enabled);
++ num_ch_enabled++;
+ }
+
+ /* Configure common interrupts */
+@@ -2109,6 +2211,11 @@ static const struct rcar_canfd_of_data of_rcanfd_v4h_compatible = {
+ .max_channels = 8,
+ };
+
++static const struct rcar_canfd_of_data of_rcanfd_s4_compatible = {
++ .chip_id = R8A779F0,
++ .max_channels = 8,
++};
++
+ static const struct rcar_canfd_of_data of_rcanfd_v3u_compatible = {
+ .chip_id = R8A779A0,
+ .max_channels = 8,
+@@ -2124,6 +2231,10 @@ static const struct of_device_id rcar_canfd_of_table[] = {
+ .compatible = "renesas,r8a779g0-canfd",
+ .data = &of_rcanfd_v4h_compatible,
+ },
++ {
++ .compatible = "renesas,r8a779f0-canfd",
++ .data = &of_rcanfd_s4_compatible,
++ },
+ {
+ .compatible = "renesas,r8a779a0-canfd",
+ .data = &of_rcanfd_v3u_compatible,
+diff --git a/drivers/pinctrl/renesas/pfc-r8a779f0.c b/drivers/pinctrl/renesas/pfc-r8a779f0.c
+index de01d4d6b1b1..822b4f7e450f 100644
+--- a/drivers/pinctrl/renesas/pfc-r8a779f0.c
++++ b/drivers/pinctrl/renesas/pfc-r8a779f0.c
+@@ -11,8 +11,10 @@
+ #include <linux/io.h>
+ #include <linux/kernel.h>
+
++#include "core.h"
+ #include "sh_pfc.h"
+
++#define ENABLE_ACCESS_TO_CONTROL_DOMAIN
+ #define CFG_FLAGS (SH_PFC_PIN_CFG_DRIVE_STRENGTH | SH_PFC_PIN_CFG_PULL_UP_DOWN)
+
+ #define CPU_ALL_GP(fn, sfx) \
+@@ -1170,6 +1172,150 @@ static const struct sh_pfc_pin pinmux_pins[] = {
+ PINMUX_GPIO_GP_ALL(),
+ };
+
++/* - CANFD0 ----------------------------------------------------------------- */
++static const unsigned int canfd0_data_pins[] = {
++ /* CANFD0_TX, CANFD0_RX */
++ RCAR_GP_PIN(7, 0), RCAR_GP_PIN(7, 1),
++};
++static const unsigned int canfd0_data_mux[] = {
++ CAN0TX_MARK, CAN0RX_INTP0_MARK,
++};
++
++/* - CANFD1 ----------------------------------------------------------------- */
++static const unsigned int canfd1_data_pins[] = {
++ /* CANFD1_TX, CANFD1_RX */
++ RCAR_GP_PIN(7, 2), RCAR_GP_PIN(7, 3),
++};
++static const unsigned int canfd1_data_mux[] = {
++ CAN1TX_MARK, CAN1RX_INTP1_MARK,
++};
++
++/* - CANFD2 ----------------------------------------------------------------- */
++static const unsigned int canfd2_data_pins[] = {
++ /* CANFD2_TX, CANFD2_RX */
++ RCAR_GP_PIN(7, 4), RCAR_GP_PIN(7, 5),
++};
++static const unsigned int canfd2_data_mux[] = {
++ CAN2TX_MARK, CAN2RX_INTP2_MARK,
++};
++
++/* - CANFD3 ----------------------------------------------------------------- */
++static const unsigned int canfd3_data_pins[] = {
++ /* CANFD2_TX, CANFD2_RX */
++ RCAR_GP_PIN(7, 6), RCAR_GP_PIN(7, 7),
++};
++static const unsigned int canfd3_data_mux[] = {
++ CAN3TX_MARK, CAN3RX_INTP3_MARK,
++};
++
++/* - CANFD4 ----------------------------------------------------------------- */
++static const unsigned int canfd4_data_pins[] = {
++ /* CANFD4_TX, CANFD4_RX */
++ RCAR_GP_PIN(7, 8), RCAR_GP_PIN(7, 9),
++};
++static const unsigned int canfd4_data_mux[] = {
++ CAN4TX_MARK, CAN4RX_INTP4_MARK,
++};
++
++/* - CANFD5 ----------------------------------------------------------------- */
++static const unsigned int canfd5_data_pins[] = {
++ /* CANFD5_TX, CANFD5_RX */
++ RCAR_GP_PIN(7, 10), RCAR_GP_PIN(7, 11),
++};
++static const unsigned int canfd5_data_mux[] = {
++ CAN5TX_MARK, CAN5RX_INTP5_MARK,
++};
++
++/* - CANFD6 ----------------------------------------------------------------- */
++static const unsigned int canfd6_data_pins[] = {
++ /* CANFD6_TX, CANFD6_RX */
++ RCAR_GP_PIN(7, 12), RCAR_GP_PIN(7, 13),
++};
++static const unsigned int canfd6_data_mux[] = {
++ CAN6TX_MARK, CAN6RX_INTP6_MARK,
++};
++
++/* - CANFD7 ----------------------------------------------------------------- */
++static const unsigned int canfd7_data_pins[] = {
++ /* CANFD7_TX, CANFD7_RX */
++ RCAR_GP_PIN(7, 14), RCAR_GP_PIN(7, 15),
++};
++static const unsigned int canfd7_data_mux[] = {
++ CAN7TX_MARK, CAN7RX_INTP7_MARK,
++};
++
++/* - CANFD8 ----------------------------------------------------------------- */
++static const unsigned int canfd8_data_pins[] = {
++ /* CANFD8_TX, CANFD8_RX */
++ RCAR_GP_PIN(7, 16), RCAR_GP_PIN(7, 17),
++};
++static const unsigned int canfd8_data_mux[] = {
++ CAN8TX_MARK, CAN8RX_INTP8_MARK,
++};
++
++/* - CANFD9 ----------------------------------------------------------------- */
++static const unsigned int canfd9_data_pins[] = {
++ /* CANFD9_TX, CANFD9_RX */
++ RCAR_GP_PIN(7, 18), RCAR_GP_PIN(7, 19),
++};
++static const unsigned int canfd9_data_mux[] = {
++ CAN9TX_MARK, CAN9RX_INTP9_MARK,
++};
++
++/* - CANFD10 ----------------------------------------------------------------- */
++static const unsigned int canfd10_data_pins[] = {
++ /* CANFD10_TX, CANFD10_RX */
++ RCAR_GP_PIN(7, 20), RCAR_GP_PIN(7, 21),
++};
++static const unsigned int canfd10_data_mux[] = {
++ CAN10TX_MARK, CAN10RX_INTP10_MARK,
++};
++
++/* - CANFD11 ----------------------------------------------------------------- */
++static const unsigned int canfd11_data_pins[] = {
++ /* CANFD11_TX, CANFD11_RX */
++ RCAR_GP_PIN(7, 22), RCAR_GP_PIN(7, 23),
++};
++static const unsigned int canfd11_data_mux[] = {
++ CAN11TX_MARK, CAN11RX_INTP11_MARK,
++};
++
++/* - CANFD12 ----------------------------------------------------------------- */
++static const unsigned int canfd12_data_pins[] = {
++ /* CANFD12_TX, CANFD12_RX */
++ RCAR_GP_PIN(7, 24), RCAR_GP_PIN(7, 25),
++};
++static const unsigned int canfd12_data_mux[] = {
++ CAN12TX_MARK, CAN12RX_INTP12_MARK,
++};
++
++/* - CANFD13 ----------------------------------------------------------------- */
++static const unsigned int canfd13_data_pins[] = {
++ /* CANFD13_TX, CANFD13_RX */
++ RCAR_GP_PIN(7, 26), RCAR_GP_PIN(7, 27),
++};
++static const unsigned int canfd13_data_mux[] = {
++ CAN13TX_MARK, CAN13RX_INTP13_MARK,
++};
++
++/* - CANFD14 ----------------------------------------------------------------- */
++static const unsigned int canfd14_data_pins[] = {
++ /* CANFD14_TX, CANFD14_RX */
++ RCAR_GP_PIN(7, 28), RCAR_GP_PIN(7, 29),
++};
++static const unsigned int canfd14_data_mux[] = {
++ CAN14TX_MARK, CAN14RX_INTP14_MARK,
++};
++
++/* - CANFD15 ----------------------------------------------------------------- */
++static const unsigned int canfd15_data_pins[] = {
++ /* CANFD15_TX, CANFD15_RX */
++ RCAR_GP_PIN(7, 30), RCAR_GP_PIN(7, 31),
++};
++static const unsigned int canfd15_data_mux[] = {
++ CAN15TX_MARK, CAN15RX_INTP15_MARK,
++};
++
+ /* - TSN0 ------------------------------------------------ */
+ static const unsigned int tsn0_link_pins[] = {
+ /* TSN0_LINK */
+@@ -1893,6 +2039,88 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
+ SH_PFC_PIN_GROUP(taud1_pwm5),
+ SH_PFC_PIN_GROUP(taud1_pwm6),
+ SH_PFC_PIN_GROUP(taud1_pwm7),
++
++ SH_PFC_PIN_GROUP(canfd0_data),
++ SH_PFC_PIN_GROUP(canfd1_data),
++ SH_PFC_PIN_GROUP(canfd2_data),
++ SH_PFC_PIN_GROUP(canfd3_data),
++ SH_PFC_PIN_GROUP(canfd4_data),
++ SH_PFC_PIN_GROUP(canfd5_data),
++ SH_PFC_PIN_GROUP(canfd6_data),
++ SH_PFC_PIN_GROUP(canfd7_data),
++
++ SH_PFC_PIN_GROUP(canfd8_data),
++ SH_PFC_PIN_GROUP(canfd9_data),
++ SH_PFC_PIN_GROUP(canfd10_data),
++ SH_PFC_PIN_GROUP(canfd11_data),
++ SH_PFC_PIN_GROUP(canfd12_data),
++ SH_PFC_PIN_GROUP(canfd13_data),
++ SH_PFC_PIN_GROUP(canfd14_data),
++ SH_PFC_PIN_GROUP(canfd15_data),
++};
++
++static const char * const canfd0_groups[] = {
++ "canfd0_data",
++};
++
++static const char * const canfd1_groups[] = {
++ "canfd1_data",
++};
++
++static const char * const canfd2_groups[] = {
++ "canfd2_data",
++};
++
++static const char * const canfd3_groups[] = {
++ "canfd3_data",
++};
++
++static const char * const canfd4_groups[] = {
++ "canfd4_data",
++};
++
++static const char * const canfd5_groups[] = {
++ "canfd5_data",
++};
++
++static const char * const canfd6_groups[] = {
++ "canfd6_data",
++};
++
++static const char * const canfd7_groups[] = {
++ "canfd7_data",
++};
++
++static const char * const canfd8_groups[] = {
++ "canfd8_data",
++};
++
++static const char * const canfd9_groups[] = {
++ "canfd9_data",
++};
++
++static const char * const canfd10_groups[] = {
++ "canfd10_data",
++};
++
++static const char * const canfd11_groups[] = {
++ "canfd11_data",
++};
++
++static const char * const canfd12_groups[] = {
++ "canfd12_data",
++};
++
++static const char * const canfd13_groups[] = {
++ "canfd13_data",
++};
++
++static const char * const canfd14_groups[] = {
++ "canfd14_data",
++};
++
++static const char * const canfd15_groups[] = {
++ "canfd15_data",
+ };
+
+ static const char * const tsn0_groups[] = {
+@@ -2050,6 +2278,24 @@ static const char * const taud1_pwm_groups[] = {
+ };
+
+ static const struct sh_pfc_function pinmux_functions[] = {
++ SH_PFC_FUNCTION(canfd0),
++ SH_PFC_FUNCTION(canfd1),
++ SH_PFC_FUNCTION(canfd2),
++ SH_PFC_FUNCTION(canfd3),
++ SH_PFC_FUNCTION(canfd4),
++ SH_PFC_FUNCTION(canfd5),
++ SH_PFC_FUNCTION(canfd6),
++ SH_PFC_FUNCTION(canfd7),
++
++ SH_PFC_FUNCTION(canfd8),
++ SH_PFC_FUNCTION(canfd9),
++ SH_PFC_FUNCTION(canfd10),
++ SH_PFC_FUNCTION(canfd11),
++ SH_PFC_FUNCTION(canfd12),
++ SH_PFC_FUNCTION(canfd13),
++ SH_PFC_FUNCTION(canfd14),
++ SH_PFC_FUNCTION(canfd15),
++
+ SH_PFC_FUNCTION(tsn0),
+ SH_PFC_FUNCTION(tsn1),
+ SH_PFC_FUNCTION(tsn2),
+--
+2.25.1
+
diff --git a/meta-agl-bsp/meta-rcar-gateway/recipes-kernel/linux/linux-renesas_%.bbappend b/meta-agl-bsp/meta-rcar-gateway/recipes-kernel/linux/linux-renesas_%.bbappend
index d565da8ac..4baf07552 100644
--- a/meta-agl-bsp/meta-rcar-gateway/recipes-kernel/linux/linux-renesas_%.bbappend
+++ b/meta-agl-bsp/meta-rcar-gateway/recipes-kernel/linux/linux-renesas_%.bbappend
@@ -1,3 +1,9 @@
+FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
+
+SRC_URI:append = " \
+ ${@bb.utils.contains('MACHINE_FEATURES', 'canfd', 'file://0001-Porting-to-support-device-driver-Canfd-from-Control-.patch', '', d)} \
+"
+
do_install:append () {
# Remove firmware file that is not packaged in the kernel.