diff mbox series

[QEMU,2/5] hw/net/can: Introduce Xilinx Versal CANFD controller

Message ID 20220910061252.2614-2-vikram.garhwal@amd.com
State New
Headers show
Series [QEMU,1/5] MAINTAINERS: Update maintainer's email for Xilinx CAN | expand

Commit Message

Vikram Garhwal Sept. 10, 2022, 6:12 a.m. UTC
The Xilinx Versal CANFD controller is developed based on SocketCAN, QEMU CAN bus
implementation. Bus connection and socketCAN connection for each CAN module
can be set through command lines.

Example for using connecting CANFD0 and CANFD1 to same bus:
    -machine xlnx-versal-virt
    -object can-bus,id=canbus
    -machine canbus0=canbus
    -machine canbus1=canbus

To create virtual CAN on the host machine, please check the QEMU CAN docs:
https://github.com/qemu/qemu/blob/master/docs/can.txt

Signed-off-by: Vikram Garhwal <vikram.garhwal@amd.com>
---
 hw/net/can/meson.build             |    1 +
 hw/net/can/trace-events            |    7 +
 hw/net/can/xlnx-versal-canfd.c     | 2157 ++++++++++++++++++++++++++++
 include/hw/net/xlnx-versal-canfd.h |   92 ++
 4 files changed, 2257 insertions(+)
 create mode 100644 hw/net/can/xlnx-versal-canfd.c
 create mode 100644 include/hw/net/xlnx-versal-canfd.h

Comments

Peter Maydell Sept. 22, 2022, 2:46 p.m. UTC | #1
On Sat, 10 Sept 2022 at 07:13, Vikram Garhwal <vikram.garhwal@amd.com> wrote:
>
> The Xilinx Versal CANFD controller is developed based on SocketCAN, QEMU CAN bus
> implementation. Bus connection and socketCAN connection for each CAN module
> can be set through command lines.
>
> Example for using connecting CANFD0 and CANFD1 to same bus:
>     -machine xlnx-versal-virt
>     -object can-bus,id=canbus
>     -machine canbus0=canbus
>     -machine canbus1=canbus
>
> To create virtual CAN on the host machine, please check the QEMU CAN docs:
> https://github.com/qemu/qemu/blob/master/docs/can.txt

That link is a 404. You could just give the relative path to the
docs in the repo, which is docs/system/devices/can.rst

For the machine specifics, you should include (either in the patch 4
where you add this to the xlnx-versal-virt board, or in a separate patch
if it seems too big) updates to docs/system/arm/xlnx-versal-virt.rst
which document the new functionality, including, if it's useful to users,
some documentation of how to use it.


> +/* To avoid the build issues on Windows machines. */
> +#undef ERROR

What ?

> +static void canfd_config_mode(XlnxVersalCANFDState *s)
> +{
> +    register_reset(&s->reg_info[R_ERROR_COUNTER_REGISTER]);
> +    register_reset(&s->reg_info[R_ERROR_STATUS_REGISTER]);
> +    register_reset(&s->reg_info[R_STATUS_REGISTER]);
> +
> +    /* Put XlnxVersalCANFDState in configuration mode. */
> +    ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, CONFIG, 1);
> +    ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, WKUP, 0);
> +    ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, SLP, 0);
> +    ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, BSOFF, 0);
> +    ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, ERROR, 0);
> +    ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXFOFLW, 0);
> +    ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXFOFLW_1, 0);
> +    ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 0);
> +    ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXOK, 0);
> +    ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, ARBLST, 0);
> +
> +    /* Clear the time stamp. */
> +    ptimer_transaction_begin(s->canfd_timer);
> +    ptimer_set_count(s->canfd_timer, 0);
> +    ptimer_transaction_commit(s->canfd_timer);
> +
> +    canfd_update_irq(s);
> +}
> +

A lot of this looks like it's just copy-and-pasted code from
the existing hw/net/can/xlnx-zynqmp-can.c. Is this just an
updated/extra-features version of that device? Is there some
way we can share the code rather than duplicating 2000-odd lines ?

> +#ifndef HW_CANFD_XILINX_H
> +#define HW_CANFD_XILINX_H
> +
> +#include "hw/register.h"
> +#include "hw/ptimer.h"
> +#include "net/can_emu.h"
> +#include "hw/qdev-clock.h"
> +
> +#define TYPE_XILINX_CANFD "xlnx.versal-canfd"

Should this be a dot or a comma? The codebase has examples of
both for xlnx devices :-(

> +
> +#define XILINX_CANFD(obj) \
> +     OBJECT_CHECK(XlnxVersalCANFDState, (obj), TYPE_XILINX_CANFD)

Please use OBJECT_DECLARE_SIMPLE_TYPE() rather than defining the
cast macro by hand.

> +
> +#define NUM_REGS_PER_MSG_SPACE 18
> +#define MAX_NUM_RX             64
> +#define CANFD_TIMER_MAX        0XFFFFUL

Don't use capital X in the 0x hex prefix, please.

> +#define CANFD_DEFAULT_CLOCK    (24 * 1000 * 1000)
> +
> +/* 0x4144/4 + 1 + (64 - 1) * 18 + 1. */

This comment isn't very informative. The #define itself is much
better because it uses symbolic constants.

What is the magic number 0x4144. It should either be defined via
some kind of symbolic constant, or if that's not possible at least
explained in a comment.

> +#define XLNX_VERSAL_CANFD_R_MAX (0x4144 / 4  + \
> +                    ((MAX_NUM_RX - 1) * NUM_REGS_PER_MSG_SPACE) + 1)

thanks
-- PMM
Pavel Pisa Sept. 22, 2022, 4:27 p.m. UTC | #2
Hello Peter,

thanks for the review and Vikram for his work, I do not know
much about Xilinx emulation nor Xilixn CAN controllers so I cannot
comment much on this part.

On Thursday 22 of September 2022 16:46:48 Peter Maydell wrote:
> On Sat, 10 Sept 2022 at 07:13, Vikram Garhwal <vikram.garhwal@amd.com> > > To create virtual CAN on the host machine, please check the QEMU CAN
> > docs: https://github.com/qemu/qemu/blob/master/docs/can.txt
>
> That link is a 404. You could just give the relative path to the
> docs in the repo, which is docs/system/devices/can.rst

The actual generated documentation is located at

  https://www.qemu.org/docs/master/system/devices/can.html

I think that that URL is stable for some time... Could it
be used directly in source to provide path to formated version?

> For the machine specifics, you should include (either in the patch 4
> where you add this to the xlnx-versal-virt board, or in a separate patch
> if it seems too big) updates to docs/system/arm/xlnx-versal-virt.rst
> which document the new functionality, including, if it's useful to users,
> some documentation of how to use it.

Some short example how to use emulation even with Xilinx Zynq and Ultra Scale
would be nice if added into the document. If the document length expands
too much, then probably division into individual documents per controllers
would be nice.

By the way, CAN in Automation publishes our overview article about our CAN
activities including some short netion of QEMU integration

  https://can-newsletter.org/uploads/media/raw/a9abe317ae034be55d99fee4410ad70e.pdf   

I hope I wind some time for CAN in QEMU, RTEMS and Linux ongoing projects,
but I need to finish some promissed project for ESA the first.

Best wishes,

                Pavel
Vikram Garhwal Oct. 21, 2022, 10:36 p.m. UTC | #3
Hi Peter,

On 9/22/22 7:46 AM, Peter Maydell wrote:
> On Sat, 10 Sept 2022 at 07:13, Vikram Garhwal <vikram.garhwal@amd.com> wrote:
>> The Xilinx Versal CANFD controller is developed based on SocketCAN, QEMU CAN bus
>> implementation. Bus connection and socketCAN connection for each CAN module
>> can be set through command lines.
>>
>> Example for using connecting CANFD0 and CANFD1 to same bus:
>>      -machine xlnx-versal-virt
>>      -object can-bus,id=canbus
>>      -machine canbus0=canbus
>>      -machine canbus1=canbus
>>
>> To create virtual CAN on the host machine, please check the QEMU CAN docs:
>> https://github.com/qemu/qemu/blob/master/docs/can.txt
> That link is a 404. You could just give the relative path to the
> docs in the repo, which is docs/system/devices/can.rst
>
> For the machine specifics, you should include (either in the patch 4
> where you add this to the xlnx-versal-virt board, or in a separate patch
> if it seems too big) updates to docs/system/arm/xlnx-versal-virt.rst
> which document the new functionality, including, if it's useful to users,
> some documentation of how to use it.

Sorry for delay in reply. I was waiting for other to review before 
sending v2. But it's been a few weeks so I will send v2 today EoD or 
tomorrow.

I will move the documentation part in xlnx-versal-virt.rst file.

>
>
>> +/* To avoid the build issues on Windows machines. */
>> +#undef ERROR
> What ?

The ERROR field of the INTERRUPT_STATUS_REGISTER colides with a macro in 
the Windows build enviorment. Build fails due to incorrect size of ERROR 
on Windows systems.

>
>> +static void canfd_config_mode(XlnxVersalCANFDState *s)
>> +{
>> +    register_reset(&s->reg_info[R_ERROR_COUNTER_REGISTER]);
>> +    register_reset(&s->reg_info[R_ERROR_STATUS_REGISTER]);
>> +    register_reset(&s->reg_info[R_STATUS_REGISTER]);
>> +
>> +    /* Put XlnxVersalCANFDState in configuration mode. */
>> +    ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, CONFIG, 1);
>> +    ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, WKUP, 0);
>> +    ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, SLP, 0);
>> +    ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, BSOFF, 0);
>> +    ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, ERROR, 0);
>> +    ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXFOFLW, 0);
>> +    ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXFOFLW_1, 0);
>> +    ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 0);
>> +    ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXOK, 0);
>> +    ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, ARBLST, 0);
>> +
>> +    /* Clear the time stamp. */
>> +    ptimer_transaction_begin(s->canfd_timer);
>> +    ptimer_set_count(s->canfd_timer, 0);
>> +    ptimer_transaction_commit(s->canfd_timer);
>> +
>> +    canfd_update_irq(s);
>> +}
>> +
> A lot of this looks like it's just copy-and-pasted code from
> the existing hw/net/can/xlnx-zynqmp-can.c. Is this just an
> updated/extra-features version of that device? Is there some
> way we can share the code rather than duplicating 2000-odd lines ?
No, both are very different controllers. Versal SoCs CANFD has lot more 
registers, RX/TX FIFOs compare to ZynqMP CAN device. Interrupt handling, 
overflow conditions are also different. I will recheck if can find some 
common function and can use for both with making the code more complex.
>
>> +#ifndef HW_CANFD_XILINX_H
>> +#define HW_CANFD_XILINX_H
>> +
>> +#include "hw/register.h"
>> +#include "hw/ptimer.h"
>> +#include "net/can_emu.h"
>> +#include "hw/qdev-clock.h"
>> +
>> +#define TYPE_XILINX_CANFD "xlnx.versal-canfd"
> Should this be a dot or a comma? The codebase has examples of
> both for xlnx devices :-(

You are right about dot or comma comment. We need to harmonize these 
across all Xilinx devices.
For Versal board, recently introduced machine has all dots, so I am 
following that.
Let me check with team here and perhaps we can send another series to 
address the dot/comma variations.

>
>> +
>> +#define XILINX_CANFD(obj) \
>> +     OBJECT_CHECK(XlnxVersalCANFDState, (obj), TYPE_XILINX_CANFD)
> Please use OBJECT_DECLARE_SIMPLE_TYPE() rather than defining the
> cast macro by hand.
>
>> +
>> +#define NUM_REGS_PER_MSG_SPACE 18
>> +#define MAX_NUM_RX             64
>> +#define CANFD_TIMER_MAX        0XFFFFUL
> Don't use capital X in the 0x hex prefix, please.
>
>> +#define CANFD_DEFAULT_CLOCK    (24 * 1000 * 1000)
>> +
>> +/* 0x4144/4 + 1 + (64 - 1) * 18 + 1. */
> This comment isn't very informative. The #define itself is much
> better because it uses symbolic constants.
>
> What is the magic number 0x4144. It should either be defined via
> some kind of symbolic constant, or if that's not possible at least
> explained in a comment.
Rest of the comments will be resolved in v2.
>> +#define XLNX_VERSAL_CANFD_R_MAX (0x4144 / 4  + \
>> +                    ((MAX_NUM_RX - 1) * NUM_REGS_PER_MSG_SPACE) + 1)
> thanks
> -- PMM
diff mbox series

Patch

diff --git a/hw/net/can/meson.build b/hw/net/can/meson.build
index 8fabbd9ee6..8d85201cb0 100644
--- a/hw/net/can/meson.build
+++ b/hw/net/can/meson.build
@@ -5,3 +5,4 @@  softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: files('can_mioe3680_pci.c'))
 softmmu_ss.add(when: 'CONFIG_CAN_CTUCANFD', if_true: files('ctucan_core.c'))
 softmmu_ss.add(when: 'CONFIG_CAN_CTUCANFD_PCI', if_true: files('ctucan_pci.c'))
 softmmu_ss.add(when: 'CONFIG_XLNX_ZYNQMP', if_true: files('xlnx-zynqmp-can.c'))
+softmmu_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal-canfd.c'))
diff --git a/hw/net/can/trace-events b/hw/net/can/trace-events
index 8346a98ab5..de64ac1b31 100644
--- a/hw/net/can/trace-events
+++ b/hw/net/can/trace-events
@@ -7,3 +7,10 @@  xlnx_can_filter_mask_pre_write(uint8_t filter_num, uint32_t value) "Filter%d MAS
 xlnx_can_tx_data(uint32_t id, uint8_t dlc, uint8_t db0, uint8_t db1, uint8_t db2, uint8_t db3, uint8_t db4, uint8_t db5, uint8_t db6, uint8_t db7) "Frame: ID: 0x%08x DLC: 0x%02x DATA: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x"
 xlnx_can_rx_data(uint32_t id, uint32_t dlc, uint8_t db0, uint8_t db1, uint8_t db2, uint8_t db3, uint8_t db4, uint8_t db5, uint8_t db6, uint8_t db7) "Frame: ID: 0x%08x DLC: 0x%02x DATA: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x"
 xlnx_can_rx_discard(uint32_t status) "Controller is not enabled for bus communication. Status Register: 0x%08x"
+
+# xlnx-versal-canfd.c
+xlnx_canfd_update_irq(char *path, uint32_t isr, uint32_t ier, uint32_t irq) "%s: ISR: 0x%08x IER: 0x%08x IRQ: 0x%08x"
+xlnx_canfd_rx_fifo_filter_reject(char *path, uint32_t id, uint8_t dlc) "%s: Frame: ID: 0x%08x DLC: 0x%02x"
+xlnx_canfd_rx_data(char *path, uint32_t id, uint8_t dlc, uint8_t flags) "%s: Frame: ID: 0x%08x DLC: 0x%02x CANFD Flag: 0x%02x"
+xlnx_canfd_tx_data(char *path, uint32_t id, uint8_t dlc, uint8_t flgas) "%s: Frame: ID: 0x%08x DLC: 0x%02x CANFD Flag: 0x%02x"
+xlnx_canfd_reset(char *path, uint32_t val) "%s: Resetting controller with value = 0x%08x"
diff --git a/hw/net/can/xlnx-versal-canfd.c b/hw/net/can/xlnx-versal-canfd.c
new file mode 100644
index 0000000000..7cfc8fee12
--- /dev/null
+++ b/hw/net/can/xlnx-versal-canfd.c
@@ -0,0 +1,2157 @@ 
+/*
+ * QEMU model of the Xilinx Versal CANFD device.
+ *
+ * This implementation is based on the following datasheet:
+ * https://docs.xilinx.com/v/u/2.0-English/pg223-canfd
+ *
+ * Copyright (c) 2022 AMD Inc.
+ *
+ * Written-by: Vikram Garhwal<vikram.garhwal@amd.com>
+ *
+ * Based on QEMU CANFD Device emulation implemented by Jin Yang, Deniz Eren and
+ * Pavel Pisa
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/irq.h"
+#include "hw/register.h"
+#include "qapi/error.h"
+#include "qemu/bitops.h"
+#include "qemu/log.h"
+#include "qemu/cutils.h"
+#include "qemu/event_notifier.h"
+#include "hw/qdev-properties.h"
+#include "qom/object_interfaces.h"
+#include "migration/vmstate.h"
+#include "hw/net/xlnx-versal-canfd.h"
+#include "trace.h"
+
+/* To avoid the build issues on Windows machines. */
+#undef ERROR
+
+REG32(SOFTWARE_RESET_REGISTER, 0x0)
+    FIELD(SOFTWARE_RESET_REGISTER, CEN, 1, 1)
+    FIELD(SOFTWARE_RESET_REGISTER, SRST, 0, 1)
+REG32(MODE_SELECT_REGISTER, 0x4)
+    FIELD(MODE_SELECT_REGISTER, ITO, 8, 8)
+    FIELD(MODE_SELECT_REGISTER, ABR, 7, 1)
+    FIELD(MODE_SELECT_REGISTER, SBR, 6, 1)
+    FIELD(MODE_SELECT_REGISTER, DPEE, 5, 1)
+    FIELD(MODE_SELECT_REGISTER, DAR, 4, 1)
+    FIELD(MODE_SELECT_REGISTER, BRSD, 3, 1)
+    FIELD(MODE_SELECT_REGISTER, SNOOP, 2, 1)
+    FIELD(MODE_SELECT_REGISTER, LBACK, 1, 1)
+    FIELD(MODE_SELECT_REGISTER, SLEEP, 0, 1)
+REG32(ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER, 0x8)
+    FIELD(ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER, BRP, 0, 8)
+REG32(ARBITRATION_PHASE_BIT_TIMING_REGISTER, 0xc)
+    FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, SJW, 16, 7)
+    FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, TS2, 8, 7)
+    FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, TS1, 0, 8)
+REG32(ERROR_COUNTER_REGISTER, 0x10)
+    FIELD(ERROR_COUNTER_REGISTER, REC, 8, 8)
+    FIELD(ERROR_COUNTER_REGISTER, TEC, 0, 8)
+REG32(ERROR_STATUS_REGISTER, 0x14)
+    FIELD(ERROR_STATUS_REGISTER, F_BERR, 11, 1)
+    FIELD(ERROR_STATUS_REGISTER, F_STER, 10, 1)
+    FIELD(ERROR_STATUS_REGISTER, F_FMER, 9, 1)
+    FIELD(ERROR_STATUS_REGISTER, F_CRCER, 8, 1)
+    FIELD(ERROR_STATUS_REGISTER, ACKER, 4, 1)
+    FIELD(ERROR_STATUS_REGISTER, BERR, 3, 1)
+    FIELD(ERROR_STATUS_REGISTER, STER, 2, 1)
+    FIELD(ERROR_STATUS_REGISTER, FMER, 1, 1)
+    FIELD(ERROR_STATUS_REGISTER, CRCER, 0, 1)
+REG32(STATUS_REGISTER, 0x18)
+    FIELD(STATUS_REGISTER, TDCV, 16, 7)
+    FIELD(STATUS_REGISTER, SNOOP, 12, 1)
+    FIELD(STATUS_REGISTER, BSFR_CONFIG, 10, 1)
+    FIELD(STATUS_REGISTER, PEE_CONFIG, 9, 1)
+    FIELD(STATUS_REGISTER, ESTAT, 7, 2)
+    FIELD(STATUS_REGISTER, ERRWRN, 6, 1)
+    FIELD(STATUS_REGISTER, BBSY, 5, 1)
+    FIELD(STATUS_REGISTER, BIDLE, 4, 1)
+    FIELD(STATUS_REGISTER, NORMAL, 3, 1)
+    FIELD(STATUS_REGISTER, SLEEP, 2, 1)
+    FIELD(STATUS_REGISTER, LBACK, 1, 1)
+    FIELD(STATUS_REGISTER, CONFIG, 0, 1)
+REG32(INTERRUPT_STATUS_REGISTER, 0x1c)
+    FIELD(INTERRUPT_STATUS_REGISTER, TXEWMFLL, 31, 1)
+    FIELD(INTERRUPT_STATUS_REGISTER, TXEOFLW, 30, 1)
+    FIELD(INTERRUPT_STATUS_REGISTER, RXBOFLW_BI, 24, 6)
+    FIELD(INTERRUPT_STATUS_REGISTER, RXLRM_BI, 18, 6)
+    FIELD(INTERRUPT_STATUS_REGISTER, RXMNF, 17, 1)
+    FIELD(INTERRUPT_STATUS_REGISTER, RXFWMFLL_1, 16, 1)
+    FIELD(INTERRUPT_STATUS_REGISTER, RXFOFLW_1, 15, 1)
+    FIELD(INTERRUPT_STATUS_REGISTER, TXCRS, 14, 1)
+    FIELD(INTERRUPT_STATUS_REGISTER, TXRRS, 13, 1)
+    FIELD(INTERRUPT_STATUS_REGISTER, RXFWMFLL, 12, 1)
+    FIELD(INTERRUPT_STATUS_REGISTER, WKUP, 11, 1)
+    FIELD(INTERRUPT_STATUS_REGISTER, SLP, 10, 1)
+    FIELD(INTERRUPT_STATUS_REGISTER, BSOFF, 9, 1)
+    FIELD(INTERRUPT_STATUS_REGISTER, ERROR, 8, 1)
+    FIELD(INTERRUPT_STATUS_REGISTER, RXFOFLW, 6, 1)
+    FIELD(INTERRUPT_STATUS_REGISTER, TSCNT_OFLW, 5, 1)
+    FIELD(INTERRUPT_STATUS_REGISTER, RXOK, 4, 1)
+    FIELD(INTERRUPT_STATUS_REGISTER, BSFRD, 3, 1)
+    FIELD(INTERRUPT_STATUS_REGISTER, PEE, 2, 1)
+    FIELD(INTERRUPT_STATUS_REGISTER, TXOK, 1, 1)
+    FIELD(INTERRUPT_STATUS_REGISTER, ARBLST, 0, 1)
+REG32(INTERRUPT_ENABLE_REGISTER, 0x20)
+    FIELD(INTERRUPT_ENABLE_REGISTER, ETXEWMFLL, 31, 1)
+    FIELD(INTERRUPT_ENABLE_REGISTER, ETXEOFLW, 30, 1)
+    FIELD(INTERRUPT_ENABLE_REGISTER, ERXMNF, 17, 1)
+    FIELD(INTERRUPT_ENABLE_REGISTER, ERXFWMFLL_1, 16, 1)
+    FIELD(INTERRUPT_ENABLE_REGISTER, ERXFOFLW_1, 15, 1)
+    FIELD(INTERRUPT_ENABLE_REGISTER, ETXCRS, 14, 1)
+    FIELD(INTERRUPT_ENABLE_REGISTER, ETXRRS, 13, 1)
+    FIELD(INTERRUPT_ENABLE_REGISTER, ERXFWMFLL, 12, 1)
+    FIELD(INTERRUPT_ENABLE_REGISTER, EWKUP, 11, 1)
+    FIELD(INTERRUPT_ENABLE_REGISTER, ESLP, 10, 1)
+    FIELD(INTERRUPT_ENABLE_REGISTER, EBSOFF, 9, 1)
+    FIELD(INTERRUPT_ENABLE_REGISTER, EERROR, 8, 1)
+    FIELD(INTERRUPT_ENABLE_REGISTER, ERFXOFLW, 6, 1)
+    FIELD(INTERRUPT_ENABLE_REGISTER, ETSCNT_OFLW, 5, 1)
+    FIELD(INTERRUPT_ENABLE_REGISTER, ERXOK, 4, 1)
+    FIELD(INTERRUPT_ENABLE_REGISTER, EBSFRD, 3, 1)
+    FIELD(INTERRUPT_ENABLE_REGISTER, EPEE, 2, 1)
+    FIELD(INTERRUPT_ENABLE_REGISTER, ETXOK, 1, 1)
+    FIELD(INTERRUPT_ENABLE_REGISTER, EARBLOST, 0, 1)
+REG32(INTERRUPT_CLEAR_REGISTER, 0x24)
+    FIELD(INTERRUPT_CLEAR_REGISTER, CTXEWMFLL, 31, 1)
+    FIELD(INTERRUPT_CLEAR_REGISTER, CTXEOFLW, 30, 1)
+    FIELD(INTERRUPT_CLEAR_REGISTER, CRXMNF, 17, 1)
+    FIELD(INTERRUPT_CLEAR_REGISTER, CRXFWMFLL_1, 16, 1)
+    FIELD(INTERRUPT_CLEAR_REGISTER, CRXFOFLW_1, 15, 1)
+    FIELD(INTERRUPT_CLEAR_REGISTER, CTXCRS, 14, 1)
+    FIELD(INTERRUPT_CLEAR_REGISTER, CTXRRS, 13, 1)
+    FIELD(INTERRUPT_CLEAR_REGISTER, CRXFWMFLL, 12, 1)
+    FIELD(INTERRUPT_CLEAR_REGISTER, CWKUP, 11, 1)
+    FIELD(INTERRUPT_CLEAR_REGISTER, CSLP, 10, 1)
+    FIELD(INTERRUPT_CLEAR_REGISTER, CBSOFF, 9, 1)
+    FIELD(INTERRUPT_CLEAR_REGISTER, CERROR, 8, 1)
+    FIELD(INTERRUPT_CLEAR_REGISTER, CRFXOFLW, 6, 1)
+    FIELD(INTERRUPT_CLEAR_REGISTER, CTSCNT_OFLW, 5, 1)
+    FIELD(INTERRUPT_CLEAR_REGISTER, CRXOK, 4, 1)
+    FIELD(INTERRUPT_CLEAR_REGISTER, CBSFRD, 3, 1)
+    FIELD(INTERRUPT_CLEAR_REGISTER, CPEE, 2, 1)
+    FIELD(INTERRUPT_CLEAR_REGISTER, CTXOK, 1, 1)
+    FIELD(INTERRUPT_CLEAR_REGISTER, CARBLOST, 0, 1)
+REG32(TIMESTAMP_REGISTER, 0x28)
+    FIELD(TIMESTAMP_REGISTER, TIMESTAMP_CNT, 16, 16)
+    FIELD(TIMESTAMP_REGISTER, CTS, 0, 1)
+REG32(DATA_PHASE_BAUD_RATE_PRESCALER_REGISTER, 0x88)
+    FIELD(DATA_PHASE_BAUD_RATE_PRESCALER_REGISTER, TDC, 16, 1)
+    FIELD(DATA_PHASE_BAUD_RATE_PRESCALER_REGISTER, TDCOFF, 8, 6)
+    FIELD(DATA_PHASE_BAUD_RATE_PRESCALER_REGISTER, DP_BRP, 0, 8)
+REG32(DATA_PHASE_BIT_TIMING_REGISTER, 0x8c)
+    FIELD(DATA_PHASE_BIT_TIMING_REGISTER, DP_SJW, 16, 4)
+    FIELD(DATA_PHASE_BIT_TIMING_REGISTER, DP_TS2, 8, 4)
+    FIELD(DATA_PHASE_BIT_TIMING_REGISTER, DP_TS1, 0, 5)
+REG32(TX_BUFFER_READY_REQUEST_REGISTER, 0x90)
+    FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR31, 31, 1)
+    FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR30, 30, 1)
+    FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR29, 29, 1)
+    FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR28, 28, 1)
+    FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR27, 27, 1)
+    FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR26, 26, 1)
+    FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR25, 25, 1)
+    FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR24, 24, 1)
+    FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR23, 23, 1)
+    FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR22, 22, 1)
+    FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR21, 21, 1)
+    FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR20, 20, 1)
+    FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR19, 19, 1)
+    FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR18, 18, 1)
+    FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR17, 17, 1)
+    FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR16, 16, 1)
+    FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR15, 15, 1)
+    FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR14, 14, 1)
+    FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR13, 13, 1)
+    FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR12, 12, 1)
+    FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR11, 11, 1)
+    FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR10, 10, 1)
+    FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR9, 9, 1)
+    FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR8, 8, 1)
+    FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR7, 7, 1)
+    FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR6, 6, 1)
+    FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR5, 5, 1)
+    FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR4, 4, 1)
+    FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR3, 3, 1)
+    FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR2, 2, 1)
+    FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR1, 1, 1)
+    FIELD(TX_BUFFER_READY_REQUEST_REGISTER, RR0, 0, 1)
+REG32(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, 0x94)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS31, 31, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS30, 30, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS29, 29, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS28, 28, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS27, 27, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS26, 26, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS25, 25, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS24, 24, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS23, 23, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS22, 22, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS21, 21, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS20, 20, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS19, 19, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS18, 18, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS17, 17, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS16, 16, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS15, 15, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS14, 14, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS13, 13, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS12, 12, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS11, 11, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS10, 10, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS9, 9, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS8, 8, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS7, 7, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS6, 6, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS5, 5, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS4, 4, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS3, 3, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS2, 2, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS1, 1, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER, ERRS0, 0, 1)
+REG32(TX_BUFFER_CANCEL_REQUEST_REGISTER, 0x98)
+    FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR31, 31, 1)
+    FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR30, 30, 1)
+    FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR29, 29, 1)
+    FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR28, 28, 1)
+    FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR27, 27, 1)
+    FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR26, 26, 1)
+    FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR25, 25, 1)
+    FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR24, 24, 1)
+    FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR23, 23, 1)
+    FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR22, 22, 1)
+    FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR21, 21, 1)
+    FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR20, 20, 1)
+    FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR19, 19, 1)
+    FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR18, 18, 1)
+    FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR17, 17, 1)
+    FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR16, 16, 1)
+    FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR15, 15, 1)
+    FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR14, 14, 1)
+    FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR13, 13, 1)
+    FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR12, 12, 1)
+    FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR11, 11, 1)
+    FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR10, 10, 1)
+    FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR9, 9, 1)
+    FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR8, 8, 1)
+    FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR7, 7, 1)
+    FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR6, 6, 1)
+    FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR5, 5, 1)
+    FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR4, 4, 1)
+    FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR3, 3, 1)
+    FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR2, 2, 1)
+    FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR1, 1, 1)
+    FIELD(TX_BUFFER_CANCEL_REQUEST_REGISTER, CR0, 0, 1)
+REG32(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, 0x9c)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS31, 31,
+            1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS30, 30,
+            1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS29, 29,
+            1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS28, 28,
+            1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS27, 27,
+            1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS26, 26,
+            1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS25, 25,
+            1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS24, 24,
+            1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS23, 23,
+            1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS22, 22,
+            1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS21, 21,
+            1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS20, 20,
+            1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS19, 19,
+            1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS18, 18,
+            1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS17, 17,
+            1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS16, 16,
+            1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS15, 15,
+            1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS14, 14,
+            1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS13, 13,
+            1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS12, 12,
+            1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS11, 11,
+            1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS10, 10,
+            1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS9, 9, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS8, 8, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS7, 7, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS6, 6, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS5, 5, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS4, 4, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS3, 3, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS2, 2, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS1, 1, 1)
+    FIELD(INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER, ECRS0, 0, 1)
+REG32(TX_EVENT_FIFO_STATUS_REGISTER, 0xa0)
+    FIELD(TX_EVENT_FIFO_STATUS_REGISTER, TXE_FL, 8, 6)
+    FIELD(TX_EVENT_FIFO_STATUS_REGISTER, TXE_IRI, 7, 1)
+    FIELD(TX_EVENT_FIFO_STATUS_REGISTER, TXE_RI, 0, 5)
+REG32(TX_EVENT_FIFO_WATERMARK_REGISTER, 0xa4)
+    FIELD(TX_EVENT_FIFO_WATERMARK_REGISTER, TXE_FWM, 0, 5)
+REG32(ACCEPTANCE_FILTER_CONTROL_REGISTER, 0xe0)
+    FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF31, 31, 1)
+    FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF30, 30, 1)
+    FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF29, 29, 1)
+    FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF28, 28, 1)
+    FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF27, 27, 1)
+    FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF26, 26, 1)
+    FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF25, 25, 1)
+    FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF24, 24, 1)
+    FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF23, 23, 1)
+    FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF22, 22, 1)
+    FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF21, 21, 1)
+    FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF20, 20, 1)
+    FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF19, 19, 1)
+    FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF18, 18, 1)
+    FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF17, 17, 1)
+    FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF16, 16, 1)
+    FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF15, 15, 1)
+    FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF14, 14, 1)
+    FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF13, 13, 1)
+    FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF12, 12, 1)
+    FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF11, 11, 1)
+    FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF10, 10, 1)
+    FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF9, 9, 1)
+    FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF8, 8, 1)
+    FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF7, 7, 1)
+    FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF6, 6, 1)
+    FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF5, 5, 1)
+    FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF4, 4, 1)
+    FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF3, 3, 1)
+    FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF2, 2, 1)
+    FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF1, 1, 1)
+    FIELD(ACCEPTANCE_FILTER_CONTROL_REGISTER, UAF0, 0, 1)
+REG32(RX_FIFO_STATUS_REGISTER, 0xe8)
+    FIELD(RX_FIFO_STATUS_REGISTER, FL_1, 24, 7)
+    FIELD(RX_FIFO_STATUS_REGISTER, IRI_1, 23, 1)
+    FIELD(RX_FIFO_STATUS_REGISTER, RI_1, 16, 6)
+    FIELD(RX_FIFO_STATUS_REGISTER, FL, 8, 7)
+    FIELD(RX_FIFO_STATUS_REGISTER, IRI, 7, 1)
+    FIELD(RX_FIFO_STATUS_REGISTER, RI, 0, 6)
+REG32(RX_FIFO_WATERMARK_REGISTER, 0xec)
+    FIELD(RX_FIFO_WATERMARK_REGISTER, RXFP, 16, 5)
+    FIELD(RX_FIFO_WATERMARK_REGISTER, RXFWM_1, 8, 6)
+    FIELD(RX_FIFO_WATERMARK_REGISTER, RXFWM, 0, 6)
+REG32(TB_ID_REGISTER, 0x100)
+    FIELD(TB_ID_REGISTER, ID, 21, 11)
+    FIELD(TB_ID_REGISTER, SRR_RTR_RRS, 20, 1)
+    FIELD(TB_ID_REGISTER, IDE, 19, 1)
+    FIELD(TB_ID_REGISTER, ID_EXT, 1, 18)
+    FIELD(TB_ID_REGISTER, RTR_RRS, 0, 1)
+REG32(TB0_DLC_REGISTER, 0x104)
+    FIELD(TB0_DLC_REGISTER, DLC, 28, 4)
+    FIELD(TB0_DLC_REGISTER, FDF, 27, 1)
+    FIELD(TB0_DLC_REGISTER, BRS, 26, 1)
+    FIELD(TB0_DLC_REGISTER, RSVD2, 25, 1)
+    FIELD(TB0_DLC_REGISTER, EFC, 24, 1)
+    FIELD(TB0_DLC_REGISTER, MM, 16, 8)
+    FIELD(TB0_DLC_REGISTER, RSVD1, 0, 16)
+REG32(TB_DW0_REGISTER, 0x108)
+    FIELD(TB_DW0_REGISTER, DATA_BYTES0, 24, 8)
+    FIELD(TB_DW0_REGISTER, DATA_BYTES1, 16, 8)
+    FIELD(TB_DW0_REGISTER, DATA_BYTES2, 8, 8)
+    FIELD(TB_DW0_REGISTER, DATA_BYTES3, 0, 8)
+REG32(TB_DW1_REGISTER, 0x10c)
+    FIELD(TB_DW1_REGISTER, DATA_BYTES4, 24, 8)
+    FIELD(TB_DW1_REGISTER, DATA_BYTES5, 16, 8)
+    FIELD(TB_DW1_REGISTER, DATA_BYTES6, 8, 8)
+    FIELD(TB_DW1_REGISTER, DATA_BYTES7, 0, 8)
+REG32(TB_DW2_REGISTER, 0x110)
+    FIELD(TB_DW2_REGISTER, DATA_BYTES8, 24, 8)
+    FIELD(TB_DW2_REGISTER, DATA_BYTES9, 16, 8)
+    FIELD(TB_DW2_REGISTER, DATA_BYTES10, 8, 8)
+    FIELD(TB_DW2_REGISTER, DATA_BYTES11, 0, 8)
+REG32(TB_DW3_REGISTER, 0x114)
+    FIELD(TB_DW3_REGISTER, DATA_BYTES12, 24, 8)
+    FIELD(TB_DW3_REGISTER, DATA_BYTES13, 16, 8)
+    FIELD(TB_DW3_REGISTER, DATA_BYTES14, 8, 8)
+    FIELD(TB_DW3_REGISTER, DATA_BYTES15, 0, 8)
+REG32(TB_DW4_REGISTER, 0x118)
+    FIELD(TB_DW4_REGISTER, DATA_BYTES16, 24, 8)
+    FIELD(TB_DW4_REGISTER, DATA_BYTES17, 16, 8)
+    FIELD(TB_DW4_REGISTER, DATA_BYTES18, 8, 8)
+    FIELD(TB_DW4_REGISTER, DATA_BYTES19, 0, 8)
+REG32(TB_DW5_REGISTER, 0x11c)
+    FIELD(TB_DW5_REGISTER, DATA_BYTES20, 24, 8)
+    FIELD(TB_DW5_REGISTER, DATA_BYTES21, 16, 8)
+    FIELD(TB_DW5_REGISTER, DATA_BYTES22, 8, 8)
+    FIELD(TB_DW5_REGISTER, DATA_BYTES23, 0, 8)
+REG32(TB_DW6_REGISTER, 0x120)
+    FIELD(TB_DW6_REGISTER, DATA_BYTES24, 24, 8)
+    FIELD(TB_DW6_REGISTER, DATA_BYTES25, 16, 8)
+    FIELD(TB_DW6_REGISTER, DATA_BYTES26, 8, 8)
+    FIELD(TB_DW6_REGISTER, DATA_BYTES27, 0, 8)
+REG32(TB_DW7_REGISTER, 0x124)
+    FIELD(TB_DW7_REGISTER, DATA_BYTES28, 24, 8)
+    FIELD(TB_DW7_REGISTER, DATA_BYTES29, 16, 8)
+    FIELD(TB_DW7_REGISTER, DATA_BYTES30, 8, 8)
+    FIELD(TB_DW7_REGISTER, DATA_BYTES31, 0, 8)
+REG32(TB_DW8_REGISTER, 0x128)
+    FIELD(TB_DW8_REGISTER, DATA_BYTES32, 24, 8)
+    FIELD(TB_DW8_REGISTER, DATA_BYTES33, 16, 8)
+    FIELD(TB_DW8_REGISTER, DATA_BYTES34, 8, 8)
+    FIELD(TB_DW8_REGISTER, DATA_BYTES35, 0, 8)
+REG32(TB_DW9_REGISTER, 0x12c)
+    FIELD(TB_DW9_REGISTER, DATA_BYTES36, 24, 8)
+    FIELD(TB_DW9_REGISTER, DATA_BYTES37, 16, 8)
+    FIELD(TB_DW9_REGISTER, DATA_BYTES38, 8, 8)
+    FIELD(TB_DW9_REGISTER, DATA_BYTES39, 0, 8)
+REG32(TB_DW10_REGISTER, 0x130)
+    FIELD(TB_DW10_REGISTER, DATA_BYTES40, 24, 8)
+    FIELD(TB_DW10_REGISTER, DATA_BYTES41, 16, 8)
+    FIELD(TB_DW10_REGISTER, DATA_BYTES42, 8, 8)
+    FIELD(TB_DW10_REGISTER, DATA_BYTES43, 0, 8)
+REG32(TB_DW11_REGISTER, 0x134)
+    FIELD(TB_DW11_REGISTER, DATA_BYTES44, 24, 8)
+    FIELD(TB_DW11_REGISTER, DATA_BYTES45, 16, 8)
+    FIELD(TB_DW11_REGISTER, DATA_BYTES46, 8, 8)
+    FIELD(TB_DW11_REGISTER, DATA_BYTES47, 0, 8)
+REG32(TB_DW12_REGISTER, 0x138)
+    FIELD(TB_DW12_REGISTER, DATA_BYTES48, 24, 8)
+    FIELD(TB_DW12_REGISTER, DATA_BYTES49, 16, 8)
+    FIELD(TB_DW12_REGISTER, DATA_BYTES50, 8, 8)
+    FIELD(TB_DW12_REGISTER, DATA_BYTES51, 0, 8)
+REG32(TB_DW13_REGISTER, 0x13c)
+    FIELD(TB_DW13_REGISTER, DATA_BYTES52, 24, 8)
+    FIELD(TB_DW13_REGISTER, DATA_BYTES53, 16, 8)
+    FIELD(TB_DW13_REGISTER, DATA_BYTES54, 8, 8)
+    FIELD(TB_DW13_REGISTER, DATA_BYTES55, 0, 8)
+REG32(TB_DW14_REGISTER, 0x140)
+    FIELD(TB_DW14_REGISTER, DATA_BYTES56, 24, 8)
+    FIELD(TB_DW14_REGISTER, DATA_BYTES57, 16, 8)
+    FIELD(TB_DW14_REGISTER, DATA_BYTES58, 8, 8)
+    FIELD(TB_DW14_REGISTER, DATA_BYTES59, 0, 8)
+REG32(TB_DW15_REGISTER, 0x144)
+    FIELD(TB_DW15_REGISTER, DATA_BYTES60, 24, 8)
+    FIELD(TB_DW15_REGISTER, DATA_BYTES61, 16, 8)
+    FIELD(TB_DW15_REGISTER, DATA_BYTES62, 8, 8)
+    FIELD(TB_DW15_REGISTER, DATA_BYTES63, 0, 8)
+REG32(AFMR_REGISTER, 0xa00)
+    FIELD(AFMR_REGISTER, AMID, 21, 11)
+    FIELD(AFMR_REGISTER, AMSRR, 20, 1)
+    FIELD(AFMR_REGISTER, AMIDE, 19, 1)
+    FIELD(AFMR_REGISTER, AMID_EXT, 1, 18)
+    FIELD(AFMR_REGISTER, AMRTR, 0, 1)
+REG32(AFIR_REGISTER, 0xa04)
+    FIELD(AFIR_REGISTER, AIID, 21, 11)
+    FIELD(AFIR_REGISTER, AISRR, 20, 1)
+    FIELD(AFIR_REGISTER, AIIDE, 19, 1)
+    FIELD(AFIR_REGISTER, AIID_EXT, 1, 18)
+    FIELD(AFIR_REGISTER, AIRTR, 0, 1)
+REG32(TXE_FIFO_TB_ID_REGISTER, 0x2000)
+    FIELD(TXE_FIFO_TB_ID_REGISTER, ID, 21, 11)
+    FIELD(TXE_FIFO_TB_ID_REGISTER, SRR_RTR_RRS, 20, 1)
+    FIELD(TXE_FIFO_TB_ID_REGISTER, IDE, 19, 1)
+    FIELD(TXE_FIFO_TB_ID_REGISTER, ID_EXT, 1, 18)
+    FIELD(TXE_FIFO_TB_ID_REGISTER, RTR_RRS, 0, 1)
+REG32(TXE_FIFO_TB_DLC_REGISTER, 0x2004)
+    FIELD(TXE_FIFO_TB_DLC_REGISTER, DLC, 28, 4)
+    FIELD(TXE_FIFO_TB_DLC_REGISTER, FDF, 27, 1)
+    FIELD(TXE_FIFO_TB_DLC_REGISTER, BRS, 26, 1)
+    FIELD(TXE_FIFO_TB_DLC_REGISTER, ET, 24, 2)
+    FIELD(TXE_FIFO_TB_DLC_REGISTER, MM, 16, 8)
+    FIELD(TXE_FIFO_TB_DLC_REGISTER, TIMESTAMP, 0, 16)
+REG32(RB_ID_REGISTER, 0x2100)
+    FIELD(RB_ID_REGISTER, ID, 21, 11)
+    FIELD(RB_ID_REGISTER, SRR_RTR_RRS, 20, 1)
+    FIELD(RB_ID_REGISTER, IDE, 19, 1)
+    FIELD(RB_ID_REGISTER, ID_EXT, 1, 18)
+    FIELD(RB_ID_REGISTER, RTR_RRS, 0, 1)
+REG32(RB_DLC_REGISTER, 0x2104)
+    FIELD(RB_DLC_REGISTER, DLC, 28, 4)
+    FIELD(RB_DLC_REGISTER, FDF, 27, 1)
+    FIELD(RB_DLC_REGISTER, BRS, 26, 1)
+    FIELD(RB_DLC_REGISTER, ESI, 25, 1)
+    FIELD(RB_DLC_REGISTER, MATCHED_FILTER_INDEX, 16, 5)
+    FIELD(RB_DLC_REGISTER, TIMESTAMP, 0, 16)
+REG32(RB_DW0_REGISTER, 0x2108)
+    FIELD(RB_DW0_REGISTER, DATA_BYTES0, 24, 8)
+    FIELD(RB_DW0_REGISTER, DATA_BYTES1, 16, 8)
+    FIELD(RB_DW0_REGISTER, DATA_BYTES2, 8, 8)
+    FIELD(RB_DW0_REGISTER, DATA_BYTES3, 0, 8)
+REG32(RB_DW1_REGISTER, 0x210c)
+    FIELD(RB_DW1_REGISTER, DATA_BYTES4, 24, 8)
+    FIELD(RB_DW1_REGISTER, DATA_BYTES5, 16, 8)
+    FIELD(RB_DW1_REGISTER, DATA_BYTES6, 8, 8)
+    FIELD(RB_DW1_REGISTER, DATA_BYTES7, 0, 8)
+REG32(RB_DW2_REGISTER, 0x2110)
+    FIELD(RB_DW2_REGISTER, DATA_BYTES8, 24, 8)
+    FIELD(RB_DW2_REGISTER, DATA_BYTES9, 16, 8)
+    FIELD(RB_DW2_REGISTER, DATA_BYTES10, 8, 8)
+    FIELD(RB_DW2_REGISTER, DATA_BYTES11, 0, 8)
+REG32(RB_DW3_REGISTER, 0x2114)
+    FIELD(RB_DW3_REGISTER, DATA_BYTES12, 24, 8)
+    FIELD(RB_DW3_REGISTER, DATA_BYTES13, 16, 8)
+    FIELD(RB_DW3_REGISTER, DATA_BYTES14, 8, 8)
+    FIELD(RB_DW3_REGISTER, DATA_BYTES15, 0, 8)
+REG32(RB_DW4_REGISTER, 0x2118)
+    FIELD(RB_DW4_REGISTER, DATA_BYTES16, 24, 8)
+    FIELD(RB_DW4_REGISTER, DATA_BYTES17, 16, 8)
+    FIELD(RB_DW4_REGISTER, DATA_BYTES18, 8, 8)
+    FIELD(RB_DW4_REGISTER, DATA_BYTES19, 0, 8)
+REG32(RB_DW5_REGISTER, 0x211c)
+    FIELD(RB_DW5_REGISTER, DATA_BYTES20, 24, 8)
+    FIELD(RB_DW5_REGISTER, DATA_BYTES21, 16, 8)
+    FIELD(RB_DW5_REGISTER, DATA_BYTES22, 8, 8)
+    FIELD(RB_DW5_REGISTER, DATA_BYTES23, 0, 8)
+REG32(RB_DW6_REGISTER, 0x2120)
+    FIELD(RB_DW6_REGISTER, DATA_BYTES24, 24, 8)
+    FIELD(RB_DW6_REGISTER, DATA_BYTES25, 16, 8)
+    FIELD(RB_DW6_REGISTER, DATA_BYTES26, 8, 8)
+    FIELD(RB_DW6_REGISTER, DATA_BYTES27, 0, 8)
+REG32(RB_DW7_REGISTER, 0x2124)
+    FIELD(RB_DW7_REGISTER, DATA_BYTES28, 24, 8)
+    FIELD(RB_DW7_REGISTER, DATA_BYTES29, 16, 8)
+    FIELD(RB_DW7_REGISTER, DATA_BYTES30, 8, 8)
+    FIELD(RB_DW7_REGISTER, DATA_BYTES31, 0, 8)
+REG32(RB_DW8_REGISTER, 0x2128)
+    FIELD(RB_DW8_REGISTER, DATA_BYTES32, 24, 8)
+    FIELD(RB_DW8_REGISTER, DATA_BYTES33, 16, 8)
+    FIELD(RB_DW8_REGISTER, DATA_BYTES34, 8, 8)
+    FIELD(RB_DW8_REGISTER, DATA_BYTES35, 0, 8)
+REG32(RB_DW9_REGISTER, 0x212c)
+    FIELD(RB_DW9_REGISTER, DATA_BYTES36, 24, 8)
+    FIELD(RB_DW9_REGISTER, DATA_BYTES37, 16, 8)
+    FIELD(RB_DW9_REGISTER, DATA_BYTES38, 8, 8)
+    FIELD(RB_DW9_REGISTER, DATA_BYTES39, 0, 8)
+REG32(RB_DW10_REGISTER, 0x2130)
+    FIELD(RB_DW10_REGISTER, DATA_BYTES40, 24, 8)
+    FIELD(RB_DW10_REGISTER, DATA_BYTES41, 16, 8)
+    FIELD(RB_DW10_REGISTER, DATA_BYTES42, 8, 8)
+    FIELD(RB_DW10_REGISTER, DATA_BYTES43, 0, 8)
+REG32(RB_DW11_REGISTER, 0x2134)
+    FIELD(RB_DW11_REGISTER, DATA_BYTES44, 24, 8)
+    FIELD(RB_DW11_REGISTER, DATA_BYTES45, 16, 8)
+    FIELD(RB_DW11_REGISTER, DATA_BYTES46, 8, 8)
+    FIELD(RB_DW11_REGISTER, DATA_BYTES47, 0, 8)
+REG32(RB_DW12_REGISTER, 0x2138)
+    FIELD(RB_DW12_REGISTER, DATA_BYTES48, 24, 8)
+    FIELD(RB_DW12_REGISTER, DATA_BYTES49, 16, 8)
+    FIELD(RB_DW12_REGISTER, DATA_BYTES50, 8, 8)
+    FIELD(RB_DW12_REGISTER, DATA_BYTES51, 0, 8)
+REG32(RB_DW13_REGISTER, 0x213c)
+    FIELD(RB_DW13_REGISTER, DATA_BYTES52, 24, 8)
+    FIELD(RB_DW13_REGISTER, DATA_BYTES53, 16, 8)
+    FIELD(RB_DW13_REGISTER, DATA_BYTES54, 8, 8)
+    FIELD(RB_DW13_REGISTER, DATA_BYTES55, 0, 8)
+REG32(RB_DW14_REGISTER, 0x2140)
+    FIELD(RB_DW14_REGISTER, DATA_BYTES56, 24, 8)
+    FIELD(RB_DW14_REGISTER, DATA_BYTES57, 16, 8)
+    FIELD(RB_DW14_REGISTER, DATA_BYTES58, 8, 8)
+    FIELD(RB_DW14_REGISTER, DATA_BYTES59, 0, 8)
+REG32(RB_DW15_REGISTER, 0x2144)
+    FIELD(RB_DW15_REGISTER, DATA_BYTES60, 24, 8)
+    FIELD(RB_DW15_REGISTER, DATA_BYTES61, 16, 8)
+    FIELD(RB_DW15_REGISTER, DATA_BYTES62, 8, 8)
+    FIELD(RB_DW15_REGISTER, DATA_BYTES63, 0, 8)
+REG32(RB_ID_REGISTER_1, 0x4100)
+    FIELD(RB_ID_REGISTER_1, ID, 21, 11)
+    FIELD(RB_ID_REGISTER_1, SRR_RTR_RRS, 20, 1)
+    FIELD(RB_ID_REGISTER_1, IDE, 19, 1)
+    FIELD(RB_ID_REGISTER_1, ID_EXT, 1, 18)
+    FIELD(RB_ID_REGISTER_1, RTR_RRS, 0, 1)
+REG32(RB_DLC_REGISTER_1, 0x4104)
+    FIELD(RB_DLC_REGISTER_1, DLC, 28, 4)
+    FIELD(RB_DLC_REGISTER_1, FDF, 27, 1)
+    FIELD(RB_DLC_REGISTER_1, BRS, 26, 1)
+    FIELD(RB_DLC_REGISTER_1, ESI, 25, 1)
+    FIELD(RB_DLC_REGISTER_1, MATCHED_FILTER_INDEX, 16, 5)
+    FIELD(RB_DLC_REGISTER_1, TIMESTAMP, 0, 16)
+REG32(RB0_DW0_REGISTER_1, 0x4108)
+    FIELD(RB0_DW0_REGISTER_1, DATA_BYTES0, 24, 8)
+    FIELD(RB0_DW0_REGISTER_1, DATA_BYTES1, 16, 8)
+    FIELD(RB0_DW0_REGISTER_1, DATA_BYTES2, 8, 8)
+    FIELD(RB0_DW0_REGISTER_1, DATA_BYTES3, 0, 8)
+REG32(RB_DW1_REGISTER_1, 0x410c)
+    FIELD(RB_DW1_REGISTER_1, DATA_BYTES4, 24, 8)
+    FIELD(RB_DW1_REGISTER_1, DATA_BYTES5, 16, 8)
+    FIELD(RB_DW1_REGISTER_1, DATA_BYTES6, 8, 8)
+    FIELD(RB_DW1_REGISTER_1, DATA_BYTES7, 0, 8)
+REG32(RB_DW2_REGISTER_1, 0x4110)
+    FIELD(RB_DW2_REGISTER_1, DATA_BYTES8, 24, 8)
+    FIELD(RB_DW2_REGISTER_1, DATA_BYTES9, 16, 8)
+    FIELD(RB_DW2_REGISTER_1, DATA_BYTES10, 8, 8)
+    FIELD(RB_DW2_REGISTER_1, DATA_BYTES11, 0, 8)
+REG32(RB_DW3_REGISTER_1, 0x4114)
+    FIELD(RB_DW3_REGISTER_1, DATA_BYTES12, 24, 8)
+    FIELD(RB_DW3_REGISTER_1, DATA_BYTES13, 16, 8)
+    FIELD(RB_DW3_REGISTER_1, DATA_BYTES14, 8, 8)
+    FIELD(RB_DW3_REGISTER_1, DATA_BYTES15, 0, 8)
+REG32(RB_DW4_REGISTER_1, 0x4118)
+    FIELD(RB_DW4_REGISTER_1, DATA_BYTES16, 24, 8)
+    FIELD(RB_DW4_REGISTER_1, DATA_BYTES17, 16, 8)
+    FIELD(RB_DW4_REGISTER_1, DATA_BYTES18, 8, 8)
+    FIELD(RB_DW4_REGISTER_1, DATA_BYTES19, 0, 8)
+REG32(RB_DW5_REGISTER_1, 0x411c)
+    FIELD(RB_DW5_REGISTER_1, DATA_BYTES20, 24, 8)
+    FIELD(RB_DW5_REGISTER_1, DATA_BYTES21, 16, 8)
+    FIELD(RB_DW5_REGISTER_1, DATA_BYTES22, 8, 8)
+    FIELD(RB_DW5_REGISTER_1, DATA_BYTES23, 0, 8)
+REG32(RB_DW6_REGISTER_1, 0x4120)
+    FIELD(RB_DW6_REGISTER_1, DATA_BYTES24, 24, 8)
+    FIELD(RB_DW6_REGISTER_1, DATA_BYTES25, 16, 8)
+    FIELD(RB_DW6_REGISTER_1, DATA_BYTES26, 8, 8)
+    FIELD(RB_DW6_REGISTER_1, DATA_BYTES27, 0, 8)
+REG32(RB_DW7_REGISTER_1, 0x4124)
+    FIELD(RB_DW7_REGISTER_1, DATA_BYTES28, 24, 8)
+    FIELD(RB_DW7_REGISTER_1, DATA_BYTES29, 16, 8)
+    FIELD(RB_DW7_REGISTER_1, DATA_BYTES30, 8, 8)
+    FIELD(RB_DW7_REGISTER_1, DATA_BYTES31, 0, 8)
+REG32(RB_DW8_REGISTER_1, 0x4128)
+    FIELD(RB_DW8_REGISTER_1, DATA_BYTES32, 24, 8)
+    FIELD(RB_DW8_REGISTER_1, DATA_BYTES33, 16, 8)
+    FIELD(RB_DW8_REGISTER_1, DATA_BYTES34, 8, 8)
+    FIELD(RB_DW8_REGISTER_1, DATA_BYTES35, 0, 8)
+REG32(RB_DW9_REGISTER_1, 0x412c)
+    FIELD(RB_DW9_REGISTER_1, DATA_BYTES36, 24, 8)
+    FIELD(RB_DW9_REGISTER_1, DATA_BYTES37, 16, 8)
+    FIELD(RB_DW9_REGISTER_1, DATA_BYTES38, 8, 8)
+    FIELD(RB_DW9_REGISTER_1, DATA_BYTES39, 0, 8)
+REG32(RB_DW10_REGISTER_1, 0x4130)
+    FIELD(RB_DW10_REGISTER_1, DATA_BYTES40, 24, 8)
+    FIELD(RB_DW10_REGISTER_1, DATA_BYTES41, 16, 8)
+    FIELD(RB_DW10_REGISTER_1, DATA_BYTES42, 8, 8)
+    FIELD(RB_DW10_REGISTER_1, DATA_BYTES43, 0, 8)
+REG32(RB_DW11_REGISTER_1, 0x4134)
+    FIELD(RB_DW11_REGISTER_1, DATA_BYTES44, 24, 8)
+    FIELD(RB_DW11_REGISTER_1, DATA_BYTES45, 16, 8)
+    FIELD(RB_DW11_REGISTER_1, DATA_BYTES46, 8, 8)
+    FIELD(RB_DW11_REGISTER_1, DATA_BYTES47, 0, 8)
+REG32(RB_DW12_REGISTER_1, 0x4138)
+    FIELD(RB_DW12_REGISTER_1, DATA_BYTES48, 24, 8)
+    FIELD(RB_DW12_REGISTER_1, DATA_BYTES49, 16, 8)
+    FIELD(RB_DW12_REGISTER_1, DATA_BYTES50, 8, 8)
+    FIELD(RB_DW12_REGISTER_1, DATA_BYTES51, 0, 8)
+REG32(RB_DW13_REGISTER_1, 0x413c)
+    FIELD(RB_DW13_REGISTER_1, DATA_BYTES52, 24, 8)
+    FIELD(RB_DW13_REGISTER_1, DATA_BYTES53, 16, 8)
+    FIELD(RB_DW13_REGISTER_1, DATA_BYTES54, 8, 8)
+    FIELD(RB_DW13_REGISTER_1, DATA_BYTES55, 0, 8)
+REG32(RB_DW14_REGISTER_1, 0x4140)
+    FIELD(RB_DW14_REGISTER_1, DATA_BYTES56, 24, 8)
+    FIELD(RB_DW14_REGISTER_1, DATA_BYTES57, 16, 8)
+    FIELD(RB_DW14_REGISTER_1, DATA_BYTES58, 8, 8)
+    FIELD(RB_DW14_REGISTER_1, DATA_BYTES59, 0, 8)
+REG32(RB_DW15_REGISTER_1, 0x4144)
+    FIELD(RB_DW15_REGISTER_1, DATA_BYTES60, 24, 8)
+    FIELD(RB_DW15_REGISTER_1, DATA_BYTES61, 16, 8)
+    FIELD(RB_DW15_REGISTER_1, DATA_BYTES62, 8, 8)
+    FIELD(RB_DW15_REGISTER_1, DATA_BYTES63, 0, 8)
+
+static uint8_t canfd_dlc_array[8] = {8, 12, 16, 20, 24, 32, 48, 64};
+
+static void canfd_update_irq(XlnxVersalCANFDState *s)
+{
+    unsigned int irq = s->regs[R_INTERRUPT_STATUS_REGISTER] &
+                        s->regs[R_INTERRUPT_ENABLE_REGISTER];
+
+    /* RX watermark interrupts. */
+    if (ARRAY_FIELD_EX32(s->regs, RX_FIFO_STATUS_REGISTER, FL) >
+        ARRAY_FIELD_EX32(s->regs, RX_FIFO_WATERMARK_REGISTER, RXFWM)) {
+        ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXFWMFLL, 1);
+    }
+
+    if (ARRAY_FIELD_EX32(s->regs, RX_FIFO_STATUS_REGISTER, FL_1) >
+        ARRAY_FIELD_EX32(s->regs, RX_FIFO_WATERMARK_REGISTER, RXFWM_1)) {
+        ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXFWMFLL_1, 1);
+    }
+
+    /* TX watermark interrupt. */
+    if (ARRAY_FIELD_EX32(s->regs, TX_EVENT_FIFO_STATUS_REGISTER, TXE_FL) >
+        ARRAY_FIELD_EX32(s->regs, TX_EVENT_FIFO_WATERMARK_REGISTER, TXE_FWM)) {
+        ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXEWMFLL, 1);
+    }
+
+    g_autofree char *path = object_get_canonical_path(OBJECT(s));
+
+    trace_xlnx_canfd_update_irq(path, s->regs[R_INTERRUPT_STATUS_REGISTER],
+                                s->regs[R_INTERRUPT_ENABLE_REGISTER], irq);
+
+    qemu_set_irq(s->irq_canfd_int, irq);
+}
+
+static void canfd_ier_post_write(RegisterInfo *reg, uint64_t val64)
+{
+    XlnxVersalCANFDState *s = XILINX_CANFD(reg->opaque);
+
+    canfd_update_irq(s);
+}
+
+static uint64_t canfd_icr_pre_write(RegisterInfo *reg, uint64_t val64)
+{
+    XlnxVersalCANFDState *s = XILINX_CANFD(reg->opaque);
+    uint32_t val = val64;
+
+    s->regs[R_INTERRUPT_STATUS_REGISTER] &= ~val;
+
+    /*
+     * RXBOFLW_BI field is automatically cleared to default if RXBOFLW bit is
+     * cleared in ISR.
+     */
+    if (ARRAY_FIELD_EX32(s->regs, INTERRUPT_STATUS_REGISTER, RXFWMFLL_1)) {
+        ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXBOFLW_BI, 0);
+    }
+
+    canfd_update_irq(s);
+
+    return 0;
+}
+
+static void canfd_config_reset(XlnxVersalCANFDState *s)
+{
+
+    unsigned int i;
+
+    /* Reset all the configuration register. */
+    for (i = 0; i < R_RX_FIFO_WATERMARK_REGISTER; ++i) {
+        register_reset(&s->reg_info[i]);
+    }
+
+    canfd_update_irq(s);
+}
+
+static void canfd_config_mode(XlnxVersalCANFDState *s)
+{
+    register_reset(&s->reg_info[R_ERROR_COUNTER_REGISTER]);
+    register_reset(&s->reg_info[R_ERROR_STATUS_REGISTER]);
+    register_reset(&s->reg_info[R_STATUS_REGISTER]);
+
+    /* Put XlnxVersalCANFDState in configuration mode. */
+    ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, CONFIG, 1);
+    ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, WKUP, 0);
+    ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, SLP, 0);
+    ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, BSOFF, 0);
+    ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, ERROR, 0);
+    ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXFOFLW, 0);
+    ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXFOFLW_1, 0);
+    ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 0);
+    ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXOK, 0);
+    ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, ARBLST, 0);
+
+    /* Clear the time stamp. */
+    ptimer_transaction_begin(s->canfd_timer);
+    ptimer_set_count(s->canfd_timer, 0);
+    ptimer_transaction_commit(s->canfd_timer);
+
+    canfd_update_irq(s);
+}
+
+static void update_status_register_mode_bits(XlnxVersalCANFDState *s)
+{
+    bool sleep_status = ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP);
+    bool sleep_mode = ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SLEEP);
+    /* Wake up interrupt bit. */
+    bool wakeup_irq_val = (sleep_mode == 0) && sleep_status;
+    /* Sleep interrupt bit. */
+    bool sleep_irq_val = sleep_mode && (sleep_status == 0);
+
+    /* Clear previous core mode status bits. */
+    ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, LBACK, 0);
+    ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SLEEP, 0);
+    ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SNOOP, 0);
+    ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, NORMAL, 0);
+
+    /* set current mode bit and generate irqs accordingly. */
+    if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, LBACK)) {
+        ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, LBACK, 1);
+    } else if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SLEEP)) {
+        ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SLEEP, 1);
+        ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, SLP,
+                         sleep_irq_val);
+    } else if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SNOOP)) {
+        ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SNOOP, 1);
+    } else {
+        /* If all bits are zero, XlnxVersalCANFDState is set in normal mode. */
+        ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, NORMAL, 1);
+        /* Set wakeup interrupt bit. */
+        ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, WKUP,
+                         wakeup_irq_val);
+    }
+
+    /* Put the CANFD in error active state. */
+    ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, ESTAT, 1);
+
+    canfd_update_irq(s);
+}
+
+static uint64_t canfd_msr_pre_write(RegisterInfo *reg, uint64_t val64)
+{
+    XlnxVersalCANFDState *s = XILINX_CANFD(reg->opaque);
+    uint32_t val = val64;
+    uint8_t multi_mode = 0;
+
+    /*
+     * Multiple mode set check. This is done to make sure user doesn't set
+     * multiple modes.
+     */
+    multi_mode = FIELD_EX32(val, MODE_SELECT_REGISTER, LBACK) +
+                 FIELD_EX32(val, MODE_SELECT_REGISTER, SLEEP) +
+                 FIELD_EX32(val, MODE_SELECT_REGISTER, SNOOP);
+
+    if (multi_mode > 1) {
+        qemu_log_mask(LOG_GUEST_ERROR, "Attempting to configure several modes "
+                      "simultaneously. One mode will be selected according to "
+                      "their priority: LBACK > SLEEP > SNOOP.\n");
+    }
+
+    if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
+        /* In configuration mode, any mode can be selected. */
+        s->regs[R_MODE_SELECT_REGISTER] = val;
+    } else {
+        bool sleep_mode_bit = FIELD_EX32(val, MODE_SELECT_REGISTER, SLEEP);
+
+        ARRAY_FIELD_DP32(s->regs, MODE_SELECT_REGISTER, SLEEP, sleep_mode_bit);
+
+        if (FIELD_EX32(val, MODE_SELECT_REGISTER, LBACK)) {
+            qemu_log_mask(LOG_GUEST_ERROR, "Attempting to set LBACK mode "
+                          "without setting CEN bit as 0\n");
+        } else if (FIELD_EX32(val, MODE_SELECT_REGISTER, SNOOP)) {
+            qemu_log_mask(LOG_GUEST_ERROR, "Attempting to set SNOOP mode "
+                          "without setting CEN bit as 0\n");
+        }
+
+        update_status_register_mode_bits(s);
+    }
+
+    return s->regs[R_MODE_SELECT_REGISTER];
+}
+
+static void canfd_exit_sleep_mode(XlnxVersalCANFDState *s)
+{
+    ARRAY_FIELD_DP32(s->regs, MODE_SELECT_REGISTER, SLEEP, 0);
+    update_status_register_mode_bits(s);
+}
+
+static void regs2frame(XlnxVersalCANFDState *s, qemu_can_frame *frame,
+                       uint32_t reg_num)
+{
+    uint32_t i = 0;
+    uint32_t j = 0;
+    uint32_t val = 0;
+    uint32_t dlc_reg_val = s->regs[reg_num + 1];
+    uint32_t dlc_value = FIELD_EX32(dlc_reg_val, TB0_DLC_REGISTER, DLC);
+
+    frame->can_id = s->regs[reg_num];
+
+    if (FIELD_EX32(dlc_reg_val, TB0_DLC_REGISTER, FDF)) {
+        /*
+         * CANFD frame.
+         * Converting dlc(0 to 15) 4 Byte data to plain length(i.e. 0 to 64)
+         * 1 Byte data. This is done to make it work with SocketCAN.
+         * On actual CANFD frame, this value can't be more than 0xF.
+         * Conversion table for DLC to plain length:
+         *
+         *  DLC                        Plain Length
+         *  0 - 8                      0 - 8
+         *  9                          9 - 12
+         *  10                         13 - 16
+         *  11                         17 - 20
+         *  12                         21 - 24
+         *  13                         25 - 32
+         *  14                         33 - 48
+         *  15                         49 - 64
+         */
+
+        frame->flags = QEMU_CAN_FRMF_TYPE_FD;
+
+        if (dlc_value < 8) {
+            frame->can_dlc = dlc_value;
+        } else {
+            frame->can_dlc = canfd_dlc_array[dlc_value - 8];
+        }
+
+        for (i = 0; i < 4 ; i++) {
+            val = 8 * i;
+
+            for (j = 0; j < frame->can_dlc / 4; j++) {
+                frame->data[i + 4 * j] = ((s->regs[reg_num + 2 + j] >> val) &
+                                           0xFF);
+            }
+        }
+    } else {
+        /*
+         * FD Format bit not set that means it is a CAN Frame.
+         * Conversion table for classic CAN:
+         *
+         *  DLC                        Plain Length
+         *  0 - 7                      0 - 7
+         *  8 - 15                     8
+         */
+
+        if (dlc_value > 8) {
+            frame->can_dlc = dlc_value;
+            dlc_value = 8;
+            qemu_log_mask(LOG_GUEST_ERROR, "Maximum DLC value for Classic CAN"
+                          "  frame can be 8. Only 8 byte data will be sent.\n");
+        } else {
+            frame->can_dlc = dlc_value;
+        }
+
+        for (i = 0; i < 4 ; i++) {
+            val = 8 * i;
+
+            for (j = 0; j < dlc_value; j++) {
+                frame->data[i + 4 * j] = ((s->regs[reg_num + 2 + j] >> val) &
+                                           0xFF);
+            }
+        }
+    }
+}
+
+static void process_cancellation_requests(XlnxVersalCANFDState *s)
+{
+    int i;
+    uint32_t val = s->regs[R_TX_BUFFER_READY_REQUEST_REGISTER];
+    uint32_t cancel_val = s->regs[R_TX_BUFFER_CANCEL_REQUEST_REGISTER];
+
+    for (i = 0; i < 32; i++) {
+
+        if ((val & 0x1) && (cancel_val & 0x1)) {
+            s->regs[R_TX_BUFFER_READY_REQUEST_REGISTER] &= ~(1 << i);
+            s->regs[R_TX_BUFFER_CANCEL_REQUEST_REGISTER] &= ~(1 << i);
+
+            ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXCRS, 1);
+        } else {
+            qemu_log_mask(LOG_GUEST_ERROR, "Data Tx going on for requested"
+                          " cancellation bit\n");
+        }
+
+        val >>= 1;
+        cancel_val >>= 1;
+    }
+    canfd_update_irq(s);
+}
+
+static void store_rx_sequential(XlnxVersalCANFDState *s,
+                                const qemu_can_frame *frame,
+                                uint32_t fill_level, uint32_t read_index,
+                                uint32_t store_location, uint8_t rx_fifo,
+                                bool rx_fifo_id, uint8_t filter_index)
+{
+    int i;
+    bool is_canfd_frame;
+    uint8_t dlc = 0;
+    uint32_t dlc_reg_val = 0;
+    uint32_t data_reg_val = 0;
+
+    /* Getting RX0/1 fill level */
+    if ((fill_level) > rx_fifo - 1) {
+        g_autofree char *path = object_get_canonical_path(OBJECT(s));
+
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: RX%d Buffer is full. Discarding the"
+                      "message\n", path, rx_fifo_id);
+
+        /* Set the corresponding RF buffer overflow interrupt. */
+        if (rx_fifo_id == 0) {
+            ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXFOFLW, 1);
+        } else {
+            ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXFOFLW_1, 1);
+        }
+    } else {
+        uint16_t rx_timestamp = CANFD_TIMER_MAX -
+                                    ptimer_get_count(s->canfd_timer);
+
+        if (rx_timestamp == 0xFFFF) {
+            ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TSCNT_OFLW, 1);
+        } else {
+            ARRAY_FIELD_DP32(s->regs, TIMESTAMP_REGISTER, TIMESTAMP_CNT,
+                             rx_timestamp);
+        }
+
+        if (rx_fifo_id == 0) {
+            ARRAY_FIELD_DP32(s->regs, RX_FIFO_STATUS_REGISTER, FL,
+                             fill_level + 1);
+        } else {
+            ARRAY_FIELD_DP32(s->regs, RX_FIFO_STATUS_REGISTER, FL_1,
+                             fill_level + 1);
+        }
+        s->regs[store_location] = frame->can_id;
+
+        if (frame->flags == QEMU_CAN_FRMF_TYPE_FD) {
+            is_canfd_frame = true;
+
+            for (i = 0; i < ARRAY_SIZE(canfd_dlc_array); i++) {
+                if (canfd_dlc_array[i] == frame->can_dlc) {
+                    dlc = 8 + i;
+                }
+
+            dlc_reg_val = FIELD_DP32(0, RB_DLC_REGISTER, DLC, dlc);
+            }
+        } else {
+            is_canfd_frame = false;
+            if (frame->can_dlc > 8) {
+                dlc = 8;
+            } else {
+                dlc = frame->can_dlc;
+            }
+
+            dlc_reg_val = FIELD_DP32(0, RB_DLC_REGISTER, DLC, frame->can_dlc);
+        }
+
+        dlc_reg_val |= FIELD_DP32(0, RB_DLC_REGISTER, FDF, is_canfd_frame);
+        dlc_reg_val |= FIELD_DP32(0, RB_DLC_REGISTER, TIMESTAMP, rx_timestamp);
+        dlc_reg_val |= FIELD_DP32(0, RB_DLC_REGISTER, MATCHED_FILTER_INDEX,
+                                  filter_index);
+        s->regs[store_location + 1] = dlc_reg_val;
+
+        for (i = 0; i <= dlc; i++) {
+            data_reg_val = FIELD_DP32(0, RB_DW0_REGISTER, DATA_BYTES3,
+                                      frame->data[4 * i]);
+            data_reg_val |= FIELD_DP32(0, RB_DW0_REGISTER, DATA_BYTES2,
+                                       frame->data[4 * i + 1]);
+            data_reg_val |= FIELD_DP32(0, RB_DW0_REGISTER, DATA_BYTES1,
+                                       frame->data[4 * i + 2]);
+            data_reg_val |= FIELD_DP32(0, RB_DW0_REGISTER, DATA_BYTES0,
+                                       frame->data[4 * i + 3]);
+            s->regs[store_location + i + 2] = data_reg_val;
+        }
+        /* set the interrupt as RXOK. */
+        ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 1);
+    }
+}
+
+static void update_rx_sequential(XlnxVersalCANFDState *s,
+                                 const qemu_can_frame *frame)
+{
+    bool filter_pass = false;
+    uint8_t filter_index = 0;
+    int i;
+    int filter_partition = ARRAY_FIELD_EX32(s->regs,
+                                            RX_FIFO_WATERMARK_REGISTER, RXFP);
+    uint32_t store_location;
+    uint32_t fill_level;
+    uint32_t read_index;
+
+    /*
+     * If all UAF bits are set to 0, then received messages are not stored
+     * in the RX buffers.
+     */
+    if (!s->regs[R_ACCEPTANCE_FILTER_CONTROL_REGISTER]) {
+        qemu_log_mask(LOG_GUEST_ERROR, "No acceptance filter is set. Received"
+                      " messages will not be stored.\n");
+    } else {
+        uint32_t acceptance_filter_status =
+                                s->regs[R_ACCEPTANCE_FILTER_CONTROL_REGISTER];
+
+        for (i = 0; i < 32; i++) {
+            if (acceptance_filter_status & 0x1) {
+                uint32_t msg_id_masked = s->regs[R_AFMR_REGISTER + 2 * i] &
+                                         frame->can_id;
+                uint32_t afir_id_masked = s->regs[R_AFIR_REGISTER + 2 * i] &
+                                          s->regs[R_AFMR_REGISTER + 2 * i];
+                uint16_t std_msg_id_masked = FIELD_EX32(msg_id_masked,
+                                                        AFIR_REGISTER, AIID);
+                uint16_t std_afir_id_masked = FIELD_EX32(afir_id_masked,
+                                                         AFIR_REGISTER, AIID);
+                uint32_t ext_msg_id_masked = FIELD_EX32(msg_id_masked,
+                                                        AFIR_REGISTER,
+                                                        AIID_EXT);
+                uint32_t ext_afir_id_masked = FIELD_EX32(afir_id_masked,
+                                                         AFIR_REGISTER,
+                                                         AIID_EXT);
+                bool ext_ide = FIELD_EX32(s->regs[R_AFMR_REGISTER + 2 * i],
+                                          AFMR_REGISTER, AMIDE);
+
+                if (std_msg_id_masked == std_afir_id_masked) {
+                    if (ext_ide) {
+                        /* Extended message ID message. */
+                        if (ext_msg_id_masked == ext_afir_id_masked) {
+                            filter_pass = true;
+                            filter_index = i;
+
+                            break;
+                        }
+                    } else {
+                        /* Standard message ID. */
+                        filter_pass = true;
+                        filter_index = i;
+
+                        break;
+                    }
+                }
+            }
+            acceptance_filter_status >>= 1;
+        }
+    }
+
+    if (!filter_pass) {
+        g_autofree char *path = object_get_canonical_path(OBJECT(s));
+
+        trace_xlnx_canfd_rx_fifo_filter_reject(path, frame->can_id,
+                                               frame->can_dlc);
+    } else {
+        if (filter_index <= filter_partition) {
+            fill_level = ARRAY_FIELD_EX32(s->regs, RX_FIFO_STATUS_REGISTER, FL);
+            read_index = ARRAY_FIELD_EX32(s->regs, RX_FIFO_STATUS_REGISTER, RI);
+            uint8_t store_index = read_index + fill_level;
+
+            if (read_index == s->cfg.rx0_fifo - 1) {
+                /*
+                 * When ri is s->cfg.rx0_fifo - 1 i.e. max, it goes cyclic that
+                 * means we reset the ri to 0x0.
+                 */
+                read_index = 0;
+                ARRAY_FIELD_DP32(s->regs, RX_FIFO_STATUS_REGISTER, RI,
+                                 read_index);
+            }
+
+            if (store_index > s->cfg.rx0_fifo - 1) {
+                store_index -= s->cfg.rx0_fifo - 1;
+            }
+
+            store_location = R_RB_ID_REGISTER +
+                          (store_index * NUM_REGS_PER_MSG_SPACE);
+
+            store_rx_sequential(s, frame, fill_level, read_index,
+                                store_location, s->cfg.rx0_fifo, 0,
+                                filter_index);
+        } else {
+            /* RX 1 fill level message */
+            fill_level = ARRAY_FIELD_EX32(s->regs, RX_FIFO_STATUS_REGISTER,
+                                          FL_1);
+            read_index = ARRAY_FIELD_EX32(s->regs, RX_FIFO_STATUS_REGISTER,
+                                          RI_1);
+            uint8_t store_index = read_index + fill_level;
+
+            if (read_index == s->cfg.rx1_fifo - 1) {
+                /*
+                 * When ri is s->cfg.rx1_fifo - 1 i.e. max, it goes cyclic that
+                 * means we reset the ri to 0x0.
+                 */
+                read_index = 0;
+                ARRAY_FIELD_DP32(s->regs, RX_FIFO_STATUS_REGISTER, RI_1,
+                                 read_index);
+            }
+
+            if (store_index > s->cfg.rx1_fifo - 1) {
+                store_index -= s->cfg.rx1_fifo - 1;
+            }
+
+            store_location = R_RB_ID_REGISTER_1 +
+                          (store_index * NUM_REGS_PER_MSG_SPACE);
+
+            store_rx_sequential(s, frame, fill_level, read_index,
+                                store_location, s->cfg.rx1_fifo, 1,
+                                filter_index);
+        }
+
+        g_autofree char *path = object_get_canonical_path(OBJECT(s));
+
+        trace_xlnx_canfd_rx_data(path, frame->can_id, frame->can_dlc,
+                                 frame->flags);
+        canfd_update_irq(s);
+    }
+}
+
+static bool tx_ready_check(XlnxVersalCANFDState *s)
+{
+    if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, SRST)) {
+        g_autofree char *path = object_get_canonical_path(OBJECT(s));
+
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer data while"
+                      " XlnxVersalCANFDState is in reset mode\n", path);
+
+        return false;
+    }
+
+    if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
+        g_autofree char *path = object_get_canonical_path(OBJECT(s));
+
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer data while"
+                      " XlnxVersalCANFDState is in configuration mode."
+                      " Reset the core so operations can start fresh\n",
+                      path);
+        return false;
+    }
+
+    if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SNOOP)) {
+        g_autofree char *path = object_get_canonical_path(OBJECT(s));
+
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer data while"
+                      " XlnxVersalCANFDState is in SNOOP MODE\n",
+                      path);
+        return false;
+    }
+
+    return true;
+}
+
+static void tx_fifo_stamp(XlnxVersalCANFDState *s, uint32_t tb0_regid)
+{
+    /*
+     * If EFC bit in DLC message is set. This means we will store the
+     * event of this transmitted message with time stamp.
+     */
+    uint32_t dlc_reg_val = 0;
+
+    if (FIELD_EX32(s->regs[tb0_regid + 1], TB0_DLC_REGISTER, EFC)) {
+        uint8_t dlc_val = FIELD_EX32(s->regs[tb0_regid + 1], TB0_DLC_REGISTER,
+                                     DLC);
+        bool fdf_val = FIELD_EX32(s->regs[tb0_regid + 1], TB0_DLC_REGISTER,
+                                  FDF);
+        bool brs_val = FIELD_EX32(s->regs[tb0_regid + 1], TB0_DLC_REGISTER,
+                                  BRS);
+        uint8_t mm_val = FIELD_EX32(s->regs[tb0_regid + 1], TB0_DLC_REGISTER,
+                                    MM);
+        uint8_t fill_level = ARRAY_FIELD_EX32(s->regs,
+                                              TX_EVENT_FIFO_STATUS_REGISTER,
+                                              TXE_FL);
+        uint8_t read_index = ARRAY_FIELD_EX32(s->regs,
+                                              TX_EVENT_FIFO_STATUS_REGISTER,
+                                              TXE_RI);
+        uint8_t store_index = fill_level + read_index;
+
+        if ((fill_level) > s->cfg.tx_fifo - 1) {
+            qemu_log_mask(LOG_GUEST_ERROR, "TX Event Buffer is full."
+                          " Discarding the message\n");
+            ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXEOFLW, 1);
+        } else {
+            if (read_index == s->cfg.tx_fifo - 1) {
+                /*
+                 * When ri is s->cfg.tx_fifo - 1 i.e. max, it goes cyclic that
+                 * means we reset the ri to 0x0.
+                 */
+                read_index = 0;
+                ARRAY_FIELD_DP32(s->regs, TX_EVENT_FIFO_STATUS_REGISTER, TXE_RI,
+                                 read_index);
+            }
+
+            if (store_index > s->cfg.tx_fifo - 1) {
+                store_index -= s->cfg.tx_fifo - 1;
+            }
+
+            uint32_t tx_event_reg0_id = R_TXE_FIFO_TB_ID_REGISTER +
+                                        (store_index * 2);
+
+            /* Store message ID in TX event register*/
+            s->regs[tx_event_reg0_id] = s->regs[tb0_regid];
+
+            uint16_t tx_timestamp = CANFD_TIMER_MAX -
+                                            ptimer_get_count(s->canfd_timer);
+
+            /* Store DLC with time stamp in DLC regs. */
+            dlc_reg_val = FIELD_DP32(0, TXE_FIFO_TB_DLC_REGISTER, DLC, dlc_val);
+            dlc_reg_val |= FIELD_DP32(0, TXE_FIFO_TB_DLC_REGISTER, FDF,
+                                      fdf_val);
+            dlc_reg_val |= FIELD_DP32(0, TXE_FIFO_TB_DLC_REGISTER, BRS,
+                                      brs_val);
+            dlc_reg_val |= FIELD_DP32(0, TXE_FIFO_TB_DLC_REGISTER, ET, 0x3);
+            dlc_reg_val |= FIELD_DP32(0, TXE_FIFO_TB_DLC_REGISTER, MM, mm_val);
+            dlc_reg_val |= FIELD_DP32(0, TXE_FIFO_TB_DLC_REGISTER, TIMESTAMP,
+                                      tx_timestamp);
+            s->regs[tx_event_reg0_id + 1] = dlc_reg_val;
+
+            ARRAY_FIELD_DP32(s->regs, TX_EVENT_FIFO_STATUS_REGISTER, TXE_FL,
+                             fill_level + 1);
+        }
+    }
+}
+
+static void add_id(txid_list **start, uint32_t can_id, uint32_t reg_num)
+{
+    txid_list *temp = (txid_list *)malloc(sizeof(txid_list));
+
+    if (temp == NULL) {
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: Couldn't allocate memory\n",
+                      __func__);
+        return;
+    }
+
+    temp->can_id = can_id;
+    temp->reg_num = reg_num;
+    temp->next = *start;
+
+    *start = temp;
+}
+
+static void swap_ids(txid_list *first, txid_list *second)
+{
+    uint32_t temp_can_id = first->can_id;
+    uint32_t temp_reg_num = first->reg_num;
+
+    first->can_id = second->can_id;
+    first->reg_num = second->reg_num;
+    second->can_id = temp_can_id;
+    second->reg_num = temp_reg_num;
+}
+
+/* Sort the data to sent in ascending order. */
+static void sort_by_id(XlnxVersalCANFDState *s, txid_list **start)
+{
+    uint8_t i = 0;
+    bool swapped = true;
+
+    uint32_t reg_num = 0;
+    uint32_t reg_ready = s->regs[R_TX_BUFFER_READY_REQUEST_REGISTER];
+
+    /* First find the messages which are ready for transaction. */
+    for (i = 0; i < s->cfg.tx_fifo; i++) {
+        if (reg_ready) {
+            reg_num = R_TB_ID_REGISTER + (NUM_REGS_PER_MSG_SPACE * i);
+            add_id(start, s->regs[reg_num], reg_num);
+        }
+
+        reg_ready >>= 1;
+        s->regs[R_TX_BUFFER_READY_REQUEST_REGISTER] &= ~(1 << i);
+        s->regs[R_TX_BUFFER_CANCEL_REQUEST_REGISTER] &= ~(1 << i);
+    }
+
+    /* If no data or only one tx data, no need to sort the ids. */
+    if (*start == NULL || (*start)->next == NULL) {
+        return;
+    }
+
+    txid_list *temp_a, *temp_b = NULL;
+
+    while (swapped) {
+        swapped = false;
+        temp_a = *start;
+
+        while (temp_a->next != temp_b) {
+            if (temp_a->can_id > temp_a->next->can_id) {
+                swap_ids(temp_a, temp_a->next);
+                swapped = true;
+            } else if (temp_a->can_id == temp_a->next->can_id) {
+                /*
+                 * If two IDs are same we sort them by their index. Lowest index
+                 * will be transmitted first.
+                 */
+                if (temp_a->reg_num > temp_a->next->reg_num) {
+                    swap_ids(temp_a, temp_a->next);
+                    swapped = true;
+                }
+            }
+
+            temp_a = temp_a->next;
+        }
+
+        temp_b = temp_a;
+    }
+}
+
+static void transfer_data(XlnxVersalCANFDState *s)
+{
+    bool canfd_tx = tx_ready_check(s);
+
+    if (canfd_tx) {
+        qemu_can_frame frame;
+        txid_list *start = NULL;
+
+        sort_by_id(s, &start);
+
+        if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, LBACK)) {
+            while (start != NULL) {
+                regs2frame(s, &frame, start->reg_num);
+                update_rx_sequential(s, &frame);
+                tx_fifo_stamp(s, start->reg_num);
+
+                start = start->next;
+            }
+
+            ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 1);
+        } else {
+            while (start != NULL) {
+                regs2frame(s, &frame, start->reg_num);
+
+                g_autofree char *path = object_get_canonical_path(OBJECT(s));
+
+                trace_xlnx_canfd_tx_data(path, frame.can_id, frame.can_dlc,
+                                         frame.flags);
+                can_bus_client_send(&s->bus_client, &frame, 1);
+                tx_fifo_stamp(s, start->reg_num);
+
+                start = start->next;
+            }
+
+            ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXRRS, 1);
+
+            if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP)) {
+                canfd_exit_sleep_mode(s);
+            }
+        }
+
+        s->tx_busy_bit = 0;
+
+        ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXOK, 1);
+        free(start);
+    } else {
+          g_autofree char *path = object_get_canonical_path(OBJECT(s));
+
+          qemu_log_mask(LOG_GUEST_ERROR, "%s: Controller not enabled for"
+                        " data transfer\n", path);
+    }
+
+    canfd_update_irq(s);
+}
+
+static uint64_t canfd_srr_pre_write(RegisterInfo *reg, uint64_t val64)
+{
+    XlnxVersalCANFDState *s = XILINX_CANFD(reg->opaque);
+    uint32_t val = val64;
+
+    ARRAY_FIELD_DP32(s->regs, SOFTWARE_RESET_REGISTER, CEN,
+                     FIELD_EX32(val, SOFTWARE_RESET_REGISTER, CEN));
+
+    if (FIELD_EX32(val, SOFTWARE_RESET_REGISTER, SRST)) {
+        g_autofree char *path = object_get_canonical_path(OBJECT(s));
+
+        trace_xlnx_canfd_reset(path, val64);
+
+        /* First, core will do software reset then will enter in config mode. */
+        canfd_config_reset(s);
+    } else if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
+        canfd_config_mode(s);
+    } else {
+        /*
+         * Leave config mode. Now XlnxVersalCANFD core will enter Normal, Sleep,
+         * snoop or Loopback mode depending upon LBACK, SLEEP, SNOOP register
+         * states.
+         */
+        ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, CONFIG, 0);
+
+        ptimer_transaction_begin(s->canfd_timer);
+        ptimer_set_count(s->canfd_timer, 0);
+        ptimer_transaction_commit(s->canfd_timer);
+        update_status_register_mode_bits(s);
+        transfer_data(s);
+    }
+
+    return s->regs[R_SOFTWARE_RESET_REGISTER];
+}
+
+static uint64_t filter_mask(RegisterInfo *reg, uint64_t val64)
+{
+    XlnxVersalCANFDState *s = XILINX_CANFD(reg->opaque);
+    uint32_t reg_idx = (reg->access->addr) / 4;
+    uint32_t val = val64;
+    uint32_t filter_offset = (reg_idx - R_AFMR_REGISTER) / 2;
+
+    if (!(s->regs[R_ACCEPTANCE_FILTER_CONTROL_REGISTER] &
+        (1 << filter_offset))) {
+        s->regs[reg_idx] = val;
+    } else {
+        g_autofree char *path = object_get_canonical_path(OBJECT(s));
+
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %dnot enabled\n",
+                      path, filter_offset + 1);
+    }
+
+    return s->regs[reg_idx];
+}
+
+static uint64_t filter_id(RegisterInfo *reg, uint64_t val64)
+{
+    XlnxVersalCANFDState *s = XILINX_CANFD(reg->opaque);
+    hwaddr reg_idx = (reg->access->addr) / 4;
+    uint32_t val = val64;
+    uint32_t filter_offset = (reg_idx - R_AFIR_REGISTER) / 2;
+
+    if (!(s->regs[R_ACCEPTANCE_FILTER_CONTROL_REGISTER] &
+        (1 << filter_offset))) {
+        s->regs[reg_idx] = val;
+    } else {
+        g_autofree char *path = object_get_canonical_path(OBJECT(s));
+
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %d not enabled\n",
+                      path, filter_offset + 1);
+    }
+
+    return s->regs[reg_idx];
+}
+
+static uint64_t canfd_tx_fifo_status_prew(RegisterInfo *reg, uint64_t val64)
+{
+    XlnxVersalCANFDState *s = XILINX_CANFD(reg->opaque);
+    uint32_t val = val64;
+    uint8_t read_ind = 0;
+    uint8_t fill_ind = ARRAY_FIELD_EX32(s->regs, TX_EVENT_FIFO_STATUS_REGISTER,
+                                        TXE_FL);
+
+    if (FIELD_EX32(val, TX_EVENT_FIFO_STATUS_REGISTER, TXE_IRI) && fill_ind) {
+        read_ind = ARRAY_FIELD_EX32(s->regs, TX_EVENT_FIFO_STATUS_REGISTER,
+                                    TXE_RI) + 1;
+
+        if (read_ind > s->cfg.tx_fifo - 1) {
+            read_ind = 0;
+        }
+
+        /*
+         * Increase the read index by 1 and decrease the fill level by 1.
+         */
+        ARRAY_FIELD_DP32(s->regs, TX_EVENT_FIFO_STATUS_REGISTER, TXE_RI,
+                         read_ind);
+        ARRAY_FIELD_DP32(s->regs, TX_EVENT_FIFO_STATUS_REGISTER, TXE_FL,
+                         fill_ind - 1);
+    }
+
+    return s->regs[R_TX_EVENT_FIFO_STATUS_REGISTER];
+}
+
+static uint64_t canfd_rx_fifo_status_prew(RegisterInfo *reg, uint64_t val64)
+{
+    XlnxVersalCANFDState *s = XILINX_CANFD(reg->opaque);
+    uint32_t val = val64;
+    uint8_t read_ind = 0;
+    uint8_t fill_ind = 0;
+
+    if (FIELD_EX32(val, RX_FIFO_STATUS_REGISTER, IRI)) {
+        /* FL index is zero, setting IRI bit has no effect. */
+        if (FIELD_EX32(val, RX_FIFO_STATUS_REGISTER, FL) != 0) {
+            read_ind = FIELD_EX32(val, RX_FIFO_STATUS_REGISTER, RI) + 1;
+
+            if (read_ind > s->cfg.rx0_fifo - 1) {
+                read_ind = 0;
+            }
+
+            fill_ind = FIELD_EX32(val, RX_FIFO_STATUS_REGISTER, FL) - 1;
+
+            ARRAY_FIELD_DP32(s->regs, RX_FIFO_STATUS_REGISTER, RI, read_ind);
+            ARRAY_FIELD_DP32(s->regs, RX_FIFO_STATUS_REGISTER, FL, fill_ind);
+        }
+    }
+
+    if (FIELD_EX32(val, RX_FIFO_STATUS_REGISTER, IRI_1)) {
+        /* FL_1 index is zero, setting IRI_1 bit has no effect. */
+        if (FIELD_EX32(val, RX_FIFO_STATUS_REGISTER, FL_1) != 0) {
+            read_ind = FIELD_EX32(val, RX_FIFO_STATUS_REGISTER, RI_1) + 1;
+
+            if (read_ind > s->cfg.rx1_fifo - 1) {
+                read_ind = 0;
+            }
+
+            fill_ind = FIELD_EX32(val, RX_FIFO_STATUS_REGISTER, FL_1) - 1;
+
+            ARRAY_FIELD_DP32(s->regs, RX_FIFO_STATUS_REGISTER, RI_1, read_ind);
+            ARRAY_FIELD_DP32(s->regs, RX_FIFO_STATUS_REGISTER, FL_1, fill_ind);
+        }
+    }
+
+    return s->regs[R_RX_FIFO_STATUS_REGISTER];
+}
+
+static uint64_t canfd_tsr_pre_write(RegisterInfo *reg, uint64_t val64)
+{
+    XlnxVersalCANFDState *s = XILINX_CANFD(reg->opaque);
+    uint32_t val = val64;
+
+    if (FIELD_EX32(val, TIMESTAMP_REGISTER, CTS)) {
+        ARRAY_FIELD_DP32(s->regs, TIMESTAMP_REGISTER, TIMESTAMP_CNT, 0);
+        ptimer_transaction_begin(s->canfd_timer);
+        ptimer_set_count(s->canfd_timer, 0);
+        ptimer_transaction_commit(s->canfd_timer);
+    }
+
+    return 0;
+}
+
+static uint64_t canfd_trr_reg_prew(RegisterInfo *reg, uint64_t val64)
+{
+    XlnxVersalCANFDState *s = XILINX_CANFD(reg->opaque);
+
+    if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SNOOP)) {
+        g_autofree char *path = object_get_canonical_path(OBJECT(s));
+
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: Controller is in SNOOP mode."
+                      "tx_ready_register will stay in reset mode\n", path);
+        return 0;
+    } else {
+        return val64;
+    }
+}
+
+static void canfd_trr_reg_postw(RegisterInfo *reg, uint64_t val64)
+{
+    XlnxVersalCANFDState *s = XILINX_CANFD(reg->opaque);
+
+    transfer_data(s);
+}
+
+static void canfd_cancel_reg_postw(RegisterInfo *reg, uint64_t val64)
+{
+    XlnxVersalCANFDState *s = XILINX_CANFD(reg->opaque);
+
+    process_cancellation_requests(s);
+}
+
+static uint64_t canfd_write_check_prew(RegisterInfo *reg, uint64_t val64)
+{
+    XlnxVersalCANFDState *s = XILINX_CANFD(reg->opaque);
+    uint32_t val = val64;
+
+    if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
+        return val;
+    }
+    return 0;
+}
+
+static const RegisterAccessInfo canfd_tx_regs[] = {
+    {   .name = "TB_ID_REGISTER",  .addr = A_TB_ID_REGISTER,
+    },{ .name = "TB0_DLC_REGISTER",  .addr = A_TB0_DLC_REGISTER,
+    },{ .name = "TB_DW0_REGISTER",  .addr = A_TB_DW0_REGISTER,
+    },{ .name = "TB_DW1_REGISTER",  .addr = A_TB_DW1_REGISTER,
+    },{ .name = "TB_DW2_REGISTER",  .addr = A_TB_DW2_REGISTER,
+    },{ .name = "TB_DW3_REGISTER",  .addr = A_TB_DW3_REGISTER,
+    },{ .name = "TB_DW4_REGISTER",  .addr = A_TB_DW4_REGISTER,
+    },{ .name = "TB_DW5_REGISTER",  .addr = A_TB_DW5_REGISTER,
+    },{ .name = "TB_DW6_REGISTER",  .addr = A_TB_DW6_REGISTER,
+    },{ .name = "TB_DW7_REGISTER",  .addr = A_TB_DW7_REGISTER,
+    },{ .name = "TB_DW8_REGISTER",  .addr = A_TB_DW8_REGISTER,
+    },{ .name = "TB_DW9_REGISTER",  .addr = A_TB_DW9_REGISTER,
+    },{ .name = "TB_DW10_REGISTER",  .addr = A_TB_DW10_REGISTER,
+    },{ .name = "TB_DW11_REGISTER",  .addr = A_TB_DW11_REGISTER,
+    },{ .name = "TB_DW12_REGISTER",  .addr = A_TB_DW12_REGISTER,
+    },{ .name = "TB_DW13_REGISTER",  .addr = A_TB_DW13_REGISTER,
+    },{ .name = "TB_DW14_REGISTER",  .addr = A_TB_DW14_REGISTER,
+    },{ .name = "TB_DW15_REGISTER",  .addr = A_TB_DW15_REGISTER,
+    }
+};
+
+static const RegisterAccessInfo canfd_rx0_regs[] = {
+    {   .name = "RB_ID_REGISTER",  .addr = A_RB_ID_REGISTER,
+        .ro = 0xffffffff,
+    },{ .name = "RB_DLC_REGISTER",  .addr = A_RB_DLC_REGISTER,
+        .ro = 0xfe1fffff,
+    },{ .name = "RB_DW0_REGISTER",  .addr = A_RB_DW0_REGISTER,
+        .ro = 0xffffffff,
+    },{ .name = "RB_DW1_REGISTER",  .addr = A_RB_DW1_REGISTER,
+        .ro = 0xffffffff,
+    },{ .name = "RB_DW2_REGISTER",  .addr = A_RB_DW2_REGISTER,
+        .ro = 0xffffffff,
+    },{ .name = "RB_DW3_REGISTER",  .addr = A_RB_DW3_REGISTER,
+        .ro = 0xffffffff,
+    },{ .name = "RB_DW4_REGISTER",  .addr = A_RB_DW4_REGISTER,
+        .ro = 0xffffffff,
+    },{ .name = "RB_DW5_REGISTER",  .addr = A_RB_DW5_REGISTER,
+        .ro = 0xffffffff,
+    },{ .name = "RB_DW6_REGISTER",  .addr = A_RB_DW6_REGISTER,
+        .ro = 0xffffffff,
+    },{ .name = "RB_DW7_REGISTER",  .addr = A_RB_DW7_REGISTER,
+        .ro = 0xffffffff,
+    },{ .name = "RB_DW8_REGISTER",  .addr = A_RB_DW8_REGISTER,
+        .ro = 0xffffffff,
+    },{ .name = "RB_DW9_REGISTER",  .addr = A_RB_DW9_REGISTER,
+        .ro = 0xffffffff,
+    },{ .name = "RB_DW10_REGISTER",  .addr = A_RB_DW10_REGISTER,
+        .ro = 0xffffffff,
+    },{ .name = "RB_DW11_REGISTER",  .addr = A_RB_DW11_REGISTER,
+        .ro = 0xffffffff,
+    },{ .name = "RB_DW12_REGISTER",  .addr = A_RB_DW12_REGISTER,
+        .ro = 0xffffffff,
+    },{ .name = "RB_DW13_REGISTER",  .addr = A_RB_DW13_REGISTER,
+        .ro = 0xffffffff,
+    },{ .name = "RB_DW14_REGISTER",  .addr = A_RB_DW14_REGISTER,
+        .ro = 0xffffffff,
+    },{ .name = "RB_DW15_REGISTER",  .addr = A_RB_DW15_REGISTER,
+        .ro = 0xffffffff,
+    }
+};
+
+static const RegisterAccessInfo canfd_rx1_regs[] = {
+    {   .name = "RB_ID_REGISTER_1",  .addr = A_RB_ID_REGISTER_1,
+        .ro = 0xffffffff,
+    },{ .name = "RB_DLC_REGISTER_1",  .addr = A_RB_DLC_REGISTER_1,
+        .ro = 0xfe1fffff,
+    },{ .name = "RB0_DW0_REGISTER_1",  .addr = A_RB0_DW0_REGISTER_1,
+        .ro = 0xffffffff,
+    },{ .name = "RB_DW1_REGISTER_1",  .addr = A_RB_DW1_REGISTER_1,
+        .ro = 0xffffffff,
+    },{ .name = "RB_DW2_REGISTER_1",  .addr = A_RB_DW2_REGISTER_1,
+        .ro = 0xffffffff,
+    },{ .name = "RB_DW3_REGISTER_1",  .addr = A_RB_DW3_REGISTER_1,
+        .ro = 0xffffffff,
+    },{ .name = "RB_DW4_REGISTER_1",  .addr = A_RB_DW4_REGISTER_1,
+        .ro = 0xffffffff,
+    },{ .name = "RB_DW5_REGISTER_1",  .addr = A_RB_DW5_REGISTER_1,
+        .ro = 0xffffffff,
+    },{ .name = "RB_DW6_REGISTER_1",  .addr = A_RB_DW6_REGISTER_1,
+        .ro = 0xffffffff,
+    },{ .name = "RB_DW7_REGISTER_1",  .addr = A_RB_DW7_REGISTER_1,
+        .ro = 0xffffffff,
+    },{ .name = "RB_DW8_REGISTER_1",  .addr = A_RB_DW8_REGISTER_1,
+        .ro = 0xffffffff,
+    },{ .name = "RB_DW9_REGISTER_1",  .addr = A_RB_DW9_REGISTER_1,
+        .ro = 0xffffffff,
+    },{ .name = "RB_DW10_REGISTER_1",  .addr = A_RB_DW10_REGISTER_1,
+        .ro = 0xffffffff,
+    },{ .name = "RB_DW11_REGISTER_1",  .addr = A_RB_DW11_REGISTER_1,
+        .ro = 0xffffffff,
+    },{ .name = "RB_DW12_REGISTER_1",  .addr = A_RB_DW12_REGISTER_1,
+        .ro = 0xffffffff,
+    },{ .name = "RB_DW13_REGISTER_1",  .addr = A_RB_DW13_REGISTER_1,
+        .ro = 0xffffffff,
+    },{ .name = "RB_DW14_REGISTER_1",  .addr = A_RB_DW14_REGISTER_1,
+        .ro = 0xffffffff,
+    },{ .name = "RB_DW15_REGISTER_1",  .addr = A_RB_DW15_REGISTER_1,
+        .ro = 0xffffffff,
+    }
+};
+
+/* Acceptance filter registers. */
+static const RegisterAccessInfo canfd_af_regs[] = {
+    {   .name = "AFMR_REGISTER",  .addr = A_AFMR_REGISTER,
+        .pre_write = filter_mask,
+    },{ .name = "AFIR_REGISTER",  .addr = A_AFIR_REGISTER,
+        .pre_write = filter_id,
+    }
+};
+
+static const RegisterAccessInfo canfd_txe_regs[] = {
+    {   .name = "TXE_FIFO_TB_ID_REGISTER",  .addr = A_TXE_FIFO_TB_ID_REGISTER,
+        .ro = 0xffffffff,
+    },{ .name = "TXE_FIFO_TB_DLC_REGISTER",  .addr = A_TXE_FIFO_TB_DLC_REGISTER,
+        .ro = 0xffffffff,
+    }
+};
+
+static const RegisterAccessInfo canfd_regs_info[] = {
+    {   .name = "SOFTWARE_RESET_REGISTER",  .addr = A_SOFTWARE_RESET_REGISTER,
+        .pre_write = canfd_srr_pre_write,
+    },{ .name = "MODE_SELECT_REGISTER",  .addr = A_MODE_SELECT_REGISTER,
+        .pre_write = canfd_msr_pre_write,
+    },{ .name = "ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER",
+        .addr = A_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER,
+        .pre_write = canfd_write_check_prew,
+    },{ .name = "ARBITRATION_PHASE_BIT_TIMING_REGISTER",
+        .addr = A_ARBITRATION_PHASE_BIT_TIMING_REGISTER,
+        .pre_write = canfd_write_check_prew,
+    },{ .name = "ERROR_COUNTER_REGISTER",  .addr = A_ERROR_COUNTER_REGISTER,
+        .ro = 0xffff,
+    },{ .name = "ERROR_STATUS_REGISTER",  .addr = A_ERROR_STATUS_REGISTER,
+        .w1c = 0xf1f,
+    },{ .name = "STATUS_REGISTER",  .addr = A_STATUS_REGISTER,
+        .reset = 0x1,
+        .ro = 0x7f17ff,
+    },{ .name = "INTERRUPT_STATUS_REGISTER",
+        .addr = A_INTERRUPT_STATUS_REGISTER,
+        .ro = 0xffffff7f,
+    },{ .name = "INTERRUPT_ENABLE_REGISTER",
+        .addr = A_INTERRUPT_ENABLE_REGISTER,
+        .post_write = canfd_ier_post_write,
+    },{ .name = "INTERRUPT_CLEAR_REGISTER",
+        .addr = A_INTERRUPT_CLEAR_REGISTER, .pre_write = canfd_icr_pre_write,
+    },{ .name = "TIMESTAMP_REGISTER",  .addr = A_TIMESTAMP_REGISTER,
+        .ro = 0xffff0000,
+        .pre_write = canfd_tsr_pre_write,
+    },{ .name = "DATA_PHASE_BAUD_RATE_PRESCALER_REGISTER",
+        .addr = A_DATA_PHASE_BAUD_RATE_PRESCALER_REGISTER,
+        .pre_write = canfd_write_check_prew,
+    },{ .name = "DATA_PHASE_BIT_TIMING_REGISTER",
+        .addr = A_DATA_PHASE_BIT_TIMING_REGISTER,
+        .pre_write = canfd_write_check_prew,
+    },{ .name = "TX_BUFFER_READY_REQUEST_REGISTER",
+        .addr = A_TX_BUFFER_READY_REQUEST_REGISTER,
+        .pre_write = canfd_trr_reg_prew,
+        .post_write = canfd_trr_reg_postw,
+    },{ .name = "INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER",
+        .addr = A_INTERRUPT_ENABLE_TX_BUFFER_READY_REQUEST_REGISTER,
+    },{ .name = "TX_BUFFER_CANCEL_REQUEST_REGISTER",
+        .addr = A_TX_BUFFER_CANCEL_REQUEST_REGISTER,
+        .post_write = canfd_cancel_reg_postw,
+    },{ .name = "INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER",
+        .addr = A_INTERRUPT_ENABLE_TX_BUFFER_CANCELLATION_REQUEST_REGISTER,
+    },{ .name = "TX_EVENT_FIFO_STATUS_REGISTER",
+        .addr = A_TX_EVENT_FIFO_STATUS_REGISTER,
+        .ro = 0x3f1f, .pre_write = canfd_tx_fifo_status_prew,
+    },{ .name = "TX_EVENT_FIFO_WATERMARK_REGISTER",
+        .addr = A_TX_EVENT_FIFO_WATERMARK_REGISTER,
+        .reset = 0xf,
+        .pre_write = canfd_write_check_prew,
+    },{ .name = "ACCEPTANCE_FILTER_CONTROL_REGISTER",
+        .addr = A_ACCEPTANCE_FILTER_CONTROL_REGISTER,
+    },{ .name = "RX_FIFO_STATUS_REGISTER",  .addr = A_RX_FIFO_STATUS_REGISTER,
+        .ro = 0x7f3f7f3f, .pre_write = canfd_rx_fifo_status_prew,
+    },{ .name = "RX_FIFO_WATERMARK_REGISTER",
+        .addr = A_RX_FIFO_WATERMARK_REGISTER,
+        .reset = 0x1f0f0f,
+        .pre_write = canfd_write_check_prew,
+    }
+};
+
+static void xlnx_versal_canfd_ptimer_cb(void *opaque)
+{
+    /* No action required on the timer rollover. */
+}
+
+static const MemoryRegionOps canfd_ops = {
+    .read = register_read_memory,
+    .write = register_write_memory,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+};
+
+static void canfd_reset(DeviceState *dev)
+{
+    XlnxVersalCANFDState *s = XILINX_CANFD(dev);
+    unsigned int i;
+
+    for (i = 0; i < ARRAY_SIZE(s->reg_info); ++i) {
+        register_reset(&s->reg_info[i]);
+    }
+
+    ptimer_transaction_begin(s->canfd_timer);
+    ptimer_set_count(s->canfd_timer, 0);
+    ptimer_transaction_commit(s->canfd_timer);
+}
+
+static bool can_xilinx_canfd_receive(CanBusClientState *client)
+{
+    XlnxVersalCANFDState *s = container_of(client, XlnxVersalCANFDState,
+                                           bus_client);
+
+    if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, SRST)) {
+        g_autofree char *path = object_get_canonical_path(OBJECT(s));
+
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: Controller is in reset state.\n",
+                      path);
+        return false;
+    } else if ((ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) == 0) {
+        g_autofree char *path = object_get_canonical_path(OBJECT(s));
+
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: Controller is disabled."
+                      " All incoming messages will be discarded\n", path);
+        return false;
+    } else {
+        return true;
+    }
+}
+
+static ssize_t canfd_xilinx_receive(CanBusClientState *client,
+                                    const qemu_can_frame *buf,
+                                    size_t buf_size)
+{
+    XlnxVersalCANFDState *s = container_of(client, XlnxVersalCANFDState,
+                                           bus_client);
+    const qemu_can_frame *frame = buf;
+
+    /* Update the status register that we are receiving message*/
+    ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, BBSY, 1);
+
+    if (buf_size <= 0) {
+        g_autofree char *path = object_get_canonical_path(OBJECT(s));
+
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: Error in the data received.\n",
+                      path);
+        return 0;
+    }
+
+    if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, LBACK)) {
+        /*
+         * XlnxVersalCANFDState will not participate in normal bus communication
+         * and does not receive any messages transmitted by other CAN nodes.
+         */
+        g_autofree char *path = object_get_canonical_path(OBJECT(s));
+
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: Controller  is in loopback mode."
+                      " It will not receive data.\n", path);
+    } else if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SNOOP)) {
+        /* Snoop Mode: Just keep the data. no response back. */
+        update_rx_sequential(s, frame);
+    } else {
+        if ((ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP))) {
+            /*
+             * XlnxVersalCANFDState is in sleep mode. Any data on bus will bring
+             * it to the wake up state.
+             */
+            canfd_exit_sleep_mode(s);
+        }
+
+        update_rx_sequential(s, frame);
+    }
+
+    /* Message processing done. Update the status back to !busy */
+    ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, BBSY, 0);
+    return 1;
+}
+
+static CanBusClientInfo canfd_xilinx_bus_client_info = {
+    .can_receive = can_xilinx_canfd_receive,
+    .receive = canfd_xilinx_receive,
+};
+
+static int xlnx_canfd_connect_to_bus(XlnxVersalCANFDState *s,
+                                     CanBusState *bus)
+{
+    s->bus_client.info = &canfd_xilinx_bus_client_info;
+
+    if (can_bus_insert_client(bus, &s->bus_client) < 0) {
+        return -1;
+    }
+    return 0;
+}
+
+#define NUM_REG_PER_AF      ARRAY_SIZE(canfd_af_regs)
+#define NUM_AF              32
+#define NUM_REG_PER_TXE     ARRAY_SIZE(canfd_txe_regs)
+#define NUM_TXE             32
+
+static int canfd_populate_regarray(XlnxVersalCANFDState *s,
+                                  RegisterInfoArray *r_array, int pos,
+                                  const RegisterAccessInfo *rae,
+                                  int num_rae)
+{
+    int i;
+
+    for (i = 0; i < num_rae; i++) {
+        int index = rae[i].addr / 4;
+        RegisterInfo *r = &s->reg_info[index];
+
+        object_initialize((void *)r, sizeof(*r), TYPE_REGISTER);
+
+        *r = (RegisterInfo) {
+            .data = &s->regs[index],
+            .data_size = sizeof(uint32_t),
+            .access = &rae[i],
+            .opaque = OBJECT(s),
+        };
+
+        r_array->r[i + pos] = r;
+    }
+    return i + pos;
+}
+
+static void canfd_create_rai(RegisterAccessInfo *rai_array,
+                                const RegisterAccessInfo *canfd_regs,
+                                int template_rai_array_sz,
+                                int num_template_to_copy)
+{
+    int i;
+    int reg_num;
+
+    for (reg_num = 0; reg_num < num_template_to_copy; reg_num++) {
+        int pos = reg_num * template_rai_array_sz;
+
+        memcpy(rai_array + pos, canfd_regs,
+               template_rai_array_sz * sizeof(RegisterAccessInfo));
+
+        for (i = 0; i < template_rai_array_sz; i++) {
+            const char *name = canfd_regs[i].name;
+            uint64_t addr = canfd_regs[i].addr;
+            rai_array[i + pos].name = g_strdup_printf("%s%d", name, reg_num);
+            rai_array[i + pos].addr = addr + pos * 4;
+        }
+    }
+}
+
+static void canfd_finalize(Object *obj)
+{
+    XlnxVersalCANFDState *s = XILINX_CANFD(obj);
+    g_free(s->tx_regs);
+    g_free(s->rx0_regs);
+    g_free(s->af_regs);
+    g_free(s->txe_regs);
+    g_free(s->rx1_regs);
+}
+
+static RegisterInfoArray *canfd_create_regarray(XlnxVersalCANFDState *s)
+{
+    const char *device_prefix = object_get_typename(OBJECT(s));
+    uint64_t memory_size = XLNX_VERSAL_CANFD_R_MAX * 4;
+    int num_regs;
+    int pos = 0;
+    RegisterInfoArray *r_array;
+
+    num_regs = ARRAY_SIZE(canfd_regs_info) +
+                s->cfg.tx_fifo * NUM_REGS_PER_MSG_SPACE +
+                s->cfg.rx0_fifo * NUM_REGS_PER_MSG_SPACE +
+                NUM_AF * NUM_REG_PER_AF +
+                NUM_TXE * NUM_REG_PER_TXE;
+
+    s->tx_regs = g_new0(RegisterAccessInfo,
+                        s->cfg.tx_fifo * ARRAY_SIZE(canfd_tx_regs));
+
+    canfd_create_rai(s->tx_regs, canfd_tx_regs,
+                     ARRAY_SIZE(canfd_tx_regs), s->cfg.tx_fifo);
+
+    s->rx0_regs = g_new0(RegisterAccessInfo,
+                         s->cfg.rx0_fifo * ARRAY_SIZE(canfd_rx0_regs));
+
+    canfd_create_rai(s->rx0_regs, canfd_rx0_regs,
+                     ARRAY_SIZE(canfd_rx0_regs), s->cfg.rx0_fifo);
+
+    s->af_regs = g_new0(RegisterAccessInfo,
+                        NUM_AF * ARRAY_SIZE(canfd_af_regs));
+
+    canfd_create_rai(s->af_regs, canfd_af_regs,
+                     ARRAY_SIZE(canfd_af_regs), NUM_AF);
+
+    s->txe_regs = g_new0(RegisterAccessInfo,
+                         NUM_TXE * ARRAY_SIZE(canfd_txe_regs));
+
+    canfd_create_rai(s->txe_regs, canfd_txe_regs,
+                     ARRAY_SIZE(canfd_txe_regs), NUM_TXE);
+
+    if (s->cfg.enable_rx_fifo1) {
+        num_regs += s->cfg.rx1_fifo * NUM_REGS_PER_MSG_SPACE;
+
+        s->rx1_regs = g_new0(RegisterAccessInfo,
+                             s->cfg.rx1_fifo * ARRAY_SIZE(canfd_rx1_regs));
+
+        canfd_create_rai(s->rx1_regs, canfd_rx1_regs,
+                         ARRAY_SIZE(canfd_rx1_regs), s->cfg.rx1_fifo);
+    }
+
+    r_array = g_new0(RegisterInfoArray, 1);
+    r_array->r = g_new0(RegisterInfo * , num_regs);
+    r_array->num_elements = num_regs;
+    r_array->prefix = device_prefix;
+
+    pos = canfd_populate_regarray(s, r_array, pos,
+                                  canfd_regs_info,
+                                  ARRAY_SIZE(canfd_regs_info));
+    pos = canfd_populate_regarray(s, r_array, pos,
+                                  s->tx_regs, s->cfg.tx_fifo *
+                                  NUM_REGS_PER_MSG_SPACE);
+    pos = canfd_populate_regarray(s, r_array, pos,
+                                  s->rx0_regs, s->cfg.rx0_fifo *
+                                  NUM_REGS_PER_MSG_SPACE);
+    if (s->cfg.enable_rx_fifo1) {
+        pos = canfd_populate_regarray(s, r_array, pos,
+                                      s->rx1_regs, s->cfg.rx1_fifo *
+                                      NUM_REGS_PER_MSG_SPACE);
+    }
+    pos = canfd_populate_regarray(s, r_array, pos,
+                                  s->af_regs, NUM_AF * NUM_REG_PER_AF);
+    pos = canfd_populate_regarray(s, r_array, pos,
+                                  s->txe_regs, NUM_TXE * NUM_REG_PER_TXE);
+
+    memory_region_init_io(&r_array->mem, OBJECT(s), &canfd_ops, r_array,
+                          device_prefix, memory_size);
+    return r_array;
+}
+
+static void canfd_realize(DeviceState *dev, Error **errp)
+{
+    XlnxVersalCANFDState *s = XILINX_CANFD(dev);
+    RegisterInfoArray *reg_array;
+
+    reg_array = canfd_create_regarray(s);
+    memory_region_add_subregion(&s->iomem, 0x00, &reg_array->mem);
+    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
+    sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq_canfd_int);
+
+    if (s->canfdbus) {
+        if (xlnx_canfd_connect_to_bus(s, s->canfdbus) < 0) {
+            g_autofree char *path = object_get_canonical_path(OBJECT(s));
+
+            error_setg(errp, "%s: xlnx_canfd_connect_to_bus failed", path);
+            return;
+        }
+
+    } else {
+        /* If no bus is set. */
+        g_autofree char *path = object_get_canonical_path(OBJECT(s));
+
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: canfdbus property not set\n", path);
+    }
+
+    /* Allocate a new timer. */
+    s->canfd_timer = ptimer_init(xlnx_versal_canfd_ptimer_cb, s,
+                                 PTIMER_POLICY_LEGACY);
+
+    ptimer_transaction_begin(s->canfd_timer);
+
+    ptimer_set_freq(s->canfd_timer, s->cfg.ext_clk_freq);
+    ptimer_set_limit(s->canfd_timer, CANFD_TIMER_MAX, 1);
+    ptimer_run(s->canfd_timer, 0);
+    ptimer_transaction_commit(s->canfd_timer);
+}
+
+static void canfd_init(Object *obj)
+{
+    XlnxVersalCANFDState *s = XILINX_CANFD(obj);
+
+    memory_region_init(&s->iomem, obj, TYPE_XILINX_CANFD,
+                       XLNX_VERSAL_CANFD_R_MAX * 4);
+}
+
+static const VMStateDescription vmstate_canfd = {
+    .name = TYPE_XILINX_CANFD,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(regs, XlnxVersalCANFDState,
+                             XLNX_VERSAL_CANFD_R_MAX),
+        VMSTATE_PTIMER(canfd_timer, XlnxVersalCANFDState),
+        VMSTATE_END_OF_LIST(),
+    }
+};
+
+static Property canfd_core_properties[] = {
+    DEFINE_PROP_UINT8("rx-fifo0", XlnxVersalCANFDState, cfg.rx0_fifo, 0x40),
+    DEFINE_PROP_UINT8("rx-fifo1", XlnxVersalCANFDState, cfg.rx1_fifo, 0x40),
+    DEFINE_PROP_UINT8("tx-fifo", XlnxVersalCANFDState, cfg.tx_fifo, 0x20),
+    DEFINE_PROP_BOOL("enable-rx-fifo1", XlnxVersalCANFDState,
+                     cfg.enable_rx_fifo1, true),
+    DEFINE_PROP_UINT32("ext_clk_freq", XlnxVersalCANFDState, cfg.ext_clk_freq,
+                       CANFD_DEFAULT_CLOCK),
+    DEFINE_PROP_LINK("canfdbus", XlnxVersalCANFDState, canfdbus, TYPE_CAN_BUS,
+                     CanBusState *),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void canfd_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->reset = canfd_reset;
+    dc->realize = canfd_realize;
+    device_class_set_props(dc, canfd_core_properties);
+    dc->vmsd = &vmstate_canfd;
+}
+
+static const TypeInfo canfd_info = {
+    .name          = TYPE_XILINX_CANFD,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(XlnxVersalCANFDState),
+    .class_init    = canfd_class_init,
+    .instance_init = canfd_init,
+    .instance_finalize = canfd_finalize,
+};
+
+static void canfd_register_types(void)
+{
+    type_register_static(&canfd_info);
+}
+
+type_init(canfd_register_types)
diff --git a/include/hw/net/xlnx-versal-canfd.h b/include/hw/net/xlnx-versal-canfd.h
new file mode 100644
index 0000000000..e550f5ccac
--- /dev/null
+++ b/include/hw/net/xlnx-versal-canfd.h
@@ -0,0 +1,92 @@ 
+/*
+ * QEMU model of the Xilinx Versal CANFD Controller.
+ *
+ * Copyright (c) 2022 AMD Inc.
+ *
+ * Written-by: Vikram Garhwal<vikram.garhwal@amd.com>
+ * Based on QEMU CANFD Device emulation implemented by Jin Yang, Deniz Eren and
+ * Pavel Pisa.
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef HW_CANFD_XILINX_H
+#define HW_CANFD_XILINX_H
+
+#include "hw/register.h"
+#include "hw/ptimer.h"
+#include "net/can_emu.h"
+#include "hw/qdev-clock.h"
+
+#define TYPE_XILINX_CANFD "xlnx.versal-canfd"
+
+#define XILINX_CANFD(obj) \
+     OBJECT_CHECK(XlnxVersalCANFDState, (obj), TYPE_XILINX_CANFD)
+
+#define NUM_REGS_PER_MSG_SPACE 18
+#define MAX_NUM_RX             64
+#define CANFD_TIMER_MAX        0XFFFFUL
+#define CANFD_DEFAULT_CLOCK    (24 * 1000 * 1000)
+
+/* 0x4144/4 + 1 + (64 - 1) * 18 + 1. */
+#define XLNX_VERSAL_CANFD_R_MAX (0x4144 / 4  + \
+                    ((MAX_NUM_RX - 1) * NUM_REGS_PER_MSG_SPACE) + 1)
+
+typedef struct XlnxVersalCANFDState {
+    SysBusDevice            parent_obj;
+    MemoryRegion            iomem;
+
+    qemu_irq                irq_canfd_int;
+    qemu_irq                irq_addr_err;
+
+    RegisterInfo            reg_info[XLNX_VERSAL_CANFD_R_MAX];
+    RegisterAccessInfo      *tx_regs;
+    RegisterAccessInfo      *rx0_regs;
+    RegisterAccessInfo      *rx1_regs;
+    RegisterAccessInfo      *af_regs;
+    RegisterAccessInfo      *txe_regs;
+    RegisterAccessInfo      *rx_mailbox_regs;
+    RegisterAccessInfo      *af_mask_regs_mailbox;
+
+    uint32_t                regs[XLNX_VERSAL_CANFD_R_MAX];
+    uint8_t                 tx_busy_bit;
+    uint8_t                 modes;
+
+    ptimer_state            *canfd_timer;
+
+    CanBusClientState       bus_client;
+    CanBusState             *canfdbus;
+
+    struct {
+        uint8_t             ctrl_idx;
+        uint8_t             rx0_fifo;
+        uint8_t             rx1_fifo;
+        uint8_t             tx_fifo;
+        bool                enable_rx_fifo1;
+        uint32_t            ext_clk_freq;
+   } cfg;
+
+} XlnxVersalCANFDState;
+
+typedef struct txid_list {
+    uint32_t can_id;
+    uint32_t reg_num;
+    struct txid_list   *next;
+} txid_list;
+
+#endif