aboutsummaryrefslogtreecommitdiffstats
path: root/roms/u-boot/drivers/serial
diff options
context:
space:
mode:
Diffstat (limited to 'roms/u-boot/drivers/serial')
-rw-r--r--roms/u-boot/drivers/serial/Kconfig947
-rw-r--r--roms/u-boot/drivers/serial/Makefile80
-rw-r--r--roms/u-boot/drivers/serial/altera_jtag_uart.c151
-rw-r--r--roms/u-boot/drivers/serial/altera_uart.c149
-rw-r--r--roms/u-boot/drivers/serial/arm_dcc.c174
-rw-r--r--roms/u-boot/drivers/serial/atmel_usart.c338
-rw-r--r--roms/u-boot/drivers/serial/atmel_usart.h293
-rw-r--r--roms/u-boot/drivers/serial/lpc32xx_hsuart.c112
-rw-r--r--roms/u-boot/drivers/serial/ns16550.c633
-rw-r--r--roms/u-boot/drivers/serial/sandbox.c249
-rw-r--r--roms/u-boot/drivers/serial/serial-uclass.c522
-rw-r--r--roms/u-boot/drivers/serial/serial.c555
-rw-r--r--roms/u-boot/drivers/serial/serial_ar933x.c243
-rw-r--r--roms/u-boot/drivers/serial/serial_arc.c159
-rw-r--r--roms/u-boot/drivers/serial/serial_bcm283x_mu.c204
-rw-r--r--roms/u-boot/drivers/serial/serial_bcm283x_pl011.c101
-rw-r--r--roms/u-boot/drivers/serial/serial_bcm6345.c296
-rw-r--r--roms/u-boot/drivers/serial/serial_coreboot.c46
-rw-r--r--roms/u-boot/drivers/serial/serial_cortina.c165
-rw-r--r--roms/u-boot/drivers/serial/serial_efi.c156
-rw-r--r--roms/u-boot/drivers/serial/serial_intel_mid.c67
-rw-r--r--roms/u-boot/drivers/serial/serial_linflexuart.c219
-rw-r--r--roms/u-boot/drivers/serial/serial_lpuart.c574
-rw-r--r--roms/u-boot/drivers/serial/serial_mcf.c180
-rw-r--r--roms/u-boot/drivers/serial/serial_meson.c195
-rw-r--r--roms/u-boot/drivers/serial/serial_mpc8xx.c258
-rw-r--r--roms/u-boot/drivers/serial/serial_msm.c247
-rw-r--r--roms/u-boot/drivers/serial/serial_mt7620.c246
-rw-r--r--roms/u-boot/drivers/serial/serial_mtk.c452
-rw-r--r--roms/u-boot/drivers/serial/serial_mvebu_a3700.c179
-rw-r--r--roms/u-boot/drivers/serial/serial_mxc.c394
-rw-r--r--roms/u-boot/drivers/serial/serial_ns16550.c254
-rw-r--r--roms/u-boot/drivers/serial/serial_nulldev.c53
-rw-r--r--roms/u-boot/drivers/serial/serial_octeon_bootcmd.c182
-rw-r--r--roms/u-boot/drivers/serial/serial_octeon_pcie_console.c365
-rw-r--r--roms/u-boot/drivers/serial/serial_omap.c171
-rw-r--r--roms/u-boot/drivers/serial/serial_owl.c136
-rw-r--r--roms/u-boot/drivers/serial/serial_pic32.c201
-rw-r--r--roms/u-boot/drivers/serial/serial_pl01x.c427
-rw-r--r--roms/u-boot/drivers/serial/serial_pl01x_internal.h145
-rw-r--r--roms/u-boot/drivers/serial/serial_pxa.c343
-rw-r--r--roms/u-boot/drivers/serial/serial_rockchip.c61
-rw-r--r--roms/u-boot/drivers/serial/serial_s5p.c241
-rw-r--r--roms/u-boot/drivers/serial/serial_sh.c369
-rw-r--r--roms/u-boot/drivers/serial/serial_sh.h505
-rw-r--r--roms/u-boot/drivers/serial/serial_sifive.c233
-rw-r--r--roms/u-boot/drivers/serial/serial_sti_asc.c212
-rw-r--r--roms/u-boot/drivers/serial/serial_stm32.c292
-rw-r--r--roms/u-boot/drivers/serial/serial_stm32.h82
-rw-r--r--roms/u-boot/drivers/serial/serial_uniphier.c177
-rw-r--r--roms/u-boot/drivers/serial/serial_xen.c183
-rw-r--r--roms/u-boot/drivers/serial/serial_xuartlite.c171
-rw-r--r--roms/u-boot/drivers/serial/serial_zynq.c240
-rw-r--r--roms/u-boot/drivers/serial/usbtty.c1042
-rw-r--r--roms/u-boot/drivers/serial/usbtty.h76
55 files changed, 14745 insertions, 0 deletions
diff --git a/roms/u-boot/drivers/serial/Kconfig b/roms/u-boot/drivers/serial/Kconfig
new file mode 100644
index 000000000..6d1c4530d
--- /dev/null
+++ b/roms/u-boot/drivers/serial/Kconfig
@@ -0,0 +1,947 @@
+#
+# Serial device configuration
+#
+
+menu "Serial drivers"
+
+config BAUDRATE
+ int "Default baudrate"
+ default 115200
+ help
+ Select a default baudrate, where "default" has a driver-specific
+ meaning of either setting the baudrate for the early debug UART
+ in the SPL stage (most drivers) or for choosing a default baudrate
+ in the absence of an environment setting (serial_mxc.c).
+
+config REQUIRE_SERIAL_CONSOLE
+ bool "Require a serial port for console"
+ # Running without a serial console is not supported by the
+ # non-dm serial code
+ depends on DM_SERIAL
+ default y
+ help
+ Require a serial port for the console, and panic if none is found
+ during serial port initialization (default y). Set this to n on
+ boards which have no debug serial port whatsoever.
+
+config SPECIFY_CONSOLE_INDEX
+ bool "Specify the port number used for console"
+ default y if !DM_SERIAL || (SPL && !SPL_DM_SERIAL) || \
+ (TPL && !TPL_DM_SERIAL)
+ help
+ In various cases, we need to specify which of the UART devices that
+ a board or SoC has available are to be used for the console device
+ in U-Boot.
+
+config SERIAL_PRESENT
+ bool "Provide a serial driver"
+ depends on DM_SERIAL
+ default y
+ help
+ In very space-constrained devices even the full UART driver is too
+ large. In this case the debug UART can still be used in some cases.
+ This option enables the full UART in U-Boot, so if is it disabled,
+ the full UART driver will be omitted, thus saving space.
+
+config SPL_SERIAL_PRESENT
+ bool "Provide a serial driver in SPL"
+ depends on DM_SERIAL && SPL
+ default y
+ help
+ In very space-constrained devices even the full UART driver is too
+ large. In this case the debug UART can still be used in some cases.
+ This option enables the full UART in SPL, so if is it disabled,
+ the full UART driver will be omitted, thus saving space.
+
+config TPL_SERIAL_PRESENT
+ bool "Provide a serial driver in TPL"
+ depends on DM_SERIAL && TPL
+ default y
+ help
+ In very space-constrained devices even the full UART driver is too
+ large. In this case the debug UART can still be used in some cases.
+ This option enables the full UART in TPL, so if is it disabled,
+ the full UART driver will be omitted, thus saving space.
+
+# Logic to allow us to use the imply keyword to set what the default port
+# should be. The default is otherwise 1.
+config CONS_INDEX_0
+ bool
+
+config CONS_INDEX_2
+ bool
+
+config CONS_INDEX_3
+ bool
+
+config CONS_INDEX_4
+ bool
+
+config CONS_INDEX_5
+ bool
+
+config CONS_INDEX_6
+ bool
+
+config CONS_INDEX
+ int "UART used for console"
+ depends on SPECIFY_CONSOLE_INDEX
+ range 0 6
+ default 0 if CONS_INDEX_0
+ default 2 if CONS_INDEX_2
+ default 3 if CONS_INDEX_3
+ default 4 if CONS_INDEX_4
+ default 5 if CONS_INDEX_5
+ default 6 if CONS_INDEX_6
+ default 1
+ help
+ Set this to match the UART number of the serial console.
+
+config DM_SERIAL
+ bool "Enable Driver Model for serial drivers"
+ depends on DM
+ select SYS_MALLOC_F
+ help
+ Enable driver model for serial. This replaces
+ drivers/serial/serial.c with the serial uclass, which
+ implements serial_putc() etc. The uclass interface is
+ defined in include/serial.h.
+
+config SERIAL_RX_BUFFER
+ bool "Enable RX buffer for serial input"
+ depends on DM_SERIAL
+ help
+ Enable RX buffer support for the serial driver. This enables
+ pasting longer strings, even when the RX FIFO of the UART is
+ not big enough (e.g. 16 bytes on the normal NS16550).
+
+config SERIAL_RX_BUFFER_SIZE
+ int "RX buffer size"
+ depends on SERIAL_RX_BUFFER
+ default 256
+ help
+ The size of the RX buffer (needs to be power of 2)
+
+config SERIAL_SEARCH_ALL
+ bool "Search for serial devices after default one failed"
+ depends on DM_SERIAL
+ help
+ The serial subsystem only searches for a single serial device
+ that was instantiated, but does not check whether it was probed
+ correctly. With this option set, we make successful probing
+ mandatory and search for fallback serial devices if the default
+ device does not work.
+
+ If unsure, say N.
+
+config SERIAL_PROBE_ALL
+ bool "Probe all available serial devices"
+ depends on DM_SERIAL
+ default n
+ help
+ The serial subsystem only probes for a single serial device,
+ but does not probe for other remaining serial devices.
+ With this option set, we make probing and searching for
+ all available devices optional.
+ Normally, U-Boot talks to one serial port at a time, but SBSA
+ compliant UART devices like PL011 require initialization
+ by firmware and to let the kernel use serial port for sending
+ and receiving the characters.
+
+ If unsure, say N.
+
+config SPL_DM_SERIAL
+ bool "Enable Driver Model for serial drivers in SPL"
+ depends on DM_SERIAL && SPL_DM
+ select SYS_SPL_MALLOC_F
+ default y
+ help
+ Enable driver model for serial in SPL. This replaces
+ drivers/serial/serial.c with the serial uclass, which
+ implements serial_putc() etc. The uclass interface is
+ defined in include/serial.h.
+
+config TPL_DM_SERIAL
+ bool "Enable Driver Model for serial drivers in TPL"
+ depends on DM_SERIAL && TPL_DM
+ select SYS_TPL_MALLOC_F
+ default y if TPL && DM_SERIAL
+ help
+ Enable driver model for serial in TPL. This replaces
+ drivers/serial/serial.c with the serial uclass, which
+ implements serial_putc() etc. The uclass interface is
+ defined in include/serial.h.
+
+config DEBUG_UART
+ bool "Enable an early debug UART for debugging"
+ help
+ The debug UART is intended for use very early in U-Boot to debug
+ problems when an ICE or other debug mechanism is not available.
+
+ To use it you should:
+ - Make sure your UART supports this interface
+ - Enable CONFIG_DEBUG_UART
+ - Enable the CONFIG for your UART to tell it to provide this interface
+ (e.g. CONFIG_DEBUG_UART_NS16550)
+ - Define the required settings as needed (see below)
+ - Call debug_uart_init() before use
+ - Call debug_uart_putc() to output a character
+
+ Depending on your platform it may be possible to use this UART before
+ a stack is available.
+
+ If your UART does not support this interface you can probably add
+ support quite easily. Remember that you cannot use driver model and
+ it is preferred to use no stack.
+
+ You must not use this UART once driver model is working and the
+ serial drivers are up and running (done in serial_init()). Otherwise
+ the drivers may conflict and you will get strange output.
+
+choice
+ prompt "Select which UART will provide the debug UART"
+ depends on DEBUG_UART
+ default DEBUG_UART_NS16550
+
+config DEBUG_UART_ALTERA_JTAGUART
+ bool "Altera JTAG UART"
+ depends on ALTERA_JTAG_UART
+ help
+ Select this to enable a debug UART using the altera_jtag_uart driver.
+ You will need to provide parameters to make this work. The driver will
+ be available until the real driver model serial is running.
+
+config DEBUG_UART_ALTERA_UART
+ bool "Altera UART"
+ depends on ALTERA_UART
+ help
+ Select this to enable a debug UART using the altera_uart driver.
+ You will need to provide parameters to make this work. The driver will
+ be available until the real driver model serial is running.
+
+config DEBUG_UART_AR933X
+ bool "QCA/Atheros ar933x"
+ depends on AR933X_UART
+ help
+ Select this to enable a debug UART using the ar933x uart driver.
+ You will need to provide parameters to make this work. The
+ driver will be available until the real driver model serial is
+ running.
+
+config DEBUG_ARC_SERIAL
+ bool "ARC UART"
+ depends on ARC_SERIAL
+ help
+ Select this to enable a debug UART using the ARC UART driver.
+ You will need to provide parameters to make this work. The
+ driver will be available until the real driver model serial is
+ running.
+
+config DEBUG_UART_ATMEL
+ bool "Atmel USART"
+ depends on ATMEL_USART
+ help
+ Select this to enable a debug UART using the atmel usart driver. You
+ will need to provide parameters to make this work. The driver will
+ be available until the real driver-model serial is running.
+
+config DEBUG_UART_BCM6345
+ bool "BCM6345 UART"
+ depends on BCM6345_SERIAL
+ help
+ Select this to enable a debug UART on BCM6345 SoCs. You
+ will need to provide parameters to make this work. The driver will
+ be available until the real driver model serial is running.
+
+config DEBUG_UART_NS16550
+ bool "ns16550"
+ depends on SYS_NS16550
+ help
+ Select this to enable a debug UART using the ns16550 driver. You
+ will need to provide parameters to make this work. The driver will
+ be available until the real driver model serial is running.
+
+config DEBUG_EFI_CONSOLE
+ bool "EFI"
+ depends on EFI_APP
+ help
+ Select this to enable a debug console which calls back to EFI to
+ output to the console. This can be useful for early debugging of
+ U-Boot when running on top of EFI (Extensive Firmware Interface).
+ This is a type of BIOS used by PCs.
+
+config DEBUG_UART_S5P
+ bool "Samsung S5P"
+ depends on ARCH_EXYNOS || ARCH_S5PC1XX
+ help
+ Select this to enable a debug UART using the serial_s5p driver. You
+ will need to provide parameters to make this work. The driver will
+ be available until the real driver-model serial is running.
+
+config DEBUG_UART_MESON
+ bool "Amlogic Meson"
+ depends on MESON_SERIAL
+ help
+ Select this to enable a debug UART using the serial_meson driver. You
+ will need to provide parameters to make this work. The driver will
+ be available until the real driver-model serial is running.
+
+config DEBUG_UART_UARTLITE
+ bool "Xilinx Uartlite"
+ depends on XILINX_UARTLITE
+ help
+ Select this to enable a debug UART using the serial_uartlite driver.
+ You will need to provide parameters to make this work. The driver will
+ be available until the real driver-model serial is running.
+
+config DEBUG_UART_ARM_DCC
+ bool "ARM DCC"
+ depends on ARM_DCC
+ help
+ Select this to enable a debug UART using the ARM JTAG DCC port.
+ The DCC port can be used for very early debugging and doesn't require
+ any additional setting like address/baudrate/clock. On systems without
+ any serial interface this is the easiest way how to get console.
+ Every ARM core has own DCC port which is the part of debug interface.
+ This port is available at least on ARMv6, ARMv7, ARMv8 and XScale
+ architectures.
+
+config DEBUG_MVEBU_A3700_UART
+ bool "Marvell Armada 3700"
+ depends on MVEBU_A3700_UART
+ help
+ Select this to enable a debug UART using the serial_mvebu driver. You
+ will need to provide parameters to make this work. The driver will
+ be available until the real driver-model serial is running.
+
+config DEBUG_UART_ZYNQ
+ bool "Xilinx Zynq"
+ depends on ZYNQ_SERIAL
+ help
+ Select this to enable a debug UART using the serial_zynq driver. You
+ will need to provide parameters to make this work. The driver will
+ be available until the real driver-model serial is running.
+
+config DEBUG_UART_APBUART
+ depends on LEON3
+ bool "Gaisler APBUART"
+ help
+ Select this to enable a debug UART using the serial_leon3 driver. You
+ will need to provide parameters to make this work. The driver will
+ be available until the real driver model serial is running.
+
+config DEBUG_UART_PL010
+ bool "pl010"
+ depends on PL01X_SERIAL
+ help
+ Select this to enable a debug UART using the pl01x driver with the
+ PL010 UART type. You will need to provide parameters to make this
+ work. The driver will be available until the real driver model
+ serial is running.
+
+config DEBUG_UART_PL011
+ bool "pl011"
+ depends on PL011_SERIAL
+ help
+ Select this to enable a debug UART using the pl01x driver with the
+ PL011 UART type. You will need to provide parameters to make this
+ work. The driver will be available until the real driver model
+ serial is running.
+
+config DEBUG_UART_PIC32
+ bool "Microchip PIC32"
+ depends on PIC32_SERIAL
+ help
+ Select this to enable a debug UART using the serial_pic32 driver. You
+ will need to provide parameters to make this work. The driver will
+ be available until the real driver model serial is running.
+
+config DEBUG_UART_MXC
+ bool "IMX Serial port"
+ depends on MXC_UART
+ help
+ Select this to enable a debug UART using the serial_mxc driver. You
+ will need to provide parameters to make this work. The driver will
+ be available until the real driver model serial is running.
+
+config DEBUG_UART_SANDBOX
+ bool "sandbox"
+ depends on SANDBOX_SERIAL
+ help
+ Select this to enable the debug UART using the sandbox driver. This
+ provides basic serial output from the console without needing to
+ start up driver model. The driver will be available until the real
+ driver model serial is running.
+
+config DEBUG_UART_SIFIVE
+ bool "SiFive UART"
+ depends on SIFIVE_SERIAL
+ help
+ Select this to enable a debug UART using the serial_sifive driver. You
+ will need to provide parameters to make this work. The driver will
+ be available until the real driver-model serial is running.
+
+config DEBUG_UART_STM32
+ bool "STMicroelectronics STM32"
+ depends on STM32_SERIAL
+ help
+ Select this to enable a debug UART using the serial_stm32 driver
+ You will need to provide parameters to make this work.
+ The driver will be available until the real driver model
+ serial is running.
+
+config DEBUG_UART_UNIPHIER
+ bool "UniPhier on-chip UART"
+ depends on ARCH_UNIPHIER
+ help
+ Select this to enable a debug UART using the UniPhier on-chip UART.
+ You will need to provide DEBUG_UART_BASE to make this work. The
+ driver will be available until the real driver-model serial is
+ running.
+
+config DEBUG_UART_OMAP
+ bool "OMAP uart"
+ depends on OMAP_SERIAL
+ help
+ Select this to enable a debug UART using the omap ns16550 driver.
+ You will need to provide parameters to make this work. The driver
+ will be available until the real driver model serial is running.
+
+config DEBUG_UART_MTK
+ bool "MediaTek High-speed UART"
+ depends on MTK_SERIAL
+ help
+ Select this to enable a debug UART using the MediaTek High-speed
+ UART driver.
+ You will need to provide parameters to make this work. The
+ driver will be available until the real driver model serial is
+ running.
+
+config DEBUG_UART_MT7620
+ bool "UART driver for MediaTek MT7620 and earlier SoCs"
+ depends on MT7620_SERIAL
+ help
+ Select this to enable a debug UART using the UART driver for
+ MediaTek MT7620 and earlier SoCs.
+ You will need to provide parameters to make this work. The
+ driver will be available until the real driver model serial is
+ running.
+
+endchoice
+
+config DEBUG_UART_BASE
+ hex "Base address of UART"
+ depends on DEBUG_UART
+ default 0 if DEBUG_UART_SANDBOX
+ help
+ This is the base address of your UART for memory-mapped UARTs.
+
+ A default should be provided by your board, but if not you will need
+ to use the correct value here.
+
+config DEBUG_UART_CLOCK
+ int "UART input clock"
+ depends on DEBUG_UART
+ default 0 if DEBUG_UART_SANDBOX
+ help
+ The UART input clock determines the speed of the internal UART
+ circuitry. The baud rate is derived from this by dividing the input
+ clock down.
+
+ A default should be provided by your board, but if not you will need
+ to use the correct value here.
+
+config DEBUG_UART_SHIFT
+ int "UART register shift"
+ depends on DEBUG_UART
+ default 0 if DEBUG_UART
+ help
+ Some UARTs (notably ns16550) support different register layouts
+ where the registers are spaced either as bytes, words or some other
+ value. Use this value to specify the shift to use, where 0=byte
+ registers, 2=32-bit word registers, etc.
+
+config DEBUG_UART_BOARD_INIT
+ bool "Enable board-specific debug UART init"
+ depends on DEBUG_UART
+ help
+ Some boards need to set things up before the debug UART can be used.
+ On these boards a call to debug_uart_init() is insufficient. When
+ this option is enabled, the function board_debug_uart_init() will
+ be called when debug_uart_init() is called. You can put any code
+ here that is needed to set up the UART ready for use, such as set
+ pin multiplexing or enable clocks.
+
+config DEBUG_UART_ANNOUNCE
+ bool "Show a message when the debug UART starts up"
+ depends on DEBUG_UART
+ help
+ Enable this option to show a message when the debug UART is ready
+ for use. You will see a message like "<debug_uart> " as soon as
+ U-Boot has the UART ready for use (i.e. your code calls
+ debug_uart_init()). This can be useful just as a check that
+ everything is working.
+
+config DEBUG_UART_SKIP_INIT
+ bool "Skip UART initialization"
+ depends on DEBUG_UART
+ help
+ Select this if the UART you want to use for debug output is already
+ initialized by the time U-Boot starts its execution.
+
+config DEBUG_UART_NS16550_CHECK_ENABLED
+ bool "Check if UART is enabled on output"
+ depends on DEBUG_UART
+ depends on DEBUG_UART_NS16550
+ help
+ Select this if puts()/putc() might be called before the debug UART
+ has been initialized. If this is disabled, putc() might sit in a
+ tight loop if it is called before debug_uart_init() has been called.
+
+ Note that this does not work for every ns16550-compatible UART and
+ so has to be enabled carefully or you might notice lost characters.
+
+config ALTERA_JTAG_UART
+ bool "Altera JTAG UART support"
+ depends on DM_SERIAL
+ help
+ Select this to enable an JTAG UART for Altera devices.The JTAG UART
+ core implements a method to communicate serial character streams
+ between a host PC and a Qsys system on an Altera FPGA. Please find
+ details on the "Embedded Peripherals IP User Guide" of Altera.
+
+config ALTERA_JTAG_UART_BYPASS
+ bool "Bypass output when no connection"
+ depends on ALTERA_JTAG_UART
+ help
+ Bypass console output and keep going even if there is no JTAG
+ terminal connection with the host. The console output will resume
+ once the JTAG terminal is connected. Without the bypass, the console
+ output will wait forever until a JTAG terminal is connected. If you
+ not are sure, say Y.
+
+config ALTERA_UART
+ bool "Altera UART support"
+ depends on DM_SERIAL
+ help
+ Select this to enable an UART for Altera devices. Please find
+ details on the "Embedded Peripherals IP User Guide" of Altera.
+
+config AR933X_UART
+ bool "QCA/Atheros ar933x UART support"
+ depends on DM_SERIAL && SOC_AR933X
+ help
+ Select this to enable UART support for QCA/Atheros ar933x
+ devices. This driver uses driver model and requires a device
+ tree binding to operate, please refer to the document at
+ doc/device-tree-bindings/serial/qca,ar9330-uart.txt.
+
+config ARC_SERIAL
+ bool "ARC UART support"
+ depends on DM_SERIAL
+ help
+ Select this to enable support for ARC UART now typically
+ only used in Synopsys DesignWare ARC simulators like nSIM.
+
+config ARM_DCC
+ bool "ARM Debug Communication Channel (DCC) as UART support"
+ depends on ARM
+ help
+ Select this to enable using the ARM DCC as a form of UART.
+
+config ATMEL_USART
+ bool "Atmel USART support"
+ help
+ Select this to enable USART support for Atmel SoCs. It can be
+ configured in the device tree, and input clock frequency can
+ be got from the clk node.
+
+config SPL_UART_CLOCK
+ int "SPL fixed UART input clock"
+ depends on ATMEL_USART && SPL && !SPL_CLK
+ default 132096000 if ARCH_AT91
+ help
+ Provide a fixed clock value as input to the UART controller. This
+ might be needed on platforms which can't enable CONFIG_SPL_CLK
+ because of SPL image size restrictions.
+
+config BCM283X_MU_SERIAL
+ bool "Support for BCM283x Mini-UART"
+ depends on DM_SERIAL && ARCH_BCM283X
+ default y
+ help
+ Select this to enable Mini-UART support on BCM283X family of SoCs.
+
+config BCM283X_PL011_SERIAL
+ bool "Support for BCM283x PL011 UART"
+ depends on PL01X_SERIAL && ARCH_BCM283X
+ default y
+ help
+ Select this to enable an overriding PL011 driver for BCM283X SoCs
+ that supports automatic disable, so that it only gets used when
+ the UART is actually muxed.
+
+config BCM6345_SERIAL
+ bool "Support for BCM6345 UART"
+ depends on DM_SERIAL
+ help
+ Select this to enable UART on BCM6345 SoCs.
+
+config COREBOOT_SERIAL
+ bool "Coreboot UART support"
+ depends on DM_SERIAL
+ default y if SYS_COREBOOT
+ select SYS_NS16550
+ help
+ Select this to enable a ns16550-style UART where the platform data
+ comes from the coreboot 'sysinfo' tables. This allows U-Boot to have
+ a serial console on any platform without needing to change the
+ device tree, etc.
+
+config CORTINA_UART
+ bool "Cortina UART support"
+ depends on DM_SERIAL
+ help
+ Select this to enable UART support for Cortina-Access UART devices
+ found on CAxxxx SoCs.
+
+config FSL_LINFLEXUART
+ bool "Freescale Linflex UART support"
+ depends on DM_SERIAL
+ help
+ Select this to enable the Linflex serial module found on some
+ NXP SoCs like S32V234.
+
+config FSL_LPUART
+ bool "Freescale LPUART support"
+ help
+ Select this to enable a Low Power UART for Freescale VF610 and
+ QorIQ Layerscape devices.
+
+config MVEBU_A3700_UART
+ bool "UART support for Armada 3700"
+ default n
+ help
+ Choose this option to add support for UART driver on the Marvell
+ Armada 3700 SoC. The base address is configured via DT.
+
+config MCFUART
+ bool "Freescale ColdFire UART support"
+ help
+ Choose this option to add support for UART driver on the ColdFire
+ SoC's family. The serial communication channel provides a full-duplex
+ asynchronous/synchronous receiver and transmitter deriving an
+ operating frequency from the internal bus clock or an external clock.
+
+config MXC_UART
+ bool "IMX serial port support"
+ depends on ARCH_MX25 || ARCH_MX31 || TARGET_FLEA3 \
+ || MX5 || MX6 || MX7 || IMX8M
+ help
+ If you have a machine based on a Motorola IMX CPU you
+ can enable its onboard serial port by enabling this option.
+
+config NULLDEV_SERIAL
+ bool "Null serial device"
+ help
+ Select this to enable null serial device support. A null serial
+ device merely acts as a placeholder for a serial device and does
+ nothing for all it's operation.
+
+config PIC32_SERIAL
+ bool "Support for Microchip PIC32 on-chip UART"
+ depends on DM_SERIAL && MACH_PIC32
+ default y
+ help
+ Support for the UART found on Microchip PIC32 SoC's.
+
+config SYS_NS16550
+ bool "NS16550 UART or compatible"
+ help
+ Support NS16550 UART or compatible. This can be enabled in the
+ device tree with the correct input clock frequency. If the input
+ clock frequency is not defined in the device tree, the macro
+ CONFIG_SYS_NS16550_CLK defined in a legacy board header file will
+ be used. It can be a constant or a function to get clock, eg,
+ get_serial_clock().
+
+config NS16550_DYNAMIC
+ bool "Allow NS16550 to be configured at runtime"
+ default y if SYS_COREBOOT || SYS_SLIMBOOTLOADER
+ help
+ Enable this option to allow device-tree control of the driver.
+
+ Normally this driver is controlled by the following options:
+
+ CONFIG_SYS_NS16550_PORT_MAPPED - indicates that port I/O is used for
+ access. If not enabled, then the UART is memory-mapped.
+ CONFIG_SYS_NS16550_MEM32 - if memory-mapped, indicates that 32-bit
+ access should be used (instead of 8-bit)
+ CONFIG_SYS_NS16550_REG_SIZE - indicates register width and also
+ endianness. If positive, big-endian access is used. If negative,
+ little-endian is used.
+
+ It is not a good practice for a driver to be statically configured,
+ since it prevents the same driver being used for different types of
+ UARTs in a system. This option avoids this problem at the cost of a
+ slightly increased code size.
+
+config INTEL_MID_SERIAL
+ bool "Intel MID platform UART support"
+ depends on DM_SERIAL && OF_CONTROL
+ depends on INTEL_MID
+ select SYS_NS16550
+ help
+ Select this to enable a UART for Intel MID platforms.
+ This uses the ns16550 driver as a library.
+
+config PL010_SERIAL
+ bool "ARM PL010 driver"
+ depends on !DM_SERIAL
+ help
+ Select this to enable a UART for platforms using PL010.
+
+config PL011_SERIAL
+ bool "ARM PL011 driver"
+ depends on !DM_SERIAL
+ help
+ Select this to enable a UART for platforms using PL011.
+
+config PL01X_SERIAL
+ bool "ARM PL010 and PL011 driver"
+ depends on DM_SERIAL
+ help
+ Select this to enable a UART for platforms using PL010 or PL011.
+
+config ROCKCHIP_SERIAL
+ bool "Rockchip on-chip UART support"
+ depends on DM_SERIAL && SPL_OF_PLATDATA
+ help
+ Select this to enable a debug UART for Rockchip devices when using
+ CONFIG_SPL_OF_PLATDATA (i.e. a compiled-in device tree replacemenmt).
+ This uses the ns16550 driver, converting the platdata from of-platdata
+ to the ns16550 format.
+
+config S5P_SERIAL
+ bool "Support for Samsung S5P UART"
+ depends on ARCH_EXYNOS || ARCH_S5PC1XX
+ default y
+ help
+ Select this to enable Samsung S5P UART support.
+
+config SANDBOX_SERIAL
+ bool "Sandbox UART support"
+ depends on SANDBOX
+ help
+ Select this to enable a seral UART for sandbox. This is required to
+ operate correctly, otherwise you will see no serial output from
+ sandbox. The emulated UART will display to the console and console
+ input will be fed into the UART. This allows you to interact with
+ U-Boot.
+
+ The operation of the console is controlled by the -t command-line
+ flag. In raw mode, U-Boot sees all characters from the terminal
+ before they are processed, including Ctrl-C. In cooked mode, Ctrl-C
+ is processed by the terminal, and terminates U-Boot. Valid options
+ are:
+
+ -t raw-with-sigs Raw mode, Ctrl-C will terminate U-Boot
+ -t raw Raw mode, Ctrl-C is processed by U-Boot
+ -t cooked Cooked mode, Ctrl-C terminates
+
+config SCIF_CONSOLE
+ bool "Renesas SCIF UART support"
+ depends on SH || ARCH_RMOBILE
+ help
+ Select this to enable Renesas SCIF UART. To operate serial ports
+ on systems with RCar or SH SoCs, say Y to this option. If unsure,
+ say N.
+
+config UNIPHIER_SERIAL
+ bool "Support for UniPhier on-chip UART"
+ depends on ARCH_UNIPHIER
+ default y
+ help
+ If you have a UniPhier based board and want to use the on-chip
+ serial ports, say Y to this option. If unsure, say N.
+
+config XILINX_UARTLITE
+ bool "Xilinx Uarlite support"
+ depends on DM_SERIAL
+ help
+ If you have a Xilinx based board and want to use the uartlite
+ serial ports, say Y to this option. If unsure, say N.
+
+config MESON_SERIAL
+ bool "Support for Amlogic Meson UART"
+ depends on DM_SERIAL && ARCH_MESON
+ help
+ If you have an Amlogic Meson based board and want to use the on-chip
+ serial ports, say Y to this option. If unsure, say N.
+
+config MSM_SERIAL
+ bool "Qualcomm on-chip UART"
+ depends on DM_SERIAL
+ help
+ Support Data Mover UART used on Qualcomm Snapdragon SoCs.
+ It should support all Qualcomm devices with UARTDM version 1.4,
+ for example APQ8016 and MSM8916.
+ Single baudrate is supported in current implementation (115200).
+
+config OCTEON_SERIAL_BOOTCMD
+ bool "MIPS Octeon PCI remote bootcmd input"
+ depends on ARCH_OCTEON
+ depends on DM_SERIAL
+ select SYS_IS_IN_ENV
+ select CONSOLE_MUX
+ help
+ This driver supports remote input over the PCIe bus from a host
+ to U-Boot for entering commands. It is utilized by the host
+ commands 'oct-remote-load' and 'oct-remote-bootcmd'.
+
+config OCTEON_SERIAL_PCIE_CONSOLE
+ bool "MIPS Octeon PCIe remote console"
+ depends on ARCH_OCTEON
+ depends on (DM_SERIAL && DM_STDIO)
+ select SYS_STDIO_DEREGISTER
+ select SYS_CONSOLE_IS_IN_ENV
+ select CONSOLE_MUX
+ help
+ This driver supports remote console over the PCIe bus when the
+ Octeon is running in PCIe target mode. The host program
+ 'oct-remote-console' can be used to connect to this console.
+ The console number will likely be 0 or 1.
+
+config OMAP_SERIAL
+ bool "Support for OMAP specific UART"
+ depends on DM_SERIAL
+ default y if (ARCH_OMAP2PLUS || ARCH_K3)
+ select SYS_NS16550
+ help
+ If you have an TI based SoC and want to use the on-chip serial
+ port, say Y to this option. If unsure say N.
+
+config OWL_SERIAL
+ bool "Actions Semi OWL UART"
+ depends on DM_SERIAL && ARCH_OWL
+ help
+ If you have a Actions Semi OWL based board and want to use the on-chip
+ serial port, say Y to this option. If unsure, say N.
+ Single baudrate is supported in current implementation (115200).
+
+config PXA_SERIAL
+ bool "PXA serial port support"
+ help
+ If you have a machine based on a Marvell XScale PXA2xx CPU you
+ can enable its onboard serial ports by enabling this option.
+
+config SIFIVE_SERIAL
+ bool "SiFive UART support"
+ depends on DM_SERIAL
+ help
+ This driver supports the SiFive UART. If unsure say N.
+
+config STI_ASC_SERIAL
+ bool "STMicroelectronics on-chip UART"
+ depends on DM_SERIAL && ARCH_STI
+ help
+ Select this to enable Asynchronous Serial Controller available
+ on STiH410 SoC. This is a basic implementation, it supports
+ following baudrate 9600, 19200, 38400, 57600 and 115200.
+
+config STM32_SERIAL
+ bool "STMicroelectronics STM32 SoCs on-chip UART"
+ depends on DM_SERIAL && (STM32F4 || STM32F7 || STM32H7 || ARCH_STM32MP)
+ help
+ If you have a machine based on a STM32 F4, F7, H7 or MP1 SOC
+ you can enable its onboard serial ports, say Y to this option.
+ If unsure, say N.
+
+config ZYNQ_SERIAL
+ bool "Cadence (Xilinx Zynq) UART support"
+ depends on DM_SERIAL
+ help
+ This driver supports the Cadence UART. It is found e.g. in Xilinx
+ Zynq/ZynqMP.
+
+config MTK_SERIAL
+ bool "MediaTek High-speed UART support"
+ depends on DM_SERIAL
+ help
+ Select this to enable UART support for MediaTek High-speed UART
+ devices. This driver uses driver model and requires a device
+ tree binding to operate.
+ The High-speed UART is compatible with the ns16550a UART and have
+ its own high-speed registers.
+
+config MT7620_SERIAL
+ bool "UART driver for MediaTek MT7620 and earlier SoCs"
+ depends on DM_SERIAL
+ help
+ Select this to enable UART support for MediaTek MT7620 and earlier
+ SoCs. This driver uses driver model and requires a device tree
+ binding to operate.
+ The UART driver for MediaTek MT7620 and earlier SoCs is *NOT*
+ compatible with the ns16550a UART.
+
+config MPC8XX_CONS
+ bool "Console driver for MPC8XX"
+ depends on MPC8xx
+ default y
+
+config XEN_SERIAL
+ bool "XEN serial support"
+ depends on XEN
+ help
+ If built without DM support, then requires Xen
+ to be built with CONFIG_VERBOSE_DEBUG.
+
+choice
+ prompt "Console port"
+ default 8xx_CONS_SMC1
+ depends on MPC8XX_CONS
+ help
+ Depending on board, select one serial port
+ (CONFIG_8xx_CONS_SMC1 or CONFIG_8xx_CONS_SMC2)
+
+config 8xx_CONS_SMC1
+ bool "SMC1"
+
+config 8xx_CONS_SMC2
+ bool "SMC2"
+
+endchoice
+
+config SYS_SMC_RXBUFLEN
+ int "Console Rx buffer length"
+ depends on MPC8XX_CONS
+ default 1
+ help
+ With CONFIG_SYS_SMC_RXBUFLEN it is possible to define
+ the maximum receive buffer length for the SMC.
+ This option is actual only for 8xx possible.
+ If using CONFIG_SYS_SMC_RXBUFLEN also CONFIG_SYS_MAXIDLE
+ must be defined, to setup the maximum idle timeout for
+ the SMC.
+
+config SYS_MAXIDLE
+ int "maximum idle timeout"
+ depends on MPC8XX_CONS
+ default 0
+
+config SYS_BRGCLK_PRESCALE
+ int "BRG Clock Prescale"
+ depends on MPC8XX_CONS
+ default 1
+
+config SYS_SDSR
+ hex "SDSR Value"
+ depends on MPC8XX_CONS
+ default 0x83
+
+config SYS_SDMR
+ hex "SDMR Value"
+ depends on MPC8XX_CONS
+ default 0
+
+endmenu
diff --git a/roms/u-boot/drivers/serial/Makefile b/roms/u-boot/drivers/serial/Makefile
new file mode 100644
index 000000000..6c0fdca58
--- /dev/null
+++ b/roms/u-boot/drivers/serial/Makefile
@@ -0,0 +1,80 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2006-2009
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+
+ifdef CONFIG_SPL_BUILD
+
+ifeq ($(CONFIG_$(SPL_TPL_)BUILD)$(CONFIG_$(SPL_TPL_)DM_SERIAL),yy)
+obj-y += serial-uclass.o
+else
+obj-y += serial.o
+endif
+
+else
+
+ifdef CONFIG_DM_SERIAL
+obj-y += serial-uclass.o
+else
+obj-y += serial.o
+endif
+
+endif
+
+ifdef CONFIG_DM_SERIAL
+obj-$(CONFIG_PL01X_SERIAL) += serial_pl01x.o
+else
+obj-$(CONFIG_PL010_SERIAL) += serial_pl01x.o
+obj-$(CONFIG_PL011_SERIAL) += serial_pl01x.o
+obj-$(CONFIG_SYS_NS16550_SERIAL) += serial_ns16550.o
+endif
+
+obj-$(CONFIG_ALTERA_UART) += altera_uart.o
+obj-$(CONFIG_ALTERA_JTAG_UART) += altera_jtag_uart.o
+obj-$(CONFIG_AR933X_UART) += serial_ar933x.o
+obj-$(CONFIG_ARM_DCC) += arm_dcc.o
+obj-$(CONFIG_ATMEL_USART) += atmel_usart.o
+obj-$(CONFIG_BCM6345_SERIAL) += serial_bcm6345.o
+obj-$(CONFIG_COREBOOT_SERIAL) += serial_coreboot.o
+obj-$(CONFIG_CORTINA_UART) += serial_cortina.o
+obj-$(CONFIG_EFI_APP) += serial_efi.o
+obj-$(CONFIG_LPC32XX_HSUART) += lpc32xx_hsuart.o
+obj-$(CONFIG_MCFUART) += serial_mcf.o
+obj-$(CONFIG_SYS_NS16550) += ns16550.o
+obj-$(CONFIG_S5P_SERIAL) += serial_s5p.o
+obj-$(CONFIG_MXC_UART) += serial_mxc.o
+obj-$(CONFIG_PXA_SERIAL) += serial_pxa.o
+obj-$(CONFIG_MESON_SERIAL) += serial_meson.o
+obj-$(CONFIG_INTEL_MID_SERIAL) += serial_intel_mid.o
+ifdef CONFIG_SPL_BUILD
+obj-$(CONFIG_ROCKCHIP_SERIAL) += serial_rockchip.o
+endif
+obj-$(CONFIG_XILINX_UARTLITE) += serial_xuartlite.o
+obj-$(CONFIG_SANDBOX_SERIAL) += sandbox.o
+obj-$(CONFIG_SCIF_CONSOLE) += serial_sh.o
+obj-$(CONFIG_ZYNQ_SERIAL) += serial_zynq.o
+obj-$(CONFIG_FSL_LPUART) += serial_lpuart.o
+obj-$(CONFIG_FSL_LINFLEXUART) += serial_linflexuart.o
+obj-$(CONFIG_ARC_SERIAL) += serial_arc.o
+obj-$(CONFIG_UNIPHIER_SERIAL) += serial_uniphier.o
+obj-$(CONFIG_STM32_SERIAL) += serial_stm32.o
+obj-$(CONFIG_STI_ASC_SERIAL) += serial_sti_asc.o
+obj-$(CONFIG_PIC32_SERIAL) += serial_pic32.o
+obj-$(CONFIG_BCM283X_MU_SERIAL) += serial_bcm283x_mu.o
+obj-$(CONFIG_BCM283X_PL011_SERIAL) += serial_bcm283x_pl011.o
+obj-$(CONFIG_MSM_SERIAL) += serial_msm.o
+obj-$(CONFIG_MVEBU_A3700_UART) += serial_mvebu_a3700.o
+obj-$(CONFIG_MPC8XX_CONS) += serial_mpc8xx.o
+obj-$(CONFIG_NULLDEV_SERIAL) += serial_nulldev.o
+obj-$(CONFIG_OCTEON_SERIAL_BOOTCMD) += serial_octeon_bootcmd.o
+obj-$(CONFIG_OCTEON_SERIAL_PCIE_CONSOLE) += serial_octeon_pcie_console.o
+obj-$(CONFIG_OWL_SERIAL) += serial_owl.o
+obj-$(CONFIG_OMAP_SERIAL) += serial_omap.o
+obj-$(CONFIG_MTK_SERIAL) += serial_mtk.o
+obj-$(CONFIG_MT7620_SERIAL) += serial_mt7620.o
+obj-$(CONFIG_SIFIVE_SERIAL) += serial_sifive.o
+obj-$(CONFIG_XEN_SERIAL) += serial_xen.o
+
+ifndef CONFIG_SPL_BUILD
+obj-$(CONFIG_USB_TTY) += usbtty.o
+endif
diff --git a/roms/u-boot/drivers/serial/altera_jtag_uart.c b/roms/u-boot/drivers/serial/altera_jtag_uart.c
new file mode 100644
index 000000000..4435fcf56
--- /dev/null
+++ b/roms/u-boot/drivers/serial/altera_jtag_uart.c
@@ -0,0 +1,151 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
+ * Scott McNutt <smcnutt@psyent.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <serial.h>
+#include <asm/io.h>
+#include <linux/bitops.h>
+
+/* data register */
+#define ALTERA_JTAG_RVALID BIT(15) /* Read valid */
+
+/* control register */
+#define ALTERA_JTAG_AC BIT(10) /* activity indicator */
+#define ALTERA_JTAG_RRDY BIT(12) /* read available */
+#define ALTERA_JTAG_WSPACE(d) ((d) >> 16) /* Write space avail */
+/* Write fifo size. FIXME: this should be extracted with sopc2dts */
+#define ALTERA_JTAG_WRITE_DEPTH 64
+
+struct altera_jtaguart_regs {
+ u32 data; /* Data register */
+ u32 control; /* Control register */
+};
+
+struct altera_jtaguart_plat {
+ struct altera_jtaguart_regs *regs;
+};
+
+static int altera_jtaguart_setbrg(struct udevice *dev, int baudrate)
+{
+ return 0;
+}
+
+static int altera_jtaguart_putc(struct udevice *dev, const char ch)
+{
+ struct altera_jtaguart_plat *plat = dev_get_plat(dev);
+ struct altera_jtaguart_regs *const regs = plat->regs;
+ u32 st = readl(&regs->control);
+
+#ifdef CONFIG_ALTERA_JTAG_UART_BYPASS
+ if (!(st & ALTERA_JTAG_AC)) /* no connection yet */
+ return -ENETUNREACH;
+#endif
+
+ if (ALTERA_JTAG_WSPACE(st) == 0)
+ return -EAGAIN;
+
+ writel(ch, &regs->data);
+
+ return 0;
+}
+
+static int altera_jtaguart_pending(struct udevice *dev, bool input)
+{
+ struct altera_jtaguart_plat *plat = dev_get_plat(dev);
+ struct altera_jtaguart_regs *const regs = plat->regs;
+ u32 st = readl(&regs->control);
+
+ if (input)
+ return st & ALTERA_JTAG_RRDY ? 1 : 0;
+ else
+ return !(ALTERA_JTAG_WSPACE(st) == ALTERA_JTAG_WRITE_DEPTH);
+}
+
+static int altera_jtaguart_getc(struct udevice *dev)
+{
+ struct altera_jtaguart_plat *plat = dev_get_plat(dev);
+ struct altera_jtaguart_regs *const regs = plat->regs;
+ u32 val;
+
+ val = readl(&regs->data);
+
+ if (!(val & ALTERA_JTAG_RVALID))
+ return -EAGAIN;
+
+ return val & 0xff;
+}
+
+static int altera_jtaguart_probe(struct udevice *dev)
+{
+#ifdef CONFIG_ALTERA_JTAG_UART_BYPASS
+ struct altera_jtaguart_plat *plat = dev_get_plat(dev);
+ struct altera_jtaguart_regs *const regs = plat->regs;
+
+ writel(ALTERA_JTAG_AC, &regs->control); /* clear AC flag */
+#endif
+ return 0;
+}
+
+static int altera_jtaguart_of_to_plat(struct udevice *dev)
+{
+ struct altera_jtaguart_plat *plat = dev_get_plat(dev);
+
+ plat->regs = map_physmem(dev_read_addr(dev),
+ sizeof(struct altera_jtaguart_regs),
+ MAP_NOCACHE);
+
+ return 0;
+}
+
+static const struct dm_serial_ops altera_jtaguart_ops = {
+ .putc = altera_jtaguart_putc,
+ .pending = altera_jtaguart_pending,
+ .getc = altera_jtaguart_getc,
+ .setbrg = altera_jtaguart_setbrg,
+};
+
+static const struct udevice_id altera_jtaguart_ids[] = {
+ { .compatible = "altr,juart-1.0" },
+ {}
+};
+
+U_BOOT_DRIVER(altera_jtaguart) = {
+ .name = "altera_jtaguart",
+ .id = UCLASS_SERIAL,
+ .of_match = altera_jtaguart_ids,
+ .of_to_plat = altera_jtaguart_of_to_plat,
+ .plat_auto = sizeof(struct altera_jtaguart_plat),
+ .probe = altera_jtaguart_probe,
+ .ops = &altera_jtaguart_ops,
+};
+
+#ifdef CONFIG_DEBUG_UART_ALTERA_JTAGUART
+
+#include <debug_uart.h>
+
+static inline void _debug_uart_init(void)
+{
+}
+
+static inline void _debug_uart_putc(int ch)
+{
+ struct altera_jtaguart_regs *regs = (void *)CONFIG_DEBUG_UART_BASE;
+
+ while (1) {
+ u32 st = readl(&regs->control);
+
+ if (ALTERA_JTAG_WSPACE(st))
+ break;
+ }
+
+ writel(ch, &regs->data);
+}
+
+DEBUG_UART_FUNCS
+
+#endif
diff --git a/roms/u-boot/drivers/serial/altera_uart.c b/roms/u-boot/drivers/serial/altera_uart.c
new file mode 100644
index 000000000..b18be6e24
--- /dev/null
+++ b/roms/u-boot/drivers/serial/altera_uart.c
@@ -0,0 +1,149 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
+ * Scott McNutt <smcnutt@psyent.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <serial.h>
+#include <asm/io.h>
+#include <linux/bitops.h>
+
+/* status register */
+#define ALTERA_UART_TMT BIT(5) /* tx empty */
+#define ALTERA_UART_TRDY BIT(6) /* tx ready */
+#define ALTERA_UART_RRDY BIT(7) /* rx ready */
+
+struct altera_uart_regs {
+ u32 rxdata; /* Rx data reg */
+ u32 txdata; /* Tx data reg */
+ u32 status; /* Status reg */
+ u32 control; /* Control reg */
+ u32 divisor; /* Baud rate divisor reg */
+ u32 endofpacket; /* End-of-packet reg */
+};
+
+struct altera_uart_plat {
+ struct altera_uart_regs *regs;
+ unsigned int uartclk;
+};
+
+static int altera_uart_setbrg(struct udevice *dev, int baudrate)
+{
+ struct altera_uart_plat *plat = dev_get_plat(dev);
+ struct altera_uart_regs *const regs = plat->regs;
+ u32 div;
+
+ div = (plat->uartclk / baudrate) - 1;
+ writel(div, &regs->divisor);
+
+ return 0;
+}
+
+static int altera_uart_putc(struct udevice *dev, const char ch)
+{
+ struct altera_uart_plat *plat = dev_get_plat(dev);
+ struct altera_uart_regs *const regs = plat->regs;
+
+ if (!(readl(&regs->status) & ALTERA_UART_TRDY))
+ return -EAGAIN;
+
+ writel(ch, &regs->txdata);
+
+ return 0;
+}
+
+static int altera_uart_pending(struct udevice *dev, bool input)
+{
+ struct altera_uart_plat *plat = dev_get_plat(dev);
+ struct altera_uart_regs *const regs = plat->regs;
+ u32 st = readl(&regs->status);
+
+ if (input)
+ return st & ALTERA_UART_RRDY ? 1 : 0;
+ else
+ return !(st & ALTERA_UART_TMT);
+}
+
+static int altera_uart_getc(struct udevice *dev)
+{
+ struct altera_uart_plat *plat = dev_get_plat(dev);
+ struct altera_uart_regs *const regs = plat->regs;
+
+ if (!(readl(&regs->status) & ALTERA_UART_RRDY))
+ return -EAGAIN;
+
+ return readl(&regs->rxdata) & 0xff;
+}
+
+static int altera_uart_probe(struct udevice *dev)
+{
+ return 0;
+}
+
+static int altera_uart_of_to_plat(struct udevice *dev)
+{
+ struct altera_uart_plat *plat = dev_get_plat(dev);
+
+ plat->regs = map_physmem(dev_read_addr(dev),
+ sizeof(struct altera_uart_regs),
+ MAP_NOCACHE);
+ plat->uartclk = dev_read_u32_default(dev, "clock-frequency", 0);
+
+ return 0;
+}
+
+static const struct dm_serial_ops altera_uart_ops = {
+ .putc = altera_uart_putc,
+ .pending = altera_uart_pending,
+ .getc = altera_uart_getc,
+ .setbrg = altera_uart_setbrg,
+};
+
+static const struct udevice_id altera_uart_ids[] = {
+ { .compatible = "altr,uart-1.0" },
+ {}
+};
+
+U_BOOT_DRIVER(altera_uart) = {
+ .name = "altera_uart",
+ .id = UCLASS_SERIAL,
+ .of_match = altera_uart_ids,
+ .of_to_plat = altera_uart_of_to_plat,
+ .plat_auto = sizeof(struct altera_uart_plat),
+ .probe = altera_uart_probe,
+ .ops = &altera_uart_ops,
+};
+
+#ifdef CONFIG_DEBUG_UART_ALTERA_UART
+
+#include <debug_uart.h>
+
+static inline void _debug_uart_init(void)
+{
+ struct altera_uart_regs *regs = (void *)CONFIG_DEBUG_UART_BASE;
+ u32 div;
+
+ div = (CONFIG_DEBUG_UART_CLOCK / CONFIG_BAUDRATE) - 1;
+ writel(div, &regs->divisor);
+}
+
+static inline void _debug_uart_putc(int ch)
+{
+ struct altera_uart_regs *regs = (void *)CONFIG_DEBUG_UART_BASE;
+
+ while (1) {
+ u32 st = readl(&regs->status);
+
+ if (st & ALTERA_UART_TRDY)
+ break;
+ }
+
+ writel(ch, &regs->txdata);
+}
+
+DEBUG_UART_FUNCS
+
+#endif
diff --git a/roms/u-boot/drivers/serial/arm_dcc.c b/roms/u-boot/drivers/serial/arm_dcc.c
new file mode 100644
index 000000000..dfcb6fd69
--- /dev/null
+++ b/roms/u-boot/drivers/serial/arm_dcc.c
@@ -0,0 +1,174 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2004-2007 ARM Limited.
+ * Copyright (C) 2008 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ * Copyright (C) 2015 - 2016 Xilinx, Inc, Michal Simek
+ *
+ * As a special exception, if other files instantiate templates or use macros
+ * or inline functions from this file, or you compile this file and link it
+ * with other works to produce a work based on this file, this file does not
+ * by itself cause the resulting work to be covered by the GNU General Public
+ * License. However the source code for this file must still be made available
+ * in accordance with section (3) of the GNU General Public License.
+
+ * This exception does not invalidate any other reasons why a work based on
+ * this file might be covered by the GNU General Public License.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <serial.h>
+
+#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V7A) || defined(CONFIG_CPU_V7R)
+/*
+ * ARMV6 & ARMV7
+ */
+#define DCC_RBIT (1 << 30)
+#define DCC_WBIT (1 << 29)
+
+#define write_dcc(x) \
+ __asm__ volatile ("mcr p14, 0, %0, c0, c5, 0\n" : : "r" (x))
+
+#define read_dcc(x) \
+ __asm__ volatile ("mrc p14, 0, %0, c0, c5, 0\n" : "=r" (x))
+
+#define status_dcc(x) \
+ __asm__ volatile ("mrc p14, 0, %0, c0, c1, 0\n" : "=r" (x))
+
+#elif defined(CONFIG_CPU_XSCALE)
+/*
+ * XSCALE
+ */
+#define DCC_RBIT (1 << 31)
+#define DCC_WBIT (1 << 28)
+
+#define write_dcc(x) \
+ __asm__ volatile ("mcr p14, 0, %0, c8, c0, 0\n" : : "r" (x))
+
+#define read_dcc(x) \
+ __asm__ volatile ("mrc p14, 0, %0, c9, c0, 0\n" : "=r" (x))
+
+#define status_dcc(x) \
+ __asm__ volatile ("mrc p14, 0, %0, c14, c0, 0\n" : "=r" (x))
+
+#elif defined(CONFIG_CPU_ARMV8)
+/*
+ * ARMV8
+ */
+#define DCC_RBIT (1 << 30)
+#define DCC_WBIT (1 << 29)
+
+#define write_dcc(x) \
+ __asm__ volatile ("msr dbgdtrtx_el0, %0\n" : : "r" (x))
+
+#define read_dcc(x) \
+ __asm__ volatile ("mrs %0, dbgdtrrx_el0\n" : "=r" (x))
+
+#define status_dcc(x) \
+ __asm__ volatile ("mrs %0, mdccsr_el0\n" : "=r" (x))
+
+#else
+#define DCC_RBIT (1 << 0)
+#define DCC_WBIT (1 << 1)
+
+#define write_dcc(x) \
+ __asm__ volatile ("mcr p14, 0, %0, c1, c0, 0\n" : : "r" (x))
+
+#define read_dcc(x) \
+ __asm__ volatile ("mrc p14, 0, %0, c1, c0, 0\n" : "=r" (x))
+
+#define status_dcc(x) \
+ __asm__ volatile ("mrc p14, 0, %0, c0, c0, 0\n" : "=r" (x))
+
+#endif
+
+#define can_read_dcc(x) do { \
+ status_dcc(x); \
+ x &= DCC_RBIT; \
+ } while (0);
+
+#define can_write_dcc(x) do { \
+ status_dcc(x); \
+ x &= DCC_WBIT; \
+ x = (x == 0); \
+ } while (0);
+
+#define TIMEOUT_COUNT 0x4000000
+
+static int arm_dcc_getc(struct udevice *dev)
+{
+ int ch;
+ register unsigned int reg;
+
+ do {
+ can_read_dcc(reg);
+ } while (!reg);
+ read_dcc(ch);
+
+ return ch;
+}
+
+static int arm_dcc_putc(struct udevice *dev, char ch)
+{
+ register unsigned int reg;
+ unsigned int timeout_count = TIMEOUT_COUNT;
+
+ while (--timeout_count) {
+ can_write_dcc(reg);
+ if (reg)
+ break;
+ }
+ if (timeout_count == 0)
+ return -EAGAIN;
+ else
+ write_dcc(ch);
+
+ return 0;
+}
+
+static int arm_dcc_pending(struct udevice *dev, bool input)
+{
+ register unsigned int reg;
+
+ if (input) {
+ can_read_dcc(reg);
+ } else {
+ can_write_dcc(reg);
+ }
+
+ return reg;
+}
+
+static const struct dm_serial_ops arm_dcc_ops = {
+ .putc = arm_dcc_putc,
+ .pending = arm_dcc_pending,
+ .getc = arm_dcc_getc,
+};
+
+static const struct udevice_id arm_dcc_ids[] = {
+ { .compatible = "arm,dcc", },
+ { }
+};
+
+U_BOOT_DRIVER(serial_dcc) = {
+ .name = "arm_dcc",
+ .id = UCLASS_SERIAL,
+ .of_match = arm_dcc_ids,
+ .ops = &arm_dcc_ops,
+};
+
+#ifdef CONFIG_DEBUG_UART_ARM_DCC
+
+#include <debug_uart.h>
+
+static inline void _debug_uart_init(void)
+{
+}
+
+static inline void _debug_uart_putc(int ch)
+{
+ arm_dcc_putc(NULL, ch);
+}
+
+DEBUG_UART_FUNCS
+#endif
diff --git a/roms/u-boot/drivers/serial/atmel_usart.c b/roms/u-boot/drivers/serial/atmel_usart.c
new file mode 100644
index 000000000..bd14f3e78
--- /dev/null
+++ b/roms/u-boot/drivers/serial/atmel_usart.c
@@ -0,0 +1,338 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2004-2006 Atmel Corporation
+ *
+ * Modified to support C structur SoC access by
+ * Andreas Bießmann <biessmann@corscience.de>
+ */
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <errno.h>
+#include <malloc.h>
+#include <watchdog.h>
+#include <serial.h>
+#include <debug_uart.h>
+#include <asm/global_data.h>
+#include <linux/compiler.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#ifdef CONFIG_DM_SERIAL
+#include <asm/arch/atmel_serial.h>
+#endif
+#include <asm/arch/clk.h>
+#include <asm/arch/hardware.h>
+
+#include "atmel_usart.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifndef CONFIG_DM_SERIAL
+static void atmel_serial_setbrg_internal(atmel_usart3_t *usart, int id,
+ int baudrate)
+{
+ unsigned long divisor;
+ unsigned long usart_hz;
+
+ /*
+ * Master Clock
+ * Baud Rate = --------------
+ * 16 * CD
+ */
+ usart_hz = get_usart_clk_rate(id);
+ divisor = (usart_hz / 16 + baudrate / 2) / baudrate;
+ writel(USART3_BF(CD, divisor), &usart->brgr);
+}
+
+static void atmel_serial_init_internal(atmel_usart3_t *usart)
+{
+ /*
+ * Just in case: drain transmitter register
+ * 1000us is enough for baudrate >= 9600
+ */
+ if (!(readl(&usart->csr) & USART3_BIT(TXEMPTY)))
+ __udelay(1000);
+
+ writel(USART3_BIT(RSTRX) | USART3_BIT(RSTTX), &usart->cr);
+}
+
+static void atmel_serial_activate(atmel_usart3_t *usart)
+{
+ writel((USART3_BF(USART_MODE, USART3_USART_MODE_NORMAL)
+ | USART3_BF(USCLKS, USART3_USCLKS_MCK)
+ | USART3_BF(CHRL, USART3_CHRL_8)
+ | USART3_BF(PAR, USART3_PAR_NONE)
+ | USART3_BF(NBSTOP, USART3_NBSTOP_1)),
+ &usart->mr);
+ writel(USART3_BIT(RXEN) | USART3_BIT(TXEN), &usart->cr);
+ /* 100us is enough for the new settings to be settled */
+ __udelay(100);
+}
+
+static void atmel_serial_setbrg(void)
+{
+ atmel_serial_setbrg_internal((atmel_usart3_t *)CONFIG_USART_BASE,
+ CONFIG_USART_ID, gd->baudrate);
+}
+
+static int atmel_serial_init(void)
+{
+ atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE;
+
+ atmel_serial_init_internal(usart);
+ serial_setbrg();
+ atmel_serial_activate(usart);
+
+ return 0;
+}
+
+static void atmel_serial_putc(char c)
+{
+ atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE;
+
+ if (c == '\n')
+ serial_putc('\r');
+
+ while (!(readl(&usart->csr) & USART3_BIT(TXRDY)));
+ writel(c, &usart->thr);
+}
+
+static int atmel_serial_getc(void)
+{
+ atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE;
+
+ while (!(readl(&usart->csr) & USART3_BIT(RXRDY)))
+ WATCHDOG_RESET();
+ return readl(&usart->rhr);
+}
+
+static int atmel_serial_tstc(void)
+{
+ atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE;
+ return (readl(&usart->csr) & USART3_BIT(RXRDY)) != 0;
+}
+
+static struct serial_device atmel_serial_drv = {
+ .name = "atmel_serial",
+ .start = atmel_serial_init,
+ .stop = NULL,
+ .setbrg = atmel_serial_setbrg,
+ .putc = atmel_serial_putc,
+ .puts = default_serial_puts,
+ .getc = atmel_serial_getc,
+ .tstc = atmel_serial_tstc,
+};
+
+void atmel_serial_initialize(void)
+{
+ serial_register(&atmel_serial_drv);
+}
+
+__weak struct serial_device *default_serial_console(void)
+{
+ return &atmel_serial_drv;
+}
+#endif
+
+#ifdef CONFIG_DM_SERIAL
+enum serial_clk_type {
+ CLK_TYPE_NORMAL = 0,
+ CLK_TYPE_DBGU,
+};
+
+struct atmel_serial_priv {
+ atmel_usart3_t *usart;
+ ulong usart_clk_rate;
+};
+
+static void _atmel_serial_set_brg(atmel_usart3_t *usart,
+ ulong usart_clk_rate, int baudrate)
+{
+ unsigned long divisor;
+
+ divisor = (usart_clk_rate / 16 + baudrate / 2) / baudrate;
+ writel(USART3_BF(CD, divisor), &usart->brgr);
+}
+
+void _atmel_serial_init(atmel_usart3_t *usart,
+ ulong usart_clk_rate, int baudrate)
+{
+ writel(USART3_BIT(RXDIS) | USART3_BIT(TXDIS), &usart->cr);
+
+ writel((USART3_BF(USART_MODE, USART3_USART_MODE_NORMAL) |
+ USART3_BF(USCLKS, USART3_USCLKS_MCK) |
+ USART3_BF(CHRL, USART3_CHRL_8) |
+ USART3_BF(PAR, USART3_PAR_NONE) |
+ USART3_BF(NBSTOP, USART3_NBSTOP_1)), &usart->mr);
+
+ _atmel_serial_set_brg(usart, usart_clk_rate, baudrate);
+
+ writel(USART3_BIT(RSTRX) | USART3_BIT(RSTTX), &usart->cr);
+ writel(USART3_BIT(RXEN) | USART3_BIT(TXEN), &usart->cr);
+}
+
+int atmel_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ struct atmel_serial_priv *priv = dev_get_priv(dev);
+
+ _atmel_serial_set_brg(priv->usart, priv->usart_clk_rate, baudrate);
+
+ return 0;
+}
+
+static int atmel_serial_getc(struct udevice *dev)
+{
+ struct atmel_serial_priv *priv = dev_get_priv(dev);
+
+ if (!(readl(&priv->usart->csr) & USART3_BIT(RXRDY)))
+ return -EAGAIN;
+
+ return readl(&priv->usart->rhr);
+}
+
+static int atmel_serial_putc(struct udevice *dev, const char ch)
+{
+ struct atmel_serial_priv *priv = dev_get_priv(dev);
+
+ if (!(readl(&priv->usart->csr) & USART3_BIT(TXRDY)))
+ return -EAGAIN;
+
+ writel(ch, &priv->usart->thr);
+
+ return 0;
+}
+
+static int atmel_serial_pending(struct udevice *dev, bool input)
+{
+ struct atmel_serial_priv *priv = dev_get_priv(dev);
+ uint32_t csr = readl(&priv->usart->csr);
+
+ if (input)
+ return csr & USART3_BIT(RXRDY) ? 1 : 0;
+ else
+ return csr & USART3_BIT(TXEMPTY) ? 0 : 1;
+}
+
+static const struct dm_serial_ops atmel_serial_ops = {
+ .putc = atmel_serial_putc,
+ .pending = atmel_serial_pending,
+ .getc = atmel_serial_getc,
+ .setbrg = atmel_serial_setbrg,
+};
+
+#if defined(CONFIG_SPL_BUILD) && !defined(CONFIG_SPL_CLK)
+static int atmel_serial_enable_clk(struct udevice *dev)
+{
+ struct atmel_serial_priv *priv = dev_get_priv(dev);
+
+ /* Use fixed clock value in SPL */
+ priv->usart_clk_rate = CONFIG_SPL_UART_CLOCK;
+
+ return 0;
+}
+#else
+static int atmel_serial_enable_clk(struct udevice *dev)
+{
+ struct atmel_serial_priv *priv = dev_get_priv(dev);
+ struct clk clk;
+ ulong clk_rate;
+ int ret;
+
+ ret = clk_get_by_index(dev, 0, &clk);
+ if (ret)
+ return -EINVAL;
+
+ if (dev_get_driver_data(dev) == CLK_TYPE_NORMAL) {
+ ret = clk_enable(&clk);
+ if (ret)
+ return ret;
+ }
+
+ clk_rate = clk_get_rate(&clk);
+ if (!clk_rate)
+ return -EINVAL;
+
+ priv->usart_clk_rate = clk_rate;
+
+ clk_free(&clk);
+
+ return 0;
+}
+#endif
+
+static int atmel_serial_probe(struct udevice *dev)
+{
+ struct atmel_serial_plat *plat = dev_get_plat(dev);
+ struct atmel_serial_priv *priv = dev_get_priv(dev);
+ int ret;
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+ fdt_addr_t addr_base;
+
+ addr_base = dev_read_addr(dev);
+ if (addr_base == FDT_ADDR_T_NONE)
+ return -ENODEV;
+
+ plat->base_addr = (uint32_t)addr_base;
+#endif
+ priv->usart = (atmel_usart3_t *)plat->base_addr;
+
+ ret = atmel_serial_enable_clk(dev);
+ if (ret)
+ return ret;
+
+ _atmel_serial_init(priv->usart, priv->usart_clk_rate, gd->baudrate);
+
+ return 0;
+}
+
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+static const struct udevice_id atmel_serial_ids[] = {
+ {
+ .compatible = "atmel,at91sam9260-dbgu",
+ .data = CLK_TYPE_DBGU,
+ },
+ {
+ .compatible = "atmel,at91sam9260-usart",
+ .data = CLK_TYPE_NORMAL,
+ },
+ { }
+};
+#endif
+
+U_BOOT_DRIVER(serial_atmel) = {
+ .name = "serial_atmel",
+ .id = UCLASS_SERIAL,
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+ .of_match = atmel_serial_ids,
+ .plat_auto = sizeof(struct atmel_serial_plat),
+#endif
+ .probe = atmel_serial_probe,
+ .ops = &atmel_serial_ops,
+#if !CONFIG_IS_ENABLED(OF_CONTROL)
+ .flags = DM_FLAG_PRE_RELOC,
+#endif
+ .priv_auto = sizeof(struct atmel_serial_priv),
+};
+#endif
+
+#ifdef CONFIG_DEBUG_UART_ATMEL
+static inline void _debug_uart_init(void)
+{
+ atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_DEBUG_UART_BASE;
+
+ _atmel_serial_init(usart, CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE);
+}
+
+static inline void _debug_uart_putc(int ch)
+{
+ atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_DEBUG_UART_BASE;
+
+ while (!(readl(&usart->csr) & USART3_BIT(TXRDY)))
+ ;
+
+ writel(ch, &usart->thr);
+}
+
+DEBUG_UART_FUNCS
+#endif
diff --git a/roms/u-boot/drivers/serial/atmel_usart.h b/roms/u-boot/drivers/serial/atmel_usart.h
new file mode 100644
index 000000000..8f2748815
--- /dev/null
+++ b/roms/u-boot/drivers/serial/atmel_usart.h
@@ -0,0 +1,293 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Register definitions for the Atmel USART3 module.
+ *
+ * Copyright (C) 2005-2006 Atmel Corporation
+ *
+ * Modified to support C structure SoC access by
+ * Andreas Bießmann <biessmann@corscience.de>
+ */
+#ifndef __DRIVERS_ATMEL_USART_H__
+#define __DRIVERS_ATMEL_USART_H__
+
+/* USART3 register footprint */
+typedef struct atmel_usart3 {
+ u32 cr;
+ u32 mr;
+ u32 ier;
+ u32 idr;
+ u32 imr;
+ u32 csr;
+ u32 rhr;
+ u32 thr;
+ u32 brgr;
+ u32 rtor;
+ u32 ttgr;
+ u32 reserved0[5];
+ u32 fidi;
+ u32 ner;
+ u32 reserved1;
+ u32 ifr;
+ u32 man;
+ u32 reserved2[54]; /* version and PDC not needed */
+} atmel_usart3_t;
+
+/* Bitfields in CR */
+#define USART3_RSTRX_OFFSET 2
+#define USART3_RSTRX_SIZE 1
+#define USART3_RSTTX_OFFSET 3
+#define USART3_RSTTX_SIZE 1
+#define USART3_RXEN_OFFSET 4
+#define USART3_RXEN_SIZE 1
+#define USART3_RXDIS_OFFSET 5
+#define USART3_RXDIS_SIZE 1
+#define USART3_TXEN_OFFSET 6
+#define USART3_TXEN_SIZE 1
+#define USART3_TXDIS_OFFSET 7
+#define USART3_TXDIS_SIZE 1
+#define USART3_RSTSTA_OFFSET 8
+#define USART3_RSTSTA_SIZE 1
+#define USART3_STTBRK_OFFSET 9
+#define USART3_STTBRK_SIZE 1
+#define USART3_STPBRK_OFFSET 10
+#define USART3_STPBRK_SIZE 1
+#define USART3_STTTO_OFFSET 11
+#define USART3_STTTO_SIZE 1
+#define USART3_SENDA_OFFSET 12
+#define USART3_SENDA_SIZE 1
+#define USART3_RSTIT_OFFSET 13
+#define USART3_RSTIT_SIZE 1
+#define USART3_RSTNACK_OFFSET 14
+#define USART3_RSTNACK_SIZE 1
+#define USART3_RETTO_OFFSET 15
+#define USART3_RETTO_SIZE 1
+#define USART3_DTREN_OFFSET 16
+#define USART3_DTREN_SIZE 1
+#define USART3_DTRDIS_OFFSET 17
+#define USART3_DTRDIS_SIZE 1
+#define USART3_RTSEN_OFFSET 18
+#define USART3_RTSEN_SIZE 1
+#define USART3_RTSDIS_OFFSET 19
+#define USART3_RTSDIS_SIZE 1
+#define USART3_COMM_TX_OFFSET 30
+#define USART3_COMM_TX_SIZE 1
+#define USART3_COMM_RX_OFFSET 31
+#define USART3_COMM_RX_SIZE 1
+
+/* Bitfields in MR */
+#define USART3_USART_MODE_OFFSET 0
+#define USART3_USART_MODE_SIZE 4
+#define USART3_USCLKS_OFFSET 4
+#define USART3_USCLKS_SIZE 2
+#define USART3_CHRL_OFFSET 6
+#define USART3_CHRL_SIZE 2
+#define USART3_SYNC_OFFSET 8
+#define USART3_SYNC_SIZE 1
+#define USART3_PAR_OFFSET 9
+#define USART3_PAR_SIZE 3
+#define USART3_NBSTOP_OFFSET 12
+#define USART3_NBSTOP_SIZE 2
+#define USART3_CHMODE_OFFSET 14
+#define USART3_CHMODE_SIZE 2
+#define USART3_MSBF_OFFSET 16
+#define USART3_MSBF_SIZE 1
+#define USART3_MODE9_OFFSET 17
+#define USART3_MODE9_SIZE 1
+#define USART3_CLKO_OFFSET 18
+#define USART3_CLKO_SIZE 1
+#define USART3_OVER_OFFSET 19
+#define USART3_OVER_SIZE 1
+#define USART3_INACK_OFFSET 20
+#define USART3_INACK_SIZE 1
+#define USART3_DSNACK_OFFSET 21
+#define USART3_DSNACK_SIZE 1
+#define USART3_MAX_ITERATION_OFFSET 24
+#define USART3_MAX_ITERATION_SIZE 3
+#define USART3_FILTER_OFFSET 28
+#define USART3_FILTER_SIZE 1
+
+/* Bitfields in CSR */
+#define USART3_RXRDY_OFFSET 0
+#define USART3_RXRDY_SIZE 1
+#define USART3_TXRDY_OFFSET 1
+#define USART3_TXRDY_SIZE 1
+#define USART3_RXBRK_OFFSET 2
+#define USART3_RXBRK_SIZE 1
+#define USART3_ENDRX_OFFSET 3
+#define USART3_ENDRX_SIZE 1
+#define USART3_ENDTX_OFFSET 4
+#define USART3_ENDTX_SIZE 1
+#define USART3_OVRE_OFFSET 5
+#define USART3_OVRE_SIZE 1
+#define USART3_FRAME_OFFSET 6
+#define USART3_FRAME_SIZE 1
+#define USART3_PARE_OFFSET 7
+#define USART3_PARE_SIZE 1
+#define USART3_TIMEOUT_OFFSET 8
+#define USART3_TIMEOUT_SIZE 1
+#define USART3_TXEMPTY_OFFSET 9
+#define USART3_TXEMPTY_SIZE 1
+#define USART3_ITERATION_OFFSET 10
+#define USART3_ITERATION_SIZE 1
+#define USART3_TXBUFE_OFFSET 11
+#define USART3_TXBUFE_SIZE 1
+#define USART3_RXBUFF_OFFSET 12
+#define USART3_RXBUFF_SIZE 1
+#define USART3_NACK_OFFSET 13
+#define USART3_NACK_SIZE 1
+#define USART3_RIIC_OFFSET 16
+#define USART3_RIIC_SIZE 1
+#define USART3_DSRIC_OFFSET 17
+#define USART3_DSRIC_SIZE 1
+#define USART3_DCDIC_OFFSET 18
+#define USART3_DCDIC_SIZE 1
+#define USART3_CTSIC_OFFSET 19
+#define USART3_CTSIC_SIZE 1
+#define USART3_RI_OFFSET 20
+#define USART3_RI_SIZE 1
+#define USART3_DSR_OFFSET 21
+#define USART3_DSR_SIZE 1
+#define USART3_DCD_OFFSET 22
+#define USART3_DCD_SIZE 1
+#define USART3_CTS_OFFSET 23
+#define USART3_CTS_SIZE 1
+
+/* Bitfields in RHR */
+#define USART3_RXCHR_OFFSET 0
+#define USART3_RXCHR_SIZE 9
+
+/* Bitfields in THR */
+#define USART3_TXCHR_OFFSET 0
+#define USART3_TXCHR_SIZE 9
+
+/* Bitfields in BRGR */
+#define USART3_CD_OFFSET 0
+#define USART3_CD_SIZE 16
+
+/* Bitfields in RTOR */
+#define USART3_TO_OFFSET 0
+#define USART3_TO_SIZE 16
+
+/* Bitfields in TTGR */
+#define USART3_TG_OFFSET 0
+#define USART3_TG_SIZE 8
+
+/* Bitfields in FIDI */
+#define USART3_FI_DI_RATIO_OFFSET 0
+#define USART3_FI_DI_RATIO_SIZE 11
+
+/* Bitfields in NER */
+#define USART3_NB_ERRORS_OFFSET 0
+#define USART3_NB_ERRORS_SIZE 8
+
+/* Bitfields in XXR */
+#define USART3_XOFF_OFFSET 0
+#define USART3_XOFF_SIZE 8
+#define USART3_XON_OFFSET 8
+#define USART3_XON_SIZE 8
+
+/* Bitfields in IFR */
+#define USART3_IRDA_FILTER_OFFSET 0
+#define USART3_IRDA_FILTER_SIZE 8
+
+/* Bitfields in RCR */
+#define USART3_RXCTR_OFFSET 0
+#define USART3_RXCTR_SIZE 16
+
+/* Bitfields in TCR */
+#define USART3_TXCTR_OFFSET 0
+#define USART3_TXCTR_SIZE 16
+
+/* Bitfields in RNCR */
+#define USART3_RXNCR_OFFSET 0
+#define USART3_RXNCR_SIZE 16
+
+/* Bitfields in TNCR */
+#define USART3_TXNCR_OFFSET 0
+#define USART3_TXNCR_SIZE 16
+
+/* Bitfields in PTCR */
+#define USART3_RXTEN_OFFSET 0
+#define USART3_RXTEN_SIZE 1
+#define USART3_RXTDIS_OFFSET 1
+#define USART3_RXTDIS_SIZE 1
+#define USART3_TXTEN_OFFSET 8
+#define USART3_TXTEN_SIZE 1
+#define USART3_TXTDIS_OFFSET 9
+#define USART3_TXTDIS_SIZE 1
+
+/* Constants for USART_MODE */
+#define USART3_USART_MODE_NORMAL 0
+#define USART3_USART_MODE_RS485 1
+#define USART3_USART_MODE_HARDWARE 2
+#define USART3_USART_MODE_MODEM 3
+#define USART3_USART_MODE_ISO7816_T0 4
+#define USART3_USART_MODE_ISO7816_T1 6
+#define USART3_USART_MODE_IRDA 8
+
+/* Constants for USCLKS */
+#define USART3_USCLKS_MCK 0
+#define USART3_USCLKS_MCK_DIV 1
+#define USART3_USCLKS_SCK 3
+
+/* Constants for CHRL */
+#define USART3_CHRL_5 0
+#define USART3_CHRL_6 1
+#define USART3_CHRL_7 2
+#define USART3_CHRL_8 3
+
+/* Constants for PAR */
+#define USART3_PAR_EVEN 0
+#define USART3_PAR_ODD 1
+#define USART3_PAR_SPACE 2
+#define USART3_PAR_MARK 3
+#define USART3_PAR_NONE 4
+#define USART3_PAR_MULTI 6
+
+/* Constants for NBSTOP */
+#define USART3_NBSTOP_1 0
+#define USART3_NBSTOP_1_5 1
+#define USART3_NBSTOP_2 2
+
+/* Constants for CHMODE */
+#define USART3_CHMODE_NORMAL 0
+#define USART3_CHMODE_ECHO 1
+#define USART3_CHMODE_LOCAL_LOOP 2
+#define USART3_CHMODE_REMOTE_LOOP 3
+
+/* Constants for MSBF */
+#define USART3_MSBF_LSBF 0
+#define USART3_MSBF_MSBF 1
+
+/* Constants for OVER */
+#define USART3_OVER_X16 0
+#define USART3_OVER_X8 1
+
+/* Constants for CD */
+#define USART3_CD_DISABLE 0
+#define USART3_CD_BYPASS 1
+
+/* Constants for TO */
+#define USART3_TO_DISABLE 0
+
+/* Constants for TG */
+#define USART3_TG_DISABLE 0
+
+/* Constants for FI_DI_RATIO */
+#define USART3_FI_DI_RATIO_DISABLE 0
+
+/* Bit manipulation macros */
+#define USART3_BIT(name) \
+ (1 << USART3_##name##_OFFSET)
+#define USART3_BF(name,value) \
+ (((value) & ((1 << USART3_##name##_SIZE) - 1)) \
+ << USART3_##name##_OFFSET)
+#define USART3_BFEXT(name,value) \
+ (((value) >> USART3_##name##_OFFSET) \
+ & ((1 << USART3_##name##_SIZE) - 1))
+#define USART3_BFINS(name,value,old) \
+ (((old) & ~(((1 << USART3_##name##_SIZE) - 1) \
+ << USART3_##name##_OFFSET)) \
+ | USART3_BF(name,value))
+
+#endif /* __DRIVERS_ATMEL_USART_H__ */
diff --git a/roms/u-boot/drivers/serial/lpc32xx_hsuart.c b/roms/u-boot/drivers/serial/lpc32xx_hsuart.c
new file mode 100644
index 000000000..d39a3c049
--- /dev/null
+++ b/roms/u-boot/drivers/serial/lpc32xx_hsuart.c
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2011-2015 Vladimir Zapolskiy <vz@mleia.com>
+ */
+
+#include <common.h>
+#include <clock_legacy.h>
+#include <dm.h>
+#include <serial.h>
+#include <dm/platform_data/lpc32xx_hsuart.h>
+
+#include <asm/arch/uart.h>
+#include <linux/compiler.h>
+
+struct lpc32xx_hsuart_priv {
+ struct hsuart_regs *hsuart;
+};
+
+static int lpc32xx_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ struct lpc32xx_hsuart_priv *priv = dev_get_priv(dev);
+ struct hsuart_regs *hsuart = priv->hsuart;
+ u32 div;
+
+ /* UART rate = PERIPH_CLK / ((HSU_RATE + 1) x 14) */
+ div = (get_serial_clock() / 14 + baudrate / 2) / baudrate - 1;
+ if (div > 255)
+ div = 255;
+
+ writel(div, &hsuart->rate);
+
+ return 0;
+}
+
+static int lpc32xx_serial_getc(struct udevice *dev)
+{
+ struct lpc32xx_hsuart_priv *priv = dev_get_priv(dev);
+ struct hsuart_regs *hsuart = priv->hsuart;
+
+ if (!(readl(&hsuart->level) & HSUART_LEVEL_RX))
+ return -EAGAIN;
+
+ return readl(&hsuart->rx) & HSUART_RX_DATA;
+}
+
+static int lpc32xx_serial_putc(struct udevice *dev, const char c)
+{
+ struct lpc32xx_hsuart_priv *priv = dev_get_priv(dev);
+ struct hsuart_regs *hsuart = priv->hsuart;
+
+ /* Wait for empty FIFO */
+ if (readl(&hsuart->level) & HSUART_LEVEL_TX)
+ return -EAGAIN;
+
+ writel(c, &hsuart->tx);
+
+ return 0;
+}
+
+static int lpc32xx_serial_pending(struct udevice *dev, bool input)
+{
+ struct lpc32xx_hsuart_priv *priv = dev_get_priv(dev);
+ struct hsuart_regs *hsuart = priv->hsuart;
+
+ if (input) {
+ if (readl(&hsuart->level) & HSUART_LEVEL_RX)
+ return 1;
+ } else {
+ if (readl(&hsuart->level) & HSUART_LEVEL_TX)
+ return 1;
+ }
+
+ return 0;
+}
+
+static int lpc32xx_serial_init(struct hsuart_regs *hsuart)
+{
+ /* Disable hardware RTS and CTS flow control, set up RX and TX FIFO */
+ writel(HSUART_CTRL_TMO_16 | HSUART_CTRL_HSU_OFFSET(20) |
+ HSUART_CTRL_HSU_RX_TRIG_32 | HSUART_CTRL_HSU_TX_TRIG_0,
+ &hsuart->ctrl);
+
+ return 0;
+}
+
+static int lpc32xx_hsuart_probe(struct udevice *dev)
+{
+ struct lpc32xx_hsuart_plat *plat = dev_get_plat(dev);
+ struct lpc32xx_hsuart_priv *priv = dev_get_priv(dev);
+
+ priv->hsuart = (struct hsuart_regs *)plat->base;
+
+ lpc32xx_serial_init(priv->hsuart);
+
+ return 0;
+}
+
+static const struct dm_serial_ops lpc32xx_hsuart_ops = {
+ .setbrg = lpc32xx_serial_setbrg,
+ .getc = lpc32xx_serial_getc,
+ .putc = lpc32xx_serial_putc,
+ .pending = lpc32xx_serial_pending,
+};
+
+U_BOOT_DRIVER(lpc32xx_hsuart) = {
+ .name = "lpc32xx_hsuart",
+ .id = UCLASS_SERIAL,
+ .probe = lpc32xx_hsuart_probe,
+ .ops = &lpc32xx_hsuart_ops,
+ .priv_auto = sizeof(struct lpc32xx_hsuart_priv),
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/roms/u-boot/drivers/serial/ns16550.c b/roms/u-boot/drivers/serial/ns16550.c
new file mode 100644
index 000000000..cc121eee2
--- /dev/null
+++ b/roms/u-boot/drivers/serial/ns16550.c
@@ -0,0 +1,633 @@
+/*
+ * COM1 NS16550 support
+ * originally from linux source (arch/powerpc/boot/ns16550.c)
+ * modified to use CONFIG_SYS_ISA_MEM and new defines
+ */
+
+#include <clock_legacy.h>
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <errno.h>
+#include <log.h>
+#include <ns16550.h>
+#include <reset.h>
+#include <serial.h>
+#include <watchdog.h>
+#include <asm/global_data.h>
+#include <linux/err.h>
+#include <linux/types.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define UART_LCRVAL UART_LCR_8N1 /* 8 data, 1 stop, no parity */
+#define UART_MCRVAL (UART_MCR_DTR | \
+ UART_MCR_RTS) /* RTS/DTR */
+
+#if !CONFIG_IS_ENABLED(DM_SERIAL)
+#ifdef CONFIG_SYS_NS16550_PORT_MAPPED
+#define serial_out(x, y) outb(x, (ulong)y)
+#define serial_in(y) inb((ulong)y)
+#elif defined(CONFIG_SYS_NS16550_MEM32) && (CONFIG_SYS_NS16550_REG_SIZE > 0)
+#define serial_out(x, y) out_be32(y, x)
+#define serial_in(y) in_be32(y)
+#elif defined(CONFIG_SYS_NS16550_MEM32) && (CONFIG_SYS_NS16550_REG_SIZE < 0)
+#define serial_out(x, y) out_le32(y, x)
+#define serial_in(y) in_le32(y)
+#else
+#define serial_out(x, y) writeb(x, y)
+#define serial_in(y) readb(y)
+#endif
+#endif /* !CONFIG_DM_SERIAL */
+
+#if defined(CONFIG_SOC_KEYSTONE)
+#define UART_REG_VAL_PWREMU_MGMT_UART_DISABLE 0
+#define UART_REG_VAL_PWREMU_MGMT_UART_ENABLE ((1 << 14) | (1 << 13) | (1 << 0))
+#undef UART_MCRVAL
+#ifdef CONFIG_SERIAL_HW_FLOW_CONTROL
+#define UART_MCRVAL (UART_MCR_RTS | UART_MCR_AFE)
+#else
+#define UART_MCRVAL (UART_MCR_RTS)
+#endif
+#endif
+
+#ifndef CONFIG_SYS_NS16550_IER
+#define CONFIG_SYS_NS16550_IER 0x00
+#endif /* CONFIG_SYS_NS16550_IER */
+
+static inline void serial_out_shift(void *addr, int shift, int value)
+{
+#ifdef CONFIG_SYS_NS16550_PORT_MAPPED
+ outb(value, (ulong)addr);
+#elif defined(CONFIG_SYS_NS16550_MEM32) && defined(CONFIG_SYS_LITTLE_ENDIAN)
+ out_le32(addr, value);
+#elif defined(CONFIG_SYS_NS16550_MEM32) && defined(CONFIG_SYS_BIG_ENDIAN)
+ out_be32(addr, value);
+#elif defined(CONFIG_SYS_NS16550_MEM32)
+ writel(value, addr);
+#elif defined(CONFIG_SYS_BIG_ENDIAN)
+ writeb(value, addr + (1 << shift) - 1);
+#else
+ writeb(value, addr);
+#endif
+}
+
+static inline int serial_in_shift(void *addr, int shift)
+{
+#ifdef CONFIG_SYS_NS16550_PORT_MAPPED
+ return inb((ulong)addr);
+#elif defined(CONFIG_SYS_NS16550_MEM32) && defined(CONFIG_SYS_LITTLE_ENDIAN)
+ return in_le32(addr);
+#elif defined(CONFIG_SYS_NS16550_MEM32) && defined(CONFIG_SYS_BIG_ENDIAN)
+ return in_be32(addr);
+#elif defined(CONFIG_SYS_NS16550_MEM32)
+ return readl(addr);
+#elif defined(CONFIG_SYS_BIG_ENDIAN)
+ return readb(addr + (1 << shift) - 1);
+#else
+ return readb(addr);
+#endif
+}
+
+#if CONFIG_IS_ENABLED(DM_SERIAL)
+
+#ifndef CONFIG_SYS_NS16550_CLK
+#define CONFIG_SYS_NS16550_CLK 0
+#endif
+
+/*
+ * Use this #ifdef for now since many platforms don't define in(), out(),
+ * out_le32(), etc. but we don't have #defines to indicate this.
+ *
+ * TODO(sjg@chromium.org): Add CONFIG options to indicate what I/O is available
+ * on a platform
+ */
+#ifdef CONFIG_NS16550_DYNAMIC
+static void serial_out_dynamic(struct ns16550_plat *plat, u8 *addr,
+ int value)
+{
+ if (plat->flags & NS16550_FLAG_IO) {
+ outb(value, addr);
+ } else if (plat->reg_width == 4) {
+ if (plat->flags & NS16550_FLAG_ENDIAN) {
+ if (plat->flags & NS16550_FLAG_BE)
+ out_be32(addr, value);
+ else
+ out_le32(addr, value);
+ } else {
+ writel(value, addr);
+ }
+ } else if (plat->flags & NS16550_FLAG_BE) {
+ writeb(value, addr + (1 << plat->reg_shift) - 1);
+ } else {
+ writeb(value, addr);
+ }
+}
+
+static int serial_in_dynamic(struct ns16550_plat *plat, u8 *addr)
+{
+ if (plat->flags & NS16550_FLAG_IO) {
+ return inb(addr);
+ } else if (plat->reg_width == 4) {
+ if (plat->flags & NS16550_FLAG_ENDIAN) {
+ if (plat->flags & NS16550_FLAG_BE)
+ return in_be32(addr);
+ else
+ return in_le32(addr);
+ } else {
+ return readl(addr);
+ }
+ } else if (plat->flags & NS16550_FLAG_BE) {
+ return readb(addr + (1 << plat->reg_shift) - 1);
+ } else {
+ return readb(addr);
+ }
+}
+#else
+static inline void serial_out_dynamic(struct ns16550_plat *plat, u8 *addr,
+ int value)
+{
+}
+
+static inline int serial_in_dynamic(struct ns16550_plat *plat, u8 *addr)
+{
+ return 0;
+}
+
+#endif /* CONFIG_NS16550_DYNAMIC */
+
+static void ns16550_writeb(struct ns16550 *port, int offset, int value)
+{
+ struct ns16550_plat *plat = port->plat;
+ unsigned char *addr;
+
+ offset *= 1 << plat->reg_shift;
+ addr = (unsigned char *)plat->base + offset + plat->reg_offset;
+
+ if (IS_ENABLED(CONFIG_NS16550_DYNAMIC))
+ serial_out_dynamic(plat, addr, value);
+ else
+ serial_out_shift(addr, plat->reg_shift, value);
+}
+
+static int ns16550_readb(struct ns16550 *port, int offset)
+{
+ struct ns16550_plat *plat = port->plat;
+ unsigned char *addr;
+
+ offset *= 1 << plat->reg_shift;
+ addr = (unsigned char *)plat->base + offset + plat->reg_offset;
+
+ if (IS_ENABLED(CONFIG_NS16550_DYNAMIC))
+ return serial_in_dynamic(plat, addr);
+ else
+ return serial_in_shift(addr, plat->reg_shift);
+}
+
+static u32 ns16550_getfcr(struct ns16550 *port)
+{
+ struct ns16550_plat *plat = port->plat;
+
+ return plat->fcr;
+}
+
+/* We can clean these up once everything is moved to driver model */
+#define serial_out(value, addr) \
+ ns16550_writeb(com_port, \
+ (unsigned char *)addr - (unsigned char *)com_port, value)
+#define serial_in(addr) \
+ ns16550_readb(com_port, \
+ (unsigned char *)addr - (unsigned char *)com_port)
+#else
+static u32 ns16550_getfcr(struct ns16550 *port)
+{
+ return UART_FCR_DEFVAL;
+}
+#endif
+
+int ns16550_calc_divisor(struct ns16550 *port, int clock, int baudrate)
+{
+ const unsigned int mode_x_div = 16;
+
+ return DIV_ROUND_CLOSEST(clock, mode_x_div * baudrate);
+}
+
+static void ns16550_setbrg(struct ns16550 *com_port, int baud_divisor)
+{
+ /* to keep serial format, read lcr before writing BKSE */
+ int lcr_val = serial_in(&com_port->lcr) & ~UART_LCR_BKSE;
+
+ serial_out(UART_LCR_BKSE | lcr_val, &com_port->lcr);
+ serial_out(baud_divisor & 0xff, &com_port->dll);
+ serial_out((baud_divisor >> 8) & 0xff, &com_port->dlm);
+ serial_out(lcr_val, &com_port->lcr);
+}
+
+void ns16550_init(struct ns16550 *com_port, int baud_divisor)
+{
+#if (defined(CONFIG_SPL_BUILD) && \
+ (defined(CONFIG_OMAP34XX) || defined(CONFIG_OMAP44XX)))
+ /*
+ * On some OMAP3/OMAP4 devices when UART3 is configured for boot mode
+ * before SPL starts only THRE bit is set. We have to empty the
+ * transmitter before initialization starts.
+ */
+ if ((serial_in(&com_port->lsr) & (UART_LSR_TEMT | UART_LSR_THRE))
+ == UART_LSR_THRE) {
+ if (baud_divisor != -1)
+ ns16550_setbrg(com_port, baud_divisor);
+ else {
+ // Re-use old baud rate divisor to flush transmit reg.
+ const int dll = serial_in(&com_port->dll);
+ const int dlm = serial_in(&com_port->dlm);
+ const int divisor = dll | (dlm << 8);
+ ns16550_setbrg(com_port, divisor);
+ }
+ serial_out(0, &com_port->mdr1);
+ }
+#endif
+
+ while (!(serial_in(&com_port->lsr) & UART_LSR_TEMT))
+ ;
+
+ serial_out(CONFIG_SYS_NS16550_IER, &com_port->ier);
+#if defined(CONFIG_ARCH_OMAP2PLUS) || defined(CONFIG_OMAP_SERIAL)
+ serial_out(0x7, &com_port->mdr1); /* mode select reset TL16C750*/
+#endif
+
+ serial_out(UART_MCRVAL, &com_port->mcr);
+ serial_out(ns16550_getfcr(com_port), &com_port->fcr);
+ /* initialize serial config to 8N1 before writing baudrate */
+ serial_out(UART_LCRVAL, &com_port->lcr);
+ if (baud_divisor != -1)
+ ns16550_setbrg(com_port, baud_divisor);
+#if defined(CONFIG_ARCH_OMAP2PLUS) || defined(CONFIG_SOC_DA8XX) || \
+ defined(CONFIG_OMAP_SERIAL)
+ /* /16 is proper to hit 115200 with 48MHz */
+ serial_out(0, &com_port->mdr1);
+#endif
+#if defined(CONFIG_SOC_KEYSTONE)
+ serial_out(UART_REG_VAL_PWREMU_MGMT_UART_ENABLE, &com_port->regC);
+#endif
+}
+
+#ifndef CONFIG_NS16550_MIN_FUNCTIONS
+void ns16550_reinit(struct ns16550 *com_port, int baud_divisor)
+{
+ serial_out(CONFIG_SYS_NS16550_IER, &com_port->ier);
+ ns16550_setbrg(com_port, 0);
+ serial_out(UART_MCRVAL, &com_port->mcr);
+ serial_out(ns16550_getfcr(com_port), &com_port->fcr);
+ ns16550_setbrg(com_port, baud_divisor);
+}
+#endif /* CONFIG_NS16550_MIN_FUNCTIONS */
+
+void ns16550_putc(struct ns16550 *com_port, char c)
+{
+ while ((serial_in(&com_port->lsr) & UART_LSR_THRE) == 0)
+ ;
+ serial_out(c, &com_port->thr);
+
+ /*
+ * Call watchdog_reset() upon newline. This is done here in putc
+ * since the environment code uses a single puts() to print the complete
+ * environment upon "printenv". So we can't put this watchdog call
+ * in puts().
+ */
+ if (c == '\n')
+ WATCHDOG_RESET();
+}
+
+#ifndef CONFIG_NS16550_MIN_FUNCTIONS
+char ns16550_getc(struct ns16550 *com_port)
+{
+ while ((serial_in(&com_port->lsr) & UART_LSR_DR) == 0) {
+#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_USB_TTY)
+ extern void usbtty_poll(void);
+ usbtty_poll();
+#endif
+ WATCHDOG_RESET();
+ }
+ return serial_in(&com_port->rbr);
+}
+
+int ns16550_tstc(struct ns16550 *com_port)
+{
+ return (serial_in(&com_port->lsr) & UART_LSR_DR) != 0;
+}
+
+#endif /* CONFIG_NS16550_MIN_FUNCTIONS */
+
+#ifdef CONFIG_DEBUG_UART_NS16550
+
+#include <debug_uart.h>
+
+static inline void _debug_uart_init(void)
+{
+ struct ns16550 *com_port = (struct ns16550 *)CONFIG_DEBUG_UART_BASE;
+ int baud_divisor;
+
+ /*
+ * We copy the code from above because it is already horribly messy.
+ * Trying to refactor to nicely remove the duplication doesn't seem
+ * feasible. The better fix is to move all users of this driver to
+ * driver model.
+ */
+ baud_divisor = ns16550_calc_divisor(com_port, CONFIG_DEBUG_UART_CLOCK,
+ CONFIG_BAUDRATE);
+ serial_dout(&com_port->ier, CONFIG_SYS_NS16550_IER);
+ serial_dout(&com_port->mcr, UART_MCRVAL);
+ serial_dout(&com_port->fcr, UART_FCR_DEFVAL);
+
+ serial_dout(&com_port->lcr, UART_LCR_BKSE | UART_LCRVAL);
+ serial_dout(&com_port->dll, baud_divisor & 0xff);
+ serial_dout(&com_port->dlm, (baud_divisor >> 8) & 0xff);
+ serial_dout(&com_port->lcr, UART_LCRVAL);
+}
+
+static inline int NS16550_read_baud_divisor(struct ns16550 *com_port)
+{
+ int ret;
+
+ serial_dout(&com_port->lcr, UART_LCR_BKSE | UART_LCRVAL);
+ ret = serial_din(&com_port->dll) & 0xff;
+ ret |= (serial_din(&com_port->dlm) & 0xff) << 8;
+ serial_dout(&com_port->lcr, UART_LCRVAL);
+
+ return ret;
+}
+
+static inline void _debug_uart_putc(int ch)
+{
+ struct ns16550 *com_port = (struct ns16550 *)CONFIG_DEBUG_UART_BASE;
+
+ while (!(serial_din(&com_port->lsr) & UART_LSR_THRE)) {
+#ifdef CONFIG_DEBUG_UART_NS16550_CHECK_ENABLED
+ if (!NS16550_read_baud_divisor(com_port))
+ return;
+#endif
+ }
+ serial_dout(&com_port->thr, ch);
+}
+
+DEBUG_UART_FUNCS
+
+#endif
+
+#if CONFIG_IS_ENABLED(DM_SERIAL)
+static int ns16550_serial_putc(struct udevice *dev, const char ch)
+{
+ struct ns16550 *const com_port = dev_get_priv(dev);
+
+ if (!(serial_in(&com_port->lsr) & UART_LSR_THRE))
+ return -EAGAIN;
+ serial_out(ch, &com_port->thr);
+
+ /*
+ * Call watchdog_reset() upon newline. This is done here in putc
+ * since the environment code uses a single puts() to print the complete
+ * environment upon "printenv". So we can't put this watchdog call
+ * in puts().
+ */
+ if (ch == '\n')
+ WATCHDOG_RESET();
+
+ return 0;
+}
+
+static int ns16550_serial_pending(struct udevice *dev, bool input)
+{
+ struct ns16550 *const com_port = dev_get_priv(dev);
+
+ if (input)
+ return (serial_in(&com_port->lsr) & UART_LSR_DR) ? 1 : 0;
+ else
+ return (serial_in(&com_port->lsr) & UART_LSR_THRE) ? 0 : 1;
+}
+
+static int ns16550_serial_getc(struct udevice *dev)
+{
+ struct ns16550 *const com_port = dev_get_priv(dev);
+
+ if (!(serial_in(&com_port->lsr) & UART_LSR_DR))
+ return -EAGAIN;
+
+ return serial_in(&com_port->rbr);
+}
+
+static int ns16550_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ struct ns16550 *const com_port = dev_get_priv(dev);
+ struct ns16550_plat *plat = com_port->plat;
+ int clock_divisor;
+
+ clock_divisor = ns16550_calc_divisor(com_port, plat->clock, baudrate);
+
+ ns16550_setbrg(com_port, clock_divisor);
+
+ return 0;
+}
+
+static int ns16550_serial_setconfig(struct udevice *dev, uint serial_config)
+{
+ struct ns16550 *const com_port = dev_get_priv(dev);
+ int lcr_val = UART_LCR_WLS_8;
+ uint parity = SERIAL_GET_PARITY(serial_config);
+ uint bits = SERIAL_GET_BITS(serial_config);
+ uint stop = SERIAL_GET_STOP(serial_config);
+
+ /*
+ * only parity config is implemented, check if other serial settings
+ * are the default one.
+ */
+ if (bits != SERIAL_8_BITS || stop != SERIAL_ONE_STOP)
+ return -ENOTSUPP; /* not supported in driver*/
+
+ switch (parity) {
+ case SERIAL_PAR_NONE:
+ /* no bits to add */
+ break;
+ case SERIAL_PAR_ODD:
+ lcr_val |= UART_LCR_PEN;
+ break;
+ case SERIAL_PAR_EVEN:
+ lcr_val |= UART_LCR_PEN | UART_LCR_EPS;
+ break;
+ default:
+ return -ENOTSUPP; /* not supported in driver*/
+ }
+
+ serial_out(lcr_val, &com_port->lcr);
+ return 0;
+}
+
+static int ns16550_serial_getinfo(struct udevice *dev,
+ struct serial_device_info *info)
+{
+ struct ns16550 *const com_port = dev_get_priv(dev);
+ struct ns16550_plat *plat = com_port->plat;
+
+ info->type = SERIAL_CHIP_16550_COMPATIBLE;
+#ifdef CONFIG_SYS_NS16550_PORT_MAPPED
+ info->addr_space = SERIAL_ADDRESS_SPACE_IO;
+#else
+ info->addr_space = SERIAL_ADDRESS_SPACE_MEMORY;
+#endif
+ info->addr = plat->base;
+ info->reg_width = plat->reg_width;
+ info->reg_shift = plat->reg_shift;
+ info->reg_offset = plat->reg_offset;
+ info->clock = plat->clock;
+
+ return 0;
+}
+
+static int ns16550_serial_assign_base(struct ns16550_plat *plat, fdt_addr_t base)
+{
+ if (base == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+#ifdef CONFIG_SYS_NS16550_PORT_MAPPED
+ plat->base = base;
+#else
+ plat->base = (unsigned long)map_physmem(base, 0, MAP_NOCACHE);
+#endif
+
+ return 0;
+}
+
+int ns16550_serial_probe(struct udevice *dev)
+{
+ struct ns16550_plat *plat = dev_get_plat(dev);
+ struct ns16550 *const com_port = dev_get_priv(dev);
+ struct reset_ctl_bulk reset_bulk;
+ fdt_addr_t addr;
+ int ret;
+
+ /*
+ * If we are on PCI bus, either directly attached to a PCI root port,
+ * or via a PCI bridge, assign plat->base before probing hardware.
+ */
+ if (device_is_on_pci_bus(dev)) {
+ addr = devfdt_get_addr_pci(dev);
+ ret = ns16550_serial_assign_base(plat, addr);
+ if (ret)
+ return ret;
+ }
+
+ ret = reset_get_bulk(dev, &reset_bulk);
+ if (!ret)
+ reset_deassert_bulk(&reset_bulk);
+
+ com_port->plat = dev_get_plat(dev);
+ ns16550_init(com_port, -1);
+
+ return 0;
+}
+
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+enum {
+ PORT_NS16550 = 0,
+ PORT_JZ4780,
+};
+#endif
+
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
+int ns16550_serial_of_to_plat(struct udevice *dev)
+{
+ struct ns16550_plat *plat = dev_get_plat(dev);
+ const u32 port_type = dev_get_driver_data(dev);
+ fdt_addr_t addr;
+ struct clk clk;
+ int err;
+
+ addr = dev_read_addr(dev);
+ err = ns16550_serial_assign_base(plat, addr);
+ if (err && !device_is_on_pci_bus(dev))
+ return err;
+
+ plat->reg_offset = dev_read_u32_default(dev, "reg-offset", 0);
+ plat->reg_shift = dev_read_u32_default(dev, "reg-shift", 0);
+ plat->reg_width = dev_read_u32_default(dev, "reg-io-width", 1);
+
+ err = clk_get_by_index(dev, 0, &clk);
+ if (!err) {
+ err = clk_get_rate(&clk);
+ if (!IS_ERR_VALUE(err))
+ plat->clock = err;
+ } else if (err != -ENOENT && err != -ENODEV && err != -ENOSYS) {
+ debug("ns16550 failed to get clock\n");
+ return err;
+ }
+
+ if (!plat->clock)
+ plat->clock = dev_read_u32_default(dev, "clock-frequency",
+ CONFIG_SYS_NS16550_CLK);
+ if (!plat->clock)
+ plat->clock = CONFIG_SYS_NS16550_CLK;
+ if (!plat->clock) {
+ debug("ns16550 clock not defined\n");
+ return -EINVAL;
+ }
+
+ plat->fcr = UART_FCR_DEFVAL;
+ if (port_type == PORT_JZ4780)
+ plat->fcr |= UART_FCR_UME;
+
+ return 0;
+}
+#endif
+
+const struct dm_serial_ops ns16550_serial_ops = {
+ .putc = ns16550_serial_putc,
+ .pending = ns16550_serial_pending,
+ .getc = ns16550_serial_getc,
+ .setbrg = ns16550_serial_setbrg,
+ .setconfig = ns16550_serial_setconfig,
+ .getinfo = ns16550_serial_getinfo,
+};
+
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
+/*
+ * Please consider existing compatible strings before adding a new
+ * one to keep this table compact. Or you may add a generic "ns16550"
+ * compatible string to your dts.
+ */
+static const struct udevice_id ns16550_serial_ids[] = {
+ { .compatible = "ns16550", .data = PORT_NS16550 },
+ { .compatible = "ns16550a", .data = PORT_NS16550 },
+ { .compatible = "ingenic,jz4780-uart", .data = PORT_JZ4780 },
+ { .compatible = "nvidia,tegra20-uart", .data = PORT_NS16550 },
+ { .compatible = "snps,dw-apb-uart", .data = PORT_NS16550 },
+ {}
+};
+#endif /* OF_CONTROL && !OF_PLATDATA */
+
+#if CONFIG_IS_ENABLED(SERIAL_PRESENT)
+
+/* TODO(sjg@chromium.org): Integrate this into a macro like CONFIG_IS_ENABLED */
+#if !defined(CONFIG_TPL_BUILD) || defined(CONFIG_TPL_DM_SERIAL)
+U_BOOT_DRIVER(ns16550_serial) = {
+ .name = "ns16550_serial",
+ .id = UCLASS_SERIAL,
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
+ .of_match = ns16550_serial_ids,
+ .of_to_plat = ns16550_serial_of_to_plat,
+ .plat_auto = sizeof(struct ns16550_plat),
+#endif
+ .priv_auto = sizeof(struct ns16550),
+ .probe = ns16550_serial_probe,
+ .ops = &ns16550_serial_ops,
+#if !CONFIG_IS_ENABLED(OF_CONTROL)
+ .flags = DM_FLAG_PRE_RELOC,
+#endif
+};
+
+DM_DRIVER_ALIAS(ns16550_serial, rockchip_rk3328_uart)
+DM_DRIVER_ALIAS(ns16550_serial, rockchip_rk3368_uart)
+DM_DRIVER_ALIAS(ns16550_serial, ti_da830_uart)
+#endif
+#endif /* SERIAL_PRESENT */
+
+#endif /* CONFIG_DM_SERIAL */
diff --git a/roms/u-boot/drivers/serial/sandbox.c b/roms/u-boot/drivers/serial/sandbox.c
new file mode 100644
index 000000000..5243c955f
--- /dev/null
+++ b/roms/u-boot/drivers/serial/sandbox.c
@@ -0,0 +1,249 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ */
+
+/*
+ * This provide a test serial port. It provides an emulated serial port where
+ * a test program and read out the serial output and inject serial input for
+ * U-Boot.
+ */
+
+#include <common.h>
+#include <console.h>
+#include <dm.h>
+#include <lcd.h>
+#include <os.h>
+#include <serial.h>
+#include <video.h>
+#include <asm/global_data.h>
+#include <linux/compiler.h>
+#include <asm/serial.h>
+#include <asm/state.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * output_ansi_colour() - Output an ANSI colour code
+ *
+ * @colour: Colour to output (0-7)
+ */
+static void output_ansi_colour(int colour)
+{
+ char ansi_code[] = "\x1b[1;3Xm";
+
+ ansi_code[5] = '0' + colour;
+ os_write(1, ansi_code, sizeof(ansi_code) - 1);
+}
+
+static void output_ansi_reset(void)
+{
+ os_write(1, "\x1b[0m", 4);
+}
+
+static int sandbox_serial_probe(struct udevice *dev)
+{
+ struct sandbox_state *state = state_get_current();
+ struct sandbox_serial_priv *priv = dev_get_priv(dev);
+
+ if (state->term_raw != STATE_TERM_COOKED)
+ os_tty_raw(0, state->term_raw == STATE_TERM_RAW_WITH_SIGS);
+ priv->start_of_line = 0;
+
+ if (state->term_raw != STATE_TERM_RAW)
+ disable_ctrlc(1);
+ membuff_init(&priv->buf, priv->serial_buf, sizeof(priv->serial_buf));
+
+ return 0;
+}
+
+static int sandbox_serial_remove(struct udevice *dev)
+{
+ struct sandbox_serial_plat *plat = dev_get_plat(dev);
+
+ if (plat->colour != -1)
+ output_ansi_reset();
+
+ return 0;
+}
+
+static int sandbox_serial_putc(struct udevice *dev, const char ch)
+{
+ struct sandbox_serial_priv *priv = dev_get_priv(dev);
+ struct sandbox_serial_plat *plat = dev_get_plat(dev);
+
+ /* With of-platdata we don't real the colour correctly, so disable it */
+ if (!CONFIG_IS_ENABLED(OF_PLATDATA) && priv->start_of_line &&
+ plat->colour != -1) {
+ priv->start_of_line = false;
+ output_ansi_colour(plat->colour);
+ }
+
+ os_write(1, &ch, 1);
+ if (ch == '\n')
+ priv->start_of_line = true;
+
+ return 0;
+}
+
+static int sandbox_serial_pending(struct udevice *dev, bool input)
+{
+ struct sandbox_serial_priv *priv = dev_get_priv(dev);
+ ssize_t count;
+ char *data;
+ int avail;
+
+ if (!input)
+ return 0;
+
+ os_usleep(100);
+ if (!IS_ENABLED(CONFIG_SPL_BUILD))
+ video_sync_all();
+ avail = membuff_putraw(&priv->buf, 100, false, &data);
+ if (!avail)
+ return 1; /* buffer full */
+
+ count = os_read(0, data, avail);
+ if (count > 0)
+ membuff_putraw(&priv->buf, count, true, &data);
+
+ return membuff_avail(&priv->buf);
+}
+
+static int sandbox_serial_getc(struct udevice *dev)
+{
+ struct sandbox_serial_priv *priv = dev_get_priv(dev);
+
+ if (!sandbox_serial_pending(dev, true))
+ return -EAGAIN; /* buffer empty */
+
+ return membuff_getbyte(&priv->buf);
+}
+
+#ifdef CONFIG_DEBUG_UART_SANDBOX
+
+#include <debug_uart.h>
+
+static inline void _debug_uart_init(void)
+{
+}
+
+static inline void _debug_uart_putc(int ch)
+{
+ os_putc(ch);
+}
+
+DEBUG_UART_FUNCS
+
+#endif /* CONFIG_DEBUG_UART_SANDBOX */
+
+static int sandbox_serial_getconfig(struct udevice *dev, uint *serial_config)
+{
+ uint config = SERIAL_DEFAULT_CONFIG;
+
+ if (!serial_config)
+ return -EINVAL;
+
+ *serial_config = config;
+
+ return 0;
+}
+
+static int sandbox_serial_setconfig(struct udevice *dev, uint serial_config)
+{
+ u8 parity = SERIAL_GET_PARITY(serial_config);
+ u8 bits = SERIAL_GET_BITS(serial_config);
+ u8 stop = SERIAL_GET_STOP(serial_config);
+
+ if (bits != SERIAL_8_BITS || stop != SERIAL_ONE_STOP ||
+ parity != SERIAL_PAR_NONE)
+ return -ENOTSUPP; /* not supported in driver*/
+
+ return 0;
+}
+
+static int sandbox_serial_getinfo(struct udevice *dev,
+ struct serial_device_info *serial_info)
+{
+ struct serial_device_info info = {
+ .type = SERIAL_CHIP_UNKNOWN,
+ .addr_space = SERIAL_ADDRESS_SPACE_IO,
+ .addr = SERIAL_DEFAULT_ADDRESS,
+ .reg_width = 1,
+ .reg_offset = 0,
+ .reg_shift = 0,
+ .clock = SERIAL_DEFAULT_CLOCK,
+ };
+
+ if (!serial_info)
+ return -EINVAL;
+
+ *serial_info = info;
+
+ return 0;
+}
+
+static const char * const ansi_colour[] = {
+ "black", "red", "green", "yellow", "blue", "megenta", "cyan",
+ "white",
+};
+
+static int sandbox_serial_of_to_plat(struct udevice *dev)
+{
+ struct sandbox_serial_plat *plat = dev_get_plat(dev);
+ const char *colour;
+ int i;
+
+ if (CONFIG_IS_ENABLED(OF_PLATDATA))
+ return 0;
+ plat->colour = -1;
+ colour = dev_read_string(dev, "sandbox,text-colour");
+ if (colour) {
+ for (i = 0; i < ARRAY_SIZE(ansi_colour); i++) {
+ if (!strcmp(colour, ansi_colour[i])) {
+ plat->colour = i;
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static const struct dm_serial_ops sandbox_serial_ops = {
+ .putc = sandbox_serial_putc,
+ .pending = sandbox_serial_pending,
+ .getc = sandbox_serial_getc,
+ .getconfig = sandbox_serial_getconfig,
+ .setconfig = sandbox_serial_setconfig,
+ .getinfo = sandbox_serial_getinfo,
+};
+
+static const struct udevice_id sandbox_serial_ids[] = {
+ { .compatible = "sandbox,serial" },
+ { }
+};
+
+U_BOOT_DRIVER(sandbox_serial) = {
+ .name = "sandbox_serial",
+ .id = UCLASS_SERIAL,
+ .of_match = sandbox_serial_ids,
+ .of_to_plat = sandbox_serial_of_to_plat,
+ .plat_auto = sizeof(struct sandbox_serial_plat),
+ .priv_auto = sizeof(struct sandbox_serial_priv),
+ .probe = sandbox_serial_probe,
+ .remove = sandbox_serial_remove,
+ .ops = &sandbox_serial_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
+
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+static const struct sandbox_serial_plat platdata_non_fdt = {
+ .colour = -1,
+};
+
+U_BOOT_DRVINFO(serial_sandbox_non_fdt) = {
+ .name = "sandbox_serial",
+ .plat = &platdata_non_fdt,
+};
+#endif
diff --git a/roms/u-boot/drivers/serial/serial-uclass.c b/roms/u-boot/drivers/serial/serial-uclass.c
new file mode 100644
index 000000000..8a87eed68
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial-uclass.c
@@ -0,0 +1,522 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2014 The Chromium OS Authors.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <env_internal.h>
+#include <errno.h>
+#include <malloc.h>
+#include <os.h>
+#include <serial.h>
+#include <stdio_dev.h>
+#include <watchdog.h>
+#include <asm/global_data.h>
+#include <dm/lists.h>
+#include <dm/device-internal.h>
+#include <dm/of_access.h>
+#include <linux/delay.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Table with supported baudrates (defined in config_xyz.h)
+ */
+static const unsigned long baudrate_table[] = CONFIG_SYS_BAUDRATE_TABLE;
+
+#if !CONFIG_VAL(SYS_MALLOC_F_LEN)
+#error "Serial is required before relocation - define CONFIG_$(SPL_)SYS_MALLOC_F_LEN to make this work"
+#endif
+
+#if CONFIG_IS_ENABLED(SERIAL_PRESENT)
+static int serial_check_stdout(const void *blob, struct udevice **devp)
+{
+ int node = -1;
+ const char *str, *p, *name;
+ int namelen;
+
+ /* Check for a chosen console */
+ str = fdtdec_get_chosen_prop(blob, "stdout-path");
+ if (str) {
+ p = strchr(str, ':');
+ namelen = p ? p - str : strlen(str);
+ node = fdt_path_offset_namelen(blob, str, namelen);
+
+ if (node < 0) {
+ /*
+ * Deal with things like
+ * stdout-path = "serial0:115200n8";
+ *
+ * We need to look up the alias and then follow it to
+ * the correct node.
+ */
+ name = fdt_get_alias_namelen(blob, str, namelen);
+ if (name)
+ node = fdt_path_offset(blob, name);
+ }
+ }
+
+ if (node < 0)
+ node = fdt_path_offset(blob, "console");
+ if (!uclass_get_device_by_of_offset(UCLASS_SERIAL, node, devp))
+ return 0;
+
+ /*
+ * If the console is not marked to be bound before relocation, bind it
+ * anyway.
+ */
+ if (node > 0 && !lists_bind_fdt(gd->dm_root, offset_to_ofnode(node),
+ devp, false)) {
+ if (!device_probe(*devp))
+ return 0;
+ }
+
+ return -ENODEV;
+}
+
+static void serial_find_console_or_panic(void)
+{
+ const void *blob = gd->fdt_blob;
+ struct udevice *dev;
+#ifdef CONFIG_SERIAL_SEARCH_ALL
+ int ret;
+#endif
+
+ if (CONFIG_IS_ENABLED(OF_PLATDATA)) {
+ uclass_first_device(UCLASS_SERIAL, &dev);
+ if (dev) {
+ gd->cur_serial_dev = dev;
+ return;
+ }
+ } else if (CONFIG_IS_ENABLED(OF_CONTROL) && blob) {
+ /* Live tree has support for stdout */
+ if (of_live_active()) {
+ struct device_node *np = of_get_stdout();
+
+ if (np && !uclass_get_device_by_ofnode(UCLASS_SERIAL,
+ np_to_ofnode(np), &dev)) {
+ gd->cur_serial_dev = dev;
+ return;
+ }
+ } else {
+ if (!serial_check_stdout(blob, &dev)) {
+ gd->cur_serial_dev = dev;
+ return;
+ }
+ }
+ }
+ if (!SPL_BUILD || !CONFIG_IS_ENABLED(OF_CONTROL) || !blob) {
+ /*
+ * Try to use CONFIG_CONS_INDEX if available (it is numbered
+ * from 1!).
+ *
+ * Failing that, get the device with sequence number 0, or in
+ * extremis just the first working serial device we can find.
+ * But we insist on having a console (even if it is silent).
+ */
+#ifdef CONFIG_CONS_INDEX
+#define INDEX (CONFIG_CONS_INDEX - 1)
+#else
+#define INDEX 0
+#endif
+
+#ifdef CONFIG_SERIAL_SEARCH_ALL
+ if (!uclass_get_device_by_seq(UCLASS_SERIAL, INDEX, &dev) ||
+ !uclass_get_device(UCLASS_SERIAL, INDEX, &dev)) {
+ if (dev_get_flags(dev) & DM_FLAG_ACTIVATED) {
+ gd->cur_serial_dev = dev;
+ return;
+ }
+ }
+
+ /* Search for any working device */
+ for (ret = uclass_first_device_check(UCLASS_SERIAL, &dev);
+ dev;
+ ret = uclass_next_device_check(&dev)) {
+ if (!ret) {
+ /* Device did succeed probing */
+ gd->cur_serial_dev = dev;
+ return;
+ }
+ }
+#else
+ if (!uclass_get_device_by_seq(UCLASS_SERIAL, INDEX, &dev) ||
+ !uclass_get_device(UCLASS_SERIAL, INDEX, &dev) ||
+ (!uclass_first_device(UCLASS_SERIAL, &dev) && dev)) {
+ gd->cur_serial_dev = dev;
+ return;
+ }
+#endif
+
+#undef INDEX
+ }
+
+#ifdef CONFIG_REQUIRE_SERIAL_CONSOLE
+ panic_str("No serial driver found");
+#endif
+}
+#endif /* CONFIG_SERIAL_PRESENT */
+
+/* Called prior to relocation */
+int serial_init(void)
+{
+#if CONFIG_IS_ENABLED(SERIAL_PRESENT)
+ serial_find_console_or_panic();
+ gd->flags |= GD_FLG_SERIAL_READY;
+ serial_setbrg();
+#endif
+
+ return 0;
+}
+
+/* Called after relocation */
+int serial_initialize(void)
+{
+ /* Scanning uclass to probe devices */
+ if (IS_ENABLED(CONFIG_SERIAL_PROBE_ALL)) {
+ int ret;
+
+ ret = uclass_probe_all(UCLASS_SERIAL);
+ if (ret)
+ return ret;
+ }
+
+ return serial_init();
+}
+
+static void _serial_putc(struct udevice *dev, char ch)
+{
+ struct dm_serial_ops *ops = serial_get_ops(dev);
+ int err;
+
+ if (ch == '\n')
+ _serial_putc(dev, '\r');
+
+ do {
+ err = ops->putc(dev, ch);
+ } while (err == -EAGAIN);
+}
+
+static void _serial_puts(struct udevice *dev, const char *str)
+{
+ while (*str)
+ _serial_putc(dev, *str++);
+}
+
+static int __serial_getc(struct udevice *dev)
+{
+ struct dm_serial_ops *ops = serial_get_ops(dev);
+ int err;
+
+ do {
+ err = ops->getc(dev);
+ if (err == -EAGAIN)
+ WATCHDOG_RESET();
+ } while (err == -EAGAIN);
+
+ return err >= 0 ? err : 0;
+}
+
+static int __serial_tstc(struct udevice *dev)
+{
+ struct dm_serial_ops *ops = serial_get_ops(dev);
+
+ if (ops->pending)
+ return ops->pending(dev, true);
+
+ return 1;
+}
+
+#if CONFIG_IS_ENABLED(SERIAL_RX_BUFFER)
+static int _serial_tstc(struct udevice *dev)
+{
+ struct serial_dev_priv *upriv = dev_get_uclass_priv(dev);
+
+ /* Read all available chars into the RX buffer */
+ while (__serial_tstc(dev)) {
+ upriv->buf[upriv->wr_ptr++] = __serial_getc(dev);
+ upriv->wr_ptr %= CONFIG_SERIAL_RX_BUFFER_SIZE;
+ }
+
+ return upriv->rd_ptr != upriv->wr_ptr ? 1 : 0;
+}
+
+static int _serial_getc(struct udevice *dev)
+{
+ struct serial_dev_priv *upriv = dev_get_uclass_priv(dev);
+ char val;
+
+ if (upriv->rd_ptr == upriv->wr_ptr)
+ return __serial_getc(dev);
+
+ val = upriv->buf[upriv->rd_ptr++];
+ upriv->rd_ptr %= CONFIG_SERIAL_RX_BUFFER_SIZE;
+
+ return val;
+}
+
+#else /* CONFIG_IS_ENABLED(SERIAL_RX_BUFFER) */
+
+static int _serial_getc(struct udevice *dev)
+{
+ return __serial_getc(dev);
+}
+
+static int _serial_tstc(struct udevice *dev)
+{
+ return __serial_tstc(dev);
+}
+#endif /* CONFIG_IS_ENABLED(SERIAL_RX_BUFFER) */
+
+void serial_putc(char ch)
+{
+ if (gd->cur_serial_dev)
+ _serial_putc(gd->cur_serial_dev, ch);
+}
+
+void serial_puts(const char *str)
+{
+ if (gd->cur_serial_dev)
+ _serial_puts(gd->cur_serial_dev, str);
+}
+
+int serial_getc(void)
+{
+ if (!gd->cur_serial_dev)
+ return 0;
+
+ return _serial_getc(gd->cur_serial_dev);
+}
+
+int serial_tstc(void)
+{
+ if (!gd->cur_serial_dev)
+ return 0;
+
+ return _serial_tstc(gd->cur_serial_dev);
+}
+
+void serial_setbrg(void)
+{
+ struct dm_serial_ops *ops;
+
+ if (!gd->cur_serial_dev)
+ return;
+
+ ops = serial_get_ops(gd->cur_serial_dev);
+ if (ops->setbrg)
+ ops->setbrg(gd->cur_serial_dev, gd->baudrate);
+}
+
+int serial_getconfig(struct udevice *dev, uint *config)
+{
+ struct dm_serial_ops *ops;
+
+ ops = serial_get_ops(dev);
+ if (ops->getconfig)
+ return ops->getconfig(dev, config);
+
+ return 0;
+}
+
+int serial_setconfig(struct udevice *dev, uint config)
+{
+ struct dm_serial_ops *ops;
+
+ ops = serial_get_ops(dev);
+ if (ops->setconfig)
+ return ops->setconfig(dev, config);
+
+ return 0;
+}
+
+int serial_getinfo(struct udevice *dev, struct serial_device_info *info)
+{
+ struct dm_serial_ops *ops;
+
+ if (!info)
+ return -EINVAL;
+
+ info->baudrate = gd->baudrate;
+
+ ops = serial_get_ops(dev);
+ if (ops->getinfo)
+ return ops->getinfo(dev, info);
+
+ return -EINVAL;
+}
+
+void serial_stdio_init(void)
+{
+}
+
+#if defined(CONFIG_DM_STDIO)
+
+#if CONFIG_IS_ENABLED(SERIAL_PRESENT)
+static void serial_stub_putc(struct stdio_dev *sdev, const char ch)
+{
+ _serial_putc(sdev->priv, ch);
+}
+#endif
+
+static void serial_stub_puts(struct stdio_dev *sdev, const char *str)
+{
+ _serial_puts(sdev->priv, str);
+}
+
+static int serial_stub_getc(struct stdio_dev *sdev)
+{
+ return _serial_getc(sdev->priv);
+}
+
+static int serial_stub_tstc(struct stdio_dev *sdev)
+{
+ return _serial_tstc(sdev->priv);
+}
+#endif
+
+/**
+ * on_baudrate() - Update the actual baudrate when the env var changes
+ *
+ * This will check for a valid baudrate and only apply it if valid.
+ */
+static int on_baudrate(const char *name, const char *value, enum env_op op,
+ int flags)
+{
+ int i;
+ int baudrate;
+
+ switch (op) {
+ case env_op_create:
+ case env_op_overwrite:
+ /*
+ * Switch to new baudrate if new baudrate is supported
+ */
+ baudrate = simple_strtoul(value, NULL, 10);
+
+ /* Not actually changing */
+ if (gd->baudrate == baudrate)
+ return 0;
+
+ for (i = 0; i < ARRAY_SIZE(baudrate_table); ++i) {
+ if (baudrate == baudrate_table[i])
+ break;
+ }
+ if (i == ARRAY_SIZE(baudrate_table)) {
+ if ((flags & H_FORCE) == 0)
+ printf("## Baudrate %d bps not supported\n",
+ baudrate);
+ return 1;
+ }
+ if ((flags & H_INTERACTIVE) != 0) {
+ printf("## Switch baudrate to %d bps and press ENTER ...\n",
+ baudrate);
+ udelay(50000);
+ }
+
+ gd->baudrate = baudrate;
+
+ serial_setbrg();
+
+ udelay(50000);
+
+ if ((flags & H_INTERACTIVE) != 0)
+ while (1) {
+ if (getchar() == '\r')
+ break;
+ }
+
+ return 0;
+ case env_op_delete:
+ printf("## Baudrate may not be deleted\n");
+ return 1;
+ default:
+ return 0;
+ }
+}
+U_BOOT_ENV_CALLBACK(baudrate, on_baudrate);
+
+#if CONFIG_IS_ENABLED(SERIAL_PRESENT)
+static int serial_post_probe(struct udevice *dev)
+{
+ struct dm_serial_ops *ops = serial_get_ops(dev);
+#ifdef CONFIG_DM_STDIO
+ struct serial_dev_priv *upriv = dev_get_uclass_priv(dev);
+ struct stdio_dev sdev;
+#endif
+ int ret;
+
+#if defined(CONFIG_NEEDS_MANUAL_RELOC)
+ if (ops->setbrg)
+ ops->setbrg += gd->reloc_off;
+ if (ops->getc)
+ ops->getc += gd->reloc_off;
+ if (ops->putc)
+ ops->putc += gd->reloc_off;
+ if (ops->pending)
+ ops->pending += gd->reloc_off;
+ if (ops->clear)
+ ops->clear += gd->reloc_off;
+ if (ops->getconfig)
+ ops->getconfig += gd->reloc_off;
+ if (ops->setconfig)
+ ops->setconfig += gd->reloc_off;
+#if CONFIG_POST & CONFIG_SYS_POST_UART
+ if (ops->loop)
+ ops->loop += gd->reloc_off;
+#endif
+ if (ops->getinfo)
+ ops->getinfo += gd->reloc_off;
+#endif
+ /* Set the baud rate */
+ if (ops->setbrg) {
+ ret = ops->setbrg(dev, gd->baudrate);
+ if (ret)
+ return ret;
+ }
+
+#ifdef CONFIG_DM_STDIO
+ if (!(gd->flags & GD_FLG_RELOC))
+ return 0;
+ memset(&sdev, '\0', sizeof(sdev));
+
+ strncpy(sdev.name, dev->name, sizeof(sdev.name));
+ sdev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT | DEV_FLAGS_DM;
+ sdev.priv = dev;
+ sdev.putc = serial_stub_putc;
+ sdev.puts = serial_stub_puts;
+ sdev.getc = serial_stub_getc;
+ sdev.tstc = serial_stub_tstc;
+
+#if CONFIG_IS_ENABLED(SERIAL_RX_BUFFER)
+ /* Allocate the RX buffer */
+ upriv->buf = malloc(CONFIG_SERIAL_RX_BUFFER_SIZE);
+#endif
+
+ stdio_register_dev(&sdev, &upriv->sdev);
+#endif
+ return 0;
+}
+
+static int serial_pre_remove(struct udevice *dev)
+{
+#if CONFIG_IS_ENABLED(SYS_STDIO_DEREGISTER)
+ struct serial_dev_priv *upriv = dev_get_uclass_priv(dev);
+
+ if (stdio_deregister_dev(upriv->sdev, true))
+ return -EPERM;
+#endif
+
+ return 0;
+}
+
+UCLASS_DRIVER(serial) = {
+ .id = UCLASS_SERIAL,
+ .name = "serial",
+ .flags = DM_UC_FLAG_SEQ_ALIAS,
+ .post_probe = serial_post_probe,
+ .pre_remove = serial_pre_remove,
+ .per_device_auto = sizeof(struct serial_dev_priv),
+};
+#endif
diff --git a/roms/u-boot/drivers/serial/serial.c b/roms/u-boot/drivers/serial/serial.c
new file mode 100644
index 000000000..dea25a049
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial.c
@@ -0,0 +1,555 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+#include <common.h>
+#include <env_internal.h>
+#include <hang.h>
+#include <serial.h>
+#include <stdio_dev.h>
+#include <post.h>
+#include <asm/global_data.h>
+#include <linux/compiler.h>
+#include <errno.h>
+#include <linux/delay.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static struct serial_device *serial_devices;
+static struct serial_device *serial_current;
+/*
+ * Table with supported baudrates (defined in config_xyz.h)
+ */
+static const unsigned long baudrate_table[] = CONFIG_SYS_BAUDRATE_TABLE;
+
+/**
+ * serial_null() - Void registration routine of a serial driver
+ *
+ * This routine implements a void registration routine of a serial
+ * driver. The registration routine of a particular driver is aliased
+ * to this empty function in case the driver is not compiled into
+ * U-Boot.
+ */
+static void serial_null(void)
+{
+}
+
+/**
+ * on_baudrate() - Update the actual baudrate when the env var changes
+ *
+ * @name: changed environment variable
+ * @value: new value of the environment variable
+ * @op: operation (create, overwrite, or delete)
+ * @flags: attributes of environment variable change,
+ * see flags H_* in include/search.h
+ *
+ * This will check for a valid baudrate and only apply it if valid.
+ *
+ * Return: 0 on success, 1 on error
+ */
+static int on_baudrate(const char *name, const char *value, enum env_op op,
+ int flags)
+{
+ int i;
+ int baudrate;
+
+ switch (op) {
+ case env_op_create:
+ case env_op_overwrite:
+ /*
+ * Switch to new baudrate if new baudrate is supported
+ */
+ baudrate = simple_strtoul(value, NULL, 10);
+
+ /* Not actually changing */
+ if (gd->baudrate == baudrate)
+ return 0;
+
+ for (i = 0; i < ARRAY_SIZE(baudrate_table); ++i) {
+ if (baudrate == baudrate_table[i])
+ break;
+ }
+ if (i == ARRAY_SIZE(baudrate_table)) {
+ if ((flags & H_FORCE) == 0)
+ printf("## Baudrate %d bps not supported\n",
+ baudrate);
+ return 1;
+ }
+ if ((flags & H_INTERACTIVE) != 0) {
+ printf("## Switch baudrate to %d"
+ " bps and press ENTER ...\n", baudrate);
+ udelay(50000);
+ }
+
+ gd->baudrate = baudrate;
+
+ serial_setbrg();
+
+ udelay(50000);
+
+ if ((flags & H_INTERACTIVE) != 0)
+ while (1) {
+ if (getchar() == '\r')
+ break;
+ }
+
+ return 0;
+ case env_op_delete:
+ printf("## Baudrate may not be deleted\n");
+ return 1;
+ default:
+ return 0;
+ }
+}
+U_BOOT_ENV_CALLBACK(baudrate, on_baudrate);
+
+/**
+ * serial_initfunc() - Forward declare of driver registration routine
+ * @name: Name of the real driver registration routine.
+ *
+ * This macro expands onto forward declaration of a driver registration
+ * routine, which is then used below in serial_initialize() function.
+ * The declaration is made weak and aliases to serial_null() so in case
+ * the driver is not compiled in, the function is still declared and can
+ * be used, but aliases to serial_null() and thus is optimized away.
+ */
+#define serial_initfunc(name) \
+ void name(void) \
+ __attribute__((weak, alias("serial_null")));
+
+serial_initfunc(atmel_serial_initialize);
+serial_initfunc(mcf_serial_initialize);
+serial_initfunc(mpc85xx_serial_initialize);
+serial_initfunc(mxc_serial_initialize);
+serial_initfunc(ns16550_serial_initialize);
+serial_initfunc(pl01x_serial_initialize);
+serial_initfunc(pxa_serial_initialize);
+serial_initfunc(sh_serial_initialize);
+serial_initfunc(mtk_serial_initialize);
+
+/**
+ * serial_register() - Register serial driver with serial driver core
+ * @dev: Pointer to the serial driver structure
+ *
+ * This function registers the serial driver supplied via @dev with
+ * serial driver core, thus making U-Boot aware of it and making it
+ * available for U-Boot to use. On platforms that still require manual
+ * relocation of constant variables, relocation of the supplied structure
+ * is performed.
+ */
+void serial_register(struct serial_device *dev)
+{
+#ifdef CONFIG_NEEDS_MANUAL_RELOC
+ if (dev->start)
+ dev->start += gd->reloc_off;
+ if (dev->stop)
+ dev->stop += gd->reloc_off;
+ if (dev->setbrg)
+ dev->setbrg += gd->reloc_off;
+ if (dev->getc)
+ dev->getc += gd->reloc_off;
+ if (dev->tstc)
+ dev->tstc += gd->reloc_off;
+ if (dev->putc)
+ dev->putc += gd->reloc_off;
+ if (dev->puts)
+ dev->puts += gd->reloc_off;
+#endif
+
+ dev->next = serial_devices;
+ serial_devices = dev;
+}
+
+/**
+ * serial_initialize() - Register all compiled-in serial port drivers
+ *
+ * This function registers all serial port drivers that are compiled
+ * into the U-Boot binary with the serial core, thus making them
+ * available to U-Boot to use. Lastly, this function assigns a default
+ * serial port to the serial core. That serial port is then used as a
+ * default output.
+ */
+int serial_initialize(void)
+{
+ atmel_serial_initialize();
+ mcf_serial_initialize();
+ mpc85xx_serial_initialize();
+ mxc_serial_initialize();
+ ns16550_serial_initialize();
+ pl01x_serial_initialize();
+ pxa_serial_initialize();
+ sh_serial_initialize();
+ mtk_serial_initialize();
+
+ serial_assign(default_serial_console()->name);
+
+ return 0;
+}
+
+static int serial_stub_start(struct stdio_dev *sdev)
+{
+ struct serial_device *dev = sdev->priv;
+
+ return dev->start();
+}
+
+static int serial_stub_stop(struct stdio_dev *sdev)
+{
+ struct serial_device *dev = sdev->priv;
+
+ return dev->stop();
+}
+
+static void serial_stub_putc(struct stdio_dev *sdev, const char ch)
+{
+ struct serial_device *dev = sdev->priv;
+
+ dev->putc(ch);
+}
+
+static void serial_stub_puts(struct stdio_dev *sdev, const char *str)
+{
+ struct serial_device *dev = sdev->priv;
+
+ dev->puts(str);
+}
+
+static int serial_stub_getc(struct stdio_dev *sdev)
+{
+ struct serial_device *dev = sdev->priv;
+
+ return dev->getc();
+}
+
+static int serial_stub_tstc(struct stdio_dev *sdev)
+{
+ struct serial_device *dev = sdev->priv;
+
+ return dev->tstc();
+}
+
+/**
+ * serial_stdio_init() - Register serial ports with STDIO core
+ *
+ * This function generates a proxy driver for each serial port driver.
+ * These proxy drivers then register with the STDIO core, making the
+ * serial drivers available as STDIO devices.
+ */
+void serial_stdio_init(void)
+{
+ struct stdio_dev dev;
+ struct serial_device *s = serial_devices;
+
+ while (s) {
+ memset(&dev, 0, sizeof(dev));
+
+ strcpy(dev.name, s->name);
+ dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT;
+
+ dev.start = serial_stub_start;
+ dev.stop = serial_stub_stop;
+ dev.putc = serial_stub_putc;
+ dev.puts = serial_stub_puts;
+ dev.getc = serial_stub_getc;
+ dev.tstc = serial_stub_tstc;
+ dev.priv = s;
+
+ stdio_register(&dev);
+
+ s = s->next;
+ }
+}
+
+/**
+ * serial_assign() - Select the serial output device by name
+ * @name: Name of the serial driver to be used as default output
+ *
+ * This function configures the serial output multiplexing by
+ * selecting which serial device will be used as default. In case
+ * the STDIO "serial" device is selected as stdin/stdout/stderr,
+ * the serial device previously configured by this function will be
+ * used for the particular operation.
+ *
+ * Returns 0 on success, negative on error.
+ */
+int serial_assign(const char *name)
+{
+ struct serial_device *s;
+
+ for (s = serial_devices; s; s = s->next) {
+ if (strcmp(s->name, name))
+ continue;
+ serial_current = s;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+/**
+ * serial_reinit_all() - Reinitialize all compiled-in serial ports
+ *
+ * This function reinitializes all serial ports that are compiled
+ * into U-Boot by calling their serial_start() functions.
+ */
+void serial_reinit_all(void)
+{
+ struct serial_device *s;
+
+ for (s = serial_devices; s; s = s->next)
+ s->start();
+}
+
+/**
+ * get_current() - Return pointer to currently selected serial port
+ *
+ * This function returns a pointer to currently selected serial port.
+ * The currently selected serial port is altered by serial_assign()
+ * function.
+ *
+ * In case this function is called before relocation or before any serial
+ * port is configured, this function calls default_serial_console() to
+ * determine the serial port. Otherwise, the configured serial port is
+ * returned.
+ *
+ * Returns pointer to the currently selected serial port on success,
+ * NULL on error.
+ */
+static struct serial_device *get_current(void)
+{
+ struct serial_device *dev;
+
+ if (!(gd->flags & GD_FLG_RELOC))
+ dev = default_serial_console();
+ else if (!serial_current)
+ dev = default_serial_console();
+ else
+ dev = serial_current;
+
+ /* We must have a console device */
+ if (!dev) {
+#ifdef CONFIG_SPL_BUILD
+ puts("Cannot find console\n");
+ hang();
+#else
+ panic("Cannot find console\n");
+#endif
+ }
+
+ return dev;
+}
+
+/**
+ * serial_init() - Initialize currently selected serial port
+ *
+ * This function initializes the currently selected serial port. This
+ * usually involves setting up the registers of that particular port,
+ * enabling clock and such. This function uses the get_current() call
+ * to determine which port is selected.
+ *
+ * Returns 0 on success, negative on error.
+ */
+int serial_init(void)
+{
+ gd->flags |= GD_FLG_SERIAL_READY;
+ return get_current()->start();
+}
+
+/**
+ * serial_setbrg() - Configure baud-rate of currently selected serial port
+ *
+ * This function configures the baud-rate of the currently selected
+ * serial port. The baud-rate is retrieved from global data within
+ * the serial port driver. This function uses the get_current() call
+ * to determine which port is selected.
+ *
+ * Returns 0 on success, negative on error.
+ */
+void serial_setbrg(void)
+{
+ get_current()->setbrg();
+}
+
+/**
+ * serial_getc() - Read character from currently selected serial port
+ *
+ * This function retrieves a character from currently selected serial
+ * port. In case there is no character waiting on the serial port,
+ * this function will block and wait for the character to appear. This
+ * function uses the get_current() call to determine which port is
+ * selected.
+ *
+ * Returns the character on success, negative on error.
+ */
+int serial_getc(void)
+{
+ return get_current()->getc();
+}
+
+/**
+ * serial_tstc() - Test if data is available on currently selected serial port
+ *
+ * This function tests if one or more characters are available on
+ * currently selected serial port. This function never blocks. This
+ * function uses the get_current() call to determine which port is
+ * selected.
+ *
+ * Returns positive if character is available, zero otherwise.
+ */
+int serial_tstc(void)
+{
+ return get_current()->tstc();
+}
+
+/**
+ * serial_putc() - Output character via currently selected serial port
+ * @c: Single character to be output from the serial port.
+ *
+ * This function outputs a character via currently selected serial
+ * port. This character is passed to the serial port driver responsible
+ * for controlling the hardware. The hardware may still be in process
+ * of transmitting another character, therefore this function may block
+ * for a short amount of time. This function uses the get_current()
+ * call to determine which port is selected.
+ */
+void serial_putc(const char c)
+{
+ get_current()->putc(c);
+}
+
+/**
+ * serial_puts() - Output string via currently selected serial port
+ * @s: Zero-terminated string to be output from the serial port.
+ *
+ * This function outputs a zero-terminated string via currently
+ * selected serial port. This function behaves as an accelerator
+ * in case the hardware can queue multiple characters for transfer.
+ * The whole string that is to be output is available to the function
+ * implementing the hardware manipulation. Transmitting the whole
+ * string may take some time, thus this function may block for some
+ * amount of time. This function uses the get_current() call to
+ * determine which port is selected.
+ */
+void serial_puts(const char *s)
+{
+ get_current()->puts(s);
+}
+
+/**
+ * default_serial_puts() - Output string by calling serial_putc() in loop
+ * @s: Zero-terminated string to be output from the serial port.
+ *
+ * This function outputs a zero-terminated string by calling serial_putc()
+ * in a loop. Most drivers do not support queueing more than one byte for
+ * transfer, thus this function precisely implements their serial_puts().
+ *
+ * To optimize the number of get_current() calls, this function only
+ * calls get_current() once and then directly accesses the putc() call
+ * of the &struct serial_device .
+ */
+void default_serial_puts(const char *s)
+{
+ struct serial_device *dev = get_current();
+ while (*s)
+ dev->putc(*s++);
+}
+
+#if CONFIG_POST & CONFIG_SYS_POST_UART
+static const int bauds[] = CONFIG_SYS_BAUDRATE_TABLE;
+
+/**
+ * uart_post_test() - Test the currently selected serial port using POST
+ * @flags: POST framework flags
+ *
+ * Do a loopback test of the currently selected serial port. This
+ * function is only useful in the context of the POST testing framwork.
+ * The serial port is first configured into loopback mode and then
+ * characters are sent through it.
+ *
+ * Returns 0 on success, value otherwise.
+ */
+/* Mark weak until post/cpu/.../uart.c migrate over */
+__weak
+int uart_post_test(int flags)
+{
+ unsigned char c;
+ int ret, saved_baud, b;
+ struct serial_device *saved_dev, *s;
+
+ /* Save current serial state */
+ ret = 0;
+ saved_dev = serial_current;
+ saved_baud = gd->baudrate;
+
+ for (s = serial_devices; s; s = s->next) {
+ /* If this driver doesn't support loop back, skip it */
+ if (!s->loop)
+ continue;
+
+ /* Test the next device */
+ serial_current = s;
+
+ ret = serial_init();
+ if (ret)
+ goto done;
+
+ /* Consume anything that happens to be queued */
+ while (serial_tstc())
+ serial_getc();
+
+ /* Enable loop back */
+ s->loop(1);
+
+ /* Test every available baud rate */
+ for (b = 0; b < ARRAY_SIZE(bauds); ++b) {
+ gd->baudrate = bauds[b];
+ serial_setbrg();
+
+ /*
+ * Stick to printable chars to avoid issues:
+ * - terminal corruption
+ * - serial program reacting to sequences and sending
+ * back random extra data
+ * - most serial drivers add in extra chars (like \r\n)
+ */
+ for (c = 0x20; c < 0x7f; ++c) {
+ /* Send it out */
+ serial_putc(c);
+
+ /* Make sure it's the same one */
+ ret = (c != serial_getc());
+ if (ret) {
+ s->loop(0);
+ goto done;
+ }
+
+ /* Clean up the output in case it was sent */
+ serial_putc('\b');
+ ret = ('\b' != serial_getc());
+ if (ret) {
+ s->loop(0);
+ goto done;
+ }
+ }
+ }
+
+ /* Disable loop back */
+ s->loop(0);
+
+ /* XXX: There is no serial_stop() !? */
+ if (s->stop)
+ s->stop();
+ }
+
+ done:
+ /* Restore previous serial state */
+ serial_current = saved_dev;
+ gd->baudrate = saved_baud;
+ serial_reinit_all();
+ serial_setbrg();
+
+ return ret;
+}
+#endif
diff --git a/roms/u-boot/drivers/serial/serial_ar933x.c b/roms/u-boot/drivers/serial/serial_ar933x.c
new file mode 100644
index 000000000..da06bef97
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_ar933x.c
@@ -0,0 +1,243 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com>
+ */
+
+#include <common.h>
+#include <clock_legacy.h>
+#include <dm.h>
+#include <div64.h>
+#include <errno.h>
+#include <serial.h>
+#include <asm/io.h>
+#include <asm/addrspace.h>
+#include <asm/types.h>
+#include <dm/pinctrl.h>
+#include <linux/bitops.h>
+#include <mach/ar71xx_regs.h>
+
+#define AR933X_UART_DATA_REG 0x00
+#define AR933X_UART_CS_REG 0x04
+#define AR933X_UART_CLK_REG 0x08
+
+#define AR933X_UART_DATA_TX_RX_MASK 0xff
+#define AR933X_UART_DATA_RX_CSR BIT(8)
+#define AR933X_UART_DATA_TX_CSR BIT(9)
+#define AR933X_UART_CS_IF_MODE_S 2
+#define AR933X_UART_CS_IF_MODE_M 0x3
+#define AR933X_UART_CS_IF_MODE_DTE 1
+#define AR933X_UART_CS_IF_MODE_DCE 2
+#define AR933X_UART_CS_TX_RDY_ORIDE BIT(7)
+#define AR933X_UART_CS_RX_RDY_ORIDE BIT(8)
+#define AR933X_UART_CLK_STEP_M 0xffff
+#define AR933X_UART_CLK_SCALE_M 0xfff
+#define AR933X_UART_CLK_SCALE_S 16
+#define AR933X_UART_CLK_STEP_S 0
+
+struct ar933x_serial_priv {
+ void __iomem *regs;
+};
+
+/*
+ * Baudrate algorithm come from Linux/drivers/tty/serial/ar933x_uart.c
+ * baudrate = (clk / (scale + 1)) * (step * (1 / 2^17))
+ */
+static u32 ar933x_serial_get_baud(u32 clk, u32 scale, u32 step)
+{
+ u64 t;
+ u32 div;
+
+ div = (2 << 16) * (scale + 1);
+ t = clk;
+ t *= step;
+ t += (div / 2);
+ do_div(t, div);
+
+ return t;
+}
+
+static void ar933x_serial_get_scale_step(u32 clk, u32 baud,
+ u32 *scale, u32 *step)
+{
+ u32 tscale, baudrate;
+ long min_diff;
+
+ *scale = 0;
+ *step = 0;
+
+ min_diff = baud;
+ for (tscale = 0; tscale < AR933X_UART_CLK_SCALE_M; tscale++) {
+ u64 tstep;
+ int diff;
+
+ tstep = baud * (tscale + 1);
+ tstep *= (2 << 16);
+ do_div(tstep, clk);
+
+ if (tstep > AR933X_UART_CLK_STEP_M)
+ break;
+
+ baudrate = ar933x_serial_get_baud(clk, tscale, tstep);
+ diff = abs(baudrate - baud);
+ if (diff < min_diff) {
+ min_diff = diff;
+ *scale = tscale;
+ *step = tstep;
+ }
+ }
+}
+
+static int ar933x_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ struct ar933x_serial_priv *priv = dev_get_priv(dev);
+ u32 val, scale, step;
+
+ val = get_serial_clock();
+ ar933x_serial_get_scale_step(val, baudrate, &scale, &step);
+
+ val = (scale & AR933X_UART_CLK_SCALE_M)
+ << AR933X_UART_CLK_SCALE_S;
+ val |= (step & AR933X_UART_CLK_STEP_M)
+ << AR933X_UART_CLK_STEP_S;
+ writel(val, priv->regs + AR933X_UART_CLK_REG);
+
+ return 0;
+}
+
+static int ar933x_serial_putc(struct udevice *dev, const char c)
+{
+ struct ar933x_serial_priv *priv = dev_get_priv(dev);
+ u32 data;
+
+ data = readl(priv->regs + AR933X_UART_DATA_REG);
+ if (!(data & AR933X_UART_DATA_TX_CSR))
+ return -EAGAIN;
+
+ data = (u32)c | AR933X_UART_DATA_TX_CSR;
+ writel(data, priv->regs + AR933X_UART_DATA_REG);
+
+ return 0;
+}
+
+static int ar933x_serial_getc(struct udevice *dev)
+{
+ struct ar933x_serial_priv *priv = dev_get_priv(dev);
+ u32 data;
+
+ data = readl(priv->regs + AR933X_UART_DATA_REG);
+ if (!(data & AR933X_UART_DATA_RX_CSR))
+ return -EAGAIN;
+
+ writel(AR933X_UART_DATA_RX_CSR, priv->regs + AR933X_UART_DATA_REG);
+ return data & AR933X_UART_DATA_TX_RX_MASK;
+}
+
+static int ar933x_serial_pending(struct udevice *dev, bool input)
+{
+ struct ar933x_serial_priv *priv = dev_get_priv(dev);
+ u32 data;
+
+ data = readl(priv->regs + AR933X_UART_DATA_REG);
+ if (input)
+ return (data & AR933X_UART_DATA_RX_CSR) ? 1 : 0;
+ else
+ return (data & AR933X_UART_DATA_TX_CSR) ? 0 : 1;
+}
+
+static int ar933x_serial_probe(struct udevice *dev)
+{
+ struct ar933x_serial_priv *priv = dev_get_priv(dev);
+ fdt_addr_t addr;
+ u32 val;
+
+ addr = dev_read_addr(dev);
+ if (addr == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ priv->regs = map_physmem(addr, AR933X_UART_SIZE,
+ MAP_NOCACHE);
+
+ /*
+ * UART controller configuration:
+ * - no DMA
+ * - no interrupt
+ * - DCE mode
+ * - no flow control
+ * - set RX ready oride
+ * - set TX ready oride
+ */
+ val = (AR933X_UART_CS_IF_MODE_DCE << AR933X_UART_CS_IF_MODE_S) |
+ AR933X_UART_CS_TX_RDY_ORIDE | AR933X_UART_CS_RX_RDY_ORIDE;
+ writel(val, priv->regs + AR933X_UART_CS_REG);
+ return 0;
+}
+
+static const struct dm_serial_ops ar933x_serial_ops = {
+ .putc = ar933x_serial_putc,
+ .pending = ar933x_serial_pending,
+ .getc = ar933x_serial_getc,
+ .setbrg = ar933x_serial_setbrg,
+};
+
+static const struct udevice_id ar933x_serial_ids[] = {
+ { .compatible = "qca,ar9330-uart" },
+ { }
+};
+
+U_BOOT_DRIVER(serial_ar933x) = {
+ .name = "serial_ar933x",
+ .id = UCLASS_SERIAL,
+ .of_match = ar933x_serial_ids,
+ .priv_auto = sizeof(struct ar933x_serial_priv),
+ .probe = ar933x_serial_probe,
+ .ops = &ar933x_serial_ops,
+};
+
+#ifdef CONFIG_DEBUG_UART_AR933X
+
+#include <debug_uart.h>
+
+static inline void _debug_uart_init(void)
+{
+ void __iomem *regs = (void *)CONFIG_DEBUG_UART_BASE;
+ u32 val, scale, step;
+
+ /*
+ * UART controller configuration:
+ * - no DMA
+ * - no interrupt
+ * - DCE mode
+ * - no flow control
+ * - set RX ready oride
+ * - set TX ready oride
+ */
+ val = (AR933X_UART_CS_IF_MODE_DCE << AR933X_UART_CS_IF_MODE_S) |
+ AR933X_UART_CS_TX_RDY_ORIDE | AR933X_UART_CS_RX_RDY_ORIDE;
+ writel(val, regs + AR933X_UART_CS_REG);
+
+ ar933x_serial_get_scale_step(CONFIG_DEBUG_UART_CLOCK,
+ CONFIG_BAUDRATE, &scale, &step);
+
+ val = (scale & AR933X_UART_CLK_SCALE_M)
+ << AR933X_UART_CLK_SCALE_S;
+ val |= (step & AR933X_UART_CLK_STEP_M)
+ << AR933X_UART_CLK_STEP_S;
+ writel(val, regs + AR933X_UART_CLK_REG);
+}
+
+static inline void _debug_uart_putc(int c)
+{
+ void __iomem *regs = (void *)CONFIG_DEBUG_UART_BASE;
+ u32 data;
+
+ do {
+ data = readl(regs + AR933X_UART_DATA_REG);
+ } while (!(data & AR933X_UART_DATA_TX_CSR));
+
+ data = (u32)c | AR933X_UART_DATA_TX_CSR;
+ writel(data, regs + AR933X_UART_DATA_REG);
+}
+
+DEBUG_UART_FUNCS
+
+#endif
diff --git a/roms/u-boot/drivers/serial/serial_arc.c b/roms/u-boot/drivers/serial/serial_arc.c
new file mode 100644
index 000000000..8f3e4dd44
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_arc.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <serial.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct arc_serial_regs {
+ unsigned int id0;
+ unsigned int id1;
+ unsigned int id2;
+ unsigned int id3;
+ unsigned int data;
+ unsigned int status;
+ unsigned int baudl;
+ unsigned int baudh;
+};
+
+
+struct arc_serial_plat {
+ struct arc_serial_regs *reg;
+ unsigned int uartclk;
+};
+
+/* Bit definitions of STATUS register */
+#define UART_RXEMPTY (1 << 5)
+#define UART_OVERFLOW_ERR (1 << 1)
+#define UART_TXEMPTY (1 << 7)
+
+static int arc_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ struct arc_serial_plat *plat = dev_get_plat(dev);
+ struct arc_serial_regs *const regs = plat->reg;
+ int arc_console_baud = gd->cpu_clk / (baudrate * 4) - 1;
+
+ writeb(arc_console_baud & 0xff, &regs->baudl);
+ writeb((arc_console_baud & 0xff00) >> 8, &regs->baudh);
+
+ return 0;
+}
+
+static int arc_serial_putc(struct udevice *dev, const char c)
+{
+ struct arc_serial_plat *plat = dev_get_plat(dev);
+ struct arc_serial_regs *const regs = plat->reg;
+
+ while (!(readb(&regs->status) & UART_TXEMPTY))
+ ;
+
+ writeb(c, &regs->data);
+
+ return 0;
+}
+
+static int arc_serial_tstc(struct arc_serial_regs *const regs)
+{
+ return !(readb(&regs->status) & UART_RXEMPTY);
+}
+
+static int arc_serial_pending(struct udevice *dev, bool input)
+{
+ struct arc_serial_plat *plat = dev_get_plat(dev);
+ struct arc_serial_regs *const regs = plat->reg;
+ uint32_t status = readb(&regs->status);
+
+ if (input)
+ return status & UART_RXEMPTY ? 0 : 1;
+ else
+ return status & UART_TXEMPTY ? 0 : 1;
+}
+
+static int arc_serial_getc(struct udevice *dev)
+{
+ struct arc_serial_plat *plat = dev_get_plat(dev);
+ struct arc_serial_regs *const regs = plat->reg;
+
+ while (!arc_serial_tstc(regs))
+ ;
+
+ /* Check for overflow errors */
+ if (readb(&regs->status) & UART_OVERFLOW_ERR)
+ return 0;
+
+ return readb(&regs->data) & 0xFF;
+}
+
+static int arc_serial_probe(struct udevice *dev)
+{
+ return 0;
+}
+
+static const struct dm_serial_ops arc_serial_ops = {
+ .putc = arc_serial_putc,
+ .pending = arc_serial_pending,
+ .getc = arc_serial_getc,
+ .setbrg = arc_serial_setbrg,
+};
+
+static const struct udevice_id arc_serial_ids[] = {
+ { .compatible = "snps,arc-uart" },
+ { }
+};
+
+static int arc_serial_of_to_plat(struct udevice *dev)
+{
+ struct arc_serial_plat *plat = dev_get_plat(dev);
+ DECLARE_GLOBAL_DATA_PTR;
+
+ plat->reg = dev_read_addr_ptr(dev);
+ plat->uartclk = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
+ "clock-frequency", 0);
+
+ return 0;
+}
+
+U_BOOT_DRIVER(serial_arc) = {
+ .name = "serial_arc",
+ .id = UCLASS_SERIAL,
+ .of_match = arc_serial_ids,
+ .of_to_plat = arc_serial_of_to_plat,
+ .plat_auto = sizeof(struct arc_serial_plat),
+ .probe = arc_serial_probe,
+ .ops = &arc_serial_ops,
+};
+
+#ifdef CONFIG_DEBUG_ARC_SERIAL
+#include <debug_uart.h>
+
+static inline void _debug_uart_init(void)
+{
+ struct arc_serial_regs *regs = (struct arc_serial_regs *)CONFIG_DEBUG_UART_BASE;
+ int arc_console_baud = CONFIG_DEBUG_UART_CLOCK / (CONFIG_BAUDRATE * 4) - 1;
+
+ writeb(arc_console_baud & 0xff, &regs->baudl);
+ writeb((arc_console_baud & 0xff00) >> 8, &regs->baudh);
+}
+
+static inline void _debug_uart_putc(int c)
+{
+ struct arc_serial_regs *regs = (struct arc_serial_regs *)CONFIG_DEBUG_UART_BASE;
+
+ while (!(readb(&regs->status) & UART_TXEMPTY))
+ ;
+
+ writeb(c, &regs->data);
+}
+
+DEBUG_UART_FUNCS
+
+#endif
diff --git a/roms/u-boot/drivers/serial/serial_bcm283x_mu.c b/roms/u-boot/drivers/serial/serial_bcm283x_mu.c
new file mode 100644
index 000000000..58fa722b4
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_bcm283x_mu.c
@@ -0,0 +1,204 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2016 Stephen Warren <swarren@wwwdotorg.org>
+ *
+ * Derived from pl01x code:
+ *
+ * (C) Copyright 2000
+ * Rob Taylor, Flying Pig Systems. robt@flyingpig.com.
+ *
+ * (C) Copyright 2004
+ * ARM Ltd.
+ * Philippe Robin, <philippe.robin@arm.com>
+ */
+
+/* Simple U-Boot driver for the BCM283x mini UART */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <watchdog.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <serial.h>
+#include <dm/platform_data/serial_bcm283x_mu.h>
+#include <dm/pinctrl.h>
+#include <linux/bitops.h>
+#include <linux/compiler.h>
+
+struct bcm283x_mu_regs {
+ u32 io;
+ u32 iir;
+ u32 ier;
+ u32 lcr;
+ u32 mcr;
+ u32 lsr;
+ u32 msr;
+ u32 scratch;
+ u32 cntl;
+ u32 stat;
+ u32 baud;
+};
+
+#define BCM283X_MU_LCR_DATA_SIZE_8 3
+
+#define BCM283X_MU_LSR_TX_IDLE BIT(6)
+/* This actually means not full, but is named not empty in the docs */
+#define BCM283X_MU_LSR_TX_EMPTY BIT(5)
+#define BCM283X_MU_LSR_RX_READY BIT(0)
+
+struct bcm283x_mu_priv {
+ struct bcm283x_mu_regs *regs;
+};
+
+static int bcm283x_mu_serial_getc(struct udevice *dev);
+
+static int bcm283x_mu_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ struct bcm283x_mu_serial_plat *plat = dev_get_plat(dev);
+ struct bcm283x_mu_priv *priv = dev_get_priv(dev);
+ struct bcm283x_mu_regs *regs = priv->regs;
+ u32 divider;
+
+ if (plat->skip_init)
+ goto out;
+
+ divider = plat->clock / (baudrate * 8);
+
+ writel(BCM283X_MU_LCR_DATA_SIZE_8, &regs->lcr);
+ writel(divider - 1, &regs->baud);
+
+out:
+ /* Flush the RX queue - all data in there is bogus */
+ while (bcm283x_mu_serial_getc(dev) != -EAGAIN) ;
+
+ return 0;
+}
+
+static int bcm283x_mu_serial_getc(struct udevice *dev)
+{
+ struct bcm283x_mu_priv *priv = dev_get_priv(dev);
+ struct bcm283x_mu_regs *regs = priv->regs;
+ u32 data;
+
+ /* Wait until there is data in the FIFO */
+ if (!(readl(&regs->lsr) & BCM283X_MU_LSR_RX_READY))
+ return -EAGAIN;
+
+ data = readl(&regs->io);
+
+ return (int)data;
+}
+
+static int bcm283x_mu_serial_putc(struct udevice *dev, const char data)
+{
+ struct bcm283x_mu_priv *priv = dev_get_priv(dev);
+ struct bcm283x_mu_regs *regs = priv->regs;
+
+ /* Wait until there is space in the FIFO */
+ if (!(readl(&regs->lsr) & BCM283X_MU_LSR_TX_EMPTY))
+ return -EAGAIN;
+
+ /* Send the character */
+ writel(data, &regs->io);
+
+ return 0;
+}
+
+static int bcm283x_mu_serial_pending(struct udevice *dev, bool input)
+{
+ struct bcm283x_mu_priv *priv = dev_get_priv(dev);
+ struct bcm283x_mu_regs *regs = priv->regs;
+ unsigned int lsr;
+
+ lsr = readl(&regs->lsr);
+
+ if (input) {
+ WATCHDOG_RESET();
+ return (lsr & BCM283X_MU_LSR_RX_READY) ? 1 : 0;
+ } else {
+ return (lsr & BCM283X_MU_LSR_TX_IDLE) ? 0 : 1;
+ }
+}
+
+static const struct dm_serial_ops bcm283x_mu_serial_ops = {
+ .putc = bcm283x_mu_serial_putc,
+ .pending = bcm283x_mu_serial_pending,
+ .getc = bcm283x_mu_serial_getc,
+ .setbrg = bcm283x_mu_serial_setbrg,
+};
+
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+static const struct udevice_id bcm283x_mu_serial_id[] = {
+ {.compatible = "brcm,bcm2835-aux-uart"},
+ {}
+};
+
+/*
+ * Check if this serial device is muxed
+ *
+ * The serial device will only work properly if it has been muxed to the serial
+ * pins by firmware. Check whether that happened here.
+ *
+ * @return true if serial device is muxed, false if not
+ */
+static bool bcm283x_is_serial_muxed(void)
+{
+ int serial_gpio = 15;
+ struct udevice *dev;
+
+ if (uclass_first_device(UCLASS_PINCTRL, &dev) || !dev)
+ return false;
+
+ if (pinctrl_get_gpio_mux(dev, 0, serial_gpio) != BCM2835_GPIO_ALT5)
+ return false;
+
+ return true;
+}
+
+static int bcm283x_mu_serial_probe(struct udevice *dev)
+{
+ struct bcm283x_mu_serial_plat *plat = dev_get_plat(dev);
+ struct bcm283x_mu_priv *priv = dev_get_priv(dev);
+ fdt_addr_t addr;
+
+ /* Don't spawn the device if it's not muxed */
+ if (!bcm283x_is_serial_muxed())
+ return -ENODEV;
+
+ /*
+ * Read the ofdata here rather than in an of_to_plat() method
+ * since we need the soc simple-bus to be probed so that the 'ranges'
+ * property is used.
+ */
+ addr = dev_read_addr(dev);
+ if (addr == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ plat->base = addr;
+ plat->clock = dev_read_u32_default(dev, "clock", 1);
+
+ /*
+ * TODO: Reinitialization doesn't always work for now, just skip
+ * init always - we know we're already initialized
+ */
+ plat->skip_init = true;
+
+ priv->regs = (struct bcm283x_mu_regs *)plat->base;
+
+ return 0;
+}
+#endif
+
+U_BOOT_DRIVER(serial_bcm283x_mu) = {
+ .name = "serial_bcm283x_mu",
+ .id = UCLASS_SERIAL,
+ .of_match = of_match_ptr(bcm283x_mu_serial_id),
+ .plat_auto = sizeof(struct bcm283x_mu_serial_plat),
+ .probe = bcm283x_mu_serial_probe,
+ .ops = &bcm283x_mu_serial_ops,
+#if !CONFIG_IS_ENABLED(OF_CONTROL) || CONFIG_IS_ENABLED(OF_BOARD)
+ .flags = DM_FLAG_PRE_RELOC,
+#endif
+ .priv_auto = sizeof(struct bcm283x_mu_priv),
+};
diff --git a/roms/u-boot/drivers/serial/serial_bcm283x_pl011.c b/roms/u-boot/drivers/serial/serial_bcm283x_pl011.c
new file mode 100644
index 000000000..2d2e97031
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_bcm283x_pl011.c
@@ -0,0 +1,101 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2018 Alexander Graf <agraf@suse.de>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/gpio.h>
+#include <dm/pinctrl.h>
+#include <dm/platform_data/serial_pl01x.h>
+#include <serial.h>
+#include "serial_pl01x_internal.h"
+
+/*
+ * Check if this serial device is muxed
+ *
+ * The serial device will only work properly if it has been muxed to the serial
+ * pins by firmware. Check whether that happened here.
+ *
+ * @return true if serial device is muxed, false if not
+ */
+static bool bcm283x_is_serial_muxed(void)
+{
+ int serial_gpio = 15;
+ struct udevice *dev;
+
+ if (uclass_first_device(UCLASS_PINCTRL, &dev) || !dev)
+ return false;
+
+ if (pinctrl_get_gpio_mux(dev, 0, serial_gpio) != BCM2835_GPIO_ALT0)
+ return false;
+
+ return true;
+}
+
+static int bcm283x_pl011_serial_probe(struct udevice *dev)
+{
+ struct pl01x_serial_plat *plat = dev_get_plat(dev);
+ int ret;
+
+ /* Don't spawn the device if it's not muxed */
+ if (!bcm283x_is_serial_muxed())
+ return -ENODEV;
+
+ /*
+ * Read the ofdata here rather than in an of_to_plat() method
+ * since we need the soc simple-bus to be probed so that the 'ranges'
+ * property is used.
+ */
+ ret = pl01x_serial_of_to_plat(dev);
+ if (ret)
+ return ret;
+
+ /*
+ * TODO: Reinitialization doesn't always work for now, just skip
+ * init always - we know we're already initialized
+ */
+ plat->skip_init = true;
+
+ return pl01x_serial_probe(dev);
+}
+
+static int bcm283x_pl011_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ int r;
+
+ r = pl01x_serial_setbrg(dev, baudrate);
+
+ /*
+ * We may have been muxed to a bogus line before. Drain the RX
+ * queue so we start at a clean slate.
+ */
+ while (pl01x_serial_getc(dev) != -EAGAIN) ;
+
+ return r;
+}
+
+static const struct dm_serial_ops bcm283x_pl011_serial_ops = {
+ .putc = pl01x_serial_putc,
+ .pending = pl01x_serial_pending,
+ .getc = pl01x_serial_getc,
+ .setbrg = bcm283x_pl011_serial_setbrg,
+};
+
+static const struct udevice_id bcm283x_pl011_serial_id[] = {
+ {.compatible = "brcm,bcm2835-pl011", .data = TYPE_PL011},
+ {}
+};
+
+U_BOOT_DRIVER(bcm283x_pl011_uart) = {
+ .name = "bcm283x_pl011",
+ .id = UCLASS_SERIAL,
+ .of_match = of_match_ptr(bcm283x_pl011_serial_id),
+ .probe = bcm283x_pl011_serial_probe,
+ .plat_auto = sizeof(struct pl01x_serial_plat),
+ .ops = &bcm283x_pl011_serial_ops,
+#if !CONFIG_IS_ENABLED(OF_CONTROL) || CONFIG_IS_ENABLED(OF_BOARD)
+ .flags = DM_FLAG_PRE_RELOC,
+#endif
+ .priv_auto = sizeof(struct pl01x_priv),
+};
diff --git a/roms/u-boot/drivers/serial/serial_bcm6345.c b/roms/u-boot/drivers/serial/serial_bcm6345.c
new file mode 100644
index 000000000..f08e91ff3
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_bcm6345.c
@@ -0,0 +1,296 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
+ *
+ * Derived from linux/drivers/tty/serial/bcm63xx_uart.c:
+ * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
+ */
+
+#include <clk.h>
+#include <dm.h>
+#include <debug_uart.h>
+#include <errno.h>
+#include <malloc.h>
+#include <serial.h>
+#include <asm/io.h>
+#include <asm/types.h>
+
+/* UART Control register */
+#define UART_CTL_REG 0x0
+#define UART_CTL_RXTIMEOUT_MASK 0x1f
+#define UART_CTL_RXTIMEOUT_5 0x5
+#define UART_CTL_RSTRXFIFO_SHIFT 6
+#define UART_CTL_RSTRXFIFO_MASK (1 << UART_CTL_RSTRXFIFO_SHIFT)
+#define UART_CTL_RSTTXFIFO_SHIFT 7
+#define UART_CTL_RSTTXFIFO_MASK (1 << UART_CTL_RSTTXFIFO_SHIFT)
+#define UART_CTL_STOPBITS_SHIFT 8
+#define UART_CTL_STOPBITS_MASK (0xf << UART_CTL_STOPBITS_SHIFT)
+#define UART_CTL_STOPBITS_1 (0x7 << UART_CTL_STOPBITS_SHIFT)
+#define UART_CTL_BITSPERSYM_SHIFT 12
+#define UART_CTL_BITSPERSYM_MASK (0x3 << UART_CTL_BITSPERSYM_SHIFT)
+#define UART_CTL_BITSPERSYM_8 (0x3 << UART_CTL_BITSPERSYM_SHIFT)
+#define UART_CTL_XMITBRK_SHIFT 14
+#define UART_CTL_XMITBRK_MASK (1 << UART_CTL_XMITBRK_SHIFT)
+#define UART_CTL_RSVD_SHIFT 15
+#define UART_CTL_RSVD_MASK (1 << UART_CTL_RSVD_SHIFT)
+#define UART_CTL_RXPAREVEN_SHIFT 16
+#define UART_CTL_RXPAREVEN_MASK (1 << UART_CTL_RXPAREVEN_SHIFT)
+#define UART_CTL_RXPAREN_SHIFT 17
+#define UART_CTL_RXPAREN_MASK (1 << UART_CTL_RXPAREN_SHIFT)
+#define UART_CTL_TXPAREVEN_SHIFT 18
+#define UART_CTL_TXPAREVEN_MASK (1 << UART_CTL_TXPAREVEN_SHIFT)
+#define UART_CTL_TXPAREN_SHIFT 19
+#define UART_CTL_TXPAREN_MASK (1 << UART_CTL_TXPAREN_SHIFT)
+#define UART_CTL_LOOPBACK_SHIFT 20
+#define UART_CTL_LOOPBACK_MASK (1 << UART_CTL_LOOPBACK_SHIFT)
+#define UART_CTL_RXEN_SHIFT 21
+#define UART_CTL_RXEN_MASK (1 << UART_CTL_RXEN_SHIFT)
+#define UART_CTL_TXEN_SHIFT 22
+#define UART_CTL_TXEN_MASK (1 << UART_CTL_TXEN_SHIFT)
+#define UART_CTL_BRGEN_SHIFT 23
+#define UART_CTL_BRGEN_MASK (1 << UART_CTL_BRGEN_SHIFT)
+
+/* UART Baudword register */
+#define UART_BAUD_REG 0x4
+
+/* UART FIFO Config register */
+#define UART_FIFO_CFG_REG 0x8
+#define UART_FIFO_CFG_RX_SHIFT 8
+#define UART_FIFO_CFG_RX_MASK (0xf << UART_FIFO_CFG_RX_SHIFT)
+#define UART_FIFO_CFG_RX_4 (0x4 << UART_FIFO_CFG_RX_SHIFT)
+#define UART_FIFO_CFG_TX_SHIFT 12
+#define UART_FIFO_CFG_TX_MASK (0xf << UART_FIFO_CFG_TX_SHIFT)
+#define UART_FIFO_CFG_TX_4 (0x4 << UART_FIFO_CFG_TX_SHIFT)
+
+/* UART Interrupt register */
+#define UART_IR_REG 0x10
+#define UART_IR_STAT(x) (1 << (x))
+#define UART_IR_TXEMPTY 5
+#define UART_IR_RXOVER 7
+#define UART_IR_RXNOTEMPTY 11
+
+/* UART FIFO register */
+#define UART_FIFO_REG 0x14
+#define UART_FIFO_VALID_MASK 0xff
+#define UART_FIFO_FRAMEERR_SHIFT 8
+#define UART_FIFO_FRAMEERR_MASK (1 << UART_FIFO_FRAMEERR_SHIFT)
+#define UART_FIFO_PARERR_SHIFT 9
+#define UART_FIFO_PARERR_MASK (1 << UART_FIFO_PARERR_SHIFT)
+#define UART_FIFO_BRKDET_SHIFT 10
+#define UART_FIFO_BRKDET_MASK (1 << UART_FIFO_BRKDET_SHIFT)
+#define UART_FIFO_ANYERR_MASK (UART_FIFO_FRAMEERR_MASK | \
+ UART_FIFO_PARERR_MASK | \
+ UART_FIFO_BRKDET_MASK)
+
+struct bcm6345_serial_priv {
+ void __iomem *base;
+ ulong uartclk;
+};
+
+/* enable rx & tx operation on uart */
+static void bcm6345_serial_enable(void __iomem *base)
+{
+ setbits_32(base + UART_CTL_REG, UART_CTL_BRGEN_MASK |
+ UART_CTL_TXEN_MASK | UART_CTL_RXEN_MASK);
+}
+
+/* disable rx & tx operation on uart */
+static void bcm6345_serial_disable(void __iomem *base)
+{
+ clrbits_32(base + UART_CTL_REG, UART_CTL_BRGEN_MASK |
+ UART_CTL_TXEN_MASK | UART_CTL_RXEN_MASK);
+}
+
+/* clear all unread data in rx fifo and unsent data in tx fifo */
+static void bcm6345_serial_flush(void __iomem *base)
+{
+ /* empty rx and tx fifo */
+ setbits_32(base + UART_CTL_REG, UART_CTL_RSTRXFIFO_MASK |
+ UART_CTL_RSTTXFIFO_MASK);
+
+ /* read any pending char to make sure all irq status are cleared */
+ readl(base + UART_FIFO_REG);
+}
+
+static int bcm6345_serial_init(void __iomem *base, ulong clk, u32 baudrate)
+{
+ u32 val;
+
+ /* mask all irq and flush port */
+ bcm6345_serial_disable(base);
+ bcm6345_serial_flush(base);
+
+ /* set uart control config */
+ clrsetbits_32(base + UART_CTL_REG,
+ /* clear rx timeout */
+ UART_CTL_RXTIMEOUT_MASK |
+ /* clear stop bits */
+ UART_CTL_STOPBITS_MASK |
+ /* clear bits per symbol */
+ UART_CTL_BITSPERSYM_MASK |
+ /* clear xmit break */
+ UART_CTL_XMITBRK_MASK |
+ /* clear reserved bit */
+ UART_CTL_RSVD_MASK |
+ /* disable parity */
+ UART_CTL_RXPAREN_MASK |
+ UART_CTL_TXPAREN_MASK |
+ /* disable loopback */
+ UART_CTL_LOOPBACK_MASK,
+ /* set timeout to 5 */
+ UART_CTL_RXTIMEOUT_5 |
+ /* set 8 bits/symbol */
+ UART_CTL_BITSPERSYM_8 |
+ /* set 1 stop bit */
+ UART_CTL_STOPBITS_1 |
+ /* set parity to even */
+ UART_CTL_RXPAREVEN_MASK |
+ UART_CTL_TXPAREVEN_MASK);
+
+ /* set uart fifo config */
+ clrsetbits_32(base + UART_FIFO_CFG_REG,
+ /* clear fifo config */
+ UART_FIFO_CFG_RX_MASK |
+ UART_FIFO_CFG_TX_MASK,
+ /* set fifo config to 4 */
+ UART_FIFO_CFG_RX_4 |
+ UART_FIFO_CFG_TX_4);
+
+ /* set baud rate */
+ val = ((clk / baudrate) >> 4);
+ if (val & 0x1)
+ val = (val >> 1);
+ else
+ val = (val >> 1) - 1;
+ writel(val, base + UART_BAUD_REG);
+
+ /* clear interrupts */
+ writel(0, base + UART_IR_REG);
+
+ /* enable uart */
+ bcm6345_serial_enable(base);
+
+ return 0;
+}
+
+static int bcm6345_serial_pending(struct udevice *dev, bool input)
+{
+ struct bcm6345_serial_priv *priv = dev_get_priv(dev);
+ u32 val = readl(priv->base + UART_IR_REG);
+
+ if (input)
+ return !!(val & UART_IR_STAT(UART_IR_RXNOTEMPTY));
+ else
+ return !(val & UART_IR_STAT(UART_IR_TXEMPTY));
+}
+
+static int bcm6345_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ struct bcm6345_serial_priv *priv = dev_get_priv(dev);
+
+ return bcm6345_serial_init(priv->base, priv->uartclk, baudrate);
+}
+
+static int bcm6345_serial_putc(struct udevice *dev, const char ch)
+{
+ struct bcm6345_serial_priv *priv = dev_get_priv(dev);
+ u32 val;
+
+ val = readl(priv->base + UART_IR_REG);
+ if (!(val & UART_IR_STAT(UART_IR_TXEMPTY)))
+ return -EAGAIN;
+
+ writel(ch, priv->base + UART_FIFO_REG);
+
+ return 0;
+}
+
+static int bcm6345_serial_getc(struct udevice *dev)
+{
+ struct bcm6345_serial_priv *priv = dev_get_priv(dev);
+ u32 val;
+
+ val = readl(priv->base + UART_IR_REG);
+ if (val & UART_IR_STAT(UART_IR_RXOVER))
+ setbits_32(priv->base + UART_CTL_REG, UART_CTL_RSTRXFIFO_MASK);
+ if (!(val & UART_IR_STAT(UART_IR_RXNOTEMPTY)))
+ return -EAGAIN;
+
+ val = readl(priv->base + UART_FIFO_REG);
+ if (val & UART_FIFO_ANYERR_MASK)
+ return -EAGAIN;
+
+ return val & UART_FIFO_VALID_MASK;
+}
+
+static int bcm6345_serial_probe(struct udevice *dev)
+{
+ struct bcm6345_serial_priv *priv = dev_get_priv(dev);
+ struct clk clk;
+ int ret;
+
+ /* get address */
+ priv->base = dev_remap_addr(dev);
+ if (!priv->base)
+ return -EINVAL;
+
+ /* get clock rate */
+ ret = clk_get_by_index(dev, 0, &clk);
+ if (ret < 0)
+ return ret;
+ priv->uartclk = clk_get_rate(&clk);
+ clk_free(&clk);
+
+ /* initialize serial */
+ return bcm6345_serial_init(priv->base, priv->uartclk, CONFIG_BAUDRATE);
+}
+
+static const struct dm_serial_ops bcm6345_serial_ops = {
+ .putc = bcm6345_serial_putc,
+ .pending = bcm6345_serial_pending,
+ .getc = bcm6345_serial_getc,
+ .setbrg = bcm6345_serial_setbrg,
+};
+
+static const struct udevice_id bcm6345_serial_ids[] = {
+ { .compatible = "brcm,bcm6345-uart" },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(bcm6345_serial) = {
+ .name = "bcm6345-uart",
+ .id = UCLASS_SERIAL,
+ .of_match = bcm6345_serial_ids,
+ .probe = bcm6345_serial_probe,
+ .priv_auto = sizeof(struct bcm6345_serial_priv),
+ .ops = &bcm6345_serial_ops,
+};
+
+#ifdef CONFIG_DEBUG_UART_BCM6345
+static inline void _debug_uart_init(void)
+{
+ void __iomem *base = (void __iomem *)CONFIG_DEBUG_UART_BASE;
+
+ bcm6345_serial_init(base, CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE);
+}
+
+static inline void wait_xfered(void __iomem *base)
+{
+ do {
+ u32 val = readl(base + UART_IR_REG);
+ if (val & UART_IR_STAT(UART_IR_TXEMPTY))
+ break;
+ } while (1);
+}
+
+static inline void _debug_uart_putc(int ch)
+{
+ void __iomem *base = (void __iomem *)CONFIG_DEBUG_UART_BASE;
+
+ wait_xfered(base);
+ writel(ch, base + UART_FIFO_REG);
+ wait_xfered(base);
+}
+
+DEBUG_UART_FUNCS
+#endif
diff --git a/roms/u-boot/drivers/serial/serial_coreboot.c b/roms/u-boot/drivers/serial/serial_coreboot.c
new file mode 100644
index 000000000..de09c8681
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_coreboot.c
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * UART support for U-Boot when launched from Coreboot
+ *
+ * Copyright 2019 Google LLC
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <ns16550.h>
+#include <serial.h>
+#include <asm/cb_sysinfo.h>
+
+static int coreboot_of_to_plat(struct udevice *dev)
+{
+ struct ns16550_plat *plat = dev_get_plat(dev);
+ struct cb_serial *cb_info = lib_sysinfo.serial;
+
+ plat->base = cb_info->baseaddr;
+ plat->reg_shift = cb_info->regwidth == 4 ? 2 : 0;
+ plat->reg_width = cb_info->regwidth;
+ plat->clock = cb_info->input_hertz;
+ plat->fcr = UART_FCR_DEFVAL;
+ plat->flags = 0;
+ if (cb_info->type == CB_SERIAL_TYPE_IO_MAPPED)
+ plat->flags |= NS16550_FLAG_IO;
+
+ return 0;
+}
+
+static const struct udevice_id coreboot_serial_ids[] = {
+ { .compatible = "coreboot-serial" },
+ { },
+};
+
+U_BOOT_DRIVER(coreboot_uart) = {
+ .name = "coreboot_uart",
+ .id = UCLASS_SERIAL,
+ .of_match = coreboot_serial_ids,
+ .priv_auto = sizeof(struct ns16550),
+ .plat_auto = sizeof(struct ns16550_plat),
+ .of_to_plat = coreboot_of_to_plat,
+ .probe = ns16550_serial_probe,
+ .ops = &ns16550_serial_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/roms/u-boot/drivers/serial/serial_cortina.c b/roms/u-boot/drivers/serial/serial_cortina.c
new file mode 100644
index 000000000..6dc81a775
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_cortina.c
@@ -0,0 +1,165 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2020 Cortina-Access Ltd.
+ * Common UART Driver for Cortina Access CAxxxx line of SoCs
+ *
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <watchdog.h>
+#include <asm/io.h>
+#include <serial.h>
+#include <linux/bitops.h>
+#include <linux/compiler.h>
+
+/* Register definitions */
+#define UCFG 0x00 /* UART config register */
+#define UFC 0x04 /* Flow Control */
+#define URX_SAMPLE 0x08 /* UART RX Sample register */
+#define URT_TUNE 0x0C /* Fine tune of UART clk */
+#define UTX_DATA 0x10 /* UART TX Character data */
+#define URX_DATA 0x14 /* UART RX Character data */
+#define UINFO 0x18 /* UART Info */
+#define UINT_EN0 0x1C /* UART Interrupt enable 0 */
+#define UINT_EN1 0x20 /* UART Interrupt enable 1 */
+#define UINT0 0x24 /* UART Interrupt 0 setting/clearing */
+#define UINT1 0x28 /* UART Interrupt 1 setting/clearing */
+#define UINT_STAT 0x2C /* UART Interrupt Status */
+
+/* UART Control Register Bit Fields */
+#define UCFG_BAUD_COUNT_MASK 0xFFFFFF00
+#define UCFG_BAUD_COUNT(x) ((x << 8) & UCFG_BAUD_COUNT_MASK)
+#define UCFG_EN BIT(7)
+#define UCFG_RX_EN BIT(6)
+#define UCFG_TX_EN BIT(5)
+#define UCFG_PARITY_EN BIT(4)
+#define UCFG_PARITY_SEL BIT(3)
+#define UCFG_2STOP_BIT BIT(2)
+#define UCFG_CNT1 BIT(1)
+#define UCFG_CNT0 BIT(0)
+#define UCFG_CHAR_5 0
+#define UCFG_CHAR_6 1
+#define UCFG_CHAR_7 2
+#define UCFG_CHAR_8 3
+
+#define UINFO_TX_FIFO_EMPTY BIT(3)
+#define UINFO_TX_FIFO_FULL BIT(2)
+#define UINFO_RX_FIFO_EMPTY BIT(1)
+#define UINFO_RX_FIFO_FULL BIT(0)
+
+#define UINT_RX_NON_EMPTY BIT(6)
+#define UINT_TX_EMPTY BIT(5)
+#define UINT_RX_UNDERRUN BIT(4)
+#define UINT_RX_OVERRUN BIT(3)
+#define UINT_RX_PARITY_ERR BIT(2)
+#define UINT_RX_STOP_ERR BIT(1)
+#define UINT_TX_OVERRUN BIT(0)
+#define UINT_MASK_ALL 0x7F
+
+struct ca_uart_priv {
+ void __iomem *base;
+};
+
+int ca_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ struct ca_uart_priv *priv = dev_get_priv(dev);
+ unsigned int uart_ctrl, baud, sample;
+
+ baud = CORTINA_UART_CLOCK / baudrate;
+
+ uart_ctrl = readl(priv->base + UCFG);
+ uart_ctrl &= ~UCFG_BAUD_COUNT_MASK;
+ uart_ctrl |= UCFG_BAUD_COUNT(baud);
+ writel(uart_ctrl, priv->base + UCFG);
+
+ sample = baud / 2;
+ sample = (sample < 7) ? 7 : sample;
+ writel(sample, priv->base + URX_SAMPLE);
+
+ return 0;
+}
+
+static int ca_serial_getc(struct udevice *dev)
+{
+ struct ca_uart_priv *priv = dev_get_priv(dev);
+ int ch;
+
+ ch = readl(priv->base + URX_DATA) & 0xFF;
+
+ return (int)ch;
+}
+
+static int ca_serial_putc(struct udevice *dev, const char ch)
+{
+ struct ca_uart_priv *priv = dev_get_priv(dev);
+ unsigned int status;
+
+ /* Retry if TX FIFO full */
+ status = readl(priv->base + UINFO);
+ if (status & UINFO_TX_FIFO_FULL)
+ return -EAGAIN;
+
+ writel(ch, priv->base + UTX_DATA);
+
+ return 0;
+}
+
+static int ca_serial_pending(struct udevice *dev, bool input)
+{
+ struct ca_uart_priv *priv = dev_get_priv(dev);
+ unsigned int status;
+
+ status = readl(priv->base + UINFO);
+
+ if (input)
+ return (status & UINFO_RX_FIFO_EMPTY) ? 0 : 1;
+ else
+ return (status & UINFO_TX_FIFO_FULL) ? 1 : 0;
+}
+
+static int ca_serial_probe(struct udevice *dev)
+{
+ struct ca_uart_priv *priv = dev_get_priv(dev);
+ u32 uart_ctrl;
+
+ /* Set data, parity and stop bits */
+ uart_ctrl = UCFG_EN | UCFG_TX_EN | UCFG_RX_EN | UCFG_CHAR_8;
+ writel(uart_ctrl, priv->base + UCFG);
+
+ return 0;
+}
+
+static int ca_serial_of_to_plat(struct udevice *dev)
+{
+ struct ca_uart_priv *priv = dev_get_priv(dev);
+
+ priv->base = dev_remap_addr_index(dev, 0);
+ if (!priv->base)
+ return -ENOENT;
+
+ return 0;
+}
+
+static const struct dm_serial_ops ca_serial_ops = {
+ .putc = ca_serial_putc,
+ .pending = ca_serial_pending,
+ .getc = ca_serial_getc,
+ .setbrg = ca_serial_setbrg,
+};
+
+static const struct udevice_id ca_serial_ids[] = {
+ {.compatible = "cortina,ca-uart"},
+ {}
+};
+
+U_BOOT_DRIVER(serial_cortina) = {
+ .name = "serial_cortina",
+ .id = UCLASS_SERIAL,
+ .of_match = ca_serial_ids,
+ .of_to_plat = ca_serial_of_to_plat,
+ .priv_auto = sizeof(struct ca_uart_priv),
+ .probe = ca_serial_probe,
+ .ops = &ca_serial_ops
+};
diff --git a/roms/u-boot/drivers/serial/serial_efi.c b/roms/u-boot/drivers/serial/serial_efi.c
new file mode 100644
index 000000000..33ddbd608
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_efi.c
@@ -0,0 +1,156 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <debug_uart.h>
+#include <dm.h>
+#include <efi.h>
+#include <efi_api.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <log.h>
+#include <linux/compiler.h>
+#include <asm/io.h>
+#include <serial.h>
+
+/* Information about the efi console */
+struct serial_efi_priv {
+ struct efi_simple_text_input_protocol *con_in;
+ struct efi_simple_text_output_protocol *con_out;
+ struct efi_input_key key;
+ bool have_key;
+};
+
+int serial_efi_setbrg(struct udevice *dev, int baudrate)
+{
+ return 0;
+}
+
+static int serial_efi_get_key(struct serial_efi_priv *priv)
+{
+ int ret;
+
+ if (priv->have_key)
+ return 0;
+ ret = priv->con_in->read_key_stroke(priv->con_in, &priv->key);
+ if (ret == EFI_NOT_READY)
+ return -EAGAIN;
+ else if (ret != EFI_SUCCESS)
+ return -EIO;
+
+ priv->have_key = true;
+
+ return 0;
+}
+
+static int serial_efi_getc(struct udevice *dev)
+{
+ struct serial_efi_priv *priv = dev_get_priv(dev);
+ int ret, ch;
+
+ ret = serial_efi_get_key(priv);
+ if (ret)
+ return ret;
+
+ priv->have_key = false;
+ ch = priv->key.unicode_char;
+
+ /*
+ * Unicode char 8 (for backspace) is never returned. Instead we get a
+ * key scan code of 8. Handle this so that backspace works correctly
+ * in the U-Boot command line.
+ */
+ if (!ch && priv->key.scan_code == 8)
+ ch = 8;
+ debug(" [%x %x %x] ", ch, priv->key.unicode_char, priv->key.scan_code);
+
+ return ch;
+}
+
+static int serial_efi_putc(struct udevice *dev, const char ch)
+{
+ struct serial_efi_priv *priv = dev_get_priv(dev);
+ uint16_t ucode[2];
+ int ret;
+
+ ucode[0] = ch;
+ ucode[1] = '\0';
+ ret = priv->con_out->output_string(priv->con_out, ucode);
+ if (ret)
+ return -EIO;
+
+ return 0;
+}
+
+static int serial_efi_pending(struct udevice *dev, bool input)
+{
+ struct serial_efi_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ /* We assume that EFI will stall if its output buffer fills up */
+ if (!input)
+ return 0;
+
+ ret = serial_efi_get_key(priv);
+ if (ret == -EAGAIN)
+ return 0;
+ else if (ret)
+ return ret;
+
+ return 1;
+}
+
+/*
+ * There is nothing to init here since the EFI console is already running by
+ * the time we enter U-Boot.
+ */
+static inline void _debug_uart_init(void)
+{
+}
+
+static inline void _debug_uart_putc(int ch)
+{
+ struct efi_system_table *sys_table = efi_get_sys_table();
+ uint16_t ucode[2];
+
+ ucode[0] = ch;
+ ucode[1] = '\0';
+ sys_table->con_out->output_string(sys_table->con_out, ucode);
+}
+
+DEBUG_UART_FUNCS
+
+static int serial_efi_probe(struct udevice *dev)
+{
+ struct efi_system_table *table = efi_get_sys_table();
+ struct serial_efi_priv *priv = dev_get_priv(dev);
+
+ priv->con_in = table->con_in;
+ priv->con_out = table->con_out;
+
+ return 0;
+}
+
+static const struct dm_serial_ops serial_efi_ops = {
+ .putc = serial_efi_putc,
+ .getc = serial_efi_getc,
+ .pending = serial_efi_pending,
+ .setbrg = serial_efi_setbrg,
+};
+
+static const struct udevice_id serial_efi_ids[] = {
+ { .compatible = "efi,uart" },
+ { }
+};
+
+U_BOOT_DRIVER(serial_efi) = {
+ .name = "serial_efi",
+ .id = UCLASS_SERIAL,
+ .of_match = serial_efi_ids,
+ .priv_auto = sizeof(struct serial_efi_priv),
+ .probe = serial_efi_probe,
+ .ops = &serial_efi_ops,
+};
diff --git a/roms/u-boot/drivers/serial/serial_intel_mid.c b/roms/u-boot/drivers/serial/serial_intel_mid.c
new file mode 100644
index 000000000..bbf19057c
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_intel_mid.c
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2017 Intel Corporation
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <ns16550.h>
+#include <serial.h>
+
+/*
+ * The UART clock is calculated as
+ *
+ * UART clock = XTAL * UART_MUL / UART_DIV
+ *
+ * The baudrate is calculated as
+ *
+ * baud rate = UART clock / UART_PS / DLAB
+ */
+#define UART_PS 0x30
+#define UART_MUL 0x34
+#define UART_DIV 0x38
+
+static void mid_writel(struct ns16550_plat *plat, int offset, int value)
+{
+ unsigned char *addr;
+
+ offset *= 1 << plat->reg_shift;
+ addr = (unsigned char *)plat->base + offset;
+
+ writel(value, addr + plat->reg_offset);
+}
+
+static int mid_serial_probe(struct udevice *dev)
+{
+ struct ns16550_plat *plat = dev_get_plat(dev);
+
+ /*
+ * Initialize fractional divider correctly for Intel Edison
+ * platform.
+ *
+ * For backward compatibility we have to set initial DLAB value
+ * to 16 and speed to 115200 baud, where initial frequency is
+ * 29491200Hz, and XTAL frequency is 38.4MHz.
+ */
+ mid_writel(plat, UART_MUL, 96);
+ mid_writel(plat, UART_DIV, 125);
+ mid_writel(plat, UART_PS, 16);
+
+ return ns16550_serial_probe(dev);
+}
+
+static const struct udevice_id mid_serial_ids[] = {
+ { .compatible = "intel,mid-uart" },
+ {}
+};
+
+U_BOOT_DRIVER(serial_intel_mid) = {
+ .name = "serial_intel_mid",
+ .id = UCLASS_SERIAL,
+ .of_match = mid_serial_ids,
+ .of_to_plat = ns16550_serial_of_to_plat,
+ .plat_auto = sizeof(struct ns16550_plat),
+ .priv_auto = sizeof(struct ns16550),
+ .probe = mid_serial_probe,
+ .ops = &ns16550_serial_ops,
+};
diff --git a/roms/u-boot/drivers/serial/serial_linflexuart.c b/roms/u-boot/drivers/serial/serial_linflexuart.c
new file mode 100644
index 000000000..876a4baa9
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_linflexuart.c
@@ -0,0 +1,219 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2013-2016 Freescale Semiconductor, Inc.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <watchdog.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <serial.h>
+#include <linux/compiler.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/clock.h>
+
+#define US1_TDRE (1 << 7)
+#define US1_RDRF (1 << 5)
+#define UC2_TE (1 << 3)
+#define LINCR1_INIT (1 << 0)
+#define LINCR1_MME (1 << 4)
+#define LINCR1_BF (1 << 7)
+#define LINSR_LINS_INITMODE (0x00001000)
+#define LINSR_LINS_MASK (0x0000F000)
+#define UARTCR_UART (1 << 0)
+#define UARTCR_WL0 (1 << 1)
+#define UARTCR_PCE (1 << 2)
+#define UARTCR_PC0 (1 << 3)
+#define UARTCR_TXEN (1 << 4)
+#define UARTCR_RXEN (1 << 5)
+#define UARTCR_PC1 (1 << 6)
+#define UARTSR_DTF (1 << 1)
+#define UARTSR_DRF (1 << 2)
+#define UARTSR_RMB (1 << 9)
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static void _linflex_serial_setbrg(struct linflex_fsl *base, int baudrate)
+{
+ u32 clk = mxc_get_clock(MXC_UART_CLK);
+ u32 ibr, fbr;
+
+ if (!baudrate)
+ baudrate = CONFIG_BAUDRATE;
+
+ ibr = (u32) (clk / (16 * gd->baudrate));
+ fbr = (u32) (clk % (16 * gd->baudrate)) * 16;
+
+ __raw_writel(ibr, &base->linibrr);
+ __raw_writel(fbr, &base->linfbrr);
+}
+
+static int _linflex_serial_getc(struct linflex_fsl *base)
+{
+ char c;
+
+ if (!(__raw_readb(&base->uartsr) & UARTSR_DRF))
+ return -EAGAIN;
+
+ if (!(__raw_readl(&base->uartsr) & UARTSR_RMB))
+ return -EAGAIN;
+
+ c = __raw_readl(&base->bdrm);
+ __raw_writeb((__raw_readb(&base->uartsr) | (UARTSR_DRF | UARTSR_RMB)),
+ &base->uartsr);
+ return c;
+}
+
+static int _linflex_serial_putc(struct linflex_fsl *base, const char c)
+{
+ __raw_writeb(c, &base->bdrl);
+
+
+ if (!(__raw_readb(&base->uartsr) & UARTSR_DTF))
+ return -EAGAIN;
+
+ __raw_writeb((__raw_readb(&base->uartsr) | UARTSR_DTF), &base->uartsr);
+
+ return 0;
+}
+
+/*
+ * Initialise the serial port with the given baudrate. The settings
+ * are always 8 data bits, no parity, 1 stop bit, no start bits.
+ */
+static int _linflex_serial_init(struct linflex_fsl *base)
+{
+ volatile u32 ctrl;
+
+ /* set the Linflex in master mode amd activate by-pass filter */
+ ctrl = LINCR1_BF | LINCR1_MME;
+ __raw_writel(ctrl, &base->lincr1);
+
+ /* init mode */
+ ctrl |= LINCR1_INIT;
+ __raw_writel(ctrl, &base->lincr1);
+
+ /* waiting for init mode entry - TODO: add a timeout */
+ while ((__raw_readl(&base->linsr) & LINSR_LINS_MASK) !=
+ LINSR_LINS_INITMODE);
+
+ /* set UART bit to allow writing other bits */
+ __raw_writel(UARTCR_UART, &base->uartcr);
+
+ /* provide data bits, parity, stop bit, etc */
+ serial_setbrg();
+
+ /* 8 bit data, no parity, Tx and Rx enabled, UART mode */
+ __raw_writel(UARTCR_PC1 | UARTCR_RXEN | UARTCR_TXEN | UARTCR_PC0
+ | UARTCR_WL0 | UARTCR_UART, &base->uartcr);
+
+ ctrl = __raw_readl(&base->lincr1);
+ ctrl &= ~LINCR1_INIT;
+ __raw_writel(ctrl, &base->lincr1); /* end init mode */
+
+ return 0;
+}
+
+struct linflex_serial_plat {
+ struct linflex_fsl *base_addr;
+ u8 port_id; /* do we need this? */
+};
+
+struct linflex_serial_priv {
+ struct linflex_fsl *lfuart;
+};
+
+int linflex_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ struct linflex_serial_priv *priv = dev_get_priv(dev);
+
+ _linflex_serial_setbrg(priv->lfuart, baudrate);
+
+ return 0;
+}
+
+static int linflex_serial_getc(struct udevice *dev)
+{
+ struct linflex_serial_priv *priv = dev_get_priv(dev);
+
+ return _linflex_serial_getc(priv->lfuart);
+}
+
+static int linflex_serial_putc(struct udevice *dev, const char ch)
+{
+
+ struct linflex_serial_priv *priv = dev_get_priv(dev);
+
+ return _linflex_serial_putc(priv->lfuart, ch);
+}
+
+static int linflex_serial_pending(struct udevice *dev, bool input)
+{
+ struct linflex_serial_priv *priv = dev_get_priv(dev);
+ uint32_t uartsr = __raw_readl(&priv->lfuart->uartsr);
+
+ if (input)
+ return ((uartsr & UARTSR_DRF) && (uartsr & UARTSR_RMB)) ? 1 : 0;
+ else
+ return uartsr & UARTSR_DTF ? 0 : 1;
+}
+
+static void linflex_serial_init_internal(struct linflex_fsl *lfuart)
+{
+ _linflex_serial_init(lfuart);
+ _linflex_serial_setbrg(lfuart, CONFIG_BAUDRATE);
+ return;
+}
+
+static int linflex_serial_probe(struct udevice *dev)
+{
+ struct linflex_serial_plat *plat = dev_get_plat(dev);
+ struct linflex_serial_priv *priv = dev_get_priv(dev);
+
+ priv->lfuart = (struct linflex_fsl *)plat->base_addr;
+ linflex_serial_init_internal(priv->lfuart);
+
+ return 0;
+}
+
+static const struct dm_serial_ops linflex_serial_ops = {
+ .putc = linflex_serial_putc,
+ .pending = linflex_serial_pending,
+ .getc = linflex_serial_getc,
+ .setbrg = linflex_serial_setbrg,
+};
+
+U_BOOT_DRIVER(serial_linflex) = {
+ .name = "serial_linflex",
+ .id = UCLASS_SERIAL,
+ .probe = linflex_serial_probe,
+ .ops = &linflex_serial_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+ .priv_auto = sizeof(struct linflex_serial_priv),
+};
+
+#ifdef CONFIG_DEBUG_UART_LINFLEXUART
+
+#include <debug_uart.h>
+
+
+static inline void _debug_uart_init(void)
+{
+ struct linflex_fsl *base = (struct linflex_fsl *)CONFIG_DEBUG_UART_BASE;
+
+ linflex_serial_init_internal(base);
+}
+
+static inline void _debug_uart_putc(int ch)
+{
+ struct linflex_fsl *base = (struct linflex_fsl *)CONFIG_DEBUG_UART_BASE;
+
+ /* XXX: Is this OK? Should this use the non-DM version? */
+ _linflex_serial_putc(base, ch);
+}
+
+DEBUG_UART_FUNCS
+
+#endif /* CONFIG_DEBUG_UART_LINFLEXUART */
diff --git a/roms/u-boot/drivers/serial/serial_lpuart.c b/roms/u-boot/drivers/serial/serial_lpuart.c
new file mode 100644
index 000000000..2b473d70f
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_lpuart.c
@@ -0,0 +1,574 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 NXP
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <fsl_lpuart.h>
+#include <log.h>
+#include <watchdog.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <serial.h>
+#include <dm/device_compat.h>
+#include <linux/bitops.h>
+#include <linux/compiler.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/clock.h>
+
+#define US1_TDRE (1 << 7)
+#define US1_RDRF (1 << 5)
+#define US1_OR (1 << 3)
+#define UC2_TE (1 << 3)
+#define UC2_RE (1 << 2)
+#define CFIFO_TXFLUSH (1 << 7)
+#define CFIFO_RXFLUSH (1 << 6)
+#define SFIFO_RXOF (1 << 2)
+#define SFIFO_RXUF (1 << 0)
+
+#define STAT_LBKDIF (1 << 31)
+#define STAT_RXEDGIF (1 << 30)
+#define STAT_TDRE (1 << 23)
+#define STAT_RDRF (1 << 21)
+#define STAT_IDLE (1 << 20)
+#define STAT_OR (1 << 19)
+#define STAT_NF (1 << 18)
+#define STAT_FE (1 << 17)
+#define STAT_PF (1 << 16)
+#define STAT_MA1F (1 << 15)
+#define STAT_MA2F (1 << 14)
+#define STAT_FLAGS (STAT_LBKDIF | STAT_RXEDGIF | STAT_IDLE | STAT_OR | \
+ STAT_NF | STAT_FE | STAT_PF | STAT_MA1F | STAT_MA2F)
+
+#define CTRL_TE (1 << 19)
+#define CTRL_RE (1 << 18)
+
+#define FIFO_RXFLUSH BIT(14)
+#define FIFO_TXFLUSH BIT(15)
+#define FIFO_TXSIZE_MASK 0x70
+#define FIFO_TXSIZE_OFF 4
+#define FIFO_RXSIZE_MASK 0x7
+#define FIFO_RXSIZE_OFF 0
+#define FIFO_TXFE 0x80
+#if defined(CONFIG_ARCH_IMX8) || defined(CONFIG_ARCH_IMXRT)
+#define FIFO_RXFE 0x08
+#else
+#define FIFO_RXFE 0x40
+#endif
+
+#define WATER_TXWATER_OFF 0
+#define WATER_RXWATER_OFF 16
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define LPUART_FLAG_REGMAP_32BIT_REG BIT(0)
+#define LPUART_FLAG_REGMAP_ENDIAN_BIG BIT(1)
+
+enum lpuart_devtype {
+ DEV_VF610 = 1,
+ DEV_LS1021A,
+ DEV_MX7ULP,
+ DEV_IMX8,
+ DEV_IMXRT,
+};
+
+struct lpuart_serial_plat {
+ void *reg;
+ enum lpuart_devtype devtype;
+ ulong flags;
+};
+
+static void lpuart_read32(u32 flags, u32 *addr, u32 *val)
+{
+ if (flags & LPUART_FLAG_REGMAP_32BIT_REG) {
+ if (flags & LPUART_FLAG_REGMAP_ENDIAN_BIG)
+ *(u32 *)val = in_be32(addr);
+ else
+ *(u32 *)val = in_le32(addr);
+ }
+}
+
+static void lpuart_write32(u32 flags, u32 *addr, u32 val)
+{
+ if (flags & LPUART_FLAG_REGMAP_32BIT_REG) {
+ if (flags & LPUART_FLAG_REGMAP_ENDIAN_BIG)
+ out_be32(addr, val);
+ else
+ out_le32(addr, val);
+ }
+}
+
+
+#ifndef CONFIG_SYS_CLK_FREQ
+#define CONFIG_SYS_CLK_FREQ 0
+#endif
+
+u32 __weak get_lpuart_clk(void)
+{
+ return CONFIG_SYS_CLK_FREQ;
+}
+
+#if CONFIG_IS_ENABLED(CLK)
+static int get_lpuart_clk_rate(struct udevice *dev, u32 *clk)
+{
+ struct clk per_clk;
+ ulong rate;
+ int ret;
+
+ ret = clk_get_by_name(dev, "per", &per_clk);
+ if (ret) {
+ dev_err(dev, "Failed to get per clk: %d\n", ret);
+ return ret;
+ }
+
+ rate = clk_get_rate(&per_clk);
+ if ((long)rate <= 0) {
+ dev_err(dev, "Failed to get per clk rate: %ld\n", (long)rate);
+ return ret;
+ }
+ *clk = rate;
+ return 0;
+}
+#else
+static inline int get_lpuart_clk_rate(struct udevice *dev, u32 *clk)
+{ return -ENOSYS; }
+#endif
+
+static bool is_lpuart32(struct udevice *dev)
+{
+ struct lpuart_serial_plat *plat = dev_get_plat(dev);
+
+ return plat->flags & LPUART_FLAG_REGMAP_32BIT_REG;
+}
+
+static void _lpuart_serial_setbrg(struct udevice *dev,
+ int baudrate)
+{
+ struct lpuart_serial_plat *plat = dev_get_plat(dev);
+ struct lpuart_fsl *base = plat->reg;
+ u32 clk;
+ u16 sbr;
+ int ret;
+
+ if (CONFIG_IS_ENABLED(CLK)) {
+ ret = get_lpuart_clk_rate(dev, &clk);
+ if (ret)
+ return;
+ } else {
+ clk = get_lpuart_clk();
+ }
+
+ sbr = (u16)(clk / (16 * baudrate));
+
+ /* place adjustment later - n/32 BRFA */
+ __raw_writeb(sbr >> 8, &base->ubdh);
+ __raw_writeb(sbr & 0xff, &base->ubdl);
+}
+
+static int _lpuart_serial_getc(struct lpuart_serial_plat *plat)
+{
+ struct lpuart_fsl *base = plat->reg;
+ while (!(__raw_readb(&base->us1) & (US1_RDRF | US1_OR)))
+ WATCHDOG_RESET();
+
+ barrier();
+
+ return __raw_readb(&base->ud);
+}
+
+static void _lpuart_serial_putc(struct lpuart_serial_plat *plat,
+ const char c)
+{
+ struct lpuart_fsl *base = plat->reg;
+
+ while (!(__raw_readb(&base->us1) & US1_TDRE))
+ WATCHDOG_RESET();
+
+ __raw_writeb(c, &base->ud);
+}
+
+/* Test whether a character is in the RX buffer */
+static int _lpuart_serial_tstc(struct lpuart_serial_plat *plat)
+{
+ struct lpuart_fsl *base = plat->reg;
+
+ if (__raw_readb(&base->urcfifo) == 0)
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Initialise the serial port with the given baudrate. The settings
+ * are always 8 data bits, no parity, 1 stop bit, no start bits.
+ */
+static int _lpuart_serial_init(struct udevice *dev)
+{
+ struct lpuart_serial_plat *plat = dev_get_plat(dev);
+ struct lpuart_fsl *base = (struct lpuart_fsl *)plat->reg;
+ u8 ctrl;
+
+ ctrl = __raw_readb(&base->uc2);
+ ctrl &= ~UC2_RE;
+ ctrl &= ~UC2_TE;
+ __raw_writeb(ctrl, &base->uc2);
+
+ __raw_writeb(0, &base->umodem);
+ __raw_writeb(0, &base->uc1);
+
+ /* Disable FIFO and flush buffer */
+ __raw_writeb(0x0, &base->upfifo);
+ __raw_writeb(0x0, &base->utwfifo);
+ __raw_writeb(0x1, &base->urwfifo);
+ __raw_writeb(CFIFO_TXFLUSH | CFIFO_RXFLUSH, &base->ucfifo);
+
+ /* provide data bits, parity, stop bit, etc */
+ _lpuart_serial_setbrg(dev, gd->baudrate);
+
+ __raw_writeb(UC2_RE | UC2_TE, &base->uc2);
+
+ return 0;
+}
+
+static void _lpuart32_serial_setbrg_7ulp(struct udevice *dev,
+ int baudrate)
+{
+ struct lpuart_serial_plat *plat = dev_get_plat(dev);
+ struct lpuart_fsl_reg32 *base = plat->reg;
+ u32 sbr, osr, baud_diff, tmp_osr, tmp_sbr, tmp_diff, tmp;
+ u32 clk;
+ int ret;
+
+ if (CONFIG_IS_ENABLED(CLK)) {
+ ret = get_lpuart_clk_rate(dev, &clk);
+ if (ret)
+ return;
+ } else {
+ clk = get_lpuart_clk();
+ }
+
+ baud_diff = baudrate;
+ osr = 0;
+ sbr = 0;
+
+ for (tmp_osr = 4; tmp_osr <= 32; tmp_osr++) {
+ tmp_sbr = (clk / (baudrate * tmp_osr));
+
+ if (tmp_sbr == 0)
+ tmp_sbr = 1;
+
+ /*calculate difference in actual buad w/ current values */
+ tmp_diff = (clk / (tmp_osr * tmp_sbr));
+ tmp_diff = tmp_diff - baudrate;
+
+ /* select best values between sbr and sbr+1 */
+ if (tmp_diff > (baudrate - (clk / (tmp_osr * (tmp_sbr + 1))))) {
+ tmp_diff = baudrate - (clk / (tmp_osr * (tmp_sbr + 1)));
+ tmp_sbr++;
+ }
+
+ if (tmp_diff <= baud_diff) {
+ baud_diff = tmp_diff;
+ osr = tmp_osr;
+ sbr = tmp_sbr;
+ }
+ }
+
+ /*
+ * TODO: handle buadrate outside acceptable rate
+ * if (baudDiff > ((config->baudRate_Bps / 100) * 3))
+ * {
+ * Unacceptable baud rate difference of more than 3%
+ * return kStatus_LPUART_BaudrateNotSupport;
+ * }
+ */
+ tmp = in_le32(&base->baud);
+
+ if ((osr > 3) && (osr < 8))
+ tmp |= LPUART_BAUD_BOTHEDGE_MASK;
+
+ tmp &= ~LPUART_BAUD_OSR_MASK;
+ tmp |= LPUART_BAUD_OSR(osr-1);
+
+ tmp &= ~LPUART_BAUD_SBR_MASK;
+ tmp |= LPUART_BAUD_SBR(sbr);
+
+ /* explicitly disable 10 bit mode & set 1 stop bit */
+ tmp &= ~(LPUART_BAUD_M10_MASK | LPUART_BAUD_SBNS_MASK);
+
+ out_le32(&base->baud, tmp);
+}
+
+static void _lpuart32_serial_setbrg(struct udevice *dev,
+ int baudrate)
+{
+ struct lpuart_serial_plat *plat = dev_get_plat(dev);
+ struct lpuart_fsl_reg32 *base = plat->reg;
+ u32 clk;
+ u32 sbr;
+ int ret;
+
+ if (CONFIG_IS_ENABLED(CLK)) {
+ ret = get_lpuart_clk_rate(dev, &clk);
+ if (ret)
+ return;
+ } else {
+ clk = get_lpuart_clk();
+ }
+
+ sbr = (clk / (16 * baudrate));
+
+ /* place adjustment later - n/32 BRFA */
+ lpuart_write32(plat->flags, &base->baud, sbr);
+}
+
+static int _lpuart32_serial_getc(struct lpuart_serial_plat *plat)
+{
+ struct lpuart_fsl_reg32 *base = plat->reg;
+ u32 stat, val;
+
+ lpuart_read32(plat->flags, &base->stat, &stat);
+ while ((stat & STAT_RDRF) == 0) {
+ lpuart_write32(plat->flags, &base->stat, STAT_FLAGS);
+ WATCHDOG_RESET();
+ lpuart_read32(plat->flags, &base->stat, &stat);
+ }
+
+ lpuart_read32(plat->flags, &base->data, &val);
+
+ lpuart_read32(plat->flags, &base->stat, &stat);
+ if (stat & STAT_OR)
+ lpuart_write32(plat->flags, &base->stat, STAT_OR);
+
+ return val & 0x3ff;
+}
+
+static void _lpuart32_serial_putc(struct lpuart_serial_plat *plat,
+ const char c)
+{
+ struct lpuart_fsl_reg32 *base = plat->reg;
+ u32 stat;
+
+ if (c == '\n')
+ serial_putc('\r');
+
+ while (true) {
+ lpuart_read32(plat->flags, &base->stat, &stat);
+
+ if ((stat & STAT_TDRE))
+ break;
+
+ WATCHDOG_RESET();
+ }
+
+ lpuart_write32(plat->flags, &base->data, c);
+}
+
+/* Test whether a character is in the RX buffer */
+static int _lpuart32_serial_tstc(struct lpuart_serial_plat *plat)
+{
+ struct lpuart_fsl_reg32 *base = plat->reg;
+ u32 water;
+
+ lpuart_read32(plat->flags, &base->water, &water);
+
+ if ((water >> 24) == 0)
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Initialise the serial port with the given baudrate. The settings
+ * are always 8 data bits, no parity, 1 stop bit, no start bits.
+ */
+static int _lpuart32_serial_init(struct udevice *dev)
+{
+ struct lpuart_serial_plat *plat = dev_get_plat(dev);
+ struct lpuart_fsl_reg32 *base = (struct lpuart_fsl_reg32 *)plat->reg;
+ u32 val, tx_fifo_size;
+
+ lpuart_read32(plat->flags, &base->ctrl, &val);
+ val &= ~CTRL_RE;
+ val &= ~CTRL_TE;
+ lpuart_write32(plat->flags, &base->ctrl, val);
+
+ lpuart_write32(plat->flags, &base->modir, 0);
+
+ lpuart_read32(plat->flags, &base->fifo, &val);
+ tx_fifo_size = (val & FIFO_TXSIZE_MASK) >> FIFO_TXSIZE_OFF;
+ /* Set the TX water to half of FIFO size */
+ if (tx_fifo_size > 1)
+ tx_fifo_size = tx_fifo_size >> 1;
+
+ /* Set RX water to 0, to be triggered by any receive data */
+ lpuart_write32(plat->flags, &base->water,
+ (tx_fifo_size << WATER_TXWATER_OFF));
+
+ /* Enable TX and RX FIFO */
+ val |= (FIFO_TXFE | FIFO_RXFE | FIFO_TXFLUSH | FIFO_RXFLUSH);
+ lpuart_write32(plat->flags, &base->fifo, val);
+
+ lpuart_write32(plat->flags, &base->match, 0);
+
+ if (plat->devtype == DEV_MX7ULP || plat->devtype == DEV_IMX8 ||
+ plat->devtype == DEV_IMXRT) {
+ _lpuart32_serial_setbrg_7ulp(dev, gd->baudrate);
+ } else {
+ /* provide data bits, parity, stop bit, etc */
+ _lpuart32_serial_setbrg(dev, gd->baudrate);
+ }
+
+ lpuart_write32(plat->flags, &base->ctrl, CTRL_RE | CTRL_TE);
+
+ return 0;
+}
+
+static int lpuart_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ struct lpuart_serial_plat *plat = dev_get_plat(dev);
+
+ if (is_lpuart32(dev)) {
+ if (plat->devtype == DEV_MX7ULP || plat->devtype == DEV_IMX8 ||
+ plat->devtype == DEV_IMXRT)
+ _lpuart32_serial_setbrg_7ulp(dev, baudrate);
+ else
+ _lpuart32_serial_setbrg(dev, baudrate);
+ } else {
+ _lpuart_serial_setbrg(dev, baudrate);
+ }
+
+ return 0;
+}
+
+static int lpuart_serial_getc(struct udevice *dev)
+{
+ struct lpuart_serial_plat *plat = dev_get_plat(dev);
+
+ if (is_lpuart32(dev))
+ return _lpuart32_serial_getc(plat);
+
+ return _lpuart_serial_getc(plat);
+}
+
+static int lpuart_serial_putc(struct udevice *dev, const char c)
+{
+ struct lpuart_serial_plat *plat = dev_get_plat(dev);
+
+ if (is_lpuart32(dev))
+ _lpuart32_serial_putc(plat, c);
+ else
+ _lpuart_serial_putc(plat, c);
+
+ return 0;
+}
+
+static int lpuart_serial_pending(struct udevice *dev, bool input)
+{
+ struct lpuart_serial_plat *plat = dev_get_plat(dev);
+ struct lpuart_fsl *reg = plat->reg;
+ struct lpuart_fsl_reg32 *reg32 = plat->reg;
+ u32 stat;
+
+ if (is_lpuart32(dev)) {
+ if (input) {
+ return _lpuart32_serial_tstc(plat);
+ } else {
+ lpuart_read32(plat->flags, &reg32->stat, &stat);
+ return stat & STAT_TDRE ? 0 : 1;
+ }
+ }
+
+ if (input)
+ return _lpuart_serial_tstc(plat);
+ else
+ return __raw_readb(&reg->us1) & US1_TDRE ? 0 : 1;
+}
+
+static int lpuart_serial_probe(struct udevice *dev)
+{
+#if CONFIG_IS_ENABLED(CLK)
+ struct clk per_clk;
+ int ret;
+
+ ret = clk_get_by_name(dev, "per", &per_clk);
+ if (!ret) {
+ ret = clk_enable(&per_clk);
+ if (ret) {
+ dev_err(dev, "Failed to get per clk: %d\n", ret);
+ return ret;
+ }
+ } else {
+ debug("%s: Failed to get per clk: %d\n", __func__, ret);
+ }
+#endif
+
+ if (is_lpuart32(dev))
+ return _lpuart32_serial_init(dev);
+ else
+ return _lpuart_serial_init(dev);
+}
+
+static int lpuart_serial_of_to_plat(struct udevice *dev)
+{
+ struct lpuart_serial_plat *plat = dev_get_plat(dev);
+ const void *blob = gd->fdt_blob;
+ int node = dev_of_offset(dev);
+ fdt_addr_t addr;
+
+ addr = dev_read_addr(dev);
+ if (addr == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ plat->reg = (void *)addr;
+ plat->flags = dev_get_driver_data(dev);
+
+ if (fdtdec_get_bool(blob, node, "little-endian"))
+ plat->flags &= ~LPUART_FLAG_REGMAP_ENDIAN_BIG;
+
+ if (!fdt_node_check_compatible(blob, node, "fsl,ls1021a-lpuart"))
+ plat->devtype = DEV_LS1021A;
+ else if (!fdt_node_check_compatible(blob, node, "fsl,imx7ulp-lpuart"))
+ plat->devtype = DEV_MX7ULP;
+ else if (!fdt_node_check_compatible(blob, node, "fsl,vf610-lpuart"))
+ plat->devtype = DEV_VF610;
+ else if (!fdt_node_check_compatible(blob, node, "fsl,imx8qm-lpuart"))
+ plat->devtype = DEV_IMX8;
+ else if (!fdt_node_check_compatible(blob, node, "fsl,imxrt-lpuart"))
+ plat->devtype = DEV_IMXRT;
+
+ return 0;
+}
+
+static const struct dm_serial_ops lpuart_serial_ops = {
+ .putc = lpuart_serial_putc,
+ .pending = lpuart_serial_pending,
+ .getc = lpuart_serial_getc,
+ .setbrg = lpuart_serial_setbrg,
+};
+
+static const struct udevice_id lpuart_serial_ids[] = {
+ { .compatible = "fsl,ls1021a-lpuart", .data =
+ LPUART_FLAG_REGMAP_32BIT_REG | LPUART_FLAG_REGMAP_ENDIAN_BIG },
+ { .compatible = "fsl,imx7ulp-lpuart",
+ .data = LPUART_FLAG_REGMAP_32BIT_REG },
+ { .compatible = "fsl,vf610-lpuart"},
+ { .compatible = "fsl,imx8qm-lpuart",
+ .data = LPUART_FLAG_REGMAP_32BIT_REG },
+ { .compatible = "fsl,imxrt-lpuart",
+ .data = LPUART_FLAG_REGMAP_32BIT_REG },
+ { }
+};
+
+U_BOOT_DRIVER(serial_lpuart) = {
+ .name = "serial_lpuart",
+ .id = UCLASS_SERIAL,
+ .of_match = lpuart_serial_ids,
+ .of_to_plat = lpuart_serial_of_to_plat,
+ .plat_auto = sizeof(struct lpuart_serial_plat),
+ .probe = lpuart_serial_probe,
+ .ops = &lpuart_serial_ops,
+};
diff --git a/roms/u-boot/drivers/serial/serial_mcf.c b/roms/u-boot/drivers/serial/serial_mcf.c
new file mode 100644
index 000000000..bb2afd0d8
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_mcf.c
@@ -0,0 +1,180 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2004-2007 Freescale Semiconductor, Inc.
+ * TsiChung Liew, Tsi-Chung.Liew@freescale.com.
+ *
+ * Modified to add device model (DM) support
+ * (C) Copyright 2015 Angelo Dureghello <angelo@sysam.it>
+ *
+ * Modified to add DM and fdt support, removed non DM code
+ * (C) Copyright 2018 Angelo Dureghello <angelo@sysam.it>
+ */
+
+/*
+ * Minimal serial functions needed to use one of the uart ports
+ * as serial console interface.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/global_data.h>
+#include <dm/platform_data/serial_coldfire.h>
+#include <serial.h>
+#include <linux/compiler.h>
+#include <asm/immap.h>
+#include <asm/uart.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+extern void uart_port_conf(int port);
+
+static int mcf_serial_init_common(uart_t *uart, int port_idx, int baudrate)
+{
+ u32 counter;
+
+ uart_port_conf(port_idx);
+
+ /* write to SICR: SIM2 = uart mode,dcd does not affect rx */
+ writeb(UART_UCR_RESET_RX, &uart->ucr);
+ writeb(UART_UCR_RESET_TX, &uart->ucr);
+ writeb(UART_UCR_RESET_ERROR, &uart->ucr);
+ writeb(UART_UCR_RESET_MR, &uart->ucr);
+ __asm__("nop");
+
+ writeb(0, &uart->uimr);
+
+ /* write to CSR: RX/TX baud rate from timers */
+ writeb(UART_UCSR_RCS_SYS_CLK | UART_UCSR_TCS_SYS_CLK, &uart->ucsr);
+
+ writeb(UART_UMR_BC_8 | UART_UMR_PM_NONE, &uart->umr);
+ writeb(UART_UMR_SB_STOP_BITS_1, &uart->umr);
+
+ /* Setting up BaudRate */
+ counter = (u32) ((gd->bus_clk / 32) + (baudrate / 2));
+ counter = counter / baudrate;
+
+ /* write to CTUR: divide counter upper byte */
+ writeb((u8)((counter & 0xff00) >> 8), &uart->ubg1);
+ /* write to CTLR: divide counter lower byte */
+ writeb((u8)(counter & 0x00ff), &uart->ubg2);
+
+ writeb(UART_UCR_RX_ENABLED | UART_UCR_TX_ENABLED, &uart->ucr);
+
+ return (0);
+}
+
+static void mcf_serial_setbrg_common(uart_t *uart, int baudrate)
+{
+ u32 counter;
+
+ /* Setting up BaudRate */
+ counter = (u32) ((gd->bus_clk / 32) + (baudrate / 2));
+ counter = counter / baudrate;
+
+ /* write to CTUR: divide counter upper byte */
+ writeb(((counter & 0xff00) >> 8), &uart->ubg1);
+ /* write to CTLR: divide counter lower byte */
+ writeb((counter & 0x00ff), &uart->ubg2);
+
+ writeb(UART_UCR_RESET_RX, &uart->ucr);
+ writeb(UART_UCR_RESET_TX, &uart->ucr);
+
+ writeb(UART_UCR_RX_ENABLED | UART_UCR_TX_ENABLED, &uart->ucr);
+}
+
+static int coldfire_serial_probe(struct udevice *dev)
+{
+ struct coldfire_serial_plat *plat = dev_get_plat(dev);
+
+ plat->port = dev_seq(dev);
+
+ return mcf_serial_init_common((uart_t *)plat->base,
+ plat->port, plat->baudrate);
+}
+
+static int coldfire_serial_putc(struct udevice *dev, const char ch)
+{
+ struct coldfire_serial_plat *plat = dev_get_plat(dev);
+ uart_t *uart = (uart_t *)plat->base;
+
+ /* Wait for last character to go. */
+ if (!(readb(&uart->usr) & UART_USR_TXRDY))
+ return -EAGAIN;
+
+ writeb(ch, &uart->utb);
+
+ return 0;
+}
+
+static int coldfire_serial_getc(struct udevice *dev)
+{
+ struct coldfire_serial_plat *plat = dev_get_plat(dev);
+ uart_t *uart = (uart_t *)(plat->base);
+
+ /* Wait for a character to arrive. */
+ if (!(readb(&uart->usr) & UART_USR_RXRDY))
+ return -EAGAIN;
+
+ return readb(&uart->urb);
+}
+
+int coldfire_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ struct coldfire_serial_plat *plat = dev_get_plat(dev);
+ uart_t *uart = (uart_t *)(plat->base);
+
+ mcf_serial_setbrg_common(uart, baudrate);
+
+ return 0;
+}
+
+static int coldfire_serial_pending(struct udevice *dev, bool input)
+{
+ struct coldfire_serial_plat *plat = dev_get_plat(dev);
+ uart_t *uart = (uart_t *)(plat->base);
+
+ if (input)
+ return readb(&uart->usr) & UART_USR_RXRDY ? 1 : 0;
+ else
+ return readb(&uart->usr) & UART_USR_TXRDY ? 0 : 1;
+
+ return 0;
+}
+
+static int coldfire_of_to_plat(struct udevice *dev)
+{
+ struct coldfire_serial_plat *plat = dev_get_plat(dev);
+ fdt_addr_t addr_base;
+
+ addr_base = dev_read_addr(dev);
+ if (addr_base == FDT_ADDR_T_NONE)
+ return -ENODEV;
+
+ plat->base = (uint32_t)addr_base;
+ plat->baudrate = gd->baudrate;
+
+ return 0;
+}
+
+static const struct dm_serial_ops coldfire_serial_ops = {
+ .putc = coldfire_serial_putc,
+ .pending = coldfire_serial_pending,
+ .getc = coldfire_serial_getc,
+ .setbrg = coldfire_serial_setbrg,
+};
+
+static const struct udevice_id coldfire_serial_ids[] = {
+ { .compatible = "fsl,mcf-uart" },
+ { }
+};
+
+U_BOOT_DRIVER(serial_coldfire) = {
+ .name = "serial_coldfire",
+ .id = UCLASS_SERIAL,
+ .of_match = coldfire_serial_ids,
+ .of_to_plat = coldfire_of_to_plat,
+ .plat_auto = sizeof(struct coldfire_serial_plat),
+ .probe = coldfire_serial_probe,
+ .ops = &coldfire_serial_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/roms/u-boot/drivers/serial/serial_meson.c b/roms/u-boot/drivers/serial/serial_meson.c
new file mode 100644
index 000000000..d69ec221e
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_meson.c
@@ -0,0 +1,195 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2016 Beniamino Galvani <b.galvani@gmail.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <linux/bitops.h>
+#include <linux/compiler.h>
+#include <serial.h>
+
+struct meson_uart {
+ u32 wfifo;
+ u32 rfifo;
+ u32 control;
+ u32 status;
+ u32 misc;
+};
+
+struct meson_serial_plat {
+ struct meson_uart *reg;
+};
+
+/* AML_UART_STATUS bits */
+#define AML_UART_PARITY_ERR BIT(16)
+#define AML_UART_FRAME_ERR BIT(17)
+#define AML_UART_TX_FIFO_WERR BIT(18)
+#define AML_UART_RX_EMPTY BIT(20)
+#define AML_UART_TX_FULL BIT(21)
+#define AML_UART_TX_EMPTY BIT(22)
+#define AML_UART_XMIT_BUSY BIT(25)
+#define AML_UART_ERR (AML_UART_PARITY_ERR | \
+ AML_UART_FRAME_ERR | \
+ AML_UART_TX_FIFO_WERR)
+
+/* AML_UART_CONTROL bits */
+#define AML_UART_TX_EN BIT(12)
+#define AML_UART_RX_EN BIT(13)
+#define AML_UART_TX_RST BIT(22)
+#define AML_UART_RX_RST BIT(23)
+#define AML_UART_CLR_ERR BIT(24)
+
+static void meson_serial_init(struct meson_uart *uart)
+{
+ u32 val;
+
+ val = readl(&uart->control);
+ val |= (AML_UART_RX_RST | AML_UART_TX_RST | AML_UART_CLR_ERR);
+ writel(val, &uart->control);
+ val &= ~(AML_UART_RX_RST | AML_UART_TX_RST | AML_UART_CLR_ERR);
+ writel(val, &uart->control);
+ val |= (AML_UART_RX_EN | AML_UART_TX_EN);
+ writel(val, &uart->control);
+}
+
+static int meson_serial_probe(struct udevice *dev)
+{
+ struct meson_serial_plat *plat = dev_get_plat(dev);
+ struct meson_uart *const uart = plat->reg;
+
+ meson_serial_init(uart);
+
+ return 0;
+}
+
+static void meson_serial_rx_error(struct udevice *dev)
+{
+ struct meson_serial_plat *plat = dev_get_plat(dev);
+ struct meson_uart *const uart = plat->reg;
+ u32 val = readl(&uart->control);
+
+ /* Clear error */
+ val |= AML_UART_CLR_ERR;
+ writel(val, &uart->control);
+ val &= ~AML_UART_CLR_ERR;
+ writel(val, &uart->control);
+
+ /* Remove spurious byte from fifo */
+ readl(&uart->rfifo);
+}
+
+static int meson_serial_getc(struct udevice *dev)
+{
+ struct meson_serial_plat *plat = dev_get_plat(dev);
+ struct meson_uart *const uart = plat->reg;
+ uint32_t status = readl(&uart->status);
+
+ if (status & AML_UART_RX_EMPTY)
+ return -EAGAIN;
+
+ if (status & AML_UART_ERR) {
+ meson_serial_rx_error(dev);
+ return -EIO;
+ }
+
+ return readl(&uart->rfifo) & 0xff;
+}
+
+static int meson_serial_putc(struct udevice *dev, const char ch)
+{
+ struct meson_serial_plat *plat = dev_get_plat(dev);
+ struct meson_uart *const uart = plat->reg;
+
+ if (readl(&uart->status) & AML_UART_TX_FULL)
+ return -EAGAIN;
+
+ writel(ch, &uart->wfifo);
+
+ return 0;
+}
+
+static int meson_serial_pending(struct udevice *dev, bool input)
+{
+ struct meson_serial_plat *plat = dev_get_plat(dev);
+ struct meson_uart *const uart = plat->reg;
+ uint32_t status = readl(&uart->status);
+
+ if (input) {
+ if (status & AML_UART_RX_EMPTY)
+ return false;
+
+ /*
+ * Handle and drop any RX error here to avoid
+ * returning true here when an error byte is in the FIFO
+ */
+ if (status & AML_UART_ERR) {
+ meson_serial_rx_error(dev);
+ return false;
+ }
+
+ return true;
+ } else {
+ return !(status & AML_UART_TX_FULL);
+ }
+}
+
+static int meson_serial_of_to_plat(struct udevice *dev)
+{
+ struct meson_serial_plat *plat = dev_get_plat(dev);
+ fdt_addr_t addr;
+
+ addr = dev_read_addr(dev);
+ if (addr == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ plat->reg = (struct meson_uart *)addr;
+
+ return 0;
+}
+
+static const struct dm_serial_ops meson_serial_ops = {
+ .putc = meson_serial_putc,
+ .pending = meson_serial_pending,
+ .getc = meson_serial_getc,
+};
+
+static const struct udevice_id meson_serial_ids[] = {
+ { .compatible = "amlogic,meson-uart" },
+ { .compatible = "amlogic,meson-gx-uart" },
+ { }
+};
+
+U_BOOT_DRIVER(serial_meson) = {
+ .name = "serial_meson",
+ .id = UCLASS_SERIAL,
+ .of_match = meson_serial_ids,
+ .probe = meson_serial_probe,
+ .ops = &meson_serial_ops,
+ .of_to_plat = meson_serial_of_to_plat,
+ .plat_auto = sizeof(struct meson_serial_plat),
+};
+
+#ifdef CONFIG_DEBUG_UART_MESON
+
+#include <debug_uart.h>
+
+static inline void _debug_uart_init(void)
+{
+}
+
+static inline void _debug_uart_putc(int ch)
+{
+ struct meson_uart *regs = (struct meson_uart *)CONFIG_DEBUG_UART_BASE;
+
+ while (readl(&regs->status) & AML_UART_TX_FULL)
+ ;
+
+ writel(ch, &regs->wfifo);
+}
+
+DEBUG_UART_FUNCS
+
+#endif
diff --git a/roms/u-boot/drivers/serial/serial_mpc8xx.c b/roms/u-boot/drivers/serial/serial_mpc8xx.c
new file mode 100644
index 000000000..0978930dc
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_mpc8xx.c
@@ -0,0 +1,258 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <serial.h>
+#include <watchdog.h>
+#include <asm/cpm_8xx.h>
+#include <asm/global_data.h>
+#include <linux/compiler.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_8xx_CONS_SMC1) /* Console on SMC1 */
+#define SMC_INDEX 0
+#define PROFF_SMC PROFF_SMC1
+#define CPM_CR_CH_SMC CPM_CR_CH_SMC1
+#define IOPINS 0xc0
+
+#elif defined(CONFIG_8xx_CONS_SMC2) /* Console on SMC2 */
+#define SMC_INDEX 1
+#define PROFF_SMC PROFF_SMC2
+#define CPM_CR_CH_SMC CPM_CR_CH_SMC2
+#define IOPINS 0xc00
+
+#endif /* CONFIG_8xx_CONS_SMCx */
+
+struct serialbuffer {
+ cbd_t rxbd; /* Rx BD */
+ cbd_t txbd; /* Tx BD */
+ uint rxindex; /* index for next character to read */
+ uchar rxbuf[CONFIG_SYS_SMC_RXBUFLEN];/* rx buffers */
+ uchar txbuf; /* tx buffers */
+};
+
+static void serial_setdivisor(cpm8xx_t __iomem *cp, int baudrate)
+{
+ int divisor = (gd->cpu_clk + 8 * baudrate) / 16 / baudrate;
+
+ if (divisor / 16 > 0x1000) {
+ /* bad divisor, assume 50MHz clock and 9600 baud */
+ divisor = (50 * 1000 * 1000 + 8 * 9600) / 16 / 9600;
+ }
+
+ divisor /= CONFIG_SYS_BRGCLK_PRESCALE;
+
+ if (divisor <= 0x1000)
+ out_be32(&cp->cp_brgc1, ((divisor - 1) << 1) | CPM_BRG_EN);
+ else
+ out_be32(&cp->cp_brgc1, ((divisor / 16 - 1) << 1) | CPM_BRG_EN |
+ CPM_BRG_DIV16);
+}
+
+/*
+ * Minimal serial functions needed to use one of the SMC ports
+ * as serial console interface.
+ */
+
+static int serial_mpc8xx_setbrg(struct udevice *dev, int baudrate)
+{
+ immap_t __iomem *im = (immap_t __iomem *)CONFIG_SYS_IMMR;
+ cpm8xx_t __iomem *cp = &(im->im_cpm);
+
+ /* Set up the baud rate generator.
+ * See 8xx_io/commproc.c for details.
+ *
+ * Wire BRG1 to SMCx
+ */
+
+ out_be32(&cp->cp_simode, 0);
+
+ serial_setdivisor(cp, baudrate);
+
+ return 0;
+}
+
+static int serial_mpc8xx_probe(struct udevice *dev)
+{
+ immap_t __iomem *im = (immap_t __iomem *)CONFIG_SYS_IMMR;
+ smc_t __iomem *sp;
+ smc_uart_t __iomem *up;
+ cpm8xx_t __iomem *cp = &(im->im_cpm);
+ struct serialbuffer __iomem *rtx;
+
+ /* initialize pointers to SMC */
+
+ sp = cp->cp_smc + SMC_INDEX;
+ up = (smc_uart_t __iomem *)&cp->cp_dparam[PROFF_SMC];
+ /* Disable relocation */
+ out_be16(&up->smc_rpbase, 0);
+
+ /* Disable transmitter/receiver. */
+ clrbits_be16(&sp->smc_smcmr, SMCMR_REN | SMCMR_TEN);
+
+ /* Enable SDMA. */
+ out_be32(&im->im_siu_conf.sc_sdcr, 1);
+
+ /* clear error conditions */
+ out_8(&im->im_sdma.sdma_sdsr, CONFIG_SYS_SDSR);
+
+ /* clear SDMA interrupt mask */
+ out_8(&im->im_sdma.sdma_sdmr, CONFIG_SYS_SDMR);
+
+ /* Use Port B for SMCx instead of other functions. */
+ setbits_be32(&cp->cp_pbpar, IOPINS);
+ clrbits_be32(&cp->cp_pbdir, IOPINS);
+ clrbits_be16(&cp->cp_pbodr, IOPINS);
+
+ /* Set the physical address of the host memory buffers in
+ * the buffer descriptors.
+ */
+ rtx = (struct serialbuffer __iomem *)&cp->cp_dpmem[CPM_SERIAL_BASE];
+ /* Allocate space for two buffer descriptors in the DP ram.
+ * For now, this address seems OK, but it may have to
+ * change with newer versions of the firmware.
+ * damm: allocating space after the two buffers for rx/tx data
+ */
+
+ out_be32(&rtx->rxbd.cbd_bufaddr, (__force uint)&rtx->rxbuf);
+ out_be16(&rtx->rxbd.cbd_sc, 0);
+
+ out_be32(&rtx->txbd.cbd_bufaddr, (__force uint)&rtx->txbuf);
+ out_be16(&rtx->txbd.cbd_sc, 0);
+
+ /* Set up the uart parameters in the parameter ram. */
+ out_be16(&up->smc_rbase, CPM_SERIAL_BASE);
+ out_be16(&up->smc_tbase, CPM_SERIAL_BASE + sizeof(cbd_t));
+ out_8(&up->smc_rfcr, SMC_EB);
+ out_8(&up->smc_tfcr, SMC_EB);
+
+ /* Set UART mode, 8 bit, no parity, one stop.
+ * Enable receive and transmit.
+ */
+ out_be16(&sp->smc_smcmr, smcr_mk_clen(9) | SMCMR_SM_UART);
+
+ /* Mask all interrupts and remove anything pending.
+ */
+ out_8(&sp->smc_smcm, 0);
+ out_8(&sp->smc_smce, 0xff);
+
+ /* Set up the baud rate generator */
+ serial_mpc8xx_setbrg(dev, gd->baudrate);
+
+ /* Make the first buffer the only buffer. */
+ setbits_be16(&rtx->txbd.cbd_sc, BD_SC_WRAP);
+ setbits_be16(&rtx->rxbd.cbd_sc, BD_SC_EMPTY | BD_SC_WRAP);
+
+ /* single/multi character receive. */
+ out_be16(&up->smc_mrblr, CONFIG_SYS_SMC_RXBUFLEN);
+ out_be16(&up->smc_maxidl, CONFIG_SYS_MAXIDLE);
+ out_be32(&rtx->rxindex, 0);
+
+ /* Initialize Tx/Rx parameters. */
+ while (in_be16(&cp->cp_cpcr) & CPM_CR_FLG) /* wait if cp is busy */
+ ;
+
+ out_be16(&cp->cp_cpcr,
+ mk_cr_cmd(CPM_CR_CH_SMC, CPM_CR_INIT_TRX) | CPM_CR_FLG);
+
+ while (in_be16(&cp->cp_cpcr) & CPM_CR_FLG) /* wait if cp is busy */
+ ;
+
+ /* Enable transmitter/receiver. */
+ setbits_be16(&sp->smc_smcmr, SMCMR_REN | SMCMR_TEN);
+
+ return 0;
+}
+
+static int serial_mpc8xx_putc(struct udevice *dev, const char c)
+{
+ immap_t __iomem *im = (immap_t __iomem *)CONFIG_SYS_IMMR;
+ cpm8xx_t __iomem *cpmp = &(im->im_cpm);
+ struct serialbuffer __iomem *rtx;
+
+ if (c == '\n')
+ serial_mpc8xx_putc(dev, '\r');
+
+ rtx = (struct serialbuffer __iomem *)&cpmp->cp_dpmem[CPM_SERIAL_BASE];
+
+ /* Wait for last character to go. */
+ out_8(&rtx->txbuf, c);
+ out_be16(&rtx->txbd.cbd_datlen, 1);
+ setbits_be16(&rtx->txbd.cbd_sc, BD_SC_READY);
+
+ while (in_be16(&rtx->txbd.cbd_sc) & BD_SC_READY)
+ WATCHDOG_RESET();
+
+ return 0;
+}
+
+static int serial_mpc8xx_getc(struct udevice *dev)
+{
+ immap_t __iomem *im = (immap_t __iomem *)CONFIG_SYS_IMMR;
+ cpm8xx_t __iomem *cpmp = &(im->im_cpm);
+ struct serialbuffer __iomem *rtx;
+ unsigned char c;
+ uint rxindex;
+
+ rtx = (struct serialbuffer __iomem *)&cpmp->cp_dpmem[CPM_SERIAL_BASE];
+
+ /* Wait for character to show up. */
+ while (in_be16(&rtx->rxbd.cbd_sc) & BD_SC_EMPTY)
+ WATCHDOG_RESET();
+
+ /* the characters are read one by one,
+ * use the rxindex to know the next char to deliver
+ */
+ rxindex = in_be32(&rtx->rxindex);
+ c = in_8(rtx->rxbuf + rxindex);
+ rxindex++;
+
+ /* check if all char are readout, then make prepare for next receive */
+ if (rxindex >= in_be16(&rtx->rxbd.cbd_datlen)) {
+ rxindex = 0;
+ setbits_be16(&rtx->rxbd.cbd_sc, BD_SC_EMPTY);
+ }
+ out_be32(&rtx->rxindex, rxindex);
+ return c;
+}
+
+static int serial_mpc8xx_pending(struct udevice *dev, bool input)
+{
+ immap_t __iomem *im = (immap_t __iomem *)CONFIG_SYS_IMMR;
+ cpm8xx_t __iomem *cpmp = &(im->im_cpm);
+ struct serialbuffer __iomem *rtx;
+
+ if (!input)
+ return 0;
+
+ rtx = (struct serialbuffer __iomem *)&cpmp->cp_dpmem[CPM_SERIAL_BASE];
+
+ return !(in_be16(&rtx->rxbd.cbd_sc) & BD_SC_EMPTY);
+}
+
+static const struct dm_serial_ops serial_mpc8xx_ops = {
+ .putc = serial_mpc8xx_putc,
+ .pending = serial_mpc8xx_pending,
+ .getc = serial_mpc8xx_getc,
+ .setbrg = serial_mpc8xx_setbrg,
+};
+
+static const struct udevice_id serial_mpc8xx_ids[] = {
+ { .compatible = "fsl,pq1-smc" },
+ { }
+};
+
+U_BOOT_DRIVER(serial_mpc8xx) = {
+ .name = "serial_mpc8xx",
+ .id = UCLASS_SERIAL,
+ .of_match = serial_mpc8xx_ids,
+ .probe = serial_mpc8xx_probe,
+ .ops = &serial_mpc8xx_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/roms/u-boot/drivers/serial/serial_msm.c b/roms/u-boot/drivers/serial/serial_msm.c
new file mode 100644
index 000000000..d8c6c2f6b
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_msm.c
@@ -0,0 +1,247 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Qualcomm UART driver
+ *
+ * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
+ *
+ * UART will work in Data Mover mode.
+ * Based on Linux driver.
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <errno.h>
+#include <malloc.h>
+#include <serial.h>
+#include <watchdog.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <linux/compiler.h>
+#include <dm/pinctrl.h>
+
+/* Serial registers - this driver works in uartdm mode*/
+
+#define UARTDM_DMRX 0x34 /* Max RX transfer length */
+#define UARTDM_NCF_TX 0x40 /* Number of chars to TX */
+
+#define UARTDM_RXFS 0x50 /* RX channel status register */
+#define UARTDM_RXFS_BUF_SHIFT 0x7 /* Number of bytes in the packing buffer */
+#define UARTDM_RXFS_BUF_MASK 0x7
+#define UARTDM_MR1 0x00
+#define UARTDM_MR2 0x04
+#define UARTDM_CSR 0xA0
+
+#define UARTDM_SR 0xA4 /* Status register */
+#define UARTDM_SR_RX_READY (1 << 0) /* Word is the receiver FIFO */
+#define UARTDM_SR_TX_EMPTY (1 << 3) /* Transmitter underrun */
+#define UARTDM_SR_UART_OVERRUN (1 << 4) /* Receive overrun */
+
+#define UARTDM_CR 0xA8 /* Command register */
+#define UARTDM_CR_CMD_RESET_ERR (3 << 4) /* Clear overrun error */
+#define UARTDM_CR_CMD_RESET_STALE_INT (8 << 4) /* Clears stale irq */
+#define UARTDM_CR_CMD_RESET_TX_READY (3 << 8) /* Clears TX Ready irq*/
+#define UARTDM_CR_CMD_FORCE_STALE (4 << 8) /* Causes stale event */
+#define UARTDM_CR_CMD_STALE_EVENT_DISABLE (6 << 8) /* Disable stale event */
+
+#define UARTDM_IMR 0xB0 /* Interrupt mask register */
+#define UARTDM_ISR 0xB4 /* Interrupt status register */
+#define UARTDM_ISR_TX_READY 0x80 /* TX FIFO empty */
+
+#define UARTDM_TF 0x100 /* UART Transmit FIFO register */
+#define UARTDM_RF 0x140 /* UART Receive FIFO register */
+
+#define UART_DM_CLK_RX_TX_BIT_RATE 0xCC
+#define MSM_BOOT_UART_DM_8_N_1_MODE 0x34
+#define MSM_BOOT_UART_DM_CMD_RESET_RX 0x10
+#define MSM_BOOT_UART_DM_CMD_RESET_TX 0x20
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct msm_serial_data {
+ phys_addr_t base;
+ unsigned chars_cnt; /* number of buffered chars */
+ uint32_t chars_buf; /* buffered chars */
+ uint32_t clk_bit_rate; /* data mover mode bit rate register value */
+};
+
+static int msm_serial_fetch(struct udevice *dev)
+{
+ struct msm_serial_data *priv = dev_get_priv(dev);
+ unsigned sr;
+
+ if (priv->chars_cnt)
+ return priv->chars_cnt;
+
+ /* Clear error in case of buffer overrun */
+ if (readl(priv->base + UARTDM_SR) & UARTDM_SR_UART_OVERRUN)
+ writel(UARTDM_CR_CMD_RESET_ERR, priv->base + UARTDM_CR);
+
+ /* We need to fetch new character */
+ sr = readl(priv->base + UARTDM_SR);
+
+ if (sr & UARTDM_SR_RX_READY) {
+ /* There are at least 4 bytes in fifo */
+ priv->chars_buf = readl(priv->base + UARTDM_RF);
+ priv->chars_cnt = 4;
+ } else {
+ /* Check if there is anything in fifo */
+ priv->chars_cnt = readl(priv->base + UARTDM_RXFS);
+ /* Extract number of characters in UART packing buffer*/
+ priv->chars_cnt = (priv->chars_cnt >>
+ UARTDM_RXFS_BUF_SHIFT) &
+ UARTDM_RXFS_BUF_MASK;
+ if (!priv->chars_cnt)
+ return 0;
+
+ /* There is at least one charcter, move it to fifo */
+ writel(UARTDM_CR_CMD_FORCE_STALE,
+ priv->base + UARTDM_CR);
+
+ priv->chars_buf = readl(priv->base + UARTDM_RF);
+ writel(UARTDM_CR_CMD_RESET_STALE_INT,
+ priv->base + UARTDM_CR);
+ writel(0x7, priv->base + UARTDM_DMRX);
+ }
+
+ return priv->chars_cnt;
+}
+
+static int msm_serial_getc(struct udevice *dev)
+{
+ struct msm_serial_data *priv = dev_get_priv(dev);
+ char c;
+
+ if (!msm_serial_fetch(dev))
+ return -EAGAIN;
+
+ c = priv->chars_buf & 0xFF;
+ priv->chars_buf >>= 8;
+ priv->chars_cnt--;
+
+ return c;
+}
+
+static int msm_serial_putc(struct udevice *dev, const char ch)
+{
+ struct msm_serial_data *priv = dev_get_priv(dev);
+
+ if (!(readl(priv->base + UARTDM_SR) & UARTDM_SR_TX_EMPTY) &&
+ !(readl(priv->base + UARTDM_ISR) & UARTDM_ISR_TX_READY))
+ return -EAGAIN;
+
+ writel(UARTDM_CR_CMD_RESET_TX_READY, priv->base + UARTDM_CR);
+
+ writel(1, priv->base + UARTDM_NCF_TX);
+ writel(ch, priv->base + UARTDM_TF);
+
+ return 0;
+}
+
+static int msm_serial_pending(struct udevice *dev, bool input)
+{
+ if (input) {
+ if (msm_serial_fetch(dev))
+ return 1;
+ }
+
+ return 0;
+}
+
+static const struct dm_serial_ops msm_serial_ops = {
+ .putc = msm_serial_putc,
+ .pending = msm_serial_pending,
+ .getc = msm_serial_getc,
+};
+
+static int msm_uart_clk_init(struct udevice *dev)
+{
+ uint clk_rate = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev),
+ "clock-frequency", 115200);
+ uint clkd[2]; /* clk_id and clk_no */
+ int clk_offset;
+ struct udevice *clk_dev;
+ struct clk clk;
+ int ret;
+
+ ret = fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev), "clock",
+ clkd, 2);
+ if (ret)
+ return ret;
+
+ clk_offset = fdt_node_offset_by_phandle(gd->fdt_blob, clkd[0]);
+ if (clk_offset < 0)
+ return clk_offset;
+
+ ret = uclass_get_device_by_of_offset(UCLASS_CLK, clk_offset, &clk_dev);
+ if (ret)
+ return ret;
+
+ clk.id = clkd[1];
+ ret = clk_request(clk_dev, &clk);
+ if (ret < 0)
+ return ret;
+
+ ret = clk_set_rate(&clk, clk_rate);
+ clk_free(&clk);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static void uart_dm_init(struct msm_serial_data *priv)
+{
+ writel(priv->clk_bit_rate, priv->base + UARTDM_CSR);
+ writel(0x0, priv->base + UARTDM_MR1);
+ writel(MSM_BOOT_UART_DM_8_N_1_MODE, priv->base + UARTDM_MR2);
+ writel(MSM_BOOT_UART_DM_CMD_RESET_RX, priv->base + UARTDM_CR);
+ writel(MSM_BOOT_UART_DM_CMD_RESET_TX, priv->base + UARTDM_CR);
+}
+static int msm_serial_probe(struct udevice *dev)
+{
+ int ret;
+ struct msm_serial_data *priv = dev_get_priv(dev);
+
+ /* No need to reinitialize the UART after relocation */
+ if (gd->flags & GD_FLG_RELOC)
+ return 0;
+
+ ret = msm_uart_clk_init(dev);
+ if (ret)
+ return ret;
+
+ pinctrl_select_state(dev, "uart");
+ uart_dm_init(priv);
+
+ return 0;
+}
+
+static int msm_serial_of_to_plat(struct udevice *dev)
+{
+ struct msm_serial_data *priv = dev_get_priv(dev);
+
+ priv->base = dev_read_addr(dev);
+ if (priv->base == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ priv->clk_bit_rate = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
+ "bit-rate", UART_DM_CLK_RX_TX_BIT_RATE);
+
+ return 0;
+}
+
+static const struct udevice_id msm_serial_ids[] = {
+ { .compatible = "qcom,msm-uartdm-v1.4" },
+ { }
+};
+
+U_BOOT_DRIVER(serial_msm) = {
+ .name = "serial_msm",
+ .id = UCLASS_SERIAL,
+ .of_match = msm_serial_ids,
+ .of_to_plat = msm_serial_of_to_plat,
+ .priv_auto = sizeof(struct msm_serial_data),
+ .probe = msm_serial_probe,
+ .ops = &msm_serial_ops,
+};
diff --git a/roms/u-boot/drivers/serial/serial_mt7620.c b/roms/u-boot/drivers/serial/serial_mt7620.c
new file mode 100644
index 000000000..826a14b49
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_mt7620.c
@@ -0,0 +1,246 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * UART driver for MediaTek MT7620 and earlier SoCs
+ *
+ * Copyright (C) 2020 MediaTek Inc.
+ * Author: Weijie Gao <weijie.gao@mediatek.com>
+ */
+
+#include <clk.h>
+#include <div64.h>
+#include <dm.h>
+#include <errno.h>
+#include <log.h>
+#include <reset.h>
+#include <serial.h>
+#include <watchdog.h>
+#include <asm/io.h>
+#include <asm/types.h>
+#include <asm/addrspace.h>
+#include <dm/device_compat.h>
+#include <linux/err.h>
+
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+#include <dt-structs.h>
+#endif
+
+struct mt7620_serial_regs {
+ u32 rbr;
+ u32 thr;
+ u32 ier;
+ u32 iir;
+ u32 fcr;
+ u32 lcr;
+ u32 mcr;
+ u32 lsr;
+ u32 msr;
+ u32 scratch;
+ u32 dl;
+ u32 dll;
+ u32 dlm;
+ u32 ifctl;
+};
+
+#define UART_LCR_WLS_8 0x03 /* 8 bit character length */
+
+#define UART_LSR_DR 0x01 /* Data ready */
+#define UART_LSR_THRE 0x20 /* Xmit holding register empty */
+#define UART_LSR_TEMT 0x40 /* Xmitter empty */
+
+#define UART_MCR_DTR 0x01 /* DTR */
+#define UART_MCR_RTS 0x02 /* RTS */
+
+#define UART_FCR_FIFO_EN 0x01 /* Fifo enable */
+#define UART_FCR_RXSR 0x02 /* Receiver soft reset */
+#define UART_FCR_TXSR 0x04 /* Transmitter soft reset */
+
+#define UART_MCRVAL (UART_MCR_DTR | \
+ UART_MCR_RTS)
+
+/* Clear & enable FIFOs */
+#define UART_FCRVAL (UART_FCR_FIFO_EN | \
+ UART_FCR_RXSR | \
+ UART_FCR_TXSR)
+
+struct mt7620_serial_plat {
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+ struct dtd_serial_mt7620 dtplat;
+#endif
+
+ struct mt7620_serial_regs __iomem *regs;
+ u32 clock;
+};
+
+static void _mt7620_serial_setbrg(struct mt7620_serial_plat *plat, int baud)
+{
+ u32 quot;
+
+ /* set divisor */
+ quot = DIV_ROUND_CLOSEST(plat->clock, 16 * baud);
+ writel(quot, &plat->regs->dl);
+
+ /* set character length and stop bits */
+ writel(UART_LCR_WLS_8, &plat->regs->lcr);
+}
+
+static int mt7620_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ struct mt7620_serial_plat *plat = dev_get_plat(dev);
+
+ _mt7620_serial_setbrg(plat, baudrate);
+
+ return 0;
+}
+
+static int mt7620_serial_putc(struct udevice *dev, const char ch)
+{
+ struct mt7620_serial_plat *plat = dev_get_plat(dev);
+
+ if (!(readl(&plat->regs->lsr) & UART_LSR_THRE))
+ return -EAGAIN;
+
+ writel(ch, &plat->regs->thr);
+
+ if (ch == '\n')
+ WATCHDOG_RESET();
+
+ return 0;
+}
+
+static int mt7620_serial_getc(struct udevice *dev)
+{
+ struct mt7620_serial_plat *plat = dev_get_plat(dev);
+
+ if (!(readl(&plat->regs->lsr) & UART_LSR_DR))
+ return -EAGAIN;
+
+ return readl(&plat->regs->rbr);
+}
+
+static int mt7620_serial_pending(struct udevice *dev, bool input)
+{
+ struct mt7620_serial_plat *plat = dev_get_plat(dev);
+
+ if (input)
+ return (readl(&plat->regs->lsr) & UART_LSR_DR) ? 1 : 0;
+
+ return (readl(&plat->regs->lsr) & UART_LSR_THRE) ? 0 : 1;
+}
+
+static int mt7620_serial_probe(struct udevice *dev)
+{
+ struct mt7620_serial_plat *plat = dev_get_plat(dev);
+
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+ plat->regs = (void __iomem *)KSEG1ADDR(plat->dtplat.reg[0]);
+ plat->clock = plat->dtplat.clock_frequency;
+#endif
+
+ /* Disable interrupt */
+ writel(0, &plat->regs->ier);
+
+ writel(UART_MCRVAL, &plat->regs->mcr);
+ writel(UART_FCRVAL, &plat->regs->fcr);
+
+ return 0;
+}
+
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+static int mt7620_serial_of_to_plat(struct udevice *dev)
+{
+ struct mt7620_serial_plat *plat = dev_get_plat(dev);
+ struct reset_ctl reset_uart;
+ struct clk clk;
+ int err;
+
+ err = reset_get_by_index(dev, 0, &reset_uart);
+ if (!err)
+ reset_deassert(&reset_uart);
+
+ plat->regs = dev_remap_addr_index(dev, 0);
+ if (!plat->regs) {
+ dev_err(dev, "mt7620_serial: unable to map UART registers\n");
+ return -EINVAL;
+ }
+
+ err = clk_get_by_index(dev, 0, &clk);
+ if (!err) {
+ err = clk_get_rate(&clk);
+ if (!IS_ERR_VALUE(err))
+ plat->clock = err;
+ } else if (err != -ENOENT && err != -ENODEV && err != -ENOSYS) {
+ dev_err(dev, "mt7620_serial: failed to get clock\n");
+ return err;
+ }
+
+ if (!plat->clock)
+ plat->clock = dev_read_u32_default(dev, "clock-frequency", 0);
+
+ if (!plat->clock) {
+ dev_err(dev, "mt7620_serial: clock not defined\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct udevice_id mt7620_serial_ids[] = {
+ { .compatible = "mediatek,mt7620-uart" },
+ { }
+};
+#endif
+
+static const struct dm_serial_ops mt7620_serial_ops = {
+ .putc = mt7620_serial_putc,
+ .pending = mt7620_serial_pending,
+ .getc = mt7620_serial_getc,
+ .setbrg = mt7620_serial_setbrg,
+};
+
+U_BOOT_DRIVER(serial_mt7620) = {
+ .name = "serial_mt7620",
+ .id = UCLASS_SERIAL,
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+ .of_match = mt7620_serial_ids,
+ .of_to_plat = mt7620_serial_of_to_plat,
+#endif
+ .plat_auto = sizeof(struct mt7620_serial_plat),
+ .probe = mt7620_serial_probe,
+ .ops = &mt7620_serial_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
+
+DM_DRIVER_ALIAS(serial_mt7620, mediatek_mt7620_uart);
+
+#ifdef CONFIG_DEBUG_UART_MT7620
+
+#include <debug_uart.h>
+
+static inline void _debug_uart_init(void)
+{
+ struct mt7620_serial_plat plat;
+
+ plat.regs = (void *)CONFIG_DEBUG_UART_BASE;
+ plat.clock = CONFIG_DEBUG_UART_CLOCK;
+
+ writel(0, &plat.regs->ier);
+ writel(UART_MCRVAL, &plat.regs->mcr);
+ writel(UART_FCRVAL, &plat.regs->fcr);
+
+ _mt7620_serial_setbrg(&plat, CONFIG_BAUDRATE);
+}
+
+static inline void _debug_uart_putc(int ch)
+{
+ struct mt7620_serial_regs __iomem *regs =
+ (void *)CONFIG_DEBUG_UART_BASE;
+
+ while (!(readl(&regs->lsr) & UART_LSR_THRE))
+ ;
+
+ writel(ch, &regs->thr);
+}
+
+DEBUG_UART_FUNCS
+
+#endif
diff --git a/roms/u-boot/drivers/serial/serial_mtk.c b/roms/u-boot/drivers/serial/serial_mtk.c
new file mode 100644
index 000000000..4145d9fdb
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_mtk.c
@@ -0,0 +1,452 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MediaTek High-speed UART driver
+ *
+ * Copyright (C) 2018 MediaTek Inc.
+ * Author: Weijie Gao <weijie.gao@mediatek.com>
+ */
+
+#include <clk.h>
+#include <common.h>
+#include <div64.h>
+#include <dm.h>
+#include <errno.h>
+#include <log.h>
+#include <serial.h>
+#include <watchdog.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <asm/types.h>
+#include <linux/err.h>
+
+struct mtk_serial_regs {
+ u32 rbr;
+ u32 ier;
+ u32 fcr;
+ u32 lcr;
+ u32 mcr;
+ u32 lsr;
+ u32 msr;
+ u32 spr;
+ u32 mdr1;
+ u32 highspeed;
+ u32 sample_count;
+ u32 sample_point;
+ u32 fracdiv_l;
+ u32 fracdiv_m;
+ u32 escape_en;
+ u32 guard;
+ u32 rx_sel;
+};
+
+#define thr rbr
+#define iir fcr
+#define dll rbr
+#define dlm ier
+
+#define UART_LCR_WLS_8 0x03 /* 8 bit character length */
+#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */
+
+#define UART_LSR_DR 0x01 /* Data ready */
+#define UART_LSR_THRE 0x20 /* Xmit holding register empty */
+#define UART_LSR_TEMT 0x40 /* Xmitter empty */
+
+#define UART_MCR_DTR 0x01 /* DTR */
+#define UART_MCR_RTS 0x02 /* RTS */
+
+#define UART_FCR_FIFO_EN 0x01 /* Fifo enable */
+#define UART_FCR_RXSR 0x02 /* Receiver soft reset */
+#define UART_FCR_TXSR 0x04 /* Transmitter soft reset */
+
+#define UART_MCRVAL (UART_MCR_DTR | \
+ UART_MCR_RTS)
+
+/* Clear & enable FIFOs */
+#define UART_FCRVAL (UART_FCR_FIFO_EN | \
+ UART_FCR_RXSR | \
+ UART_FCR_TXSR)
+
+/* the data is correct if the real baud is within 3%. */
+#define BAUD_ALLOW_MAX(baud) ((baud) + (baud) * 3 / 100)
+#define BAUD_ALLOW_MIX(baud) ((baud) - (baud) * 3 / 100)
+
+struct mtk_serial_priv {
+ struct mtk_serial_regs __iomem *regs;
+ u32 clock;
+ bool force_highspeed;
+};
+
+static void _mtk_serial_setbrg(struct mtk_serial_priv *priv, int baud)
+{
+ u32 quot, realbaud, samplecount = 1;
+
+ /* Special case for low baud clock */
+ if (baud <= 115200 && priv->clock <= 12000000) {
+ writel(3, &priv->regs->highspeed);
+
+ quot = DIV_ROUND_CLOSEST(priv->clock, 256 * baud);
+ if (quot == 0)
+ quot = 1;
+
+ samplecount = DIV_ROUND_CLOSEST(priv->clock, quot * baud);
+
+ realbaud = priv->clock / samplecount / quot;
+ if (realbaud > BAUD_ALLOW_MAX(baud) ||
+ realbaud < BAUD_ALLOW_MIX(baud)) {
+ pr_info("baud %d can't be handled\n", baud);
+ }
+
+ goto set_baud;
+ }
+
+ if (priv->force_highspeed)
+ goto use_hs3;
+
+ if (baud <= 115200) {
+ writel(0, &priv->regs->highspeed);
+ quot = DIV_ROUND_CLOSEST(priv->clock, 16 * baud);
+ } else if (baud <= 576000) {
+ writel(2, &priv->regs->highspeed);
+
+ /* Set to next lower baudrate supported */
+ if ((baud == 500000) || (baud == 576000))
+ baud = 460800;
+
+ quot = DIV_ROUND_UP(priv->clock, 4 * baud);
+ } else {
+use_hs3:
+ writel(3, &priv->regs->highspeed);
+
+ quot = DIV_ROUND_UP(priv->clock, 256 * baud);
+ samplecount = DIV_ROUND_CLOSEST(priv->clock, quot * baud);
+ }
+
+set_baud:
+ /* set divisor */
+ writel(UART_LCR_WLS_8 | UART_LCR_DLAB, &priv->regs->lcr);
+ writel(quot & 0xff, &priv->regs->dll);
+ writel((quot >> 8) & 0xff, &priv->regs->dlm);
+ writel(UART_LCR_WLS_8, &priv->regs->lcr);
+
+ /* set highspeed mode sample count & point */
+ writel(samplecount - 1, &priv->regs->sample_count);
+ writel((samplecount - 2) >> 1, &priv->regs->sample_point);
+}
+
+static int _mtk_serial_putc(struct mtk_serial_priv *priv, const char ch)
+{
+ if (!(readl(&priv->regs->lsr) & UART_LSR_THRE))
+ return -EAGAIN;
+
+ writel(ch, &priv->regs->thr);
+
+ if (ch == '\n')
+ WATCHDOG_RESET();
+
+ return 0;
+}
+
+static int _mtk_serial_getc(struct mtk_serial_priv *priv)
+{
+ if (!(readl(&priv->regs->lsr) & UART_LSR_DR))
+ return -EAGAIN;
+
+ return readl(&priv->regs->rbr);
+}
+
+static int _mtk_serial_pending(struct mtk_serial_priv *priv, bool input)
+{
+ if (input)
+ return (readl(&priv->regs->lsr) & UART_LSR_DR) ? 1 : 0;
+ else
+ return (readl(&priv->regs->lsr) & UART_LSR_THRE) ? 0 : 1;
+}
+
+#if defined(CONFIG_DM_SERIAL) && \
+ (!defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_DM))
+static int mtk_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ struct mtk_serial_priv *priv = dev_get_priv(dev);
+
+ _mtk_serial_setbrg(priv, baudrate);
+
+ return 0;
+}
+
+static int mtk_serial_putc(struct udevice *dev, const char ch)
+{
+ struct mtk_serial_priv *priv = dev_get_priv(dev);
+
+ return _mtk_serial_putc(priv, ch);
+}
+
+static int mtk_serial_getc(struct udevice *dev)
+{
+ struct mtk_serial_priv *priv = dev_get_priv(dev);
+
+ return _mtk_serial_getc(priv);
+}
+
+static int mtk_serial_pending(struct udevice *dev, bool input)
+{
+ struct mtk_serial_priv *priv = dev_get_priv(dev);
+
+ return _mtk_serial_pending(priv, input);
+}
+
+static int mtk_serial_probe(struct udevice *dev)
+{
+ struct mtk_serial_priv *priv = dev_get_priv(dev);
+
+ /* Disable interrupt */
+ writel(0, &priv->regs->ier);
+
+ writel(UART_MCRVAL, &priv->regs->mcr);
+ writel(UART_FCRVAL, &priv->regs->fcr);
+
+ return 0;
+}
+
+static int mtk_serial_of_to_plat(struct udevice *dev)
+{
+ struct mtk_serial_priv *priv = dev_get_priv(dev);
+ fdt_addr_t addr;
+ struct clk clk;
+ int err;
+
+ addr = dev_read_addr(dev);
+ if (addr == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ priv->regs = map_physmem(addr, 0, MAP_NOCACHE);
+
+ err = clk_get_by_index(dev, 0, &clk);
+ if (!err) {
+ err = clk_get_rate(&clk);
+ if (!IS_ERR_VALUE(err))
+ priv->clock = err;
+ } else if (err != -ENOENT && err != -ENODEV && err != -ENOSYS) {
+ debug("mtk_serial: failed to get clock\n");
+ return err;
+ }
+
+ if (!priv->clock)
+ priv->clock = dev_read_u32_default(dev, "clock-frequency", 0);
+
+ if (!priv->clock) {
+ debug("mtk_serial: clock not defined\n");
+ return -EINVAL;
+ }
+
+ priv->force_highspeed = dev_read_bool(dev, "mediatek,force-highspeed");
+
+ return 0;
+}
+
+static const struct dm_serial_ops mtk_serial_ops = {
+ .putc = mtk_serial_putc,
+ .pending = mtk_serial_pending,
+ .getc = mtk_serial_getc,
+ .setbrg = mtk_serial_setbrg,
+};
+
+static const struct udevice_id mtk_serial_ids[] = {
+ { .compatible = "mediatek,hsuart" },
+ { .compatible = "mediatek,mt6577-uart" },
+ { }
+};
+
+U_BOOT_DRIVER(serial_mtk) = {
+ .name = "serial_mtk",
+ .id = UCLASS_SERIAL,
+ .of_match = mtk_serial_ids,
+ .of_to_plat = mtk_serial_of_to_plat,
+ .priv_auto = sizeof(struct mtk_serial_priv),
+ .probe = mtk_serial_probe,
+ .ops = &mtk_serial_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
+#else
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define DECLARE_HSUART_PRIV(port) \
+ static struct mtk_serial_priv mtk_hsuart##port = { \
+ .regs = (struct mtk_serial_regs *)CONFIG_SYS_NS16550_COM##port, \
+ .clock = CONFIG_SYS_NS16550_CLK \
+};
+
+#define DECLARE_HSUART_FUNCTIONS(port) \
+ static int mtk_serial##port##_init(void) \
+ { \
+ writel(0, &mtk_hsuart##port.regs->ier); \
+ writel(UART_MCRVAL, &mtk_hsuart##port.regs->mcr); \
+ writel(UART_FCRVAL, &mtk_hsuart##port.regs->fcr); \
+ _mtk_serial_setbrg(&mtk_hsuart##port, gd->baudrate); \
+ return 0 ; \
+ } \
+ static void mtk_serial##port##_setbrg(void) \
+ { \
+ _mtk_serial_setbrg(&mtk_hsuart##port, gd->baudrate); \
+ } \
+ static int mtk_serial##port##_getc(void) \
+ { \
+ int err; \
+ do { \
+ err = _mtk_serial_getc(&mtk_hsuart##port); \
+ if (err == -EAGAIN) \
+ WATCHDOG_RESET(); \
+ } while (err == -EAGAIN); \
+ return err >= 0 ? err : 0; \
+ } \
+ static int mtk_serial##port##_tstc(void) \
+ { \
+ return _mtk_serial_pending(&mtk_hsuart##port, true); \
+ } \
+ static void mtk_serial##port##_putc(const char c) \
+ { \
+ int err; \
+ if (c == '\n') \
+ mtk_serial##port##_putc('\r'); \
+ do { \
+ err = _mtk_serial_putc(&mtk_hsuart##port, c); \
+ } while (err == -EAGAIN); \
+ } \
+ static void mtk_serial##port##_puts(const char *s) \
+ { \
+ while (*s) { \
+ mtk_serial##port##_putc(*s++); \
+ } \
+ }
+
+/* Serial device descriptor */
+#define INIT_HSUART_STRUCTURE(port, __name) { \
+ .name = __name, \
+ .start = mtk_serial##port##_init, \
+ .stop = NULL, \
+ .setbrg = mtk_serial##port##_setbrg, \
+ .getc = mtk_serial##port##_getc, \
+ .tstc = mtk_serial##port##_tstc, \
+ .putc = mtk_serial##port##_putc, \
+ .puts = mtk_serial##port##_puts, \
+}
+
+#define DECLARE_HSUART(port, __name) \
+ DECLARE_HSUART_PRIV(port); \
+ DECLARE_HSUART_FUNCTIONS(port); \
+ struct serial_device mtk_hsuart##port##_device = \
+ INIT_HSUART_STRUCTURE(port, __name);
+
+#if !defined(CONFIG_CONS_INDEX)
+#elif (CONFIG_CONS_INDEX < 1) || (CONFIG_CONS_INDEX > 6)
+#error "Invalid console index value."
+#endif
+
+#if CONFIG_CONS_INDEX == 1 && !defined(CONFIG_SYS_NS16550_COM1)
+#error "Console port 1 defined but not configured."
+#elif CONFIG_CONS_INDEX == 2 && !defined(CONFIG_SYS_NS16550_COM2)
+#error "Console port 2 defined but not configured."
+#elif CONFIG_CONS_INDEX == 3 && !defined(CONFIG_SYS_NS16550_COM3)
+#error "Console port 3 defined but not configured."
+#elif CONFIG_CONS_INDEX == 4 && !defined(CONFIG_SYS_NS16550_COM4)
+#error "Console port 4 defined but not configured."
+#elif CONFIG_CONS_INDEX == 5 && !defined(CONFIG_SYS_NS16550_COM5)
+#error "Console port 5 defined but not configured."
+#elif CONFIG_CONS_INDEX == 6 && !defined(CONFIG_SYS_NS16550_COM6)
+#error "Console port 6 defined but not configured."
+#endif
+
+#if defined(CONFIG_SYS_NS16550_COM1)
+DECLARE_HSUART(1, "mtk-hsuart0");
+#endif
+#if defined(CONFIG_SYS_NS16550_COM2)
+DECLARE_HSUART(2, "mtk-hsuart1");
+#endif
+#if defined(CONFIG_SYS_NS16550_COM3)
+DECLARE_HSUART(3, "mtk-hsuart2");
+#endif
+#if defined(CONFIG_SYS_NS16550_COM4)
+DECLARE_HSUART(4, "mtk-hsuart3");
+#endif
+#if defined(CONFIG_SYS_NS16550_COM5)
+DECLARE_HSUART(5, "mtk-hsuart4");
+#endif
+#if defined(CONFIG_SYS_NS16550_COM6)
+DECLARE_HSUART(6, "mtk-hsuart5");
+#endif
+
+__weak struct serial_device *default_serial_console(void)
+{
+#if CONFIG_CONS_INDEX == 1
+ return &mtk_hsuart1_device;
+#elif CONFIG_CONS_INDEX == 2
+ return &mtk_hsuart2_device;
+#elif CONFIG_CONS_INDEX == 3
+ return &mtk_hsuart3_device;
+#elif CONFIG_CONS_INDEX == 4
+ return &mtk_hsuart4_device;
+#elif CONFIG_CONS_INDEX == 5
+ return &mtk_hsuart5_device;
+#elif CONFIG_CONS_INDEX == 6
+ return &mtk_hsuart6_device;
+#else
+#error "Bad CONFIG_CONS_INDEX."
+#endif
+}
+
+void mtk_serial_initialize(void)
+{
+#if defined(CONFIG_SYS_NS16550_COM1)
+ serial_register(&mtk_hsuart1_device);
+#endif
+#if defined(CONFIG_SYS_NS16550_COM2)
+ serial_register(&mtk_hsuart2_device);
+#endif
+#if defined(CONFIG_SYS_NS16550_COM3)
+ serial_register(&mtk_hsuart3_device);
+#endif
+#if defined(CONFIG_SYS_NS16550_COM4)
+ serial_register(&mtk_hsuart4_device);
+#endif
+#if defined(CONFIG_SYS_NS16550_COM5)
+ serial_register(&mtk_hsuart5_device);
+#endif
+#if defined(CONFIG_SYS_NS16550_COM6)
+ serial_register(&mtk_hsuart6_device);
+#endif
+}
+
+#endif
+
+#ifdef CONFIG_DEBUG_UART_MTK
+
+#include <debug_uart.h>
+
+static inline void _debug_uart_init(void)
+{
+ struct mtk_serial_priv priv;
+
+ priv.regs = (void *) CONFIG_DEBUG_UART_BASE;
+ priv.clock = CONFIG_DEBUG_UART_CLOCK;
+
+ writel(0, &priv.regs->ier);
+ writel(UART_MCRVAL, &priv.regs->mcr);
+ writel(UART_FCRVAL, &priv.regs->fcr);
+
+ _mtk_serial_setbrg(&priv, CONFIG_BAUDRATE);
+}
+
+static inline void _debug_uart_putc(int ch)
+{
+ struct mtk_serial_regs __iomem *regs =
+ (void *) CONFIG_DEBUG_UART_BASE;
+
+ while (!(readl(&regs->lsr) & UART_LSR_THRE))
+ ;
+
+ writel(ch, &regs->thr);
+}
+
+DEBUG_UART_FUNCS
+
+#endif
diff --git a/roms/u-boot/drivers/serial/serial_mvebu_a3700.c b/roms/u-boot/drivers/serial/serial_mvebu_a3700.c
new file mode 100644
index 000000000..8f404879a
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_mvebu_a3700.c
@@ -0,0 +1,179 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <serial.h>
+#include <asm/io.h>
+
+struct mvebu_plat {
+ void __iomem *base;
+};
+
+/*
+ * Register offset
+ */
+#define UART_RX_REG 0x00
+#define UART_TX_REG 0x04
+#define UART_CTRL_REG 0x08
+#define UART_STATUS_REG 0x0c
+#define UART_BAUD_REG 0x10
+#define UART_POSSR_REG 0x14
+
+#define UART_STATUS_RX_RDY 0x10
+#define UART_STATUS_TX_EMPTY 0x40
+#define UART_STATUS_TXFIFO_FULL 0x800
+
+#define UART_CTRL_RXFIFO_RESET 0x4000
+#define UART_CTRL_TXFIFO_RESET 0x8000
+
+#define CONFIG_UART_BASE_CLOCK 25804800
+
+static int mvebu_serial_putc(struct udevice *dev, const char ch)
+{
+ struct mvebu_plat *plat = dev_get_plat(dev);
+ void __iomem *base = plat->base;
+
+ while (readl(base + UART_STATUS_REG) & UART_STATUS_TXFIFO_FULL)
+ ;
+
+ writel(ch, base + UART_TX_REG);
+
+ return 0;
+}
+
+static int mvebu_serial_getc(struct udevice *dev)
+{
+ struct mvebu_plat *plat = dev_get_plat(dev);
+ void __iomem *base = plat->base;
+
+ while (!(readl(base + UART_STATUS_REG) & UART_STATUS_RX_RDY))
+ ;
+
+ return readl(base + UART_RX_REG) & 0xff;
+}
+
+static int mvebu_serial_pending(struct udevice *dev, bool input)
+{
+ struct mvebu_plat *plat = dev_get_plat(dev);
+ void __iomem *base = plat->base;
+
+ if (input) {
+ if (readl(base + UART_STATUS_REG) & UART_STATUS_RX_RDY)
+ return 1;
+ } else {
+ if (!(readl(base + UART_STATUS_REG) & UART_STATUS_TX_EMPTY))
+ return 1;
+ }
+
+ return 0;
+}
+
+static int mvebu_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ struct mvebu_plat *plat = dev_get_plat(dev);
+ void __iomem *base = plat->base;
+
+ /*
+ * Calculate divider
+ * baudrate = clock / 16 / divider
+ */
+ writel(CONFIG_UART_BASE_CLOCK / baudrate / 16, base + UART_BAUD_REG);
+
+ /*
+ * Set Programmable Oversampling Stack to 0,
+ * UART defaults to 16x scheme
+ */
+ writel(0, base + UART_POSSR_REG);
+
+ return 0;
+}
+
+static int mvebu_serial_probe(struct udevice *dev)
+{
+ struct mvebu_plat *plat = dev_get_plat(dev);
+ void __iomem *base = plat->base;
+
+ /* reset FIFOs */
+ writel(UART_CTRL_RXFIFO_RESET | UART_CTRL_TXFIFO_RESET,
+ base + UART_CTRL_REG);
+
+ /* No Parity, 1 Stop */
+ writel(0, base + UART_CTRL_REG);
+
+ return 0;
+}
+
+static int mvebu_serial_of_to_plat(struct udevice *dev)
+{
+ struct mvebu_plat *plat = dev_get_plat(dev);
+
+ plat->base = dev_read_addr_ptr(dev);
+
+ return 0;
+}
+
+static const struct dm_serial_ops mvebu_serial_ops = {
+ .putc = mvebu_serial_putc,
+ .pending = mvebu_serial_pending,
+ .getc = mvebu_serial_getc,
+ .setbrg = mvebu_serial_setbrg,
+};
+
+static const struct udevice_id mvebu_serial_ids[] = {
+ { .compatible = "marvell,armada-3700-uart" },
+ { }
+};
+
+U_BOOT_DRIVER(serial_mvebu) = {
+ .name = "serial_mvebu",
+ .id = UCLASS_SERIAL,
+ .of_match = mvebu_serial_ids,
+ .of_to_plat = mvebu_serial_of_to_plat,
+ .plat_auto = sizeof(struct mvebu_plat),
+ .probe = mvebu_serial_probe,
+ .ops = &mvebu_serial_ops,
+};
+
+#ifdef CONFIG_DEBUG_MVEBU_A3700_UART
+
+#include <debug_uart.h>
+
+static inline void _debug_uart_init(void)
+{
+ void __iomem *base = (void __iomem *)CONFIG_DEBUG_UART_BASE;
+
+ /* reset FIFOs */
+ writel(UART_CTRL_RXFIFO_RESET | UART_CTRL_TXFIFO_RESET,
+ base + UART_CTRL_REG);
+
+ /* No Parity, 1 Stop */
+ writel(0, base + UART_CTRL_REG);
+
+ /*
+ * Calculate divider
+ * baudrate = clock / 16 / divider
+ */
+ writel(CONFIG_UART_BASE_CLOCK / 115200 / 16, base + UART_BAUD_REG);
+
+ /*
+ * Set Programmable Oversampling Stack to 0,
+ * UART defaults to 16x scheme
+ */
+ writel(0, base + UART_POSSR_REG);
+}
+
+static inline void _debug_uart_putc(int ch)
+{
+ void __iomem *base = (void __iomem *)CONFIG_DEBUG_UART_BASE;
+
+ while (readl(base + UART_STATUS_REG) & UART_STATUS_TXFIFO_FULL)
+ ;
+
+ writel(ch, base + UART_TX_REG);
+}
+
+DEBUG_UART_FUNCS
+#endif
diff --git a/roms/u-boot/drivers/serial/serial_mxc.c b/roms/u-boot/drivers/serial/serial_mxc.c
new file mode 100644
index 000000000..e4970a169
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_mxc.c
@@ -0,0 +1,394 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <watchdog.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/clock.h>
+#include <asm/global_data.h>
+#include <dm/platform_data/serial_mxc.h>
+#include <serial.h>
+#include <linux/compiler.h>
+
+/* UART Control Register Bit Fields.*/
+#define URXD_CHARRDY (1<<15)
+#define URXD_ERR (1<<14)
+#define URXD_OVRRUN (1<<13)
+#define URXD_FRMERR (1<<12)
+#define URXD_BRK (1<<11)
+#define URXD_PRERR (1<<10)
+#define URXD_RX_DATA (0xFF)
+#define UCR1_ADEN (1<<15) /* Auto dectect interrupt */
+#define UCR1_ADBR (1<<14) /* Auto detect baud rate */
+#define UCR1_TRDYEN (1<<13) /* Transmitter ready interrupt enable */
+#define UCR1_IDEN (1<<12) /* Idle condition interrupt */
+#define UCR1_RRDYEN (1<<9) /* Recv ready interrupt enable */
+#define UCR1_RDMAEN (1<<8) /* Recv ready DMA enable */
+#define UCR1_IREN (1<<7) /* Infrared interface enable */
+#define UCR1_TXMPTYEN (1<<6) /* Transimitter empty interrupt enable */
+#define UCR1_RTSDEN (1<<5) /* RTS delta interrupt enable */
+#define UCR1_SNDBRK (1<<4) /* Send break */
+#define UCR1_TDMAEN (1<<3) /* Transmitter ready DMA enable */
+#define UCR1_UARTCLKEN (1<<2) /* UART clock enabled */
+#define UCR1_DOZE (1<<1) /* Doze */
+#define UCR1_UARTEN (1<<0) /* UART enabled */
+#define UCR2_ESCI (1<<15) /* Escape seq interrupt enable */
+#define UCR2_IRTS (1<<14) /* Ignore RTS pin */
+#define UCR2_CTSC (1<<13) /* CTS pin control */
+#define UCR2_CTS (1<<12) /* Clear to send */
+#define UCR2_ESCEN (1<<11) /* Escape enable */
+#define UCR2_PREN (1<<8) /* Parity enable */
+#define UCR2_PROE (1<<7) /* Parity odd/even */
+#define UCR2_STPB (1<<6) /* Stop */
+#define UCR2_WS (1<<5) /* Word size */
+#define UCR2_RTSEN (1<<4) /* Request to send interrupt enable */
+#define UCR2_TXEN (1<<2) /* Transmitter enabled */
+#define UCR2_RXEN (1<<1) /* Receiver enabled */
+#define UCR2_SRST (1<<0) /* SW reset */
+#define UCR3_DTREN (1<<13) /* DTR interrupt enable */
+#define UCR3_PARERREN (1<<12) /* Parity enable */
+#define UCR3_FRAERREN (1<<11) /* Frame error interrupt enable */
+#define UCR3_DSR (1<<10) /* Data set ready */
+#define UCR3_DCD (1<<9) /* Data carrier detect */
+#define UCR3_RI (1<<8) /* Ring indicator */
+#define UCR3_ADNIMP (1<<7) /* Autobaud Detection Not Improved */
+#define UCR3_RXDSEN (1<<6) /* Receive status interrupt enable */
+#define UCR3_AIRINTEN (1<<5) /* Async IR wake interrupt enable */
+#define UCR3_AWAKEN (1<<4) /* Async wake interrupt enable */
+#define UCR3_REF25 (1<<3) /* Ref freq 25 MHz */
+#define UCR3_REF30 (1<<2) /* Ref Freq 30 MHz */
+#define UCR3_INVT (1<<1) /* Inverted Infrared transmission */
+#define UCR3_BPEN (1<<0) /* Preset registers enable */
+#define UCR4_CTSTL_32 (32<<10) /* CTS trigger level (32 chars) */
+#define UCR4_INVR (1<<9) /* Inverted infrared reception */
+#define UCR4_ENIRI (1<<8) /* Serial infrared interrupt enable */
+#define UCR4_WKEN (1<<7) /* Wake interrupt enable */
+#define UCR4_REF16 (1<<6) /* Ref freq 16 MHz */
+#define UCR4_IRSC (1<<5) /* IR special case */
+#define UCR4_TCEN (1<<3) /* Transmit complete interrupt enable */
+#define UCR4_BKEN (1<<2) /* Break condition interrupt enable */
+#define UCR4_OREN (1<<1) /* Receiver overrun interrupt enable */
+#define UCR4_DREN (1<<0) /* Recv data ready interrupt enable */
+#define UFCR_RXTL_SHF 0 /* Receiver trigger level shift */
+#define UFCR_RFDIV (7<<7) /* Reference freq divider mask */
+#define UFCR_RFDIV_SHF 7 /* Reference freq divider shift */
+#define RFDIV 4 /* divide input clock by 2 */
+#define UFCR_DCEDTE (1<<6) /* DTE mode select */
+#define UFCR_TXTL_SHF 10 /* Transmitter trigger level shift */
+#define USR1_PARITYERR (1<<15) /* Parity error interrupt flag */
+#define USR1_RTSS (1<<14) /* RTS pin status */
+#define USR1_TRDY (1<<13) /* Transmitter ready interrupt/dma flag */
+#define USR1_RTSD (1<<12) /* RTS delta */
+#define USR1_ESCF (1<<11) /* Escape seq interrupt flag */
+#define USR1_FRAMERR (1<<10) /* Frame error interrupt flag */
+#define USR1_RRDY (1<<9) /* Receiver ready interrupt/dma flag */
+#define USR1_TIMEOUT (1<<7) /* Receive timeout interrupt status */
+#define USR1_RXDS (1<<6) /* Receiver idle interrupt flag */
+#define USR1_AIRINT (1<<5) /* Async IR wake interrupt flag */
+#define USR1_AWAKE (1<<4) /* Aysnc wake interrupt flag */
+#define USR2_ADET (1<<15) /* Auto baud rate detect complete */
+#define USR2_TXFE (1<<14) /* Transmit buffer FIFO empty */
+#define USR2_DTRF (1<<13) /* DTR edge interrupt flag */
+#define USR2_IDLE (1<<12) /* Idle condition */
+#define USR2_IRINT (1<<8) /* Serial infrared interrupt flag */
+#define USR2_WAKE (1<<7) /* Wake */
+#define USR2_RTSF (1<<4) /* RTS edge interrupt flag */
+#define USR2_TXDC (1<<3) /* Transmitter complete */
+#define USR2_BRCD (1<<2) /* Break condition */
+#define USR2_ORE (1<<1) /* Overrun error */
+#define USR2_RDR (1<<0) /* Recv data ready */
+#define UTS_FRCPERR (1<<13) /* Force parity error */
+#define UTS_LOOP (1<<12) /* Loop tx and rx */
+#define UTS_TXEMPTY (1<<6) /* TxFIFO empty */
+#define UTS_RXEMPTY (1<<5) /* RxFIFO empty */
+#define UTS_TXFULL (1<<4) /* TxFIFO full */
+#define UTS_RXFULL (1<<3) /* RxFIFO full */
+#define UTS_SOFTRS (1<<0) /* Software reset */
+#define TXTL 2 /* reset default */
+#define RXTL 1 /* reset default */
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct mxc_uart {
+ u32 rxd;
+ u32 spare0[15];
+
+ u32 txd;
+ u32 spare1[15];
+
+ u32 cr1;
+ u32 cr2;
+ u32 cr3;
+ u32 cr4;
+
+ u32 fcr;
+ u32 sr1;
+ u32 sr2;
+ u32 esc;
+
+ u32 tim;
+ u32 bir;
+ u32 bmr;
+ u32 brc;
+
+ u32 onems;
+ u32 ts;
+};
+
+static void _mxc_serial_init(struct mxc_uart *base, int use_dte)
+{
+ writel(0, &base->cr1);
+ writel(0, &base->cr2);
+
+ while (!(readl(&base->cr2) & UCR2_SRST));
+
+ if (use_dte)
+ writel(0x404 | UCR3_ADNIMP, &base->cr3);
+ else
+ writel(0x704 | UCR3_ADNIMP, &base->cr3);
+
+ writel(0x704 | UCR3_ADNIMP, &base->cr3);
+ writel(0x8000, &base->cr4);
+ writel(0x2b, &base->esc);
+ writel(0, &base->tim);
+
+ writel(0, &base->ts);
+}
+
+static void _mxc_serial_setbrg(struct mxc_uart *base, unsigned long clk,
+ unsigned long baudrate, bool use_dte)
+{
+ u32 tmp;
+
+ tmp = RFDIV << UFCR_RFDIV_SHF;
+ if (use_dte)
+ tmp |= UFCR_DCEDTE;
+ else
+ tmp |= (TXTL << UFCR_TXTL_SHF) | (RXTL << UFCR_RXTL_SHF);
+ writel(tmp, &base->fcr);
+
+ writel(0xf, &base->bir);
+ writel(clk / (2 * baudrate), &base->bmr);
+
+ writel(UCR2_WS | UCR2_IRTS | UCR2_RXEN | UCR2_TXEN | UCR2_SRST,
+ &base->cr2);
+ writel(UCR1_UARTEN, &base->cr1);
+}
+
+#if !CONFIG_IS_ENABLED(DM_SERIAL)
+
+#ifndef CONFIG_MXC_UART_BASE
+#error "define CONFIG_MXC_UART_BASE to use the MXC UART driver"
+#endif
+
+#define mxc_base ((struct mxc_uart *)CONFIG_MXC_UART_BASE)
+
+static void mxc_serial_setbrg(void)
+{
+ u32 clk = imx_get_uartclk();
+
+ if (!gd->baudrate)
+ gd->baudrate = CONFIG_BAUDRATE;
+
+ _mxc_serial_setbrg(mxc_base, clk, gd->baudrate, false);
+}
+
+static int mxc_serial_getc(void)
+{
+ while (readl(&mxc_base->ts) & UTS_RXEMPTY)
+ WATCHDOG_RESET();
+ return (readl(&mxc_base->rxd) & URXD_RX_DATA); /* mask out status from upper word */
+}
+
+static void mxc_serial_putc(const char c)
+{
+ /* If \n, also do \r */
+ if (c == '\n')
+ serial_putc('\r');
+
+ writel(c, &mxc_base->txd);
+
+ /* wait for transmitter to be ready */
+ while (!(readl(&mxc_base->ts) & UTS_TXEMPTY))
+ WATCHDOG_RESET();
+}
+
+/* Test whether a character is in the RX buffer */
+static int mxc_serial_tstc(void)
+{
+ /* If receive fifo is empty, return false */
+ if (readl(&mxc_base->ts) & UTS_RXEMPTY)
+ return 0;
+ return 1;
+}
+
+/*
+ * Initialise the serial port with the given baudrate. The settings
+ * are always 8 data bits, no parity, 1 stop bit, no start bits.
+ */
+static int mxc_serial_init(void)
+{
+ _mxc_serial_init(mxc_base, false);
+
+ serial_setbrg();
+
+ return 0;
+}
+
+static struct serial_device mxc_serial_drv = {
+ .name = "mxc_serial",
+ .start = mxc_serial_init,
+ .stop = NULL,
+ .setbrg = mxc_serial_setbrg,
+ .putc = mxc_serial_putc,
+ .puts = default_serial_puts,
+ .getc = mxc_serial_getc,
+ .tstc = mxc_serial_tstc,
+};
+
+void mxc_serial_initialize(void)
+{
+ serial_register(&mxc_serial_drv);
+}
+
+__weak struct serial_device *default_serial_console(void)
+{
+ return &mxc_serial_drv;
+}
+#endif
+
+#if CONFIG_IS_ENABLED(DM_SERIAL)
+
+int mxc_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ struct mxc_serial_plat *plat = dev_get_plat(dev);
+ u32 clk = imx_get_uartclk();
+
+ _mxc_serial_setbrg(plat->reg, clk, baudrate, plat->use_dte);
+
+ return 0;
+}
+
+static int mxc_serial_probe(struct udevice *dev)
+{
+ struct mxc_serial_plat *plat = dev_get_plat(dev);
+
+ _mxc_serial_init(plat->reg, plat->use_dte);
+
+ return 0;
+}
+
+static int mxc_serial_getc(struct udevice *dev)
+{
+ struct mxc_serial_plat *plat = dev_get_plat(dev);
+ struct mxc_uart *const uart = plat->reg;
+
+ if (readl(&uart->ts) & UTS_RXEMPTY)
+ return -EAGAIN;
+
+ return readl(&uart->rxd) & URXD_RX_DATA;
+}
+
+static int mxc_serial_putc(struct udevice *dev, const char ch)
+{
+ struct mxc_serial_plat *plat = dev_get_plat(dev);
+ struct mxc_uart *const uart = plat->reg;
+
+ if (!(readl(&uart->ts) & UTS_TXEMPTY))
+ return -EAGAIN;
+
+ writel(ch, &uart->txd);
+
+ return 0;
+}
+
+static int mxc_serial_pending(struct udevice *dev, bool input)
+{
+ struct mxc_serial_plat *plat = dev_get_plat(dev);
+ struct mxc_uart *const uart = plat->reg;
+ uint32_t sr2 = readl(&uart->sr2);
+
+ if (input)
+ return sr2 & USR2_RDR ? 1 : 0;
+ else
+ return sr2 & USR2_TXDC ? 0 : 1;
+}
+
+static const struct dm_serial_ops mxc_serial_ops = {
+ .putc = mxc_serial_putc,
+ .pending = mxc_serial_pending,
+ .getc = mxc_serial_getc,
+ .setbrg = mxc_serial_setbrg,
+};
+
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+static int mxc_serial_of_to_plat(struct udevice *dev)
+{
+ struct mxc_serial_plat *plat = dev_get_plat(dev);
+ fdt_addr_t addr;
+
+ addr = dev_read_addr(dev);
+ if (addr == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ plat->reg = (struct mxc_uart *)addr;
+
+ plat->use_dte = fdtdec_get_bool(gd->fdt_blob, dev_of_offset(dev),
+ "fsl,dte-mode");
+ return 0;
+}
+
+static const struct udevice_id mxc_serial_ids[] = {
+ { .compatible = "fsl,imx21-uart" },
+ { .compatible = "fsl,imx53-uart" },
+ { .compatible = "fsl,imx6sx-uart" },
+ { .compatible = "fsl,imx6ul-uart" },
+ { .compatible = "fsl,imx7d-uart" },
+ { .compatible = "fsl,imx6q-uart" },
+ { }
+};
+#endif
+
+U_BOOT_DRIVER(serial_mxc) = {
+ .name = "serial_mxc",
+ .id = UCLASS_SERIAL,
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+ .of_match = mxc_serial_ids,
+ .of_to_plat = mxc_serial_of_to_plat,
+ .plat_auto = sizeof(struct mxc_serial_plat),
+#endif
+ .probe = mxc_serial_probe,
+ .ops = &mxc_serial_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
+#endif
+
+#ifdef CONFIG_DEBUG_UART_MXC
+#include <debug_uart.h>
+
+static inline void _debug_uart_init(void)
+{
+ struct mxc_uart *base = (struct mxc_uart *)CONFIG_DEBUG_UART_BASE;
+
+ _mxc_serial_init(base, false);
+ _mxc_serial_setbrg(base, CONFIG_DEBUG_UART_CLOCK,
+ CONFIG_BAUDRATE, false);
+}
+
+static inline void _debug_uart_putc(int ch)
+{
+ struct mxc_uart *base = (struct mxc_uart *)CONFIG_DEBUG_UART_BASE;
+
+ while (!(readl(&base->ts) & UTS_TXEMPTY))
+ WATCHDOG_RESET();
+
+ writel(ch, &base->txd);
+}
+
+DEBUG_UART_FUNCS
+
+#endif
diff --git a/roms/u-boot/drivers/serial/serial_ns16550.c b/roms/u-boot/drivers/serial/serial_ns16550.c
new file mode 100644
index 000000000..97b6a4ff4
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_ns16550.c
@@ -0,0 +1,254 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000
+ * Rob Taylor, Flying Pig Systems. robt@flyingpig.com.
+ */
+
+#include <common.h>
+#include <clock_legacy.h>
+#include <ns16550.h>
+#include <serial.h>
+#include <asm/global_data.h>
+#include <linux/compiler.h>
+
+#ifndef CONFIG_NS16550_MIN_FUNCTIONS
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if !defined(CONFIG_CONS_INDEX)
+#elif (CONFIG_CONS_INDEX < 1) || (CONFIG_CONS_INDEX > 6)
+#error "Invalid console index value."
+#endif
+
+#if CONFIG_CONS_INDEX == 1 && !defined(CONFIG_SYS_NS16550_COM1)
+#error "Console port 1 defined but not configured."
+#elif CONFIG_CONS_INDEX == 2 && !defined(CONFIG_SYS_NS16550_COM2)
+#error "Console port 2 defined but not configured."
+#elif CONFIG_CONS_INDEX == 3 && !defined(CONFIG_SYS_NS16550_COM3)
+#error "Console port 3 defined but not configured."
+#elif CONFIG_CONS_INDEX == 4 && !defined(CONFIG_SYS_NS16550_COM4)
+#error "Console port 4 defined but not configured."
+#elif CONFIG_CONS_INDEX == 5 && !defined(CONFIG_SYS_NS16550_COM5)
+#error "Console port 5 defined but not configured."
+#elif CONFIG_CONS_INDEX == 6 && !defined(CONFIG_SYS_NS16550_COM6)
+#error "Console port 6 defined but not configured."
+#endif
+
+/* Note: The port number specified in the functions is 1 based.
+ * the array is 0 based.
+ */
+static struct ns16550 *serial_ports[6] = {
+#ifdef CONFIG_SYS_NS16550_COM1
+ (struct ns16550 *)CONFIG_SYS_NS16550_COM1,
+#else
+ NULL,
+#endif
+#ifdef CONFIG_SYS_NS16550_COM2
+ (struct ns16550 *)CONFIG_SYS_NS16550_COM2,
+#else
+ NULL,
+#endif
+#ifdef CONFIG_SYS_NS16550_COM3
+ (struct ns16550 *)CONFIG_SYS_NS16550_COM3,
+#else
+ NULL,
+#endif
+#ifdef CONFIG_SYS_NS16550_COM4
+ (struct ns16550 *)CONFIG_SYS_NS16550_COM4,
+#else
+ NULL,
+#endif
+#ifdef CONFIG_SYS_NS16550_COM5
+ (struct ns16550 *)CONFIG_SYS_NS16550_COM5,
+#else
+ NULL,
+#endif
+#ifdef CONFIG_SYS_NS16550_COM6
+ (struct ns16550 *)CONFIG_SYS_NS16550_COM6
+#else
+ NULL
+#endif
+};
+
+#define PORT serial_ports[port-1]
+
+/* Multi serial device functions */
+#define DECLARE_ESERIAL_FUNCTIONS(port) \
+ static int eserial##port##_init(void) \
+ { \
+ int clock_divisor; \
+ clock_divisor = ns16550_calc_divisor(serial_ports[port-1], \
+ CONFIG_SYS_NS16550_CLK, gd->baudrate); \
+ ns16550_init(serial_ports[port - 1], clock_divisor); \
+ return 0 ; \
+ } \
+ static void eserial##port##_setbrg(void) \
+ { \
+ serial_setbrg_dev(port); \
+ } \
+ static int eserial##port##_getc(void) \
+ { \
+ return serial_getc_dev(port); \
+ } \
+ static int eserial##port##_tstc(void) \
+ { \
+ return serial_tstc_dev(port); \
+ } \
+ static void eserial##port##_putc(const char c) \
+ { \
+ serial_putc_dev(port, c); \
+ } \
+ static void eserial##port##_puts(const char *s) \
+ { \
+ serial_puts_dev(port, s); \
+ }
+
+/* Serial device descriptor */
+#define INIT_ESERIAL_STRUCTURE(port, __name) { \
+ .name = __name, \
+ .start = eserial##port##_init, \
+ .stop = NULL, \
+ .setbrg = eserial##port##_setbrg, \
+ .getc = eserial##port##_getc, \
+ .tstc = eserial##port##_tstc, \
+ .putc = eserial##port##_putc, \
+ .puts = eserial##port##_puts, \
+}
+
+static void _serial_putc(const char c, const int port)
+{
+ if (c == '\n')
+ ns16550_putc(PORT, '\r');
+
+ ns16550_putc(PORT, c);
+}
+
+static void _serial_puts(const char *s, const int port)
+{
+ while (*s) {
+ _serial_putc(*s++, port);
+ }
+}
+
+static int _serial_getc(const int port)
+{
+ return ns16550_getc(PORT);
+}
+
+static int _serial_tstc(const int port)
+{
+ return ns16550_tstc(PORT);
+}
+
+static void _serial_setbrg(const int port)
+{
+ int clock_divisor;
+
+ clock_divisor = ns16550_calc_divisor(PORT, CONFIG_SYS_NS16550_CLK,
+ gd->baudrate);
+ ns16550_reinit(PORT, clock_divisor);
+}
+
+static inline void
+serial_putc_dev(unsigned int dev_index,const char c)
+{
+ _serial_putc(c,dev_index);
+}
+
+static inline void
+serial_puts_dev(unsigned int dev_index,const char *s)
+{
+ _serial_puts(s,dev_index);
+}
+
+static inline int
+serial_getc_dev(unsigned int dev_index)
+{
+ return _serial_getc(dev_index);
+}
+
+static inline int
+serial_tstc_dev(unsigned int dev_index)
+{
+ return _serial_tstc(dev_index);
+}
+
+static inline void
+serial_setbrg_dev(unsigned int dev_index)
+{
+ _serial_setbrg(dev_index);
+}
+
+#if defined(CONFIG_SYS_NS16550_COM1)
+DECLARE_ESERIAL_FUNCTIONS(1);
+struct serial_device eserial1_device =
+ INIT_ESERIAL_STRUCTURE(1, "eserial0");
+#endif
+#if defined(CONFIG_SYS_NS16550_COM2)
+DECLARE_ESERIAL_FUNCTIONS(2);
+struct serial_device eserial2_device =
+ INIT_ESERIAL_STRUCTURE(2, "eserial1");
+#endif
+#if defined(CONFIG_SYS_NS16550_COM3)
+DECLARE_ESERIAL_FUNCTIONS(3);
+struct serial_device eserial3_device =
+ INIT_ESERIAL_STRUCTURE(3, "eserial2");
+#endif
+#if defined(CONFIG_SYS_NS16550_COM4)
+DECLARE_ESERIAL_FUNCTIONS(4);
+struct serial_device eserial4_device =
+ INIT_ESERIAL_STRUCTURE(4, "eserial3");
+#endif
+#if defined(CONFIG_SYS_NS16550_COM5)
+DECLARE_ESERIAL_FUNCTIONS(5);
+struct serial_device eserial5_device =
+ INIT_ESERIAL_STRUCTURE(5, "eserial4");
+#endif
+#if defined(CONFIG_SYS_NS16550_COM6)
+DECLARE_ESERIAL_FUNCTIONS(6);
+struct serial_device eserial6_device =
+ INIT_ESERIAL_STRUCTURE(6, "eserial5");
+#endif
+
+__weak struct serial_device *default_serial_console(void)
+{
+#if CONFIG_CONS_INDEX == 1
+ return &eserial1_device;
+#elif CONFIG_CONS_INDEX == 2
+ return &eserial2_device;
+#elif CONFIG_CONS_INDEX == 3
+ return &eserial3_device;
+#elif CONFIG_CONS_INDEX == 4
+ return &eserial4_device;
+#elif CONFIG_CONS_INDEX == 5
+ return &eserial5_device;
+#elif CONFIG_CONS_INDEX == 6
+ return &eserial6_device;
+#else
+#error "Bad CONFIG_CONS_INDEX."
+#endif
+}
+
+void ns16550_serial_initialize(void)
+{
+#if defined(CONFIG_SYS_NS16550_COM1)
+ serial_register(&eserial1_device);
+#endif
+#if defined(CONFIG_SYS_NS16550_COM2)
+ serial_register(&eserial2_device);
+#endif
+#if defined(CONFIG_SYS_NS16550_COM3)
+ serial_register(&eserial3_device);
+#endif
+#if defined(CONFIG_SYS_NS16550_COM4)
+ serial_register(&eserial4_device);
+#endif
+#if defined(CONFIG_SYS_NS16550_COM5)
+ serial_register(&eserial5_device);
+#endif
+#if defined(CONFIG_SYS_NS16550_COM6)
+ serial_register(&eserial6_device);
+#endif
+}
+
+#endif /* !CONFIG_NS16550_MIN_FUNCTIONS */
diff --git a/roms/u-boot/drivers/serial/serial_nulldev.c b/roms/u-boot/drivers/serial/serial_nulldev.c
new file mode 100644
index 000000000..efae14dd6
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_nulldev.c
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2015 National Instruments
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <serial.h>
+
+static int nulldev_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ return 0;
+}
+
+static int nulldev_serial_getc(struct udevice *dev)
+{
+ return -EAGAIN;
+}
+
+static int nulldev_serial_pending(struct udevice *dev, bool input)
+{
+ return 0;
+}
+
+static int nulldev_serial_input(struct udevice *dev)
+{
+ return 0;
+}
+
+static int nulldev_serial_putc(struct udevice *dev, const char ch)
+{
+ return 0;
+}
+
+static const struct udevice_id nulldev_serial_ids[] = {
+ { .compatible = "nulldev-serial" },
+ { }
+};
+
+
+const struct dm_serial_ops nulldev_serial_ops = {
+ .putc = nulldev_serial_putc,
+ .pending = nulldev_serial_pending,
+ .getc = nulldev_serial_getc,
+ .setbrg = nulldev_serial_setbrg,
+};
+
+U_BOOT_DRIVER(serial_nulldev) = {
+ .name = "serial_nulldev",
+ .id = UCLASS_SERIAL,
+ .of_match = nulldev_serial_ids,
+ .ops = &nulldev_serial_ops,
+};
diff --git a/roms/u-boot/drivers/serial/serial_octeon_bootcmd.c b/roms/u-boot/drivers/serial/serial_octeon_bootcmd.c
new file mode 100644
index 000000000..4bcff77eb
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_octeon_bootcmd.c
@@ -0,0 +1,182 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Marvell International Ltd.
+ * Copyright (C) 2021 Stefan Roese <sr@denx.de>
+ */
+
+#include <dm.h>
+#include <dm/uclass.h>
+#include <errno.h>
+#include <input.h>
+#include <iomux.h>
+#include <log.h>
+#include <serial.h>
+#include <stdio_dev.h>
+#include <string.h>
+#include <watchdog.h>
+#include <linux/delay.h>
+#include <asm/addrspace.h>
+#include <asm/io.h>
+#include <mach/cvmx-regs.h>
+#include <mach/cvmx-bootmem.h>
+
+#define DRIVER_NAME "pci-bootcmd"
+
+/*
+ * Important:
+ * This address cannot be changed as the PCI console tool relies on exactly
+ * this value!
+ */
+#define BOOTLOADER_PCI_READ_BUFFER_BASE 0x6c000
+#define BOOTLOADER_PCI_READ_BUFFER_SIZE 256
+#define BOOTLOADER_PCI_WRITE_BUFFER_SIZE 256
+
+#define BOOTLOADER_PCI_READ_BUFFER_STR_LEN \
+ (BOOTLOADER_PCI_READ_BUFFER_SIZE - 8)
+#define BOOTLOADER_PCI_WRITE_BUFFER_STR_LEN \
+ (BOOTLOADER_PCI_WRITE_BUFFER_SIZE - 8)
+
+#define BOOTLOADER_PCI_READ_BUFFER_OWNER_ADDR \
+ (BOOTLOADER_PCI_READ_BUFFER_BASE + 0)
+#define BOOTLOADER_PCI_READ_BUFFER_LEN_ADDR \
+ (BOOTLOADER_PCI_READ_BUFFER_BASE + 4)
+#define BOOTLOADER_PCI_READ_BUFFER_DATA_ADDR \
+ (BOOTLOADER_PCI_READ_BUFFER_BASE + 8)
+
+enum octeon_pci_io_buf_owner {
+ /* Must be zero, set when memory cleared */
+ OCTEON_PCI_IO_BUF_OWNER_INVALID = 0,
+ OCTEON_PCI_IO_BUF_OWNER_OCTEON = 1,
+ OCTEON_PCI_IO_BUF_OWNER_HOST = 2,
+};
+
+/* Structure for bootloader PCI IO buffers */
+struct octeon_pci_io_buf {
+ u32 owner;
+ u32 len;
+ char data[0];
+};
+
+struct octeon_bootcmd_priv {
+ bool started;
+ int copy_offset;
+ bool eol;
+ bool unlocked;
+ struct octeon_pci_io_buf *buf;
+};
+
+static int octeon_bootcmd_pending(struct udevice *dev, bool input)
+{
+ struct octeon_bootcmd_priv *priv = dev_get_priv(dev);
+
+ if (!input)
+ return 0;
+
+ if (priv->eol)
+ return 1;
+
+ CVMX_SYNC;
+ if (priv->buf->owner != OCTEON_PCI_IO_BUF_OWNER_OCTEON)
+ return 0;
+
+ if (priv->buf->len > priv->copy_offset &&
+ (priv->buf->data[priv->copy_offset] != '\0'))
+ return 1;
+
+ return 0;
+}
+
+static int octeon_bootcmd_getc(struct udevice *dev)
+{
+ struct octeon_bootcmd_priv *priv = dev_get_priv(dev);
+ char c;
+
+ /* There's no EOL for boot commands so we fake it. */
+ if (priv->eol) {
+ priv->eol = false;
+ return '\n';
+ }
+
+ while (!octeon_bootcmd_pending(dev, true)) {
+ WATCHDOG_RESET();
+ /*
+ * ToDo:
+ * The original code calls octeon_board_poll() here. We may
+ * need to implement something similar here.
+ */
+ udelay(100);
+ }
+
+ c = priv->buf->data[priv->copy_offset];
+ priv->buf->data[priv->copy_offset++] = '\0';
+
+ if (priv->copy_offset >= min_t(int, CONFIG_SYS_CBSIZE - 1,
+ BOOTLOADER_PCI_READ_BUFFER_STR_LEN - 1) ||
+ (priv->buf->data[priv->copy_offset] == '\0')) {
+ priv->copy_offset = 0;
+ priv->buf->len = 0;
+ priv->buf->owner = OCTEON_PCI_IO_BUF_OWNER_HOST;
+ priv->eol = true;
+ CVMX_SYNC;
+ }
+
+ return c;
+}
+
+static const struct dm_serial_ops octeon_bootcmd_ops = {
+ .getc = octeon_bootcmd_getc,
+ .pending = octeon_bootcmd_pending,
+};
+
+static int octeon_bootcmd_probe(struct udevice *dev)
+{
+ struct octeon_bootcmd_priv *priv = dev_get_priv(dev);
+
+ priv->buf = (void *)CKSEG0ADDR(BOOTLOADER_PCI_READ_BUFFER_BASE);
+ memset(priv->buf, 0, BOOTLOADER_PCI_READ_BUFFER_SIZE);
+ priv->eol = false;
+
+ /*
+ * When the bootcmd console is first started it is started as locked to
+ * block any calls sending a command until U-Boot is ready to accept
+ * commands. Just before the main loop starts to accept commands the
+ * bootcmd console is unlocked.
+ */
+ if (priv->unlocked)
+ priv->buf->owner = OCTEON_PCI_IO_BUF_OWNER_HOST;
+ else
+ priv->buf->owner = OCTEON_PCI_IO_BUF_OWNER_OCTEON;
+
+ debug("%s called, buffer ptr: 0x%p, owner: %s\n", __func__,
+ priv->buf,
+ priv->buf->owner == OCTEON_PCI_IO_BUF_OWNER_HOST ?
+ "host" : "octeon");
+ debug("&priv->copy_offset: 0x%p\n", &priv->copy_offset);
+ CVMX_SYNC;
+
+ /*
+ * Perhaps reinvestige this: In the original code, "unlocked" etc
+ * is set in the octeon_pci_bootcmd_unlock() function called very
+ * late.
+ */
+ priv->buf->owner = OCTEON_PCI_IO_BUF_OWNER_HOST;
+ priv->unlocked = true;
+ priv->started = true;
+ CVMX_SYNC;
+
+ return 0;
+}
+
+static const struct udevice_id octeon_bootcmd_serial_id[] = {
+ { .compatible = "marvell,pci-bootcmd", },
+ { },
+};
+
+U_BOOT_DRIVER(octeon_bootcmd) = {
+ .name = DRIVER_NAME,
+ .id = UCLASS_SERIAL,
+ .ops = &octeon_bootcmd_ops,
+ .of_match = of_match_ptr(octeon_bootcmd_serial_id),
+ .probe = octeon_bootcmd_probe,
+ .priv_auto = sizeof(struct octeon_bootcmd_priv),
+};
diff --git a/roms/u-boot/drivers/serial/serial_octeon_pcie_console.c b/roms/u-boot/drivers/serial/serial_octeon_pcie_console.c
new file mode 100644
index 000000000..c76e787d0
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_octeon_pcie_console.c
@@ -0,0 +1,365 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Marvell International Ltd.
+ * Copyright (C) 2021 Stefan Roese <sr@denx.de>
+ */
+
+#include <dm.h>
+#include <dm/uclass.h>
+#include <errno.h>
+#include <input.h>
+#include <iomux.h>
+#include <log.h>
+#include <serial.h>
+#include <stdio_dev.h>
+#include <string.h>
+#include <watchdog.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <mach/cvmx-regs.h>
+#include <mach/cvmx-bootmem.h>
+
+#define DRIVER_NAME "pci-console"
+#define OCTEONTX_PCIE_CONSOLE_NAME_LEN 16
+
+/* Current versions */
+#define OCTEON_PCIE_CONSOLE_MAJOR_VERSION 1
+#define OCTEON_PCIE_CONSOLE_MINOR_VERSION 0
+
+#define OCTEON_PCIE_CONSOLE_BLOCK_NAME "__pci_console"
+
+/*
+ * Structure that defines a single console.
+ * Note: when read_index == write_index, the buffer is empty.
+ * The actual usable size of each console is console_buf_size -1;
+ */
+struct octeon_pcie_console {
+ u64 input_base_addr;
+ u32 input_read_index;
+ u32 input_write_index;
+ u64 output_base_addr;
+ u32 output_read_index;
+ u32 output_write_index;
+ u32 lock;
+ u32 buf_size;
+};
+
+/*
+ * This is the main container structure that contains all the information
+ * about all PCI consoles. The address of this structure is passed to various
+ * routines that operation on PCI consoles.
+ */
+struct octeon_pcie_console_desc {
+ u32 major_version;
+ u32 minor_version;
+ u32 lock;
+ u32 flags;
+ u32 num_consoles;
+ u32 pad;
+ /* must be 64 bit aligned here... */
+ /* Array of addresses of octeon_pcie_console_t structures */
+ u64 console_addr_array[0];
+ /* Implicit storage for console_addr_array */
+};
+
+struct octeon_pcie_console_priv {
+ struct octeon_pcie_console *console;
+ int console_num;
+ bool console_active;
+};
+
+/* Flag definitions for read/write functions */
+enum {
+ /*
+ * If set, read/write functions won't block waiting for space or data.
+ * For reads, 0 bytes may be read, and for writes not all of the
+ * supplied data may be written.
+ */
+ OCT_PCI_CON_FLAG_NONBLOCK = 1 << 0,
+};
+
+static int buffer_free_bytes(u32 buffer_size, u32 wr_idx, u32 rd_idx)
+{
+ if (rd_idx >= buffer_size || wr_idx >= buffer_size)
+ return -1;
+
+ return ((buffer_size - 1) - (wr_idx - rd_idx)) % buffer_size;
+}
+
+static int buffer_avail_bytes(u32 buffer_size, u32 wr_idx, u32 rd_idx)
+{
+ if (rd_idx >= buffer_size || wr_idx >= buffer_size)
+ return -1;
+
+ return buffer_size - 1 - buffer_free_bytes(buffer_size, wr_idx, rd_idx);
+}
+
+static int buffer_read_avail(struct udevice *dev, unsigned int console_num)
+{
+ struct octeon_pcie_console_priv *priv = dev_get_priv(dev);
+ struct octeon_pcie_console *cons_ptr = priv->console;
+ int avail;
+
+ avail = buffer_avail_bytes(cons_ptr->buf_size,
+ cons_ptr->input_write_index,
+ cons_ptr->input_read_index);
+ if (avail >= 0)
+ return avail;
+
+ return 0;
+}
+
+static int octeon_pcie_console_read(struct udevice *dev,
+ unsigned int console_num, char *buffer,
+ int buffer_size, u32 flags)
+{
+ struct octeon_pcie_console_priv *priv = dev_get_priv(dev);
+ struct octeon_pcie_console *cons_ptr = priv->console;
+ int avail;
+ char *buf_ptr;
+ int bytes_read;
+ int read_size;
+
+ buf_ptr = (char *)cvmx_phys_to_ptr(cons_ptr->input_base_addr);
+
+ avail = buffer_avail_bytes(cons_ptr->buf_size,
+ cons_ptr->input_write_index,
+ cons_ptr->input_read_index);
+ if (avail < 0)
+ return avail;
+
+ if (!(flags & OCT_PCI_CON_FLAG_NONBLOCK)) {
+ /* Wait for some data to be available */
+ while (0 == (avail = buffer_avail_bytes(cons_ptr->buf_size,
+ cons_ptr->input_write_index,
+ cons_ptr->input_read_index))) {
+ mdelay(10);
+ WATCHDOG_RESET();
+ }
+ }
+
+ bytes_read = 0;
+
+ /* Don't overflow the buffer passed to us */
+ read_size = min_t(int, avail, buffer_size);
+
+ /* Limit ourselves to what we can input in a contiguous block */
+ if (cons_ptr->input_read_index + read_size >= cons_ptr->buf_size)
+ read_size = cons_ptr->buf_size - cons_ptr->input_read_index;
+
+ memcpy(buffer, buf_ptr + cons_ptr->input_read_index, read_size);
+ cons_ptr->input_read_index =
+ (cons_ptr->input_read_index + read_size) % cons_ptr->buf_size;
+ bytes_read += read_size;
+
+ /* Mark the PCIe console to be active from now on */
+ if (bytes_read)
+ priv->console_active = true;
+
+ return bytes_read;
+}
+
+static int octeon_pcie_console_write(struct udevice *dev,
+ unsigned int console_num,
+ const char *buffer,
+ int bytes_to_write, u32 flags)
+{
+ struct octeon_pcie_console_priv *priv = dev_get_priv(dev);
+ struct octeon_pcie_console *cons_ptr = priv->console;
+ int avail;
+ char *buf_ptr;
+ int bytes_written;
+
+ buf_ptr = (char *)cvmx_phys_to_ptr(cons_ptr->output_base_addr);
+ bytes_written = 0;
+ while (bytes_to_write > 0) {
+ avail = buffer_free_bytes(cons_ptr->buf_size,
+ cons_ptr->output_write_index,
+ cons_ptr->output_read_index);
+
+ if (avail > 0) {
+ int write_size = min_t(int, avail, bytes_to_write);
+
+ /*
+ * Limit ourselves to what we can output in a contiguous
+ * block
+ */
+ if (cons_ptr->output_write_index + write_size >=
+ cons_ptr->buf_size) {
+ write_size = cons_ptr->buf_size -
+ cons_ptr->output_write_index;
+ }
+
+ memcpy(buf_ptr + cons_ptr->output_write_index,
+ buffer + bytes_written, write_size);
+ /*
+ * Make sure data is visible before changing write
+ * index
+ */
+ CVMX_SYNCW;
+ cons_ptr->output_write_index =
+ (cons_ptr->output_write_index + write_size) %
+ cons_ptr->buf_size;
+ bytes_to_write -= write_size;
+ bytes_written += write_size;
+ } else if (avail == 0) {
+ /*
+ * Check to see if we should wait for room, or return
+ * after a partial write
+ */
+ if (flags & OCT_PCI_CON_FLAG_NONBLOCK)
+ goto done;
+
+ WATCHDOG_RESET();
+ mdelay(10); /* Delay if we are spinning */
+ } else {
+ bytes_written = -1;
+ goto done;
+ }
+ }
+
+done:
+ return bytes_written;
+}
+
+static struct octeon_pcie_console_desc *octeon_pcie_console_init(int num_consoles,
+ int buffer_size)
+{
+ struct octeon_pcie_console_desc *cons_desc_ptr;
+ struct octeon_pcie_console *cons_ptr;
+ s64 addr;
+ u64 avail_addr;
+ int alloc_size;
+ int i;
+
+ /* Compute size required for pci console structure */
+ alloc_size = num_consoles *
+ (buffer_size * 2 + sizeof(struct octeon_pcie_console) +
+ sizeof(u64)) + sizeof(struct octeon_pcie_console_desc);
+
+ /*
+ * Allocate memory for the consoles. This must be in the range
+ * addresssible by the bootloader.
+ * Try to do so in a manner which minimizes fragmentation. We try to
+ * put it at the top of DDR0 or bottom of DDR2 first, and only do
+ * generic allocation if those fail
+ */
+ addr = cvmx_bootmem_phy_named_block_alloc(alloc_size,
+ OCTEON_DDR0_SIZE - alloc_size - 128,
+ OCTEON_DDR0_SIZE, 128,
+ OCTEON_PCIE_CONSOLE_BLOCK_NAME,
+ CVMX_BOOTMEM_FLAG_END_ALLOC);
+ if (addr < 0) {
+ addr = cvmx_bootmem_phy_named_block_alloc(alloc_size, 0,
+ 0x1fffffff, 128,
+ OCTEON_PCIE_CONSOLE_BLOCK_NAME,
+ CVMX_BOOTMEM_FLAG_END_ALLOC);
+ }
+ if (addr < 0)
+ return 0;
+
+ cons_desc_ptr = cvmx_phys_to_ptr(addr);
+
+ /* Clear entire alloc'ed memory */
+ memset(cons_desc_ptr, 0, alloc_size);
+
+ /* Initialize as locked until we are done */
+ cons_desc_ptr->lock = 1;
+ CVMX_SYNCW;
+ cons_desc_ptr->num_consoles = num_consoles;
+ cons_desc_ptr->flags = 0;
+ cons_desc_ptr->major_version = OCTEON_PCIE_CONSOLE_MAJOR_VERSION;
+ cons_desc_ptr->minor_version = OCTEON_PCIE_CONSOLE_MINOR_VERSION;
+
+ avail_addr = addr + sizeof(struct octeon_pcie_console_desc) +
+ num_consoles * sizeof(u64);
+
+ for (i = 0; i < num_consoles; i++) {
+ cons_desc_ptr->console_addr_array[i] = avail_addr;
+ cons_ptr = (void *)cons_desc_ptr->console_addr_array[i];
+ avail_addr += sizeof(struct octeon_pcie_console);
+ cons_ptr->input_base_addr = avail_addr;
+ avail_addr += buffer_size;
+ cons_ptr->output_base_addr = avail_addr;
+ avail_addr += buffer_size;
+ cons_ptr->buf_size = buffer_size;
+ }
+ CVMX_SYNCW;
+ cons_desc_ptr->lock = 0;
+
+ return cvmx_phys_to_ptr(addr);
+}
+
+static int octeon_pcie_console_getc(struct udevice *dev)
+{
+ char c;
+
+ octeon_pcie_console_read(dev, 0, &c, 1, 0);
+ return c;
+}
+
+static int octeon_pcie_console_putc(struct udevice *dev, const char c)
+{
+ struct octeon_pcie_console_priv *priv = dev_get_priv(dev);
+
+ if (priv->console_active)
+ octeon_pcie_console_write(dev, 0, (char *)&c, 1, 0);
+
+ return 0;
+}
+
+static int octeon_pcie_console_pending(struct udevice *dev, bool input)
+{
+ if (input) {
+ udelay(100);
+ return buffer_read_avail(dev, 0) > 0;
+ }
+
+ return 0;
+}
+
+static const struct dm_serial_ops octeon_pcie_console_ops = {
+ .getc = octeon_pcie_console_getc,
+ .putc = octeon_pcie_console_putc,
+ .pending = octeon_pcie_console_pending,
+};
+
+static int octeon_pcie_console_probe(struct udevice *dev)
+{
+ struct octeon_pcie_console_priv *priv = dev_get_priv(dev);
+ struct octeon_pcie_console_desc *cons_desc;
+ int console_count;
+ int console_size;
+ int console_num;
+
+ /*
+ * Currently only 1 console is supported. Perhaps we need to add
+ * a console nexus if more than one needs to be supported.
+ */
+ console_count = 1;
+ console_size = 1024;
+ console_num = 0;
+
+ cons_desc = octeon_pcie_console_init(console_count, console_size);
+ priv->console =
+ cvmx_phys_to_ptr(cons_desc->console_addr_array[console_num]);
+
+ debug("PCI console init succeeded, %d consoles, %d bytes each\n",
+ console_count, console_size);
+
+ return 0;
+}
+
+static const struct udevice_id octeon_pcie_console_serial_id[] = {
+ { .compatible = "marvell,pci-console", },
+ { },
+};
+
+U_BOOT_DRIVER(octeon_pcie_console) = {
+ .name = DRIVER_NAME,
+ .id = UCLASS_SERIAL,
+ .ops = &octeon_pcie_console_ops,
+ .of_match = of_match_ptr(octeon_pcie_console_serial_id),
+ .probe = octeon_pcie_console_probe,
+ .priv_auto = sizeof(struct octeon_pcie_console_priv),
+};
diff --git a/roms/u-boot/drivers/serial/serial_omap.c b/roms/u-boot/drivers/serial/serial_omap.c
new file mode 100644
index 000000000..2b23ece44
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_omap.c
@@ -0,0 +1,171 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Texas Instruments' OMAP serial driver
+ *
+ * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+ * Lokesh Vutla <lokeshvutla@ti.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dt-structs.h>
+#include <log.h>
+#include <ns16550.h>
+#include <serial.h>
+#include <clk.h>
+#include <linux/err.h>
+
+#ifndef CONFIG_SYS_NS16550_CLK
+#define CONFIG_SYS_NS16550_CLK 0
+#endif
+
+#ifdef CONFIG_DEBUG_UART_OMAP
+
+#ifndef CONFIG_SYS_NS16550_IER
+#define CONFIG_SYS_NS16550_IER 0x00
+#endif
+
+#define UART_MCRVAL 0x00
+#define UART_LCRVAL UART_LCR_8N1
+
+static inline void serial_out_shift(void *addr, int shift, int value)
+{
+#ifdef CONFIG_SYS_NS16550_PORT_MAPPED
+ outb(value, (ulong)addr);
+#elif defined(CONFIG_SYS_NS16550_MEM32) && defined(CONFIG_SYS_LITTLE_ENDIAN)
+ out_le32(addr, value);
+#elif defined(CONFIG_SYS_NS16550_MEM32) && defined(CONFIG_SYS_BIG_ENDIAN)
+ out_be32(addr, value);
+#elif defined(CONFIG_SYS_NS16550_MEM32)
+ writel(value, addr);
+#elif defined(CONFIG_SYS_BIG_ENDIAN)
+ writeb(value, addr + (1 << shift) - 1);
+#else
+ writeb(value, addr);
+#endif
+}
+
+static inline int serial_in_shift(void *addr, int shift)
+{
+#ifdef CONFIG_SYS_NS16550_PORT_MAPPED
+ return inb((ulong)addr);
+#elif defined(CONFIG_SYS_NS16550_MEM32) && defined(CONFIG_SYS_LITTLE_ENDIAN)
+ return in_le32(addr);
+#elif defined(CONFIG_SYS_NS16550_MEM32) && defined(CONFIG_SYS_BIG_ENDIAN)
+ return in_be32(addr);
+#elif defined(CONFIG_SYS_NS16550_MEM32)
+ return readl(addr);
+#elif defined(CONFIG_SYS_BIG_ENDIAN)
+ return readb(addr + (1 << shift) - 1);
+#else
+ return readb(addr);
+#endif
+}
+
+#include <debug_uart.h>
+
+static inline void _debug_uart_init(void)
+{
+ struct ns16550 *com_port = (struct ns16550 *)CONFIG_DEBUG_UART_BASE;
+ int baud_divisor;
+
+ baud_divisor = ns16550_calc_divisor(com_port, CONFIG_DEBUG_UART_CLOCK,
+ CONFIG_BAUDRATE);
+ serial_dout(&com_port->ier, CONFIG_SYS_NS16550_IER);
+ serial_dout(&com_port->mdr1, 0x7);
+ serial_dout(&com_port->mcr, UART_MCRVAL);
+ serial_dout(&com_port->fcr, UART_FCR_DEFVAL);
+
+ serial_dout(&com_port->lcr, UART_LCR_BKSE | UART_LCRVAL);
+ serial_dout(&com_port->dll, baud_divisor & 0xff);
+ serial_dout(&com_port->dlm, (baud_divisor >> 8) & 0xff);
+ serial_dout(&com_port->lcr, UART_LCRVAL);
+ serial_dout(&com_port->mdr1, 0x0);
+}
+
+static inline void _debug_uart_putc(int ch)
+{
+ struct ns16550 *com_port = (struct ns16550 *)CONFIG_DEBUG_UART_BASE;
+
+ while (!(serial_din(&com_port->lsr) & UART_LSR_THRE))
+ ;
+ serial_dout(&com_port->thr, ch);
+}
+
+DEBUG_UART_FUNCS
+
+#endif
+
+#if CONFIG_IS_ENABLED(DM_SERIAL)
+
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
+static int omap_serial_of_to_plat(struct udevice *dev)
+{
+ struct ns16550_plat *plat = dev_get_plat(dev);
+ fdt_addr_t addr;
+ struct clk clk;
+ int err;
+
+ /* try Processor Local Bus device first */
+ addr = dev_read_addr(dev);
+ if (addr == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ plat->base = (unsigned long)map_physmem(addr, 0, MAP_NOCACHE);
+
+ plat->reg_offset = dev_read_u32_default(dev, "reg-offset", 0);
+ plat->reg_shift = 2;
+
+ err = clk_get_by_index(dev, 0, &clk);
+ if (!err) {
+ err = clk_get_rate(&clk);
+ if (!IS_ERR_VALUE(err))
+ plat->clock = err;
+ } else if (err != -ENOENT && err != -ENODEV && err != -ENOSYS) {
+ debug("omap serial failed to get clock\n");
+ return err;
+ }
+
+ if (!plat->clock)
+ plat->clock = dev_read_u32_default(dev, "clock-frequency",
+ CONFIG_SYS_NS16550_CLK);
+ if (!plat->clock) {
+ debug("omap serial clock not defined\n");
+ return -EINVAL;
+ }
+
+ plat->fcr = UART_FCR_DEFVAL;
+
+ return 0;
+}
+
+static const struct udevice_id omap_serial_ids[] = {
+ { .compatible = "ti,omap2-uart", },
+ { .compatible = "ti,omap3-uart", },
+ { .compatible = "ti,omap4-uart", },
+ { .compatible = "ti,am3352-uart", },
+ { .compatible = "ti,am4372-uart", },
+ { .compatible = "ti,dra742-uart", },
+ { .compatible = "ti,am654-uart", },
+ {}
+};
+#endif /* OF_CONTROL && !OF_PLATDATA */
+
+#if CONFIG_IS_ENABLED(SERIAL_PRESENT)
+U_BOOT_DRIVER(omap_serial) = {
+ .name = "omap_serial",
+ .id = UCLASS_SERIAL,
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
+ .of_match = omap_serial_ids,
+ .of_to_plat = omap_serial_of_to_plat,
+ .plat_auto = sizeof(struct ns16550_plat),
+#endif
+ .priv_auto = sizeof(struct ns16550),
+ .probe = ns16550_serial_probe,
+ .ops = &ns16550_serial_ops,
+#if !CONFIG_IS_ENABLED(OF_CONTROL)
+ .flags = DM_FLAG_PRE_RELOC,
+#endif
+};
+#endif
+#endif /* DM_SERIAL */
diff --git a/roms/u-boot/drivers/serial/serial_owl.c b/roms/u-boot/drivers/serial/serial_owl.c
new file mode 100644
index 000000000..3b795785f
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_owl.c
@@ -0,0 +1,136 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Actions Semi OWL SoCs UART driver
+ *
+ * Copyright (C) 2015 Actions Semi Co., Ltd.
+ * Copyright (C) 2018 Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <serial.h>
+#include <asm/io.h>
+#include <asm/types.h>
+#include <linux/bitops.h>
+
+/* UART Registers */
+#define OWL_UART_CTL (0x0000)
+#define OWL_UART_RXDAT (0x0004)
+#define OWL_UART_TXDAT (0x0008)
+#define OWL_UART_STAT (0x000C)
+
+/* UART_CTL Register Definitions */
+#define OWL_UART_CTL_PRS_NONE GENMASK(6, 4)
+#define OWL_UART_CTL_STPS BIT(2)
+#define OWL_UART_CTL_DWLS 3
+
+/* UART_STAT Register Definitions */
+#define OWL_UART_STAT_TFES BIT(10) /* TX FIFO Empty Status */
+#define OWL_UART_STAT_RFFS BIT(9) /* RX FIFO full Status */
+#define OWL_UART_STAT_TFFU BIT(6) /* TX FIFO full Status */
+#define OWL_UART_STAT_RFEM BIT(5) /* RX FIFO Empty Status */
+
+struct owl_serial_priv {
+ phys_addr_t base;
+};
+
+int owl_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ /* Driver supports only fixed baudrate */
+ return 0;
+}
+
+static int owl_serial_getc(struct udevice *dev)
+{
+ struct owl_serial_priv *priv = dev_get_priv(dev);
+
+ if (readl(priv->base + OWL_UART_STAT) & OWL_UART_STAT_RFEM)
+ return -EAGAIN;
+
+ return (int)(readl(priv->base + OWL_UART_RXDAT));
+}
+
+static int owl_serial_putc(struct udevice *dev, const char ch)
+{
+ struct owl_serial_priv *priv = dev_get_priv(dev);
+
+ if (readl(priv->base + OWL_UART_STAT) & OWL_UART_STAT_TFFU)
+ return -EAGAIN;
+
+ writel(ch, priv->base + OWL_UART_TXDAT);
+
+ return 0;
+}
+
+static int owl_serial_pending(struct udevice *dev, bool input)
+{
+ struct owl_serial_priv *priv = dev_get_priv(dev);
+ unsigned int stat = readl(priv->base + OWL_UART_STAT);
+
+ if (input)
+ return !(stat & OWL_UART_STAT_RFEM);
+ else
+ return !(stat & OWL_UART_STAT_TFES);
+}
+
+static int owl_serial_probe(struct udevice *dev)
+{
+ struct owl_serial_priv *priv = dev_get_priv(dev);
+ struct clk clk;
+ u32 uart_ctl;
+ int ret;
+
+ /* Set data, parity and stop bits */
+ uart_ctl = readl(priv->base + OWL_UART_CTL);
+ uart_ctl &= ~(OWL_UART_CTL_PRS_NONE);
+ uart_ctl &= ~(OWL_UART_CTL_STPS);
+ uart_ctl |= OWL_UART_CTL_DWLS;
+ writel(uart_ctl, priv->base + OWL_UART_CTL);
+
+ /* Enable UART clock */
+ ret = clk_get_by_index(dev, 0, &clk);
+ if (ret < 0)
+ return ret;
+
+ ret = clk_enable(&clk);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int owl_serial_of_to_plat(struct udevice *dev)
+{
+ struct owl_serial_priv *priv = dev_get_priv(dev);
+
+ priv->base = dev_read_addr(dev);
+ if (priv->base == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ return 0;
+}
+
+static const struct dm_serial_ops owl_serial_ops = {
+ .putc = owl_serial_putc,
+ .pending = owl_serial_pending,
+ .getc = owl_serial_getc,
+ .setbrg = owl_serial_setbrg,
+};
+
+static const struct udevice_id owl_serial_ids[] = {
+ { .compatible = "actions,owl-uart" },
+ { }
+};
+
+U_BOOT_DRIVER(serial_owl) = {
+ .name = "serial_owl",
+ .id = UCLASS_SERIAL,
+ .of_match = owl_serial_ids,
+ .of_to_plat = owl_serial_of_to_plat,
+ .priv_auto = sizeof(struct owl_serial_priv),
+ .probe = owl_serial_probe,
+ .ops = &owl_serial_ops,
+};
diff --git a/roms/u-boot/drivers/serial/serial_pic32.c b/roms/u-boot/drivers/serial/serial_pic32.c
new file mode 100644
index 000000000..ccdda9f03
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_pic32.c
@@ -0,0 +1,201 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (c) 2015 Paul Thacker <paul.thacker@microchip.com>
+ *
+ */
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <malloc.h>
+#include <serial.h>
+#include <wait_bit.h>
+#include <asm/global_data.h>
+#include <linux/bitops.h>
+#include <mach/pic32.h>
+#include <dt-bindings/clock/microchip,clock.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* UART Control Registers */
+#define U_MOD 0x00
+#define U_MODCLR (U_MOD + _CLR_OFFSET)
+#define U_MODSET (U_MOD + _SET_OFFSET)
+#define U_STA 0x10
+#define U_STACLR (U_STA + _CLR_OFFSET)
+#define U_STASET (U_STA + _SET_OFFSET)
+#define U_TXR 0x20
+#define U_RXR 0x30
+#define U_BRG 0x40
+
+/* U_MOD bits */
+#define UART_ENABLE BIT(15)
+
+/* U_STA bits */
+#define UART_RX_ENABLE BIT(12)
+#define UART_TX_BRK BIT(11)
+#define UART_TX_ENABLE BIT(10)
+#define UART_TX_FULL BIT(9)
+#define UART_TX_EMPTY BIT(8)
+#define UART_RX_OVER BIT(1)
+#define UART_RX_DATA_AVAIL BIT(0)
+
+struct pic32_uart_priv {
+ void __iomem *base;
+ ulong uartclk;
+};
+
+/*
+ * Initialize the serial port with the given baudrate.
+ * The settings are always 8 data bits, no parity, 1 stop bit, no start bits.
+ */
+static int pic32_serial_init(void __iomem *base, ulong clk, u32 baudrate)
+{
+ u32 div = DIV_ROUND_CLOSEST(clk, baudrate * 16);
+
+ /* wait for TX FIFO to empty */
+ wait_for_bit_le32(base + U_STA, UART_TX_EMPTY,
+ true, CONFIG_SYS_HZ, false);
+
+ /* send break */
+ writel(UART_TX_BRK, base + U_STASET);
+
+ /* disable and clear mode */
+ writel(0, base + U_MOD);
+ writel(0, base + U_STA);
+
+ /* set baud rate generator */
+ writel(div - 1, base + U_BRG);
+
+ /* enable the UART for TX and RX */
+ writel(UART_TX_ENABLE | UART_RX_ENABLE, base + U_STASET);
+
+ /* enable the UART */
+ writel(UART_ENABLE, base + U_MODSET);
+ return 0;
+}
+
+/* Check whether any char pending in RX fifo */
+static int pic32_uart_pending_input(void __iomem *base)
+{
+ /* check if rx buffer overrun error has occurred */
+ if (readl(base + U_STA) & UART_RX_OVER) {
+ readl(base + U_RXR);
+
+ /* clear overrun error to keep receiving */
+ writel(UART_RX_OVER, base + U_STACLR);
+ }
+
+ /* In PIC32 there is no way to know number of outstanding
+ * chars in rx-fifo. Only it can be known whether there is any.
+ */
+ return readl(base + U_STA) & UART_RX_DATA_AVAIL;
+}
+
+static int pic32_uart_pending(struct udevice *dev, bool input)
+{
+ struct pic32_uart_priv *priv = dev_get_priv(dev);
+
+ if (input)
+ return pic32_uart_pending_input(priv->base);
+
+ return !(readl(priv->base + U_STA) & UART_TX_EMPTY);
+}
+
+static int pic32_uart_setbrg(struct udevice *dev, int baudrate)
+{
+ struct pic32_uart_priv *priv = dev_get_priv(dev);
+
+ return pic32_serial_init(priv->base, priv->uartclk, baudrate);
+}
+
+static int pic32_uart_putc(struct udevice *dev, const char ch)
+{
+ struct pic32_uart_priv *priv = dev_get_priv(dev);
+
+ /* Check if Tx FIFO is full */
+ if (readl(priv->base + U_STA) & UART_TX_FULL)
+ return -EAGAIN;
+
+ /* pump the char to tx buffer */
+ writel(ch, priv->base + U_TXR);
+
+ return 0;
+}
+
+static int pic32_uart_getc(struct udevice *dev)
+{
+ struct pic32_uart_priv *priv = dev_get_priv(dev);
+
+ /* return error if RX fifo is empty */
+ if (!pic32_uart_pending_input(priv->base))
+ return -EAGAIN;
+
+ /* read the character from rx buffer */
+ return readl(priv->base + U_RXR) & 0xff;
+}
+
+static int pic32_uart_probe(struct udevice *dev)
+{
+ struct pic32_uart_priv *priv = dev_get_priv(dev);
+ struct clk clk;
+ fdt_addr_t addr;
+ fdt_size_t size;
+ int ret;
+
+ /* get address */
+ addr = fdtdec_get_addr_size(gd->fdt_blob, dev_of_offset(dev), "reg",
+ &size);
+ if (addr == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ priv->base = ioremap(addr, size);
+
+ /* get clock rate */
+ ret = clk_get_by_index(dev, 0, &clk);
+ if (ret < 0)
+ return ret;
+ priv->uartclk = clk_get_rate(&clk);
+ clk_free(&clk);
+
+ /* initialize serial */
+ return pic32_serial_init(priv->base, priv->uartclk, CONFIG_BAUDRATE);
+}
+
+static const struct dm_serial_ops pic32_uart_ops = {
+ .putc = pic32_uart_putc,
+ .pending = pic32_uart_pending,
+ .getc = pic32_uart_getc,
+ .setbrg = pic32_uart_setbrg,
+};
+
+static const struct udevice_id pic32_uart_ids[] = {
+ { .compatible = "microchip,pic32mzda-uart" },
+ {}
+};
+
+U_BOOT_DRIVER(pic32_serial) = {
+ .name = "pic32-uart",
+ .id = UCLASS_SERIAL,
+ .of_match = pic32_uart_ids,
+ .probe = pic32_uart_probe,
+ .ops = &pic32_uart_ops,
+ .priv_auto = sizeof(struct pic32_uart_priv),
+};
+
+#ifdef CONFIG_DEBUG_UART_PIC32
+#include <debug_uart.h>
+
+static inline void _debug_uart_init(void)
+{
+ void __iomem *base = (void __iomem *)CONFIG_DEBUG_UART_BASE;
+
+ pic32_serial_init(base, CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE);
+}
+
+static inline void _debug_uart_putc(int ch)
+{
+ writel(ch, CONFIG_DEBUG_UART_BASE + U_TXR);
+}
+
+DEBUG_UART_FUNCS
+#endif
diff --git a/roms/u-boot/drivers/serial/serial_pl01x.c b/roms/u-boot/drivers/serial/serial_pl01x.c
new file mode 100644
index 000000000..5283d5ed1
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_pl01x.c
@@ -0,0 +1,427 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000
+ * Rob Taylor, Flying Pig Systems. robt@flyingpig.com.
+ *
+ * (C) Copyright 2004
+ * ARM Ltd.
+ * Philippe Robin, <philippe.robin@arm.com>
+ */
+
+/* Simple U-Boot driver for the PrimeCell PL010/PL011 UARTs */
+
+#include <common.h>
+#include <asm/global_data.h>
+/* For get_bus_freq() */
+#include <clock_legacy.h>
+#include <dm.h>
+#include <clk.h>
+#include <errno.h>
+#include <watchdog.h>
+#include <asm/io.h>
+#include <serial.h>
+#include <dm/device_compat.h>
+#include <dm/platform_data/serial_pl01x.h>
+#include <linux/compiler.h>
+#include "serial_pl01x_internal.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifndef CONFIG_DM_SERIAL
+
+static volatile unsigned char *const port[] = CONFIG_PL01x_PORTS;
+static enum pl01x_type pl01x_type __section(".data");
+static struct pl01x_regs *base_regs __section(".data");
+#define NUM_PORTS (sizeof(port)/sizeof(port[0]))
+
+#endif
+
+static int pl01x_putc(struct pl01x_regs *regs, char c)
+{
+ /* Wait until there is space in the FIFO */
+ if (readl(&regs->fr) & UART_PL01x_FR_TXFF)
+ return -EAGAIN;
+
+ /* Send the character */
+ writel(c, &regs->dr);
+
+ return 0;
+}
+
+static int pl01x_getc(struct pl01x_regs *regs)
+{
+ unsigned int data;
+
+ /* Wait until there is data in the FIFO */
+ if (readl(&regs->fr) & UART_PL01x_FR_RXFE)
+ return -EAGAIN;
+
+ data = readl(&regs->dr);
+
+ /* Check for an error flag */
+ if (data & 0xFFFFFF00) {
+ /* Clear the error */
+ writel(0xFFFFFFFF, &regs->ecr);
+ return -1;
+ }
+
+ return (int) data;
+}
+
+static int pl01x_tstc(struct pl01x_regs *regs)
+{
+ WATCHDOG_RESET();
+ return !(readl(&regs->fr) & UART_PL01x_FR_RXFE);
+}
+
+static int pl01x_generic_serial_init(struct pl01x_regs *regs,
+ enum pl01x_type type)
+{
+ switch (type) {
+ case TYPE_PL010:
+ /* disable everything */
+ writel(0, &regs->pl010_cr);
+ break;
+ case TYPE_PL011:
+ /* disable everything */
+ writel(0, &regs->pl011_cr);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int pl011_set_line_control(struct pl01x_regs *regs)
+{
+ unsigned int lcr;
+ /*
+ * Internal update of baud rate register require line
+ * control register write
+ */
+ lcr = UART_PL011_LCRH_WLEN_8 | UART_PL011_LCRH_FEN;
+ writel(lcr, &regs->pl011_lcrh);
+ return 0;
+}
+
+static int pl01x_generic_setbrg(struct pl01x_regs *regs, enum pl01x_type type,
+ int clock, int baudrate)
+{
+ switch (type) {
+ case TYPE_PL010: {
+ unsigned int divisor;
+
+ /* disable everything */
+ writel(0, &regs->pl010_cr);
+
+ switch (baudrate) {
+ case 9600:
+ divisor = UART_PL010_BAUD_9600;
+ break;
+ case 19200:
+ divisor = UART_PL010_BAUD_19200;
+ break;
+ case 38400:
+ divisor = UART_PL010_BAUD_38400;
+ break;
+ case 57600:
+ divisor = UART_PL010_BAUD_57600;
+ break;
+ case 115200:
+ divisor = UART_PL010_BAUD_115200;
+ break;
+ default:
+ divisor = UART_PL010_BAUD_38400;
+ }
+
+ writel((divisor & 0xf00) >> 8, &regs->pl010_lcrm);
+ writel(divisor & 0xff, &regs->pl010_lcrl);
+
+ /*
+ * Set line control for the PL010 to be 8 bits, 1 stop bit,
+ * no parity, fifo enabled
+ */
+ writel(UART_PL010_LCRH_WLEN_8 | UART_PL010_LCRH_FEN,
+ &regs->pl010_lcrh);
+ /* Finally, enable the UART */
+ writel(UART_PL010_CR_UARTEN, &regs->pl010_cr);
+ break;
+ }
+ case TYPE_PL011: {
+ unsigned int temp;
+ unsigned int divider;
+ unsigned int remainder;
+ unsigned int fraction;
+
+ /* Without a valid clock rate we cannot set up the baudrate. */
+ if (clock) {
+ /*
+ * Set baud rate
+ *
+ * IBRD = UART_CLK / (16 * BAUD_RATE)
+ * FBRD = RND((64 * MOD(UART_CLK,(16 * BAUD_RATE)))
+ * / (16 * BAUD_RATE))
+ */
+ temp = 16 * baudrate;
+ divider = clock / temp;
+ remainder = clock % temp;
+ temp = (8 * remainder) / baudrate;
+ fraction = (temp >> 1) + (temp & 1);
+
+ writel(divider, &regs->pl011_ibrd);
+ writel(fraction, &regs->pl011_fbrd);
+ }
+
+ pl011_set_line_control(regs);
+ /* Finally, enable the UART */
+ writel(UART_PL011_CR_UARTEN | UART_PL011_CR_TXE |
+ UART_PL011_CR_RXE | UART_PL011_CR_RTS, &regs->pl011_cr);
+ break;
+ }
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+#ifndef CONFIG_DM_SERIAL
+static void pl01x_serial_init_baud(int baudrate)
+{
+ int clock = 0;
+
+#if defined(CONFIG_PL010_SERIAL)
+ pl01x_type = TYPE_PL010;
+#elif defined(CONFIG_PL011_SERIAL)
+ pl01x_type = TYPE_PL011;
+ clock = CONFIG_PL011_CLOCK;
+#endif
+ base_regs = (struct pl01x_regs *)port[CONFIG_CONS_INDEX];
+
+ pl01x_generic_serial_init(base_regs, pl01x_type);
+ pl01x_generic_setbrg(base_regs, pl01x_type, clock, baudrate);
+}
+
+/*
+ * Integrator AP has two UARTs, we use the first one, at 38400-8-N-1
+ * Integrator CP has two UARTs, use the first one, at 38400-8-N-1
+ * Versatile PB has four UARTs.
+ */
+int pl01x_serial_init(void)
+{
+ pl01x_serial_init_baud(CONFIG_BAUDRATE);
+
+ return 0;
+}
+
+static void pl01x_serial_putc(const char c)
+{
+ if (c == '\n')
+ while (pl01x_putc(base_regs, '\r') == -EAGAIN);
+
+ while (pl01x_putc(base_regs, c) == -EAGAIN);
+}
+
+static int pl01x_serial_getc(void)
+{
+ while (1) {
+ int ch = pl01x_getc(base_regs);
+
+ if (ch == -EAGAIN) {
+ WATCHDOG_RESET();
+ continue;
+ }
+
+ return ch;
+ }
+}
+
+static int pl01x_serial_tstc(void)
+{
+ return pl01x_tstc(base_regs);
+}
+
+static void pl01x_serial_setbrg(void)
+{
+ /*
+ * Flush FIFO and wait for non-busy before changing baudrate to avoid
+ * crap in console
+ */
+ while (!(readl(&base_regs->fr) & UART_PL01x_FR_TXFE))
+ WATCHDOG_RESET();
+ while (readl(&base_regs->fr) & UART_PL01x_FR_BUSY)
+ WATCHDOG_RESET();
+ pl01x_serial_init_baud(gd->baudrate);
+}
+
+static struct serial_device pl01x_serial_drv = {
+ .name = "pl01x_serial",
+ .start = pl01x_serial_init,
+ .stop = NULL,
+ .setbrg = pl01x_serial_setbrg,
+ .putc = pl01x_serial_putc,
+ .puts = default_serial_puts,
+ .getc = pl01x_serial_getc,
+ .tstc = pl01x_serial_tstc,
+};
+
+void pl01x_serial_initialize(void)
+{
+ serial_register(&pl01x_serial_drv);
+}
+
+__weak struct serial_device *default_serial_console(void)
+{
+ return &pl01x_serial_drv;
+}
+
+#endif /* nCONFIG_DM_SERIAL */
+
+#ifdef CONFIG_DM_SERIAL
+
+int pl01x_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ struct pl01x_serial_plat *plat = dev_get_plat(dev);
+ struct pl01x_priv *priv = dev_get_priv(dev);
+
+ if (!plat->skip_init) {
+ pl01x_generic_setbrg(priv->regs, priv->type, plat->clock,
+ baudrate);
+ }
+
+ return 0;
+}
+
+int pl01x_serial_probe(struct udevice *dev)
+{
+ struct pl01x_serial_plat *plat = dev_get_plat(dev);
+ struct pl01x_priv *priv = dev_get_priv(dev);
+
+ priv->regs = (struct pl01x_regs *)plat->base;
+ priv->type = plat->type;
+ if (!plat->skip_init)
+ return pl01x_generic_serial_init(priv->regs, priv->type);
+ else
+ return 0;
+}
+
+int pl01x_serial_getc(struct udevice *dev)
+{
+ struct pl01x_priv *priv = dev_get_priv(dev);
+
+ return pl01x_getc(priv->regs);
+}
+
+int pl01x_serial_putc(struct udevice *dev, const char ch)
+{
+ struct pl01x_priv *priv = dev_get_priv(dev);
+
+ return pl01x_putc(priv->regs, ch);
+}
+
+int pl01x_serial_pending(struct udevice *dev, bool input)
+{
+ struct pl01x_priv *priv = dev_get_priv(dev);
+ unsigned int fr = readl(&priv->regs->fr);
+
+ if (input)
+ return pl01x_tstc(priv->regs);
+ else
+ return fr & UART_PL01x_FR_TXFF ? 0 : 1;
+}
+
+static const struct dm_serial_ops pl01x_serial_ops = {
+ .putc = pl01x_serial_putc,
+ .pending = pl01x_serial_pending,
+ .getc = pl01x_serial_getc,
+ .setbrg = pl01x_serial_setbrg,
+};
+
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+static const struct udevice_id pl01x_serial_id[] ={
+ {.compatible = "arm,pl011", .data = TYPE_PL011},
+ {.compatible = "arm,pl010", .data = TYPE_PL010},
+ {}
+};
+
+#ifndef CONFIG_PL011_CLOCK
+#define CONFIG_PL011_CLOCK 0
+#endif
+
+int pl01x_serial_of_to_plat(struct udevice *dev)
+{
+ struct pl01x_serial_plat *plat = dev_get_plat(dev);
+ struct clk clk;
+ fdt_addr_t addr;
+ int ret;
+
+ addr = dev_read_addr(dev);
+ if (addr == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ plat->base = addr;
+ plat->clock = dev_read_u32_default(dev, "clock", CONFIG_PL011_CLOCK);
+ ret = clk_get_by_index(dev, 0, &clk);
+ if (!ret) {
+ ret = clk_enable(&clk);
+ if (ret && ret != -ENOSYS) {
+ dev_err(dev, "failed to enable clock\n");
+ return ret;
+ }
+
+ plat->clock = clk_get_rate(&clk);
+ if (IS_ERR_VALUE(plat->clock)) {
+ dev_err(dev, "failed to get rate\n");
+ return plat->clock;
+ }
+ debug("%s: CLK %d\n", __func__, plat->clock);
+ }
+ plat->type = dev_get_driver_data(dev);
+ plat->skip_init = dev_read_bool(dev, "skip-init");
+
+ return 0;
+}
+#endif
+
+U_BOOT_DRIVER(serial_pl01x) = {
+ .name = "serial_pl01x",
+ .id = UCLASS_SERIAL,
+ .of_match = of_match_ptr(pl01x_serial_id),
+ .of_to_plat = of_match_ptr(pl01x_serial_of_to_plat),
+ .plat_auto = sizeof(struct pl01x_serial_plat),
+ .probe = pl01x_serial_probe,
+ .ops = &pl01x_serial_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+ .priv_auto = sizeof(struct pl01x_priv),
+};
+
+#endif
+
+#if defined(CONFIG_DEBUG_UART_PL010) || defined(CONFIG_DEBUG_UART_PL011)
+
+#include <debug_uart.h>
+
+static void _debug_uart_init(void)
+{
+#ifndef CONFIG_DEBUG_UART_SKIP_INIT
+ struct pl01x_regs *regs = (struct pl01x_regs *)CONFIG_DEBUG_UART_BASE;
+ enum pl01x_type type = CONFIG_IS_ENABLED(DEBUG_UART_PL011) ?
+ TYPE_PL011 : TYPE_PL010;
+
+ pl01x_generic_serial_init(regs, type);
+ pl01x_generic_setbrg(regs, type,
+ CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE);
+#endif
+}
+
+static inline void _debug_uart_putc(int ch)
+{
+ struct pl01x_regs *regs = (struct pl01x_regs *)CONFIG_DEBUG_UART_BASE;
+
+ pl01x_putc(regs, ch);
+}
+
+DEBUG_UART_FUNCS
+
+#endif
diff --git a/roms/u-boot/drivers/serial/serial_pl01x_internal.h b/roms/u-boot/drivers/serial/serial_pl01x_internal.h
new file mode 100644
index 000000000..dfd95a0b7
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_pl01x_internal.h
@@ -0,0 +1,145 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2003, 2004
+ * ARM Ltd.
+ * Philippe Robin, <philippe.robin@arm.com>
+ */
+
+/*
+ * ARM PrimeCell UART's (PL010 & PL011)
+ * ------------------------------------
+ *
+ * Definitions common to both PL010 & PL011
+ *
+ */
+
+#ifndef __ASSEMBLY__
+/*
+ * We can use a combined structure for PL010 and PL011, because they overlap
+ * only in common registers.
+ */
+struct pl01x_regs {
+ u32 dr; /* 0x00 Data register */
+ u32 ecr; /* 0x04 Error clear register (Write) */
+ u32 pl010_lcrh; /* 0x08 Line control register, high byte */
+ u32 pl010_lcrm; /* 0x0C Line control register, middle byte */
+ u32 pl010_lcrl; /* 0x10 Line control register, low byte */
+ u32 pl010_cr; /* 0x14 Control register */
+ u32 fr; /* 0x18 Flag register (Read only) */
+#ifdef CONFIG_PL011_SERIAL_RLCR
+ u32 pl011_rlcr; /* 0x1c Receive line control register */
+#else
+ u32 reserved;
+#endif
+ u32 ilpr; /* 0x20 IrDA low-power counter register */
+ u32 pl011_ibrd; /* 0x24 Integer baud rate register */
+ u32 pl011_fbrd; /* 0x28 Fractional baud rate register */
+ u32 pl011_lcrh; /* 0x2C Line control register */
+ u32 pl011_cr; /* 0x30 Control register */
+};
+
+#ifdef CONFIG_DM_SERIAL
+
+int pl01x_serial_of_to_plat(struct udevice *dev);
+int pl01x_serial_probe(struct udevice *dev);
+
+/* Needed for external pl01x_serial_ops drivers */
+int pl01x_serial_putc(struct udevice *dev, const char ch);
+int pl01x_serial_pending(struct udevice *dev, bool input);
+int pl01x_serial_getc(struct udevice *dev);
+int pl01x_serial_setbrg(struct udevice *dev, int baudrate);
+
+struct pl01x_priv {
+ struct pl01x_regs *regs;
+ enum pl01x_type type;
+};
+
+#endif /* CONFIG_DM_SERIAL */
+#endif /* !__ASSEMBLY__ */
+
+#define UART_PL01x_RSR_OE 0x08
+#define UART_PL01x_RSR_BE 0x04
+#define UART_PL01x_RSR_PE 0x02
+#define UART_PL01x_RSR_FE 0x01
+
+#define UART_PL01x_FR_TXFE 0x80
+#define UART_PL01x_FR_RXFF 0x40
+#define UART_PL01x_FR_TXFF 0x20
+#define UART_PL01x_FR_RXFE 0x10
+#define UART_PL01x_FR_BUSY 0x08
+#define UART_PL01x_FR_TMSK (UART_PL01x_FR_TXFF + UART_PL01x_FR_BUSY)
+
+/*
+ * PL010 definitions
+ *
+ */
+#define UART_PL010_CR_LPE (1 << 7)
+#define UART_PL010_CR_RTIE (1 << 6)
+#define UART_PL010_CR_TIE (1 << 5)
+#define UART_PL010_CR_RIE (1 << 4)
+#define UART_PL010_CR_MSIE (1 << 3)
+#define UART_PL010_CR_IIRLP (1 << 2)
+#define UART_PL010_CR_SIREN (1 << 1)
+#define UART_PL010_CR_UARTEN (1 << 0)
+
+#define UART_PL010_LCRH_WLEN_8 (3 << 5)
+#define UART_PL010_LCRH_WLEN_7 (2 << 5)
+#define UART_PL010_LCRH_WLEN_6 (1 << 5)
+#define UART_PL010_LCRH_WLEN_5 (0 << 5)
+#define UART_PL010_LCRH_FEN (1 << 4)
+#define UART_PL010_LCRH_STP2 (1 << 3)
+#define UART_PL010_LCRH_EPS (1 << 2)
+#define UART_PL010_LCRH_PEN (1 << 1)
+#define UART_PL010_LCRH_BRK (1 << 0)
+
+
+#define UART_PL010_BAUD_460800 1
+#define UART_PL010_BAUD_230400 3
+#define UART_PL010_BAUD_115200 7
+#define UART_PL010_BAUD_57600 15
+#define UART_PL010_BAUD_38400 23
+#define UART_PL010_BAUD_19200 47
+#define UART_PL010_BAUD_14400 63
+#define UART_PL010_BAUD_9600 95
+#define UART_PL010_BAUD_4800 191
+#define UART_PL010_BAUD_2400 383
+#define UART_PL010_BAUD_1200 767
+/*
+ * PL011 definitions
+ *
+ */
+#define UART_PL011_LCRH_SPS (1 << 7)
+#define UART_PL011_LCRH_WLEN_8 (3 << 5)
+#define UART_PL011_LCRH_WLEN_7 (2 << 5)
+#define UART_PL011_LCRH_WLEN_6 (1 << 5)
+#define UART_PL011_LCRH_WLEN_5 (0 << 5)
+#define UART_PL011_LCRH_FEN (1 << 4)
+#define UART_PL011_LCRH_STP2 (1 << 3)
+#define UART_PL011_LCRH_EPS (1 << 2)
+#define UART_PL011_LCRH_PEN (1 << 1)
+#define UART_PL011_LCRH_BRK (1 << 0)
+
+#define UART_PL011_CR_CTSEN (1 << 15)
+#define UART_PL011_CR_RTSEN (1 << 14)
+#define UART_PL011_CR_OUT2 (1 << 13)
+#define UART_PL011_CR_OUT1 (1 << 12)
+#define UART_PL011_CR_RTS (1 << 11)
+#define UART_PL011_CR_DTR (1 << 10)
+#define UART_PL011_CR_RXE (1 << 9)
+#define UART_PL011_CR_TXE (1 << 8)
+#define UART_PL011_CR_LPE (1 << 7)
+#define UART_PL011_CR_IIRLP (1 << 2)
+#define UART_PL011_CR_SIREN (1 << 1)
+#define UART_PL011_CR_UARTEN (1 << 0)
+
+#define UART_PL011_IMSC_OEIM (1 << 10)
+#define UART_PL011_IMSC_BEIM (1 << 9)
+#define UART_PL011_IMSC_PEIM (1 << 8)
+#define UART_PL011_IMSC_FEIM (1 << 7)
+#define UART_PL011_IMSC_RTIM (1 << 6)
+#define UART_PL011_IMSC_TXIM (1 << 5)
+#define UART_PL011_IMSC_RXIM (1 << 4)
+#define UART_PL011_IMSC_DSRMIM (1 << 3)
+#define UART_PL011_IMSC_DCDMIM (1 << 2)
+#define UART_PL011_IMSC_CTSMIM (1 << 1)
+#define UART_PL011_IMSC_RIMIM (1 << 0)
diff --git a/roms/u-boot/drivers/serial/serial_pxa.c b/roms/u-boot/drivers/serial/serial_pxa.c
new file mode 100644
index 000000000..330fc127e
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_pxa.c
@@ -0,0 +1,343 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * (C) Copyright 2002
+ * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.de>
+ *
+ * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
+ *
+ * Modified to add driver model (DM) support
+ * (C) Copyright 2016 Marcel Ziswiler <marcel.ziswiler@toradex.com>
+ */
+
+#include <common.h>
+#include <hang.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/regs-uart.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <dm.h>
+#include <dm/platform_data/serial_pxa.h>
+#include <linux/compiler.h>
+#include <serial.h>
+#include <watchdog.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static uint32_t pxa_uart_get_baud_divider(int baudrate)
+{
+ return 921600 / baudrate;
+}
+
+static void pxa_uart_toggle_clock(uint32_t uart_index, int enable)
+{
+ uint32_t clk_reg, clk_offset, reg;
+
+ clk_reg = UART_CLK_REG;
+ clk_offset = UART_CLK_BASE << uart_index;
+
+ reg = readl(clk_reg);
+
+ if (enable)
+ reg |= clk_offset;
+ else
+ reg &= ~clk_offset;
+
+ writel(reg, clk_reg);
+}
+
+/*
+ * Enable clock and set baud rate, parity etc.
+ */
+void pxa_setbrg_common(struct pxa_uart_regs *uart_regs, int port, int baudrate)
+{
+ uint32_t divider = pxa_uart_get_baud_divider(baudrate);
+ if (!divider)
+ hang();
+
+
+ pxa_uart_toggle_clock(port, 1);
+
+ /* Disable interrupts and FIFOs */
+ writel(0, &uart_regs->ier);
+ writel(0, &uart_regs->fcr);
+
+ /* Set baud rate */
+ writel(LCR_WLS0 | LCR_WLS1 | LCR_DLAB, &uart_regs->lcr);
+ writel(divider & 0xff, &uart_regs->dll);
+ writel(divider >> 8, &uart_regs->dlh);
+ writel(LCR_WLS0 | LCR_WLS1, &uart_regs->lcr);
+
+ /* Enable UART */
+ writel(IER_UUE, &uart_regs->ier);
+}
+
+#ifndef CONFIG_DM_SERIAL
+static struct pxa_uart_regs *pxa_uart_index_to_regs(uint32_t uart_index)
+{
+ switch (uart_index) {
+ case FFUART_INDEX: return (struct pxa_uart_regs *)FFUART_BASE;
+ case BTUART_INDEX: return (struct pxa_uart_regs *)BTUART_BASE;
+ case STUART_INDEX: return (struct pxa_uart_regs *)STUART_BASE;
+ case HWUART_INDEX: return (struct pxa_uart_regs *)HWUART_BASE;
+ default:
+ return NULL;
+ }
+}
+
+/*
+ * Enable clock and set baud rate, parity etc.
+ */
+void pxa_setbrg_dev(uint32_t uart_index)
+{
+ struct pxa_uart_regs *uart_regs = pxa_uart_index_to_regs(uart_index);
+ if (!uart_regs)
+ panic("Failed getting UART registers\n");
+
+ pxa_setbrg_common(uart_regs, uart_index, gd->baudrate);
+}
+
+/*
+ * Initialise the serial port with the given baudrate. The settings
+ * are always 8 data bits, no parity, 1 stop bit, no start bits.
+ */
+int pxa_init_dev(unsigned int uart_index)
+{
+ pxa_setbrg_dev(uart_index);
+ return 0;
+}
+
+/*
+ * Output a single byte to the serial port.
+ */
+void pxa_putc_dev(unsigned int uart_index, const char c)
+{
+ struct pxa_uart_regs *uart_regs;
+
+ /* If \n, also do \r */
+ if (c == '\n')
+ pxa_putc_dev(uart_index, '\r');
+
+ uart_regs = pxa_uart_index_to_regs(uart_index);
+ if (!uart_regs)
+ hang();
+
+ while (!(readl(&uart_regs->lsr) & LSR_TEMT))
+ WATCHDOG_RESET();
+ writel(c, &uart_regs->thr);
+}
+
+/*
+ * Read a single byte from the serial port. Returns 1 on success, 0
+ * otherwise. When the function is succesfull, the character read is
+ * written into its argument c.
+ */
+int pxa_tstc_dev(unsigned int uart_index)
+{
+ struct pxa_uart_regs *uart_regs;
+
+ uart_regs = pxa_uart_index_to_regs(uart_index);
+ if (!uart_regs)
+ return -1;
+
+ return readl(&uart_regs->lsr) & LSR_DR;
+}
+
+/*
+ * Read a single byte from the serial port. Returns 1 on success, 0
+ * otherwise. When the function is succesfull, the character read is
+ * written into its argument c.
+ */
+int pxa_getc_dev(unsigned int uart_index)
+{
+ struct pxa_uart_regs *uart_regs;
+
+ uart_regs = pxa_uart_index_to_regs(uart_index);
+ if (!uart_regs)
+ return -1;
+
+ while (!(readl(&uart_regs->lsr) & LSR_DR))
+ WATCHDOG_RESET();
+ return readl(&uart_regs->rbr) & 0xff;
+}
+
+void pxa_puts_dev(unsigned int uart_index, const char *s)
+{
+ while (*s)
+ pxa_putc_dev(uart_index, *s++);
+}
+
+#define pxa_uart(uart, UART) \
+ int uart##_init(void) \
+ { \
+ return pxa_init_dev(UART##_INDEX); \
+ } \
+ \
+ void uart##_setbrg(void) \
+ { \
+ return pxa_setbrg_dev(UART##_INDEX); \
+ } \
+ \
+ void uart##_putc(const char c) \
+ { \
+ return pxa_putc_dev(UART##_INDEX, c); \
+ } \
+ \
+ void uart##_puts(const char *s) \
+ { \
+ return pxa_puts_dev(UART##_INDEX, s); \
+ } \
+ \
+ int uart##_getc(void) \
+ { \
+ return pxa_getc_dev(UART##_INDEX); \
+ } \
+ \
+ int uart##_tstc(void) \
+ { \
+ return pxa_tstc_dev(UART##_INDEX); \
+ } \
+
+#define pxa_uart_desc(uart) \
+ struct serial_device serial_##uart##_device = \
+ { \
+ .name = "serial_"#uart, \
+ .start = uart##_init, \
+ .stop = NULL, \
+ .setbrg = uart##_setbrg, \
+ .getc = uart##_getc, \
+ .tstc = uart##_tstc, \
+ .putc = uart##_putc, \
+ .puts = uart##_puts, \
+ };
+
+#define pxa_uart_multi(uart, UART) \
+ pxa_uart(uart, UART) \
+ pxa_uart_desc(uart)
+
+#if defined(CONFIG_HWUART)
+ pxa_uart_multi(hwuart, HWUART)
+#endif
+#if defined(CONFIG_STUART)
+ pxa_uart_multi(stuart, STUART)
+#endif
+#if defined(CONFIG_FFUART)
+ pxa_uart_multi(ffuart, FFUART)
+#endif
+#if defined(CONFIG_BTUART)
+ pxa_uart_multi(btuart, BTUART)
+#endif
+
+__weak struct serial_device *default_serial_console(void)
+{
+#if CONFIG_CONS_INDEX == 1
+ return &serial_hwuart_device;
+#elif CONFIG_CONS_INDEX == 2
+ return &serial_stuart_device;
+#elif CONFIG_CONS_INDEX == 3
+ return &serial_ffuart_device;
+#elif CONFIG_CONS_INDEX == 4
+ return &serial_btuart_device;
+#else
+#error "Bad CONFIG_CONS_INDEX."
+#endif
+}
+
+void pxa_serial_initialize(void)
+{
+#if defined(CONFIG_FFUART)
+ serial_register(&serial_ffuart_device);
+#endif
+#if defined(CONFIG_BTUART)
+ serial_register(&serial_btuart_device);
+#endif
+#if defined(CONFIG_STUART)
+ serial_register(&serial_stuart_device);
+#endif
+}
+#endif /* CONFIG_DM_SERIAL */
+
+#ifdef CONFIG_DM_SERIAL
+static int pxa_serial_probe(struct udevice *dev)
+{
+ struct pxa_serial_plat *plat = dev_get_plat(dev);
+
+ pxa_setbrg_common((struct pxa_uart_regs *)plat->base, plat->port,
+ plat->baudrate);
+ return 0;
+}
+
+static int pxa_serial_putc(struct udevice *dev, const char ch)
+{
+ struct pxa_serial_plat *plat = dev_get_plat(dev);
+ struct pxa_uart_regs *uart_regs = (struct pxa_uart_regs *)plat->base;
+
+ /* Wait for last character to go. */
+ if (!(readl(&uart_regs->lsr) & LSR_TEMT))
+ return -EAGAIN;
+
+ writel(ch, &uart_regs->thr);
+
+ return 0;
+}
+
+static int pxa_serial_getc(struct udevice *dev)
+{
+ struct pxa_serial_plat *plat = dev_get_plat(dev);
+ struct pxa_uart_regs *uart_regs = (struct pxa_uart_regs *)plat->base;
+
+ /* Wait for a character to arrive. */
+ if (!(readl(&uart_regs->lsr) & LSR_DR))
+ return -EAGAIN;
+
+ return readl(&uart_regs->rbr) & 0xff;
+}
+
+int pxa_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ struct pxa_serial_plat *plat = dev_get_plat(dev);
+ struct pxa_uart_regs *uart_regs = (struct pxa_uart_regs *)plat->base;
+ int port = plat->port;
+
+ pxa_setbrg_common(uart_regs, port, baudrate);
+
+ return 0;
+}
+
+static int pxa_serial_pending(struct udevice *dev, bool input)
+{
+ struct pxa_serial_plat *plat = dev_get_plat(dev);
+ struct pxa_uart_regs *uart_regs = (struct pxa_uart_regs *)plat->base;
+
+ if (input)
+ return readl(&uart_regs->lsr) & LSR_DR ? 1 : 0;
+ else
+ return readl(&uart_regs->lsr) & LSR_TEMT ? 0 : 1;
+
+ return 0;
+}
+
+static const struct dm_serial_ops pxa_serial_ops = {
+ .putc = pxa_serial_putc,
+ .pending = pxa_serial_pending,
+ .getc = pxa_serial_getc,
+ .setbrg = pxa_serial_setbrg,
+};
+
+U_BOOT_DRIVER(serial_pxa) = {
+ .name = "serial_pxa",
+ .id = UCLASS_SERIAL,
+ .probe = pxa_serial_probe,
+ .ops = &pxa_serial_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
+#endif /* CONFIG_DM_SERIAL */
diff --git a/roms/u-boot/drivers/serial/serial_rockchip.c b/roms/u-boot/drivers/serial/serial_rockchip.c
new file mode 100644
index 000000000..97d40869a
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_rockchip.c
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2015 Google, Inc
+ */
+
+#include <common.h>
+#include <debug_uart.h>
+#include <dm.h>
+#include <dt-structs.h>
+#include <ns16550.h>
+#include <serial.h>
+#include <asm/arch-rockchip/clock.h>
+#include <dm/device-internal.h>
+
+#if defined(CONFIG_ROCKCHIP_RK3188)
+struct rockchip_uart_plat {
+ struct dtd_rockchip_rk3188_uart dtplat;
+ struct ns16550_plat plat;
+};
+struct dtd_rockchip_rk3188_uart *dtplat, s_dtplat;
+#elif defined(CONFIG_ROCKCHIP_RK3288)
+struct rockchip_uart_plat {
+ struct dtd_rockchip_rk3288_uart dtplat;
+ struct ns16550_plat plat;
+};
+struct dtd_rockchip_rk3288_uart *dtplat, s_dtplat;
+#endif
+
+static int rockchip_serial_probe(struct udevice *dev)
+{
+ struct rockchip_uart_plat *plat = dev_get_plat(dev);
+
+ /* Create some new platform data for the standard driver */
+ plat->plat.base = plat->dtplat.reg[0];
+ plat->plat.reg_shift = plat->dtplat.reg_shift;
+ plat->plat.clock = plat->dtplat.clock_frequency;
+ plat->plat.fcr = UART_FCR_DEFVAL;
+ dev_set_plat(dev, &plat->plat);
+
+ return ns16550_serial_probe(dev);
+}
+
+U_BOOT_DRIVER(rockchip_rk3188_uart) = {
+ .name = "rockchip_rk3188_uart",
+ .id = UCLASS_SERIAL,
+ .priv_auto = sizeof(struct ns16550),
+ .plat_auto = sizeof(struct rockchip_uart_plat),
+ .probe = rockchip_serial_probe,
+ .ops = &ns16550_serial_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
+
+U_BOOT_DRIVER(rockchip_rk3288_uart) = {
+ .name = "rockchip_rk3288_uart",
+ .id = UCLASS_SERIAL,
+ .priv_auto = sizeof(struct ns16550),
+ .plat_auto = sizeof(struct rockchip_uart_plat),
+ .probe = rockchip_serial_probe,
+ .ops = &ns16550_serial_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/roms/u-boot/drivers/serial/serial_s5p.c b/roms/u-boot/drivers/serial/serial_s5p.c
new file mode 100644
index 000000000..6d09952a5
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_s5p.c
@@ -0,0 +1,241 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2009 SAMSUNG Electronics
+ * Minkyu Kang <mk7.kang@samsung.com>
+ * Heungjun Kim <riverful.kim@samsung.com>
+ *
+ * based on drivers/serial/s3c64xx.c
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <asm/global_data.h>
+#include <linux/compiler.h>
+#include <asm/io.h>
+#include <asm/arch/clk.h>
+#include <asm/arch/uart.h>
+#include <serial.h>
+#include <clk.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define RX_FIFO_COUNT_SHIFT 0
+#define RX_FIFO_COUNT_MASK (0xff << RX_FIFO_COUNT_SHIFT)
+#define RX_FIFO_FULL (1 << 8)
+#define TX_FIFO_COUNT_SHIFT 16
+#define TX_FIFO_COUNT_MASK (0xff << TX_FIFO_COUNT_SHIFT)
+#define TX_FIFO_FULL (1 << 24)
+
+/* Information about a serial port */
+struct s5p_serial_plat {
+ struct s5p_uart *reg; /* address of registers in physical memory */
+ u8 port_id; /* uart port number */
+};
+
+/*
+ * The coefficient, used to calculate the baudrate on S5P UARTs is
+ * calculated as
+ * C = UBRDIV * 16 + number_of_set_bits_in_UDIVSLOT
+ * however, section 31.6.11 of the datasheet doesn't recomment using 1 for 1,
+ * 3 for 2, ... (2^n - 1) for n, instead, they suggest using these constants:
+ */
+static const int udivslot[] = {
+ 0,
+ 0x0080,
+ 0x0808,
+ 0x0888,
+ 0x2222,
+ 0x4924,
+ 0x4a52,
+ 0x54aa,
+ 0x5555,
+ 0xd555,
+ 0xd5d5,
+ 0xddd5,
+ 0xdddd,
+ 0xdfdd,
+ 0xdfdf,
+ 0xffdf,
+};
+
+static void __maybe_unused s5p_serial_init(struct s5p_uart *uart)
+{
+ /* enable FIFOs, auto clear Rx FIFO */
+ writel(0x3, &uart->ufcon);
+ writel(0, &uart->umcon);
+ /* 8N1 */
+ writel(0x3, &uart->ulcon);
+ /* No interrupts, no DMA, pure polling */
+ writel(0x245, &uart->ucon);
+}
+
+static void __maybe_unused s5p_serial_baud(struct s5p_uart *uart, uint uclk,
+ int baudrate)
+{
+ u32 val;
+
+ val = uclk / baudrate;
+
+ writel(val / 16 - 1, &uart->ubrdiv);
+
+ if (s5p_uart_divslot())
+ writew(udivslot[val % 16], &uart->rest.slot);
+ else
+ writeb(val % 16, &uart->rest.value);
+}
+
+#ifndef CONFIG_SPL_BUILD
+int s5p_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ struct s5p_serial_plat *plat = dev_get_plat(dev);
+ struct s5p_uart *const uart = plat->reg;
+ u32 uclk;
+
+#ifdef CONFIG_CLK_EXYNOS
+ struct clk clk;
+ u32 ret;
+
+ ret = clk_get_by_index(dev, 1, &clk);
+ if (ret < 0)
+ return ret;
+ uclk = clk_get_rate(&clk);
+#else
+ uclk = get_uart_clk(plat->port_id);
+#endif
+
+ s5p_serial_baud(uart, uclk, baudrate);
+
+ return 0;
+}
+
+static int s5p_serial_probe(struct udevice *dev)
+{
+ struct s5p_serial_plat *plat = dev_get_plat(dev);
+ struct s5p_uart *const uart = plat->reg;
+
+ s5p_serial_init(uart);
+
+ return 0;
+}
+
+static int serial_err_check(const struct s5p_uart *const uart, int op)
+{
+ unsigned int mask;
+
+ /*
+ * UERSTAT
+ * Break Detect [3]
+ * Frame Err [2] : receive operation
+ * Parity Err [1] : receive operation
+ * Overrun Err [0] : receive operation
+ */
+ if (op)
+ mask = 0x8;
+ else
+ mask = 0xf;
+
+ return readl(&uart->uerstat) & mask;
+}
+
+static int s5p_serial_getc(struct udevice *dev)
+{
+ struct s5p_serial_plat *plat = dev_get_plat(dev);
+ struct s5p_uart *const uart = plat->reg;
+
+ if (!(readl(&uart->ufstat) & RX_FIFO_COUNT_MASK))
+ return -EAGAIN;
+
+ serial_err_check(uart, 0);
+ return (int)(readb(&uart->urxh) & 0xff);
+}
+
+static int s5p_serial_putc(struct udevice *dev, const char ch)
+{
+ struct s5p_serial_plat *plat = dev_get_plat(dev);
+ struct s5p_uart *const uart = plat->reg;
+
+ if (readl(&uart->ufstat) & TX_FIFO_FULL)
+ return -EAGAIN;
+
+ writeb(ch, &uart->utxh);
+ serial_err_check(uart, 1);
+
+ return 0;
+}
+
+static int s5p_serial_pending(struct udevice *dev, bool input)
+{
+ struct s5p_serial_plat *plat = dev_get_plat(dev);
+ struct s5p_uart *const uart = plat->reg;
+ uint32_t ufstat = readl(&uart->ufstat);
+
+ if (input)
+ return (ufstat & RX_FIFO_COUNT_MASK) >> RX_FIFO_COUNT_SHIFT;
+ else
+ return (ufstat & TX_FIFO_COUNT_MASK) >> TX_FIFO_COUNT_SHIFT;
+}
+
+static int s5p_serial_of_to_plat(struct udevice *dev)
+{
+ struct s5p_serial_plat *plat = dev_get_plat(dev);
+ fdt_addr_t addr;
+
+ addr = dev_read_addr(dev);
+ if (addr == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ plat->reg = (struct s5p_uart *)addr;
+ plat->port_id = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
+ "id", dev_seq(dev));
+ return 0;
+}
+
+static const struct dm_serial_ops s5p_serial_ops = {
+ .putc = s5p_serial_putc,
+ .pending = s5p_serial_pending,
+ .getc = s5p_serial_getc,
+ .setbrg = s5p_serial_setbrg,
+};
+
+static const struct udevice_id s5p_serial_ids[] = {
+ { .compatible = "samsung,exynos4210-uart" },
+ { }
+};
+
+U_BOOT_DRIVER(serial_s5p) = {
+ .name = "serial_s5p",
+ .id = UCLASS_SERIAL,
+ .of_match = s5p_serial_ids,
+ .of_to_plat = s5p_serial_of_to_plat,
+ .plat_auto = sizeof(struct s5p_serial_plat),
+ .probe = s5p_serial_probe,
+ .ops = &s5p_serial_ops,
+};
+#endif
+
+#ifdef CONFIG_DEBUG_UART_S5P
+
+#include <debug_uart.h>
+
+static inline void _debug_uart_init(void)
+{
+ struct s5p_uart *uart = (struct s5p_uart *)CONFIG_DEBUG_UART_BASE;
+
+ s5p_serial_init(uart);
+ s5p_serial_baud(uart, CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE);
+}
+
+static inline void _debug_uart_putc(int ch)
+{
+ struct s5p_uart *uart = (struct s5p_uart *)CONFIG_DEBUG_UART_BASE;
+
+ while (readl(&uart->ufstat) & TX_FIFO_FULL);
+
+ writeb(ch, &uart->utxh);
+}
+
+DEBUG_UART_FUNCS
+
+#endif
diff --git a/roms/u-boot/drivers/serial/serial_sh.c b/roms/u-boot/drivers/serial/serial_sh.c
new file mode 100644
index 000000000..e6c23cedf
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_sh.c
@@ -0,0 +1,369 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * SuperH SCIF device driver.
+ * Copyright (C) 2013 Renesas Electronics Corporation
+ * Copyright (C) 2007,2008,2010, 2014 Nobuhiro Iwamatsu
+ * Copyright (C) 2002 - 2008 Paul Mundt
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <clk.h>
+#include <dm.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <serial.h>
+#include <linux/compiler.h>
+#include <dm/platform_data/serial_sh.h>
+#include <linux/delay.h>
+#include "serial_sh.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_CPU_SH7780)
+static int scif_rxfill(struct uart_port *port)
+{
+ return sci_in(port, SCRFDR) & 0xff;
+}
+#elif defined(CONFIG_CPU_SH7763)
+static int scif_rxfill(struct uart_port *port)
+{
+ if ((port->mapbase == 0xffe00000) ||
+ (port->mapbase == 0xffe08000)) {
+ /* SCIF0/1*/
+ return sci_in(port, SCRFDR) & 0xff;
+ } else {
+ /* SCIF2 */
+ return sci_in(port, SCFDR) & SCIF2_RFDC_MASK;
+ }
+}
+#else
+static int scif_rxfill(struct uart_port *port)
+{
+ return sci_in(port, SCFDR) & SCIF_RFDC_MASK;
+}
+#endif
+
+static void sh_serial_init_generic(struct uart_port *port)
+{
+ sci_out(port, SCSCR , SCSCR_INIT(port));
+ sci_out(port, SCSCR , SCSCR_INIT(port));
+ sci_out(port, SCSMR, 0);
+ sci_out(port, SCSMR, 0);
+ sci_out(port, SCFCR, SCFCR_RFRST|SCFCR_TFRST);
+ sci_in(port, SCFCR);
+ sci_out(port, SCFCR, 0);
+#if defined(CONFIG_RZA1)
+ sci_out(port, SCSPTR, 0x0003);
+#endif
+}
+
+static void
+sh_serial_setbrg_generic(struct uart_port *port, int clk, int baudrate)
+{
+ if (port->clk_mode == EXT_CLK) {
+ unsigned short dl = DL_VALUE(baudrate, clk);
+ sci_out(port, DL, dl);
+ /* Need wait: Clock * 1/dl * 1/16 */
+ udelay((1000000 * dl * 16 / clk) * 1000 + 1);
+ } else {
+ sci_out(port, SCBRR, SCBRR_VALUE(baudrate, clk));
+ }
+}
+
+static void handle_error(struct uart_port *port)
+{
+ sci_in(port, SCxSR);
+ sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
+ sci_in(port, SCLSR);
+ sci_out(port, SCLSR, 0x00);
+}
+
+static int serial_raw_putc(struct uart_port *port, const char c)
+{
+ /* Tx fifo is empty */
+ if (!(sci_in(port, SCxSR) & SCxSR_TEND(port)))
+ return -EAGAIN;
+
+ sci_out(port, SCxTDR, c);
+ sci_out(port, SCxSR, sci_in(port, SCxSR) & ~SCxSR_TEND(port));
+
+ return 0;
+}
+
+static int serial_rx_fifo_level(struct uart_port *port)
+{
+ return scif_rxfill(port);
+}
+
+static int sh_serial_tstc_generic(struct uart_port *port)
+{
+ if (sci_in(port, SCxSR) & SCIF_ERRORS) {
+ handle_error(port);
+ return 0;
+ }
+
+ return serial_rx_fifo_level(port) ? 1 : 0;
+}
+
+static int serial_getc_check(struct uart_port *port)
+{
+ unsigned short status;
+
+ status = sci_in(port, SCxSR);
+
+ if (status & SCIF_ERRORS)
+ handle_error(port);
+ if (sci_in(port, SCLSR) & SCxSR_ORER(port))
+ handle_error(port);
+ status &= (SCIF_DR | SCxSR_RDxF(port));
+ if (status)
+ return status;
+ return scif_rxfill(port);
+}
+
+static int sh_serial_getc_generic(struct uart_port *port)
+{
+ unsigned short status;
+ char ch;
+
+ if (!serial_getc_check(port))
+ return -EAGAIN;
+
+ ch = sci_in(port, SCxRDR);
+ status = sci_in(port, SCxSR);
+
+ sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
+
+ if (status & SCIF_ERRORS)
+ handle_error(port);
+
+ if (sci_in(port, SCLSR) & SCxSR_ORER(port))
+ handle_error(port);
+
+ return ch;
+}
+
+#if CONFIG_IS_ENABLED(DM_SERIAL)
+
+static int sh_serial_pending(struct udevice *dev, bool input)
+{
+ struct uart_port *priv = dev_get_priv(dev);
+
+ return sh_serial_tstc_generic(priv);
+}
+
+static int sh_serial_putc(struct udevice *dev, const char ch)
+{
+ struct uart_port *priv = dev_get_priv(dev);
+
+ return serial_raw_putc(priv, ch);
+}
+
+static int sh_serial_getc(struct udevice *dev)
+{
+ struct uart_port *priv = dev_get_priv(dev);
+
+ return sh_serial_getc_generic(priv);
+}
+
+static int sh_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ struct sh_serial_plat *plat = dev_get_plat(dev);
+ struct uart_port *priv = dev_get_priv(dev);
+
+ sh_serial_setbrg_generic(priv, plat->clk, baudrate);
+
+ return 0;
+}
+
+static int sh_serial_probe(struct udevice *dev)
+{
+ struct sh_serial_plat *plat = dev_get_plat(dev);
+ struct uart_port *priv = dev_get_priv(dev);
+
+ priv->membase = (unsigned char *)plat->base;
+ priv->mapbase = plat->base;
+ priv->type = plat->type;
+ priv->clk_mode = plat->clk_mode;
+
+ sh_serial_init_generic(priv);
+
+ return 0;
+}
+
+static const struct dm_serial_ops sh_serial_ops = {
+ .putc = sh_serial_putc,
+ .pending = sh_serial_pending,
+ .getc = sh_serial_getc,
+ .setbrg = sh_serial_setbrg,
+};
+
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+static const struct udevice_id sh_serial_id[] ={
+ {.compatible = "renesas,sci", .data = PORT_SCI},
+ {.compatible = "renesas,scif", .data = PORT_SCIF},
+ {.compatible = "renesas,scifa", .data = PORT_SCIFA},
+ {}
+};
+
+static int sh_serial_of_to_plat(struct udevice *dev)
+{
+ struct sh_serial_plat *plat = dev_get_plat(dev);
+ struct clk sh_serial_clk;
+ fdt_addr_t addr;
+ int ret;
+
+ addr = dev_read_addr(dev);
+ if (!addr)
+ return -EINVAL;
+
+ plat->base = addr;
+
+ ret = clk_get_by_name(dev, "fck", &sh_serial_clk);
+ if (!ret) {
+ ret = clk_enable(&sh_serial_clk);
+ if (!ret)
+ plat->clk = clk_get_rate(&sh_serial_clk);
+ } else {
+ plat->clk = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
+ "clock", 1);
+ }
+
+ plat->type = dev_get_driver_data(dev);
+ return 0;
+}
+#endif
+
+U_BOOT_DRIVER(serial_sh) = {
+ .name = "serial_sh",
+ .id = UCLASS_SERIAL,
+ .of_match = of_match_ptr(sh_serial_id),
+ .of_to_plat = of_match_ptr(sh_serial_of_to_plat),
+ .plat_auto = sizeof(struct sh_serial_plat),
+ .probe = sh_serial_probe,
+ .ops = &sh_serial_ops,
+#if !CONFIG_IS_ENABLED(OF_CONTROL)
+ .flags = DM_FLAG_PRE_RELOC,
+#endif
+ .priv_auto = sizeof(struct uart_port),
+};
+
+#else /* CONFIG_DM_SERIAL */
+
+#if defined(CONFIG_CONS_SCIF0)
+# define SCIF_BASE SCIF0_BASE
+#elif defined(CONFIG_CONS_SCIF1)
+# define SCIF_BASE SCIF1_BASE
+#elif defined(CONFIG_CONS_SCIF2)
+# define SCIF_BASE SCIF2_BASE
+#elif defined(CONFIG_CONS_SCIF3)
+# define SCIF_BASE SCIF3_BASE
+#elif defined(CONFIG_CONS_SCIF4)
+# define SCIF_BASE SCIF4_BASE
+#elif defined(CONFIG_CONS_SCIF5)
+# define SCIF_BASE SCIF5_BASE
+#elif defined(CONFIG_CONS_SCIF6)
+# define SCIF_BASE SCIF6_BASE
+#elif defined(CONFIG_CONS_SCIF7)
+# define SCIF_BASE SCIF7_BASE
+#elif defined(CONFIG_CONS_SCIFA0)
+# define SCIF_BASE SCIFA0_BASE
+#else
+# error "Default SCIF doesn't set....."
+#endif
+
+#if defined(CONFIG_SCIF_A)
+ #define SCIF_BASE_PORT PORT_SCIFA
+#elif defined(CONFIG_SCI)
+ #define SCIF_BASE_PORT PORT_SCI
+#else
+ #define SCIF_BASE_PORT PORT_SCIF
+#endif
+
+static struct uart_port sh_sci = {
+ .membase = (unsigned char *)SCIF_BASE,
+ .mapbase = SCIF_BASE,
+ .type = SCIF_BASE_PORT,
+#ifdef CONFIG_SCIF_USE_EXT_CLK
+ .clk_mode = EXT_CLK,
+#endif
+};
+
+static void sh_serial_setbrg(void)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+ struct uart_port *port = &sh_sci;
+
+ sh_serial_setbrg_generic(port, CONFIG_SH_SCIF_CLK_FREQ, gd->baudrate);
+}
+
+static int sh_serial_init(void)
+{
+ struct uart_port *port = &sh_sci;
+
+ sh_serial_init_generic(port);
+ serial_setbrg();
+
+ return 0;
+}
+
+static void sh_serial_putc(const char c)
+{
+ struct uart_port *port = &sh_sci;
+
+ if (c == '\n') {
+ while (1) {
+ if (serial_raw_putc(port, '\r') != -EAGAIN)
+ break;
+ }
+ }
+ while (1) {
+ if (serial_raw_putc(port, c) != -EAGAIN)
+ break;
+ }
+}
+
+static int sh_serial_tstc(void)
+{
+ struct uart_port *port = &sh_sci;
+
+ return sh_serial_tstc_generic(port);
+}
+
+static int sh_serial_getc(void)
+{
+ struct uart_port *port = &sh_sci;
+ int ch;
+
+ while (1) {
+ ch = sh_serial_getc_generic(port);
+ if (ch != -EAGAIN)
+ break;
+ }
+
+ return ch;
+}
+
+static struct serial_device sh_serial_drv = {
+ .name = "sh_serial",
+ .start = sh_serial_init,
+ .stop = NULL,
+ .setbrg = sh_serial_setbrg,
+ .putc = sh_serial_putc,
+ .puts = default_serial_puts,
+ .getc = sh_serial_getc,
+ .tstc = sh_serial_tstc,
+};
+
+void sh_serial_initialize(void)
+{
+ serial_register(&sh_serial_drv);
+}
+
+__weak struct serial_device *default_serial_console(void)
+{
+ return &sh_serial_drv;
+}
+#endif /* CONFIG_DM_SERIAL */
diff --git a/roms/u-boot/drivers/serial/serial_sh.h b/roms/u-boot/drivers/serial/serial_sh.h
new file mode 100644
index 000000000..11deaa951
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_sh.h
@@ -0,0 +1,505 @@
+/*
+ * Copy and modify from linux/drivers/serial/sh-sci.h
+ */
+
+#include <dm/platform_data/serial_sh.h>
+
+struct uart_port {
+ unsigned long iobase; /* in/out[bwl] */
+ unsigned char *membase; /* read/write[bwl] */
+ unsigned long mapbase; /* for ioremap */
+ enum sh_serial_type type; /* port type */
+ enum sh_clk_mode clk_mode; /* clock mode */
+};
+
+#if defined(CONFIG_CPU_SH7721) || \
+ defined(CONFIG_SH73A0) || \
+ defined(CONFIG_R8A7740)
+# define SCSCR_INIT(port) 0x0030 /* TIE=0,RIE=0,TE=1,RE=1 */
+# define PORT_PTCR 0xA405011EUL
+# define PORT_PVCR 0xA4050122UL
+# define SCIF_ORER 0x0200 /* overrun error bit */
+#elif defined(CONFIG_CPU_SH7750) || \
+ defined(CONFIG_CPU_SH7750R) || \
+ defined(CONFIG_CPU_SH7750S) || \
+ defined(CONFIG_CPU_SH7751) || \
+ defined(CONFIG_CPU_SH7751R)
+# define SCSPTR1 0xffe0001c /* 8 bit SCI */
+# define SCSPTR2 0xFFE80020 /* 16 bit SCIF */
+# define SCIF_ORER 0x0001 /* overrun error bit */
+# define SCSCR_INIT(port) (((port)->type == PORT_SCI) ? \
+ 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ : \
+ 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */)
+#elif defined(CONFIG_CPU_SH7722)
+# define PADR 0xA4050120
+# undef PSDR
+# define PSDR 0xA405013e
+# define PWDR 0xA4050166
+# define PSCR 0xA405011E
+# define SCIF_ORER 0x0001 /* overrun error bit */
+# define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
+#elif defined(CONFIG_CPU_SH7723)
+# define SCSPTR0 0xa4050160
+# define SCSPTR1 0xa405013e
+# define SCSPTR2 0xa4050160
+# define SCSPTR3 0xa405013e
+# define SCSPTR4 0xa4050128
+# define SCSPTR5 0xa4050128
+# define SCIF_ORER 0x0001 /* overrun error bit */
+# define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
+#elif defined(CONFIG_CPU_SH7734)
+# define SCSPTR0 0xFFE40020
+# define SCSPTR1 0xFFE41020
+# define SCSPTR2 0xFFE42020
+# define SCSPTR3 0xFFE43020
+# define SCSPTR4 0xFFE44020
+# define SCSPTR5 0xFFE45020
+# define SCIF_ORER 0x0001 /* overrun error bit */
+# define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
+#elif defined(CONFIG_CPU_SH7757) || \
+ defined(CONFIG_CPU_SH7752) || \
+ defined(CONFIG_CPU_SH7753)
+# define SCSPTR0 0xfe4b0020
+# define SCSPTR1 0xfe4b0020
+# define SCSPTR2 0xfe4b0020
+# define SCIF_ORER 0x0001
+# define SCSCR_INIT(port) 0x38
+# define SCIF_ONLY
+#elif defined(CONFIG_CPU_SH7763)
+# define SCSPTR0 0xffe00024 /* 16 bit SCIF */
+# define SCSPTR1 0xffe08024 /* 16 bit SCIF */
+# define SCSPTR2 0xffe10020 /* 16 bit SCIF/IRDA */
+# define SCIF_ORER 0x0001 /* overrun error bit */
+# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
+#elif defined(CONFIG_CPU_SH7780)
+# define SCSPTR0 0xffe00024 /* 16 bit SCIF */
+# define SCSPTR1 0xffe10024 /* 16 bit SCIF */
+# define SCIF_ORER 0x0001 /* Overrun error bit */
+
+/* TIE=0,RIE=0,TE=1,RE=1,REIE=1,CKE1=1 */
+# define SCSCR_INIT(port) 0x3a
+
+#elif defined(CONFIG_RZA1)
+# define SCSPTR0 0xe8007020 /* 16 bit SCIF */
+# define SCSPTR1 0xe8007820 /* 16 bit SCIF */
+# define SCSPTR2 0xe8008020 /* 16 bit SCIF */
+# define SCSPTR3 0xe8008820 /* 16 bit SCIF */
+# define SCSPTR4 0xe8009020 /* 16 bit SCIF */
+# define SCSPTR5 0xe8009820 /* 16 bit SCIF */
+# define SCSPTR6 0xe800a020 /* 16 bit SCIF */
+# define SCSPTR7 0xe800a820 /* 16 bit SCIF */
+# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
+# define SCIF_ORER 0x0001 /* overrun error bit */
+#elif defined(CONFIG_RCAR_GEN2) || defined(CONFIG_RCAR_GEN3) || \
+ defined(CONFIG_R7S72100)
+# if defined(CONFIG_SCIF_A)
+# define SCIF_ORER 0x0200
+# else
+# define SCIF_ORER 0x0001
+# endif
+# define SCSCR_INIT(port) (port->clk_mode == EXT_CLK ? 0x32 : 0x30)
+ /* TIE=0,RIE=0,TE=1,RE=1,REIE=0, */
+#else
+# error CPU subtype not defined
+#endif
+
+/* SCSCR */
+#define SCI_CTRL_FLAGS_TIE 0x80 /* all */
+#define SCI_CTRL_FLAGS_RIE 0x40 /* all */
+#define SCI_CTRL_FLAGS_TE 0x20 /* all */
+#define SCI_CTRL_FLAGS_RE 0x10 /* all */
+#if defined(CONFIG_CPU_SH7750) || \
+ defined(CONFIG_CPU_SH7750R) || \
+ defined(CONFIG_CPU_SH7722) || \
+ defined(CONFIG_CPU_SH7734) || \
+ defined(CONFIG_CPU_SH7750S) || \
+ defined(CONFIG_CPU_SH7751) || \
+ defined(CONFIG_CPU_SH7751R) || \
+ defined(CONFIG_CPU_SH7763) || \
+ defined(CONFIG_CPU_SH7780)
+#define SCI_CTRL_FLAGS_REIE 0x08 /* 7750 SCIF */
+#else
+#define SCI_CTRL_FLAGS_REIE 0
+#endif
+/* SCI_CTRL_FLAGS_MPIE 0x08 * 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
+/* SCI_CTRL_FLAGS_TEIE 0x04 * 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
+/* SCI_CTRL_FLAGS_CKE1 0x02 * all */
+/* SCI_CTRL_FLAGS_CKE0 0x01 * 7707 SCI/SCIF, 7708 SCI, 7709 SCI/SCIF, 7750 SCI */
+
+/* SCxSR SCI */
+#define SCI_TDRE 0x80 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
+#define SCI_RDRF 0x40 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
+#define SCI_ORER 0x20 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
+#define SCI_FER 0x10 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
+#define SCI_PER 0x08 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
+#define SCI_TEND 0x04 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
+/* SCI_MPB 0x02 * 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
+/* SCI_MPBT 0x01 * 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */
+
+#define SCI_ERRORS ( SCI_PER | SCI_FER | SCI_ORER)
+
+/* SCxSR SCIF */
+#define SCIF_ER 0x0080 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
+#define SCIF_TEND 0x0040 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
+#define SCIF_TDFE 0x0020 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
+#define SCIF_BRK 0x0010 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
+#define SCIF_FER 0x0008 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
+#define SCIF_PER 0x0004 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
+#define SCIF_RDF 0x0002 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
+#define SCIF_DR 0x0001 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */
+
+#if defined(CONFIG_CPU_SH7721) || \
+ defined(CONFIG_SH73A0) || \
+ defined(CONFIG_R8A7740)
+# define SCIF_ORER 0x0200
+# define SCIF_ERRORS (SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK | SCIF_ORER)
+# define SCIF_RFDC_MASK 0x007f
+# define SCIF_TXROOM_MAX 64
+#elif defined(CONFIG_CPU_SH7763)
+# define SCIF_ERRORS (SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK)
+# define SCIF_RFDC_MASK 0x007f
+# define SCIF_TXROOM_MAX 64
+/* SH7763 SCIF2 support */
+# define SCIF2_RFDC_MASK 0x001f
+# define SCIF2_TXROOM_MAX 16
+#elif defined(CONFIG_RCAR_GEN2)
+# define SCIF_ERRORS (SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK)
+# if defined(CONFIG_SCIF_A)
+# define SCIF_RFDC_MASK 0x007f
+# else
+# define SCIF_RFDC_MASK 0x001f
+# endif
+#else
+# define SCIF_ERRORS (SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK)
+# define SCIF_RFDC_MASK 0x001f
+# define SCIF_TXROOM_MAX 16
+#endif
+
+#ifndef SCIF_ORER
+#define SCIF_ORER 0x0000
+#endif
+
+#define SCxSR_TEND(port)\
+ (((port)->type == PORT_SCI) ? SCI_TEND : SCIF_TEND)
+#define SCxSR_ERRORS(port)\
+ (((port)->type == PORT_SCI) ? SCI_ERRORS : SCIF_ERRORS)
+#define SCxSR_RDxF(port)\
+ (((port)->type == PORT_SCI) ? SCI_RDRF : SCIF_RDF)
+#define SCxSR_TDxE(port)\
+ (((port)->type == PORT_SCI) ? SCI_TDRE : SCIF_TDFE)
+#define SCxSR_FER(port)\
+ (((port)->type == PORT_SCI) ? SCI_FER : SCIF_FER)
+#define SCxSR_PER(port)\
+ (((port)->type == PORT_SCI) ? SCI_PER : SCIF_PER)
+#define SCxSR_BRK(port)\
+ ((port)->type == PORT_SCI) ? 0x00 : SCIF_BRK)
+#define SCxSR_ORER(port)\
+ (((port)->type == PORT_SCI) ? SCI_ORER : SCIF_ORER)
+
+#if defined(CONFIG_CPU_SH7721) || \
+ defined(CONFIG_SH73A0) || \
+ defined(CONFIG_R8A7740)
+# define SCxSR_RDxF_CLEAR(port) (sci_in(port, SCxSR) & 0xfffc)
+# define SCxSR_ERROR_CLEAR(port) (sci_in(port, SCxSR) & 0xfd73)
+# define SCxSR_TDxE_CLEAR(port) (sci_in(port, SCxSR) & 0xffdf)
+# define SCxSR_BREAK_CLEAR(port) (sci_in(port, SCxSR) & 0xffe3)
+#else
+# define SCxSR_RDxF_CLEAR(port) (((port)->type == PORT_SCI) ? 0xbc : 0x00fc)
+# define SCxSR_ERROR_CLEAR(port) (((port)->type == PORT_SCI) ? 0xc4 : 0x0073)
+# define SCxSR_TDxE_CLEAR(port) (((port)->type == PORT_SCI) ? 0x78 : 0x00df)
+# define SCxSR_BREAK_CLEAR(port) (((port)->type == PORT_SCI) ? 0xc4 : 0x00e3)
+#endif
+
+/* SCFCR */
+#define SCFCR_RFRST 0x0002
+#define SCFCR_TFRST 0x0004
+#define SCFCR_TCRST 0x4000
+#define SCFCR_MCE 0x0008
+
+#define SCI_MAJOR 204
+#define SCI_MINOR_START 8
+
+/* Generic serial flags */
+#define SCI_RX_THROTTLE 0x0000001
+
+#define SCI_MAGIC 0xbabeface
+
+/*
+ * Events are used to schedule things to happen at timer-interrupt
+ * time, instead of at rs interrupt time.
+ */
+#define SCI_EVENT_WRITE_WAKEUP 0
+
+#define SCI_IN(size, offset)\
+ if ((size) == 8) {\
+ return readb(port->membase + (offset));\
+ } else {\
+ return readw(port->membase + (offset));\
+ }
+#define SCI_OUT(size, offset, value)\
+ if ((size) == 8) {\
+ writeb(value, port->membase + (offset));\
+ } else if ((size) == 16) {\
+ writew(value, port->membase + (offset));\
+ }
+
+#define CPU_SCIx_FNS(name, sci_offset, sci_size, scif_offset, scif_size)\
+ static inline unsigned int sci_##name##_in(struct uart_port *port) {\
+ if (port->type == PORT_SCIF || port->type == PORT_SCIFB) {\
+ SCI_IN(scif_size, scif_offset)\
+ } else { /* PORT_SCI or PORT_SCIFA */\
+ SCI_IN(sci_size, sci_offset);\
+ }\
+ }\
+static inline void sci_##name##_out(struct uart_port *port,\
+ unsigned int value) {\
+ if (port->type == PORT_SCIF || port->type == PORT_SCIFB) {\
+ SCI_OUT(scif_size, scif_offset, value)\
+ } else { /* PORT_SCI or PORT_SCIFA */\
+ SCI_OUT(sci_size, sci_offset, value);\
+ }\
+}
+
+#define CPU_SCIF_FNS(name, scif_offset, scif_size) \
+ static inline unsigned int sci_##name##_in(struct uart_port *port) {\
+ SCI_IN(scif_size, scif_offset);\
+ }\
+ static inline void sci_##name##_out(struct uart_port *port,\
+ unsigned int value) {\
+ SCI_OUT(scif_size, scif_offset, value);\
+ }
+
+#define CPU_SCI_FNS(name, sci_offset, sci_size)\
+ static inline unsigned int sci_##name##_in(struct uart_port *port) {\
+ SCI_IN(sci_size, sci_offset);\
+ }\
+ static inline void sci_##name##_out(struct uart_port *port,\
+ unsigned int value) {\
+ SCI_OUT(sci_size, sci_offset, value);\
+ }
+
+#if defined(CONFIG_SH73A0) || \
+ defined(CONFIG_R8A7740)
+#if defined(CONFIG_CPU_SH7721) || \
+ defined(CONFIG_SH73A0)
+#define SCIF_FNS(name, scif_offset, scif_size) \
+ CPU_SCIF_FNS(name, scif_offset, scif_size)
+#elif defined(CONFIG_R8A7740)
+#define SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size,\
+ sh4_scifb_offset, sh4_scifb_size) \
+ CPU_SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size,\
+ sh4_scifb_offset, sh4_scifb_size)
+#define SCIF_FNS(name, scif_offset, scif_size) \
+ CPU_SCIF_FNS(name, scif_offset, scif_size)
+#else
+#define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size,\
+ sh4_sci_offset, sh4_sci_size, \
+ sh3_scif_offset, sh3_scif_size,\
+ sh4_scif_offset, sh4_scif_size, \
+ h8_sci_offset, h8_sci_size) \
+ CPU_SCIx_FNS(name, sh3_sci_offset, sh3_sci_size,\
+ sh3_scif_offset, sh3_scif_size)
+#define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size,\
+ sh4_scif_offset, sh4_scif_size) \
+ CPU_SCIF_FNS(name, sh3_scif_offset, sh3_scif_size)
+#endif
+#elif defined(CONFIG_CPU_SH7723)
+ #define SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size,\
+ sh4_scif_offset, sh4_scif_size) \
+ CPU_SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size,\
+ sh4_scif_offset, sh4_scif_size)
+ #define SCIF_FNS(name, sh4_scif_offset, sh4_scif_size) \
+ CPU_SCIF_FNS(name, sh4_scif_offset, sh4_scif_size)
+#else
+#define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size,\
+ sh4_sci_offset, sh4_sci_size, \
+ sh3_scif_offset, sh3_scif_size,\
+ sh4_scif_offset, sh4_scif_size, \
+ h8_sci_offset, h8_sci_size) \
+ CPU_SCIx_FNS(name, sh4_sci_offset, sh4_sci_size,\
+ sh4_scif_offset, sh4_scif_size)
+#define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size, \
+ sh4_scif_offset, sh4_scif_size) \
+ CPU_SCIF_FNS(name, sh4_scif_offset, sh4_scif_size)
+#endif
+
+#if defined(CONFIG_CPU_SH7721) || \
+ defined(CONFIG_SH73A0)
+
+SCIF_FNS(SCSMR, 0x00, 16)
+SCIF_FNS(SCBRR, 0x04, 8)
+SCIF_FNS(SCSCR, 0x08, 16)
+SCIF_FNS(SCTDSR, 0x0c, 8)
+SCIF_FNS(SCFER, 0x10, 16)
+SCIF_FNS(SCxSR, 0x14, 16)
+SCIF_FNS(SCFCR, 0x18, 16)
+SCIF_FNS(SCFDR, 0x1c, 16)
+SCIF_FNS(SCxTDR, 0x20, 8)
+SCIF_FNS(SCxRDR, 0x24, 8)
+SCIF_FNS(SCLSR, 0x00, 0)
+SCIF_FNS(DL, 0x00, 0) /* dummy */
+#elif defined(CONFIG_R8A7740)
+SCIF_FNS(SCSMR, 0x00, 16)
+SCIF_FNS(SCBRR, 0x04, 8)
+SCIF_FNS(SCSCR, 0x08, 16)
+SCIF_FNS(SCTDSR, 0x0c, 16)
+SCIF_FNS(SCFER, 0x10, 16)
+SCIF_FNS(SCxSR, 0x14, 16)
+SCIF_FNS(SCFCR, 0x18, 16)
+SCIF_FNS(SCFDR, 0x1c, 16)
+SCIF_FNS(SCTFDR, 0x38, 16)
+SCIF_FNS(SCRFDR, 0x3c, 16)
+SCIx_FNS(SCxTDR, 0x20, 8, 0x40, 8)
+SCIx_FNS(SCxRDR, 0x24, 8, 0x60, 8)
+SCIF_FNS(SCLSR, 0x00, 0)
+SCIF_FNS(DL, 0x00, 0) /* dummy */
+#elif defined(CONFIG_CPU_SH7723)
+SCIx_FNS(SCSMR, 0x00, 16, 0x00, 16)
+SCIx_FNS(SCBRR, 0x04, 8, 0x04, 8)
+SCIx_FNS(SCSCR, 0x08, 16, 0x08, 16)
+SCIx_FNS(SCxTDR, 0x20, 8, 0x0c, 8)
+SCIx_FNS(SCxSR, 0x14, 16, 0x10, 16)
+SCIx_FNS(SCxRDR, 0x24, 8, 0x14, 8)
+SCIx_FNS(SCSPTR, 0, 0, 0, 0)
+SCIF_FNS(SCTDSR, 0x0c, 8)
+SCIF_FNS(SCFER, 0x10, 16)
+SCIF_FNS(SCFCR, 0x18, 16)
+SCIF_FNS(SCFDR, 0x1c, 16)
+SCIF_FNS(SCLSR, 0x24, 16)
+SCIF_FNS(DL, 0x00, 0) /* dummy */
+#elif defined(CONFIG_RCAR_GEN2)
+/* SCIFA and SCIF register offsets and size */
+SCIx_FNS(SCSMR, 0, 0, 0x00, 16, 0, 0, 0x00, 16, 0, 0)
+SCIx_FNS(SCBRR, 0, 0, 0x04, 8, 0, 0, 0x04, 8, 0, 0)
+SCIx_FNS(SCSCR, 0, 0, 0x08, 16, 0, 0, 0x08, 16, 0, 0)
+SCIx_FNS(SCxTDR, 0, 0, 0x20, 8, 0, 0, 0x0C, 8, 0, 0)
+SCIx_FNS(SCxSR, 0, 0, 0x14, 16, 0, 0, 0x10, 16, 0, 0)
+SCIx_FNS(SCxRDR, 0, 0, 0x24, 8, 0, 0, 0x14, 8, 0, 0)
+SCIF_FNS(SCFCR, 0, 0, 0x18, 16)
+SCIF_FNS(SCFDR, 0, 0, 0x1C, 16)
+SCIF_FNS(SCSPTR, 0, 0, 0x20, 16)
+SCIF_FNS(DL, 0, 0, 0x30, 16)
+SCIF_FNS(CKS, 0, 0, 0x34, 16)
+#if defined(CONFIG_SCIF_A)
+SCIF_FNS(SCLSR, 0, 0, 0x14, 16)
+#else
+SCIF_FNS(SCLSR, 0, 0, 0x24, 16)
+#endif
+#else
+/* reg SCI/SH3 SCI/SH4 SCIF/SH3 SCIF/SH4 SCI/H8*/
+/* name off sz off sz off sz off sz off sz*/
+SCIx_FNS(SCSMR, 0x00, 8, 0x00, 8, 0x00, 8, 0x00, 16, 0x00, 8)
+SCIx_FNS(SCBRR, 0x02, 8, 0x04, 8, 0x02, 8, 0x04, 8, 0x01, 8)
+SCIx_FNS(SCSCR, 0x04, 8, 0x08, 8, 0x04, 8, 0x08, 16, 0x02, 8)
+SCIx_FNS(SCxTDR, 0x06, 8, 0x0c, 8, 0x06, 8, 0x0C, 8, 0x03, 8)
+SCIx_FNS(SCxSR, 0x08, 8, 0x10, 8, 0x08, 16, 0x10, 16, 0x04, 8)
+SCIx_FNS(SCxRDR, 0x0a, 8, 0x14, 8, 0x0A, 8, 0x14, 8, 0x05, 8)
+SCIF_FNS(SCFCR, 0x0c, 8, 0x18, 16)
+#if defined(CONFIG_CPU_SH7780)
+SCIF_FNS(SCFDR, 0x0e, 16, 0x1C, 16)
+SCIF_FNS(SCTFDR, 0x0e, 16, 0x1C, 16)
+SCIF_FNS(SCRFDR, 0x0e, 16, 0x20, 16)
+SCIF_FNS(SCSPTR, 0, 0, 0x24, 16)
+SCIF_FNS(SCLSR, 0, 0, 0x28, 16)
+#elif defined(CONFIG_CPU_SH7763)
+SCIF_FNS(SCFDR, 0, 0, 0x1C, 16)
+SCIF_FNS(SCSPTR2, 0, 0, 0x20, 16)
+SCIF_FNS(SCLSR2, 0, 0, 0x24, 16)
+SCIF_FNS(SCTFDR, 0x0e, 16, 0x1C, 16)
+SCIF_FNS(SCRFDR, 0x0e, 16, 0x20, 16)
+SCIF_FNS(SCSPTR, 0, 0, 0x24, 16)
+SCIF_FNS(SCLSR, 0, 0, 0x28, 16)
+#else
+
+SCIF_FNS(SCFDR, 0x0e, 16, 0x1C, 16)
+#if defined(CONFIG_CPU_SH7722)
+SCIF_FNS(SCSPTR, 0, 0, 0, 0)
+#else
+SCIF_FNS(SCSPTR, 0, 0, 0x20, 16)
+#endif
+SCIF_FNS(SCLSR, 0, 0, 0x24, 16)
+#endif
+SCIF_FNS(DL, 0, 0, 0x0, 0) /* dummy */
+#endif
+#define sci_in(port, reg) sci_##reg##_in(port)
+#define sci_out(port, reg, value) sci_##reg##_out(port, value)
+
+#if defined(CONFIG_CPU_SH7750) || \
+ defined(CONFIG_CPU_SH7751) || \
+ defined(CONFIG_CPU_SH7751R) || \
+ defined(CONFIG_CPU_SH7750R) || \
+ defined(CONFIG_CPU_SH7750S)
+static inline int sci_rxd_in(struct uart_port *port)
+{
+ if (port->mapbase == 0xffe00000)
+ return __raw_readb(SCSPTR1)&0x01 ? 1 : 0; /* SCI */
+ return 1;
+}
+#else /* default case for non-SCI processors */
+static inline int sci_rxd_in(struct uart_port *port)
+{
+ return 1;
+}
+#endif
+
+/*
+ * Values for the BitRate Register (SCBRR)
+ *
+ * The values are actually divisors for a frequency which can
+ * be internal to the SH3 (14.7456MHz) or derived from an external
+ * clock source. This driver assumes the internal clock is used;
+ * to support using an external clock source, config options or
+ * possibly command-line options would need to be added.
+ *
+ * Also, to support speeds below 2400 (why?) the lower 2 bits of
+ * the SCSMR register would also need to be set to non-zero values.
+ *
+ * -- Greg Banks 27Feb2000
+ *
+ * Answer: The SCBRR register is only eight bits, and the value in
+ * it gets larger with lower baud rates. At around 2400 (depending on
+ * the peripherial module clock) you run out of bits. However the
+ * lower two bits of SCSMR allow the module clock to be divided down,
+ * scaling the value which is needed in SCBRR.
+ *
+ * -- Stuart Menefy - 23 May 2000
+ *
+ * I meant, why would anyone bother with bitrates below 2400.
+ *
+ * -- Greg Banks - 7Jul2000
+ *
+ * You "speedist"! How will I use my 110bps ASR-33 teletype with paper
+ * tape reader as a console!
+ *
+ * -- Mitch Davis - 15 Jul 2000
+ */
+
+#if defined(CONFIG_CPU_SH7780)
+#define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(16*bps)-1)
+#elif defined(CONFIG_CPU_SH7721) || \
+ defined(CONFIG_SH73A0) || \
+ defined(CONFIG_R8A7740)
+#define SCBRR_VALUE(bps, clk) (((clk*2)+16*bps)/(32*bps)-1)
+#elif defined(CONFIG_CPU_SH7723)
+static inline int scbrr_calc(struct uart_port *port, int bps, int clk)
+{
+ if (port->type == PORT_SCIF)
+ return (clk+16*bps)/(32*bps)-1;
+ else
+ return ((clk*2)+16*bps)/(16*bps)-1;
+}
+#define SCBRR_VALUE(bps, clk) scbrr_calc(port, bps, clk)
+#elif defined(CONFIG_RCAR_GEN2)
+#define DL_VALUE(bps, clk) (clk / bps / 16) /* External Clock */
+ #if defined(CONFIG_SCIF_A)
+ #define SCBRR_VALUE(bps, clk) (clk / bps / 16 - 1) /* Internal Clock */
+ #else
+ #define SCBRR_VALUE(bps, clk) (clk / bps / 32 - 1) /* Internal Clock */
+ #endif
+#else /* Generic SH */
+#define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(32*bps)-1)
+#endif
+
+#ifndef DL_VALUE
+#define DL_VALUE(bps, clk) 0
+#endif
diff --git a/roms/u-boot/drivers/serial/serial_sifive.c b/roms/u-boot/drivers/serial/serial_sifive.c
new file mode 100644
index 000000000..794f9c924
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_sifive.c
@@ -0,0 +1,233 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Anup Patel <anup@brainfault.org>
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <debug_uart.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <log.h>
+#include <watchdog.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <linux/compiler.h>
+#include <serial.h>
+#include <linux/err.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define UART_TXFIFO_FULL 0x80000000
+#define UART_RXFIFO_EMPTY 0x80000000
+#define UART_RXFIFO_DATA 0x000000ff
+#define UART_TXCTRL_TXEN 0x1
+#define UART_RXCTRL_RXEN 0x1
+
+/* IP register */
+#define UART_IP_RXWM 0x2
+
+struct uart_sifive {
+ u32 txfifo;
+ u32 rxfifo;
+ u32 txctrl;
+ u32 rxctrl;
+ u32 ie;
+ u32 ip;
+ u32 div;
+};
+
+struct sifive_uart_plat {
+ unsigned long clock;
+ struct uart_sifive *regs;
+};
+
+/**
+ * Find minimum divisor divides in_freq to max_target_hz;
+ * Based on uart driver n SiFive FSBL.
+ *
+ * f_baud = f_in / (div + 1) => div = (f_in / f_baud) - 1
+ * The nearest integer solution requires rounding up as to not exceed
+ * max_target_hz.
+ * div = ceil(f_in / f_baud) - 1
+ * = floor((f_in - 1 + f_baud) / f_baud) - 1
+ * This should not overflow as long as (f_in - 1 + f_baud) does not exceed
+ * 2^32 - 1, which is unlikely since we represent frequencies in kHz.
+ */
+static inline unsigned int uart_min_clk_divisor(unsigned long in_freq,
+ unsigned long max_target_hz)
+{
+ unsigned long quotient =
+ (in_freq + max_target_hz - 1) / (max_target_hz);
+ /* Avoid underflow */
+ if (quotient == 0)
+ return 0;
+ else
+ return quotient - 1;
+}
+
+/* Set up the baud rate in gd struct */
+static void _sifive_serial_setbrg(struct uart_sifive *regs,
+ unsigned long clock, unsigned long baud)
+{
+ writel((uart_min_clk_divisor(clock, baud)), &regs->div);
+}
+
+static void _sifive_serial_init(struct uart_sifive *regs)
+{
+ writel(UART_TXCTRL_TXEN, &regs->txctrl);
+ writel(UART_RXCTRL_RXEN, &regs->rxctrl);
+ writel(0, &regs->ie);
+}
+
+static int _sifive_serial_putc(struct uart_sifive *regs, const char c)
+{
+ if (readl(&regs->txfifo) & UART_TXFIFO_FULL)
+ return -EAGAIN;
+
+ writel(c, &regs->txfifo);
+
+ return 0;
+}
+
+static int _sifive_serial_getc(struct uart_sifive *regs)
+{
+ int ch = readl(&regs->rxfifo);
+
+ if (ch & UART_RXFIFO_EMPTY)
+ return -EAGAIN;
+ ch &= UART_RXFIFO_DATA;
+
+ return ch;
+}
+
+static int sifive_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ int ret;
+ struct clk clk;
+ struct sifive_uart_plat *plat = dev_get_plat(dev);
+ u32 clock = 0;
+
+ ret = clk_get_by_index(dev, 0, &clk);
+ if (IS_ERR_VALUE(ret)) {
+ debug("SiFive UART failed to get clock\n");
+ ret = dev_read_u32(dev, "clock-frequency", &clock);
+ if (IS_ERR_VALUE(ret)) {
+ debug("SiFive UART clock not defined\n");
+ return 0;
+ }
+ } else {
+ clock = clk_get_rate(&clk);
+ if (IS_ERR_VALUE(clock)) {
+ debug("SiFive UART clock get rate failed\n");
+ return 0;
+ }
+ }
+ plat->clock = clock;
+ _sifive_serial_setbrg(plat->regs, plat->clock, baudrate);
+
+ return 0;
+}
+
+static int sifive_serial_probe(struct udevice *dev)
+{
+ struct sifive_uart_plat *plat = dev_get_plat(dev);
+
+ /* No need to reinitialize the UART after relocation */
+ if (gd->flags & GD_FLG_RELOC)
+ return 0;
+
+ _sifive_serial_init(plat->regs);
+
+ return 0;
+}
+
+static int sifive_serial_getc(struct udevice *dev)
+{
+ int c;
+ struct sifive_uart_plat *plat = dev_get_plat(dev);
+ struct uart_sifive *regs = plat->regs;
+
+ while ((c = _sifive_serial_getc(regs)) == -EAGAIN) ;
+
+ return c;
+}
+
+static int sifive_serial_putc(struct udevice *dev, const char ch)
+{
+ int rc;
+ struct sifive_uart_plat *plat = dev_get_plat(dev);
+
+ while ((rc = _sifive_serial_putc(plat->regs, ch)) == -EAGAIN) ;
+
+ return rc;
+}
+
+static int sifive_serial_pending(struct udevice *dev, bool input)
+{
+ struct sifive_uart_plat *plat = dev_get_plat(dev);
+ struct uart_sifive *regs = plat->regs;
+
+ if (input)
+ return (readl(&regs->ip) & UART_IP_RXWM);
+ else
+ return !!(readl(&regs->txfifo) & UART_TXFIFO_FULL);
+}
+
+static int sifive_serial_of_to_plat(struct udevice *dev)
+{
+ struct sifive_uart_plat *plat = dev_get_plat(dev);
+
+ plat->regs = (struct uart_sifive *)(uintptr_t)dev_read_addr(dev);
+ if (IS_ERR(plat->regs))
+ return PTR_ERR(plat->regs);
+
+ return 0;
+}
+
+static const struct dm_serial_ops sifive_serial_ops = {
+ .putc = sifive_serial_putc,
+ .getc = sifive_serial_getc,
+ .pending = sifive_serial_pending,
+ .setbrg = sifive_serial_setbrg,
+};
+
+static const struct udevice_id sifive_serial_ids[] = {
+ { .compatible = "sifive,uart0" },
+ { }
+};
+
+U_BOOT_DRIVER(serial_sifive) = {
+ .name = "serial_sifive",
+ .id = UCLASS_SERIAL,
+ .of_match = sifive_serial_ids,
+ .of_to_plat = sifive_serial_of_to_plat,
+ .plat_auto = sizeof(struct sifive_uart_plat),
+ .probe = sifive_serial_probe,
+ .ops = &sifive_serial_ops,
+};
+
+#ifdef CONFIG_DEBUG_UART_SIFIVE
+static inline void _debug_uart_init(void)
+{
+ struct uart_sifive *regs =
+ (struct uart_sifive *)CONFIG_DEBUG_UART_BASE;
+
+ _sifive_serial_setbrg(regs, CONFIG_DEBUG_UART_CLOCK,
+ CONFIG_BAUDRATE);
+ _sifive_serial_init(regs);
+}
+
+static inline void _debug_uart_putc(int ch)
+{
+ struct uart_sifive *regs =
+ (struct uart_sifive *)CONFIG_DEBUG_UART_BASE;
+
+ while (_sifive_serial_putc(regs, ch) == -EAGAIN)
+ WATCHDOG_RESET();
+}
+
+DEBUG_UART_FUNCS
+
+#endif
diff --git a/roms/u-boot/drivers/serial/serial_sti_asc.c b/roms/u-boot/drivers/serial/serial_sti_asc.c
new file mode 100644
index 000000000..2cada4efb
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_sti_asc.c
@@ -0,0 +1,212 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Support for Serial I/O using STMicroelectronics' on-chip ASC.
+ *
+ * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
+ * Author(s): Patrice Chotard, <patrice.chotard@foss.st.com> for STMicroelectronics.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <log.h>
+#include <serial.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <linux/bitops.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define BAUDMODE 0x00001000
+#define RXENABLE 0x00000100
+#define RUN 0x00000080
+#define MODE 0x00000001
+#define MODE_8BIT 0x0001
+#define STOP_1BIT 0x0008
+#define PARITYODD 0x0020
+
+#define STA_TF BIT(9)
+#define STA_RBF BIT(0)
+
+struct sti_asc_uart {
+ u32 baudrate;
+ u32 txbuf;
+ u32 rxbuf;
+ u32 control;
+ u32 inten;
+ u32 status;
+ u32 guardtime;
+ u32 timeout;
+ u32 txreset;
+ u32 rxreset;
+};
+
+struct sti_asc_serial {
+ /* address of registers in physical memory */
+ struct sti_asc_uart *regs;
+};
+
+/* Values for the BAUDRATE Register */
+#define PCLK (200ul * 1000000ul)
+#define BAUDRATE_VAL_M0(bps) (PCLK / (16 * (bps)))
+#define BAUDRATE_VAL_M1(bps) ((bps * (1 << 14)) + (1<<13)) / (PCLK/(1 << 6))
+
+/*
+ * MODE 0
+ * ICCLK
+ * ASCBaudRate = ----------------
+ * baudrate * 16
+ *
+ * MODE 1
+ * baudrate * 16 * 2^16
+ * ASCBaudRate = ------------------------
+ * ICCLK
+ *
+ * NOTE:
+ * Mode 1 should be used for baudrates of 19200, and above, as it
+ * has a lower deviation error than Mode 0 for higher frequencies.
+ * Mode 0 should be used for all baudrates below 19200.
+ */
+
+static int sti_asc_pending(struct udevice *dev, bool input)
+{
+ struct sti_asc_serial *priv = dev_get_priv(dev);
+ struct sti_asc_uart *const uart = priv->regs;
+ unsigned long status;
+
+ status = readl(&uart->status);
+ if (input)
+ return status & STA_RBF;
+ else
+ return status & STA_TF;
+}
+
+static int _sti_asc_serial_setbrg(struct sti_asc_uart *uart, int baudrate)
+{
+ unsigned long val;
+ int t, mode = 1;
+
+ switch (baudrate) {
+ case 9600:
+ t = BAUDRATE_VAL_M0(9600);
+ mode = 0;
+ break;
+ case 19200:
+ t = BAUDRATE_VAL_M1(19200);
+ break;
+ case 38400:
+ t = BAUDRATE_VAL_M1(38400);
+ break;
+ case 57600:
+ t = BAUDRATE_VAL_M1(57600);
+ break;
+ default:
+ debug("ASC: unsupported baud rate: %d, using 115200 instead.\n",
+ baudrate);
+ case 115200:
+ t = BAUDRATE_VAL_M1(115200);
+ break;
+ }
+
+ /* disable the baudrate generator */
+ val = readl(&uart->control);
+ writel(val & ~RUN, &uart->control);
+
+ /* set baud generator reload value */
+ writel(t, &uart->baudrate);
+ /* reset the RX & TX buffers */
+ writel(1, &uart->txreset);
+ writel(1, &uart->rxreset);
+
+ /* set baud generator mode */
+ if (mode)
+ val |= BAUDMODE;
+
+ /* finally, write value and enable ASC */
+ writel(val, &uart->control);
+
+ return 0;
+}
+
+/* called to adjust baud-rate */
+static int sti_asc_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ struct sti_asc_serial *priv = dev_get_priv(dev);
+ struct sti_asc_uart *const uart = priv->regs;
+
+ return _sti_asc_serial_setbrg(uart, baudrate);
+}
+
+/* blocking function, that returns next char */
+static int sti_asc_serial_getc(struct udevice *dev)
+{
+ struct sti_asc_serial *priv = dev_get_priv(dev);
+ struct sti_asc_uart *const uart = priv->regs;
+
+ /* polling wait: for a char to be read */
+ if (!sti_asc_pending(dev, true))
+ return -EAGAIN;
+
+ return readl(&uart->rxbuf);
+}
+
+/* write write out a single char */
+static int sti_asc_serial_putc(struct udevice *dev, const char c)
+{
+ struct sti_asc_serial *priv = dev_get_priv(dev);
+ struct sti_asc_uart *const uart = priv->regs;
+
+ /* wait till safe to write next char */
+ if (sti_asc_pending(dev, false))
+ return -EAGAIN;
+
+ /* finally, write next char */
+ writel(c, &uart->txbuf);
+
+ return 0;
+}
+
+/* initialize the ASC */
+static int sti_asc_serial_probe(struct udevice *dev)
+{
+ struct sti_asc_serial *priv = dev_get_priv(dev);
+ unsigned long val;
+ fdt_addr_t base;
+
+ base = dev_read_addr(dev);
+ if (base == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ priv->regs = (struct sti_asc_uart *)base;
+ sti_asc_serial_setbrg(dev, gd->baudrate);
+
+ /*
+ * build up the value to be written to CONTROL
+ * set character length, bit stop number, odd parity
+ */
+ val = RXENABLE | RUN | MODE_8BIT | STOP_1BIT | PARITYODD;
+ writel(val, &priv->regs->control);
+
+ return 0;
+}
+
+static const struct dm_serial_ops sti_asc_serial_ops = {
+ .putc = sti_asc_serial_putc,
+ .pending = sti_asc_pending,
+ .getc = sti_asc_serial_getc,
+ .setbrg = sti_asc_serial_setbrg,
+};
+
+static const struct udevice_id sti_serial_of_match[] = {
+ { .compatible = "st,asc" },
+ { }
+};
+
+U_BOOT_DRIVER(serial_sti_asc) = {
+ .name = "serial_sti_asc",
+ .id = UCLASS_SERIAL,
+ .of_match = sti_serial_of_match,
+ .ops = &sti_asc_serial_ops,
+ .probe = sti_asc_serial_probe,
+ .priv_auto = sizeof(struct sti_asc_serial),
+};
+
diff --git a/roms/u-boot/drivers/serial/serial_stm32.c b/roms/u-boot/drivers/serial/serial_stm32.c
new file mode 100644
index 000000000..f6cb708c3
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_stm32.c
@@ -0,0 +1,292 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2016, STMicroelectronics - All Rights Reserved
+ * Author(s): Vikas Manocha, <vikas.manocha@st.com> for STMicroelectronics.
+ */
+
+#define LOG_CATEGORY UCLASS_SERIAL
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <log.h>
+#include <reset.h>
+#include <serial.h>
+#include <watchdog.h>
+#include <asm/io.h>
+#include <asm/arch/stm32.h>
+#include <dm/device_compat.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include "serial_stm32.h"
+#include <dm/device_compat.h>
+
+static void _stm32_serial_setbrg(fdt_addr_t base,
+ struct stm32_uart_info *uart_info,
+ u32 clock_rate,
+ int baudrate)
+{
+ bool stm32f4 = uart_info->stm32f4;
+ u32 int_div, mantissa, fraction, oversampling;
+
+ int_div = DIV_ROUND_CLOSEST(clock_rate, baudrate);
+
+ if (int_div < 16) {
+ oversampling = 8;
+ setbits_le32(base + CR1_OFFSET(stm32f4), USART_CR1_OVER8);
+ } else {
+ oversampling = 16;
+ clrbits_le32(base + CR1_OFFSET(stm32f4), USART_CR1_OVER8);
+ }
+
+ mantissa = (int_div / oversampling) << USART_BRR_M_SHIFT;
+ fraction = int_div % oversampling;
+
+ writel(mantissa | fraction, base + BRR_OFFSET(stm32f4));
+}
+
+static int stm32_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ struct stm32x7_serial_plat *plat = dev_get_plat(dev);
+
+ _stm32_serial_setbrg(plat->base, plat->uart_info,
+ plat->clock_rate, baudrate);
+
+ return 0;
+}
+
+static int stm32_serial_setconfig(struct udevice *dev, uint serial_config)
+{
+ struct stm32x7_serial_plat *plat = dev_get_plat(dev);
+ bool stm32f4 = plat->uart_info->stm32f4;
+ u8 uart_enable_bit = plat->uart_info->uart_enable_bit;
+ u32 cr1 = plat->base + CR1_OFFSET(stm32f4);
+ u32 config = 0;
+ uint parity = SERIAL_GET_PARITY(serial_config);
+ uint bits = SERIAL_GET_BITS(serial_config);
+ uint stop = SERIAL_GET_STOP(serial_config);
+
+ /*
+ * only parity config is implemented, check if other serial settings
+ * are the default one.
+ * (STM32F4 serial IP didn't support parity setting)
+ */
+ if (bits != SERIAL_8_BITS || stop != SERIAL_ONE_STOP || stm32f4)
+ return -ENOTSUPP; /* not supported in driver*/
+
+ clrbits_le32(cr1, USART_CR1_RE | USART_CR1_TE | BIT(uart_enable_bit));
+ /* update usart configuration (uart need to be disable)
+ * PCE: parity check enable
+ * PS : '0' : Even / '1' : Odd
+ * M[1:0] = '00' : 8 Data bits
+ * M[1:0] = '01' : 9 Data bits with parity
+ */
+ switch (parity) {
+ default:
+ case SERIAL_PAR_NONE:
+ config = 0;
+ break;
+ case SERIAL_PAR_ODD:
+ config = USART_CR1_PCE | USART_CR1_PS | USART_CR1_M0;
+ break;
+ case SERIAL_PAR_EVEN:
+ config = USART_CR1_PCE | USART_CR1_M0;
+ break;
+ }
+
+ clrsetbits_le32(cr1,
+ USART_CR1_PCE | USART_CR1_PS | USART_CR1_M1 |
+ USART_CR1_M0,
+ config);
+ setbits_le32(cr1, USART_CR1_RE | USART_CR1_TE | BIT(uart_enable_bit));
+
+ return 0;
+}
+
+static int stm32_serial_getc(struct udevice *dev)
+{
+ struct stm32x7_serial_plat *plat = dev_get_plat(dev);
+ bool stm32f4 = plat->uart_info->stm32f4;
+ fdt_addr_t base = plat->base;
+ u32 isr = readl(base + ISR_OFFSET(stm32f4));
+
+ if ((isr & USART_ISR_RXNE) == 0)
+ return -EAGAIN;
+
+ if (isr & (USART_ISR_PE | USART_ISR_ORE | USART_ISR_FE)) {
+ if (!stm32f4)
+ setbits_le32(base + ICR_OFFSET,
+ USART_ICR_PCECF | USART_ICR_ORECF |
+ USART_ICR_FECF);
+ else
+ readl(base + RDR_OFFSET(stm32f4));
+ return -EIO;
+ }
+
+ return readl(base + RDR_OFFSET(stm32f4));
+}
+
+static int _stm32_serial_putc(fdt_addr_t base,
+ struct stm32_uart_info *uart_info,
+ const char c)
+{
+ bool stm32f4 = uart_info->stm32f4;
+
+ if ((readl(base + ISR_OFFSET(stm32f4)) & USART_ISR_TXE) == 0)
+ return -EAGAIN;
+
+ writel(c, base + TDR_OFFSET(stm32f4));
+
+ return 0;
+}
+
+static int stm32_serial_putc(struct udevice *dev, const char c)
+{
+ struct stm32x7_serial_plat *plat = dev_get_plat(dev);
+
+ return _stm32_serial_putc(plat->base, plat->uart_info, c);
+}
+
+static int stm32_serial_pending(struct udevice *dev, bool input)
+{
+ struct stm32x7_serial_plat *plat = dev_get_plat(dev);
+ bool stm32f4 = plat->uart_info->stm32f4;
+ fdt_addr_t base = plat->base;
+
+ if (input)
+ return readl(base + ISR_OFFSET(stm32f4)) &
+ USART_ISR_RXNE ? 1 : 0;
+ else
+ return readl(base + ISR_OFFSET(stm32f4)) &
+ USART_ISR_TXE ? 0 : 1;
+}
+
+static void _stm32_serial_init(fdt_addr_t base,
+ struct stm32_uart_info *uart_info)
+{
+ bool stm32f4 = uart_info->stm32f4;
+ u8 uart_enable_bit = uart_info->uart_enable_bit;
+
+ /* Disable uart-> enable fifo -> enable uart */
+ clrbits_le32(base + CR1_OFFSET(stm32f4), USART_CR1_RE | USART_CR1_TE |
+ BIT(uart_enable_bit));
+ if (uart_info->has_fifo)
+ setbits_le32(base + CR1_OFFSET(stm32f4), USART_CR1_FIFOEN);
+ setbits_le32(base + CR1_OFFSET(stm32f4), USART_CR1_RE | USART_CR1_TE |
+ BIT(uart_enable_bit));
+}
+
+static int stm32_serial_probe(struct udevice *dev)
+{
+ struct stm32x7_serial_plat *plat = dev_get_plat(dev);
+ struct clk clk;
+ struct reset_ctl reset;
+ int ret;
+
+ plat->uart_info = (struct stm32_uart_info *)dev_get_driver_data(dev);
+
+ ret = clk_get_by_index(dev, 0, &clk);
+ if (ret < 0)
+ return ret;
+
+ ret = clk_enable(&clk);
+ if (ret) {
+ dev_err(dev, "failed to enable clock\n");
+ return ret;
+ }
+
+ ret = reset_get_by_index(dev, 0, &reset);
+ if (!ret) {
+ reset_assert(&reset);
+ udelay(2);
+ reset_deassert(&reset);
+ }
+
+ plat->clock_rate = clk_get_rate(&clk);
+ if (!plat->clock_rate) {
+ clk_disable(&clk);
+ return -EINVAL;
+ };
+
+ _stm32_serial_init(plat->base, plat->uart_info);
+
+ return 0;
+}
+
+static const struct udevice_id stm32_serial_id[] = {
+ { .compatible = "st,stm32-uart", .data = (ulong)&stm32f4_info},
+ { .compatible = "st,stm32f7-uart", .data = (ulong)&stm32f7_info},
+ { .compatible = "st,stm32h7-uart", .data = (ulong)&stm32h7_info},
+ {}
+};
+
+static int stm32_serial_of_to_plat(struct udevice *dev)
+{
+ struct stm32x7_serial_plat *plat = dev_get_plat(dev);
+
+ plat->base = dev_read_addr(dev);
+ if (plat->base == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ return 0;
+}
+
+static const struct dm_serial_ops stm32_serial_ops = {
+ .putc = stm32_serial_putc,
+ .pending = stm32_serial_pending,
+ .getc = stm32_serial_getc,
+ .setbrg = stm32_serial_setbrg,
+ .setconfig = stm32_serial_setconfig
+};
+
+U_BOOT_DRIVER(serial_stm32) = {
+ .name = "serial_stm32",
+ .id = UCLASS_SERIAL,
+ .of_match = of_match_ptr(stm32_serial_id),
+ .of_to_plat = of_match_ptr(stm32_serial_of_to_plat),
+ .plat_auto = sizeof(struct stm32x7_serial_plat),
+ .ops = &stm32_serial_ops,
+ .probe = stm32_serial_probe,
+#if !CONFIG_IS_ENABLED(OF_CONTROL)
+ .flags = DM_FLAG_PRE_RELOC,
+#endif
+};
+
+#ifdef CONFIG_DEBUG_UART_STM32
+#include <debug_uart.h>
+static inline struct stm32_uart_info *_debug_uart_info(void)
+{
+ struct stm32_uart_info *uart_info;
+
+#if defined(CONFIG_STM32F4)
+ uart_info = &stm32f4_info;
+#elif defined(CONFIG_STM32F7)
+ uart_info = &stm32f7_info;
+#else
+ uart_info = &stm32h7_info;
+#endif
+ return uart_info;
+}
+
+static inline void _debug_uart_init(void)
+{
+ fdt_addr_t base = CONFIG_DEBUG_UART_BASE;
+ struct stm32_uart_info *uart_info = _debug_uart_info();
+
+ _stm32_serial_init(base, uart_info);
+ _stm32_serial_setbrg(base, uart_info,
+ CONFIG_DEBUG_UART_CLOCK,
+ CONFIG_BAUDRATE);
+}
+
+static inline void _debug_uart_putc(int c)
+{
+ fdt_addr_t base = CONFIG_DEBUG_UART_BASE;
+ struct stm32_uart_info *uart_info = _debug_uart_info();
+
+ while (_stm32_serial_putc(base, uart_info, c) == -EAGAIN)
+ ;
+}
+
+DEBUG_UART_FUNCS
+#endif
diff --git a/roms/u-boot/drivers/serial/serial_stm32.h b/roms/u-boot/drivers/serial/serial_stm32.h
new file mode 100644
index 000000000..5bee68fa9
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_stm32.h
@@ -0,0 +1,82 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2016, STMicroelectronics - All Rights Reserved
+ * Author(s): Vikas Manocha, <vikas.manocha@st.com> for STMicroelectronics.
+ */
+
+#ifndef _SERIAL_STM32_
+#define _SERIAL_STM32_
+
+#include <linux/bitops.h>
+#define CR1_OFFSET(x) (x ? 0x0c : 0x00)
+#define CR3_OFFSET(x) (x ? 0x14 : 0x08)
+#define BRR_OFFSET(x) (x ? 0x08 : 0x0c)
+#define ISR_OFFSET(x) (x ? 0x00 : 0x1c)
+
+#define ICR_OFFSET 0x20
+
+/*
+ * STM32F4 has one Data Register (DR) for received or transmitted
+ * data, so map Receive Data Register (RDR) and Transmit Data
+ * Register (TDR) at the same offset
+ */
+#define RDR_OFFSET(x) (x ? 0x04 : 0x24)
+#define TDR_OFFSET(x) (x ? 0x04 : 0x28)
+
+struct stm32_uart_info {
+ u8 uart_enable_bit; /* UART_CR1_UE */
+ bool stm32f4; /* true for STM32F4, false otherwise */
+ bool has_fifo;
+};
+
+struct stm32_uart_info stm32f4_info = {
+ .stm32f4 = true,
+ .uart_enable_bit = 13,
+ .has_fifo = false,
+};
+
+struct stm32_uart_info stm32f7_info = {
+ .uart_enable_bit = 0,
+ .stm32f4 = false,
+ .has_fifo = true,
+};
+
+struct stm32_uart_info stm32h7_info = {
+ .uart_enable_bit = 0,
+ .stm32f4 = false,
+ .has_fifo = true,
+};
+
+/* Information about a serial port */
+struct stm32x7_serial_plat {
+ fdt_addr_t base; /* address of registers in physical memory */
+ struct stm32_uart_info *uart_info;
+ unsigned long int clock_rate;
+};
+
+#define USART_CR1_FIFOEN BIT(29)
+#define USART_CR1_M1 BIT(28)
+#define USART_CR1_OVER8 BIT(15)
+#define USART_CR1_M0 BIT(12)
+#define USART_CR1_PCE BIT(10)
+#define USART_CR1_PS BIT(9)
+#define USART_CR1_TE BIT(3)
+#define USART_CR1_RE BIT(2)
+
+#define USART_CR3_OVRDIS BIT(12)
+
+#define USART_ISR_TXE BIT(7)
+#define USART_ISR_RXNE BIT(5)
+#define USART_ISR_ORE BIT(3)
+#define USART_ISR_FE BIT(1)
+#define USART_ISR_PE BIT(0)
+
+#define USART_BRR_F_MASK GENMASK(7, 0)
+#define USART_BRR_M_SHIFT 4
+#define USART_BRR_M_MASK GENMASK(15, 4)
+
+#define USART_ICR_ORECF BIT(3)
+#define USART_ICR_FECF BIT(1)
+#define USART_ICR_PCECF BIT(0)
+
+#endif
diff --git a/roms/u-boot/drivers/serial/serial_uniphier.c b/roms/u-boot/drivers/serial/serial_uniphier.c
new file mode 100644
index 000000000..27e4b92c3
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_uniphier.c
@@ -0,0 +1,177 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2012-2015 Panasonic Corporation
+ * Copyright (C) 2015-2016 Socionext Inc.
+ * Author: Masahiro Yamada <yamada.masahiro@socionext.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/bug.h>
+#include <linux/io.h>
+#include <linux/serial_reg.h>
+#include <linux/sizes.h>
+#include <linux/errno.h>
+#include <serial.h>
+#include <fdtdec.h>
+
+#define UNIPHIER_UART_REGSHIFT 2
+
+#define UNIPHIER_UART_RX (0 << (UNIPHIER_UART_REGSHIFT))
+#define UNIPHIER_UART_TX UNIPHIER_UART_RX
+/* bit[15:8] = CHAR, bit[7:0] = FCR */
+#define UNIPHIER_UART_CHAR_FCR (3 << (UNIPHIER_UART_REGSHIFT))
+#define UNIPHIER_UART_FCR_MASK GENMASK(7, 0)
+/* bit[15:8] = LCR, bit[7:0] = MCR */
+#define UNIPHIER_UART_LCR_MCR (4 << (UNIPHIER_UART_REGSHIFT))
+#define UNIPHIER_UART_LCR_MASK GENMASK(15, 8)
+#define UNIPHIER_UART_LSR (5 << (UNIPHIER_UART_REGSHIFT))
+/* Divisor Latch Register */
+#define UNIPHIER_UART_DLR (9 << (UNIPHIER_UART_REGSHIFT))
+
+struct uniphier_serial_priv {
+ void __iomem *membase;
+ unsigned int uartclk;
+};
+
+static int uniphier_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ struct uniphier_serial_priv *priv = dev_get_priv(dev);
+ static const unsigned int mode_x_div = 16;
+ unsigned int divisor;
+
+ divisor = DIV_ROUND_CLOSEST(priv->uartclk, mode_x_div * baudrate);
+
+ /* flush the trasmitter before changing hw setting */
+ while (!(readl(priv->membase + UNIPHIER_UART_LSR) & UART_LSR_TEMT))
+ ;
+
+ writel(divisor, priv->membase + UNIPHIER_UART_DLR);
+
+ return 0;
+}
+
+static int uniphier_serial_getc(struct udevice *dev)
+{
+ struct uniphier_serial_priv *priv = dev_get_priv(dev);
+
+ if (!(readl(priv->membase + UNIPHIER_UART_LSR) & UART_LSR_DR))
+ return -EAGAIN;
+
+ return readl(priv->membase + UNIPHIER_UART_RX);
+}
+
+static int uniphier_serial_putc(struct udevice *dev, const char c)
+{
+ struct uniphier_serial_priv *priv = dev_get_priv(dev);
+
+ if (!(readl(priv->membase + UNIPHIER_UART_LSR) & UART_LSR_THRE))
+ return -EAGAIN;
+
+ writel(c, priv->membase + UNIPHIER_UART_TX);
+
+ return 0;
+}
+
+static int uniphier_serial_pending(struct udevice *dev, bool input)
+{
+ struct uniphier_serial_priv *priv = dev_get_priv(dev);
+
+ if (input)
+ return readl(priv->membase + UNIPHIER_UART_LSR) & UART_LSR_DR;
+ else
+ return !(readl(priv->membase + UNIPHIER_UART_LSR) & UART_LSR_THRE);
+}
+
+/*
+ * SPL does not have enough memory footprint for the clock driver.
+ * Hardcode clock frequency for each SoC.
+ */
+struct uniphier_serial_clk_data {
+ const char *compatible;
+ unsigned int clk_rate;
+};
+
+static const struct uniphier_serial_clk_data uniphier_serial_clk_data[] = {
+ { .compatible = "socionext,uniphier-ld4", .clk_rate = 36864000 },
+ { .compatible = "socionext,uniphier-pro4", .clk_rate = 73728000 },
+ { .compatible = "socionext,uniphier-sld8", .clk_rate = 80000000 },
+ { .compatible = "socionext,uniphier-pro5", .clk_rate = 73728000 },
+ { .compatible = "socionext,uniphier-pxs2", .clk_rate = 88888888 },
+ { .compatible = "socionext,uniphier-ld6b", .clk_rate = 88888888 },
+ { .compatible = "socionext,uniphier-ld11", .clk_rate = 58823529 },
+ { .compatible = "socionext,uniphier-ld20", .clk_rate = 58823529 },
+ { .compatible = "socionext,uniphier-pxs3", .clk_rate = 58823529 },
+ { /* sentinel */ },
+};
+
+static int uniphier_serial_probe(struct udevice *dev)
+{
+ struct uniphier_serial_priv *priv = dev_get_priv(dev);
+ const struct uniphier_serial_clk_data *clk_data;
+ ofnode root_node;
+ fdt_addr_t base;
+ u32 tmp;
+
+ base = dev_read_addr(dev);
+ if (base == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ priv->membase = devm_ioremap(dev, base, SZ_64);
+ if (!priv->membase)
+ return -ENOMEM;
+
+ root_node = ofnode_path("/");
+ clk_data = uniphier_serial_clk_data;
+ while (clk_data->compatible) {
+ if (ofnode_device_is_compatible(root_node,
+ clk_data->compatible))
+ break;
+ clk_data++;
+ }
+
+ if (WARN_ON(!clk_data->compatible))
+ return -ENOTSUPP;
+
+ priv->uartclk = clk_data->clk_rate;
+
+ /* flush the trasmitter before changing hw setting */
+ while (!(readl(priv->membase + UNIPHIER_UART_LSR) & UART_LSR_TEMT))
+ ;
+
+ /* enable FIFO */
+ tmp = readl(priv->membase + UNIPHIER_UART_CHAR_FCR);
+ tmp &= ~UNIPHIER_UART_FCR_MASK;
+ tmp |= FIELD_PREP(UNIPHIER_UART_FCR_MASK, UART_FCR_ENABLE_FIFO);
+ writel(tmp, priv->membase + UNIPHIER_UART_CHAR_FCR);
+
+ tmp = readl(priv->membase + UNIPHIER_UART_LCR_MCR);
+ tmp &= ~UNIPHIER_UART_LCR_MASK;
+ tmp |= FIELD_PREP(UNIPHIER_UART_LCR_MASK, UART_LCR_WLEN8);
+ writel(tmp, priv->membase + UNIPHIER_UART_LCR_MCR);
+
+ return 0;
+}
+
+static const struct udevice_id uniphier_uart_of_match[] = {
+ { .compatible = "socionext,uniphier-uart" },
+ { /* sentinel */ }
+};
+
+static const struct dm_serial_ops uniphier_serial_ops = {
+ .setbrg = uniphier_serial_setbrg,
+ .getc = uniphier_serial_getc,
+ .putc = uniphier_serial_putc,
+ .pending = uniphier_serial_pending,
+};
+
+U_BOOT_DRIVER(uniphier_serial) = {
+ .name = "uniphier-uart",
+ .id = UCLASS_SERIAL,
+ .of_match = uniphier_uart_of_match,
+ .probe = uniphier_serial_probe,
+ .priv_auto = sizeof(struct uniphier_serial_priv),
+ .ops = &uniphier_serial_ops,
+};
diff --git a/roms/u-boot/drivers/serial/serial_xen.c b/roms/u-boot/drivers/serial/serial_xen.c
new file mode 100644
index 000000000..e1d5b229b
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_xen.c
@@ -0,0 +1,183 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) 2018 NXP
+ * (C) 2020 EPAM Systems Inc.
+ */
+#include <common.h>
+#include <cpu_func.h>
+#include <dm.h>
+#include <serial.h>
+#include <watchdog.h>
+#include <asm/global_data.h>
+
+#include <linux/bug.h>
+
+#include <xen/hvm.h>
+#include <xen/events.h>
+
+#include <xen/interface/sched.h>
+#include <xen/interface/hvm/hvm_op.h>
+#include <xen/interface/hvm/params.h>
+#include <xen/interface/io/console.h>
+#include <xen/interface/io/ring.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+u32 console_evtchn;
+
+/*
+ * struct xen_uart_priv - Structure representing a Xen UART info
+ * @intf: Console I/O interface for Xen guest OSes
+ * @evtchn: Console event channel
+ */
+struct xen_uart_priv {
+ struct xencons_interface *intf;
+ u32 evtchn;
+};
+
+int xen_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ return 0;
+}
+
+static int xen_serial_probe(struct udevice *dev)
+{
+ struct xen_uart_priv *priv = dev_get_priv(dev);
+ u64 val = 0;
+ unsigned long gfn;
+ int ret;
+
+ ret = hvm_get_parameter(HVM_PARAM_CONSOLE_EVTCHN, &val);
+ if (ret < 0 || val == 0)
+ return ret;
+
+ priv->evtchn = val;
+ console_evtchn = val;
+
+ ret = hvm_get_parameter(HVM_PARAM_CONSOLE_PFN, &val);
+ if (ret < 0)
+ return ret;
+
+ if (!val)
+ return -EINVAL;
+
+ gfn = val;
+ priv->intf = (struct xencons_interface *)(gfn << XEN_PAGE_SHIFT);
+
+ return 0;
+}
+
+static int xen_serial_pending(struct udevice *dev, bool input)
+{
+ struct xen_uart_priv *priv = dev_get_priv(dev);
+ struct xencons_interface *intf = priv->intf;
+
+ if (!input || intf->in_cons == intf->in_prod)
+ return 0;
+
+ return 1;
+}
+
+static int xen_serial_getc(struct udevice *dev)
+{
+ struct xen_uart_priv *priv = dev_get_priv(dev);
+ struct xencons_interface *intf = priv->intf;
+ XENCONS_RING_IDX cons;
+ char c;
+
+ while (intf->in_cons == intf->in_prod)
+ mb(); /* wait */
+
+ cons = intf->in_cons;
+ mb(); /* get pointers before reading ring */
+
+ c = intf->in[MASK_XENCONS_IDX(cons++, intf->in)];
+
+ mb(); /* read ring before consuming */
+ intf->in_cons = cons;
+
+ notify_remote_via_evtchn(priv->evtchn);
+
+ return c;
+}
+
+static int __write_console(struct udevice *dev, const char *data, int len)
+{
+ struct xen_uart_priv *priv = dev_get_priv(dev);
+ struct xencons_interface *intf = priv->intf;
+ XENCONS_RING_IDX cons, prod;
+ int sent = 0;
+
+ cons = intf->out_cons;
+ prod = intf->out_prod;
+ mb(); /* Update pointer */
+
+ WARN_ON((prod - cons) > sizeof(intf->out));
+
+ while ((sent < len) && ((prod - cons) < sizeof(intf->out)))
+ intf->out[MASK_XENCONS_IDX(prod++, intf->out)] = data[sent++];
+
+ mb(); /* Update data before pointer */
+ intf->out_prod = prod;
+
+ if (sent)
+ notify_remote_via_evtchn(priv->evtchn);
+
+ return sent;
+}
+
+static int write_console(struct udevice *dev, const char *data, int len)
+{
+ /*
+ * Make sure the whole buffer is emitted, polling if
+ * necessary. We don't ever want to rely on the hvc daemon
+ * because the most interesting console output is when the
+ * kernel is crippled.
+ */
+ while (len) {
+ int sent = __write_console(dev, data, len);
+
+ data += sent;
+ len -= sent;
+
+ if (unlikely(len))
+ HYPERVISOR_sched_op(SCHEDOP_yield, NULL);
+ }
+
+ return 0;
+}
+
+static int xen_serial_putc(struct udevice *dev, const char ch)
+{
+ write_console(dev, &ch, 1);
+
+ return 0;
+}
+
+static const struct dm_serial_ops xen_serial_ops = {
+ .putc = xen_serial_putc,
+ .getc = xen_serial_getc,
+ .pending = xen_serial_pending,
+};
+
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+static const struct udevice_id xen_serial_ids[] = {
+ { .compatible = "xen,xen" },
+ { }
+};
+#endif
+
+U_BOOT_DRIVER(serial_xen) = {
+ .name = "serial_xen",
+ .id = UCLASS_SERIAL,
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+ .of_match = xen_serial_ids,
+#endif
+ .priv_auto = sizeof(struct xen_uart_priv),
+ .probe = xen_serial_probe,
+ .ops = &xen_serial_ops,
+#if !CONFIG_IS_ENABLED(OF_CONTROL)
+ .flags = DM_FLAG_PRE_RELOC,
+#endif
+};
+
diff --git a/roms/u-boot/drivers/serial/serial_xuartlite.c b/roms/u-boot/drivers/serial/serial_xuartlite.c
new file mode 100644
index 000000000..9780a44d0
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_xuartlite.c
@@ -0,0 +1,171 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2008 - 2015 Michal Simek <monstr@monstr.eu>
+ * Clean driver and add xilinx constant from header file
+ *
+ * (C) Copyright 2004 Atmark Techno, Inc.
+ * Yasushi SHOJI <yashi@atmark-techno.com>
+ */
+
+#include <config.h>
+#include <common.h>
+#include <dm.h>
+#include <asm/io.h>
+#include <linux/bitops.h>
+#include <linux/compiler.h>
+#include <serial.h>
+
+#define SR_TX_FIFO_FULL BIT(3) /* transmit FIFO full */
+#define SR_TX_FIFO_EMPTY BIT(2) /* transmit FIFO empty */
+#define SR_RX_FIFO_VALID_DATA BIT(0) /* data in receive FIFO */
+#define SR_RX_FIFO_FULL BIT(1) /* receive FIFO full */
+
+#define ULITE_CONTROL_RST_TX 0x01
+#define ULITE_CONTROL_RST_RX 0x02
+
+static bool little_endian;
+
+struct uartlite {
+ unsigned int rx_fifo;
+ unsigned int tx_fifo;
+ unsigned int status;
+ unsigned int control;
+};
+
+struct uartlite_plat {
+ struct uartlite *regs;
+};
+
+static u32 uart_in32(void __iomem *addr)
+{
+ if (little_endian)
+ return in_le32(addr);
+ else
+ return in_be32(addr);
+}
+
+static void uart_out32(void __iomem *addr, u32 val)
+{
+ if (little_endian)
+ out_le32(addr, val);
+ else
+ out_be32(addr, val);
+}
+
+static int uartlite_serial_putc(struct udevice *dev, const char ch)
+{
+ struct uartlite_plat *plat = dev_get_plat(dev);
+ struct uartlite *regs = plat->regs;
+
+ if (uart_in32(&regs->status) & SR_TX_FIFO_FULL)
+ return -EAGAIN;
+
+ uart_out32(&regs->tx_fifo, ch & 0xff);
+
+ return 0;
+}
+
+static int uartlite_serial_getc(struct udevice *dev)
+{
+ struct uartlite_plat *plat = dev_get_plat(dev);
+ struct uartlite *regs = plat->regs;
+
+ if (!(uart_in32(&regs->status) & SR_RX_FIFO_VALID_DATA))
+ return -EAGAIN;
+
+ return uart_in32(&regs->rx_fifo) & 0xff;
+}
+
+static int uartlite_serial_pending(struct udevice *dev, bool input)
+{
+ struct uartlite_plat *plat = dev_get_plat(dev);
+ struct uartlite *regs = plat->regs;
+
+ if (input)
+ return uart_in32(&regs->status) & SR_RX_FIFO_VALID_DATA;
+
+ return !(uart_in32(&regs->status) & SR_TX_FIFO_EMPTY);
+}
+
+static int uartlite_serial_probe(struct udevice *dev)
+{
+ struct uartlite_plat *plat = dev_get_plat(dev);
+ struct uartlite *regs = plat->regs;
+ int ret;
+
+ uart_out32(&regs->control, 0);
+ uart_out32(&regs->control, ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX);
+ ret = uart_in32(&regs->status);
+ /* Endianness detection */
+ if ((ret & SR_TX_FIFO_EMPTY) != SR_TX_FIFO_EMPTY) {
+ little_endian = true;
+ uart_out32(&regs->control, ULITE_CONTROL_RST_RX |
+ ULITE_CONTROL_RST_TX);
+ }
+
+ return 0;
+}
+
+static int uartlite_serial_of_to_plat(struct udevice *dev)
+{
+ struct uartlite_plat *plat = dev_get_plat(dev);
+
+ plat->regs = dev_read_addr_ptr(dev);
+
+ return 0;
+}
+
+static const struct dm_serial_ops uartlite_serial_ops = {
+ .putc = uartlite_serial_putc,
+ .pending = uartlite_serial_pending,
+ .getc = uartlite_serial_getc,
+};
+
+static const struct udevice_id uartlite_serial_ids[] = {
+ { .compatible = "xlnx,opb-uartlite-1.00.b", },
+ { .compatible = "xlnx,xps-uartlite-1.00.a" },
+ { }
+};
+
+U_BOOT_DRIVER(serial_uartlite) = {
+ .name = "serial_uartlite",
+ .id = UCLASS_SERIAL,
+ .of_match = uartlite_serial_ids,
+ .of_to_plat = uartlite_serial_of_to_plat,
+ .plat_auto = sizeof(struct uartlite_plat),
+ .probe = uartlite_serial_probe,
+ .ops = &uartlite_serial_ops,
+};
+
+#ifdef CONFIG_DEBUG_UART_UARTLITE
+
+#include <debug_uart.h>
+
+static inline void _debug_uart_init(void)
+{
+ struct uartlite *regs = (struct uartlite *)CONFIG_DEBUG_UART_BASE;
+ int ret;
+
+ uart_out32(&regs->control, 0);
+ uart_out32(&regs->control, ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX);
+ ret = uart_in32(&regs->status);
+ /* Endianness detection */
+ if ((ret & SR_TX_FIFO_EMPTY) != SR_TX_FIFO_EMPTY) {
+ little_endian = true;
+ uart_out32(&regs->control, ULITE_CONTROL_RST_RX |
+ ULITE_CONTROL_RST_TX);
+ }
+}
+
+static inline void _debug_uart_putc(int ch)
+{
+ struct uartlite *regs = (struct uartlite *)CONFIG_DEBUG_UART_BASE;
+
+ while (uart_in32(&regs->status) & SR_TX_FIFO_FULL)
+ ;
+
+ uart_out32(&regs->tx_fifo, ch & 0xff);
+}
+
+DEBUG_UART_FUNCS
+#endif
diff --git a/roms/u-boot/drivers/serial/serial_zynq.c b/roms/u-boot/drivers/serial/serial_zynq.c
new file mode 100644
index 000000000..799d52404
--- /dev/null
+++ b/roms/u-boot/drivers/serial/serial_zynq.c
@@ -0,0 +1,240 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2012 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2011-2012 Xilinx, Inc. All rights reserved.
+ */
+
+#include <clk.h>
+#include <common.h>
+#include <debug_uart.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <log.h>
+#include <watchdog.h>
+#include <asm/io.h>
+#include <dm/device_compat.h>
+#include <linux/bitops.h>
+#include <linux/compiler.h>
+#include <serial.h>
+#include <linux/err.h>
+
+#define ZYNQ_UART_SR_TXACTIVE BIT(11) /* TX active */
+#define ZYNQ_UART_SR_TXFULL BIT(4) /* TX FIFO full */
+#define ZYNQ_UART_SR_RXEMPTY BIT(1) /* RX FIFO empty */
+
+#define ZYNQ_UART_CR_TX_EN BIT(4) /* TX enabled */
+#define ZYNQ_UART_CR_RX_EN BIT(2) /* RX enabled */
+#define ZYNQ_UART_CR_TXRST BIT(1) /* TX logic reset */
+#define ZYNQ_UART_CR_RXRST BIT(0) /* RX logic reset */
+
+#define ZYNQ_UART_MR_PARITY_NONE 0x00000020 /* No parity mode */
+
+struct uart_zynq {
+ u32 control; /* 0x0 - Control Register [8:0] */
+ u32 mode; /* 0x4 - Mode Register [10:0] */
+ u32 reserved1[4];
+ u32 baud_rate_gen; /* 0x18 - Baud Rate Generator [15:0] */
+ u32 reserved2[4];
+ u32 channel_sts; /* 0x2c - Channel Status [11:0] */
+ u32 tx_rx_fifo; /* 0x30 - FIFO [15:0] or [7:0] */
+ u32 baud_rate_divider; /* 0x34 - Baud Rate Divider [7:0] */
+};
+
+struct zynq_uart_plat {
+ struct uart_zynq *regs;
+};
+
+/* Set up the baud rate */
+static void _uart_zynq_serial_setbrg(struct uart_zynq *regs,
+ unsigned long clock, unsigned long baud)
+{
+ /* Calculation results. */
+ unsigned int calc_bauderror, bdiv, bgen;
+ unsigned long calc_baud = 0;
+
+ /* Covering case where input clock is so slow */
+ if (clock < 1000000 && baud > 4800)
+ baud = 4800;
+
+ /* master clock
+ * Baud rate = ------------------
+ * bgen * (bdiv + 1)
+ *
+ * Find acceptable values for baud generation.
+ */
+ for (bdiv = 4; bdiv < 255; bdiv++) {
+ bgen = clock / (baud * (bdiv + 1));
+ if (bgen < 2 || bgen > 65535)
+ continue;
+
+ calc_baud = clock / (bgen * (bdiv + 1));
+
+ /*
+ * Use first calculated baudrate with
+ * an acceptable (<3%) error
+ */
+ if (baud > calc_baud)
+ calc_bauderror = baud - calc_baud;
+ else
+ calc_bauderror = calc_baud - baud;
+ if (((calc_bauderror * 100) / baud) < 3)
+ break;
+ }
+
+ writel(bdiv, &regs->baud_rate_divider);
+ writel(bgen, &regs->baud_rate_gen);
+}
+
+/* Initialize the UART, with...some settings. */
+static void _uart_zynq_serial_init(struct uart_zynq *regs)
+{
+ /* RX/TX enabled & reset */
+ writel(ZYNQ_UART_CR_TX_EN | ZYNQ_UART_CR_RX_EN | ZYNQ_UART_CR_TXRST | \
+ ZYNQ_UART_CR_RXRST, &regs->control);
+ writel(ZYNQ_UART_MR_PARITY_NONE, &regs->mode); /* 8 bit, no parity */
+}
+
+static int _uart_zynq_serial_putc(struct uart_zynq *regs, const char c)
+{
+ if (readl(&regs->channel_sts) & ZYNQ_UART_SR_TXFULL)
+ return -EAGAIN;
+
+ writel(c, &regs->tx_rx_fifo);
+
+ return 0;
+}
+
+static int zynq_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ struct zynq_uart_plat *plat = dev_get_plat(dev);
+ unsigned long clock;
+
+ int ret;
+ struct clk clk;
+
+ ret = clk_get_by_index(dev, 0, &clk);
+ if (ret < 0) {
+ dev_err(dev, "failed to get clock\n");
+ return ret;
+ }
+
+ clock = clk_get_rate(&clk);
+ if (IS_ERR_VALUE(clock)) {
+ dev_err(dev, "failed to get rate\n");
+ return clock;
+ }
+ debug("%s: CLK %ld\n", __func__, clock);
+
+ ret = clk_enable(&clk);
+ if (ret) {
+ dev_err(dev, "failed to enable clock\n");
+ return ret;
+ }
+
+ _uart_zynq_serial_setbrg(plat->regs, clock, baudrate);
+
+ return 0;
+}
+
+static int zynq_serial_probe(struct udevice *dev)
+{
+ struct zynq_uart_plat *plat = dev_get_plat(dev);
+ struct uart_zynq *regs = plat->regs;
+ u32 val;
+
+ /* No need to reinitialize the UART if TX already enabled */
+ val = readl(&regs->control);
+ if (val & ZYNQ_UART_CR_TX_EN)
+ return 0;
+
+ _uart_zynq_serial_init(plat->regs);
+
+ return 0;
+}
+
+static int zynq_serial_getc(struct udevice *dev)
+{
+ struct zynq_uart_plat *plat = dev_get_plat(dev);
+ struct uart_zynq *regs = plat->regs;
+
+ if (readl(&regs->channel_sts) & ZYNQ_UART_SR_RXEMPTY)
+ return -EAGAIN;
+
+ return readl(&regs->tx_rx_fifo);
+}
+
+static int zynq_serial_putc(struct udevice *dev, const char ch)
+{
+ struct zynq_uart_plat *plat = dev_get_plat(dev);
+
+ return _uart_zynq_serial_putc(plat->regs, ch);
+}
+
+static int zynq_serial_pending(struct udevice *dev, bool input)
+{
+ struct zynq_uart_plat *plat = dev_get_plat(dev);
+ struct uart_zynq *regs = plat->regs;
+
+ if (input)
+ return !(readl(&regs->channel_sts) & ZYNQ_UART_SR_RXEMPTY);
+ else
+ return !!(readl(&regs->channel_sts) & ZYNQ_UART_SR_TXACTIVE);
+}
+
+static int zynq_serial_of_to_plat(struct udevice *dev)
+{
+ struct zynq_uart_plat *plat = dev_get_plat(dev);
+
+ plat->regs = (struct uart_zynq *)dev_read_addr(dev);
+ if (IS_ERR(plat->regs))
+ return PTR_ERR(plat->regs);
+
+ return 0;
+}
+
+static const struct dm_serial_ops zynq_serial_ops = {
+ .putc = zynq_serial_putc,
+ .pending = zynq_serial_pending,
+ .getc = zynq_serial_getc,
+ .setbrg = zynq_serial_setbrg,
+};
+
+static const struct udevice_id zynq_serial_ids[] = {
+ { .compatible = "xlnx,xuartps" },
+ { .compatible = "cdns,uart-r1p8" },
+ { .compatible = "cdns,uart-r1p12" },
+ { }
+};
+
+U_BOOT_DRIVER(serial_zynq) = {
+ .name = "serial_zynq",
+ .id = UCLASS_SERIAL,
+ .of_match = zynq_serial_ids,
+ .of_to_plat = zynq_serial_of_to_plat,
+ .plat_auto = sizeof(struct zynq_uart_plat),
+ .probe = zynq_serial_probe,
+ .ops = &zynq_serial_ops,
+};
+
+#ifdef CONFIG_DEBUG_UART_ZYNQ
+static inline void _debug_uart_init(void)
+{
+ struct uart_zynq *regs = (struct uart_zynq *)CONFIG_DEBUG_UART_BASE;
+
+ _uart_zynq_serial_init(regs);
+ _uart_zynq_serial_setbrg(regs, CONFIG_DEBUG_UART_CLOCK,
+ CONFIG_BAUDRATE);
+}
+
+static inline void _debug_uart_putc(int ch)
+{
+ struct uart_zynq *regs = (struct uart_zynq *)CONFIG_DEBUG_UART_BASE;
+
+ while (_uart_zynq_serial_putc(regs, ch) == -EAGAIN)
+ WATCHDOG_RESET();
+}
+
+DEBUG_UART_FUNCS
+
+#endif
diff --git a/roms/u-boot/drivers/serial/usbtty.c b/roms/u-boot/drivers/serial/usbtty.c
new file mode 100644
index 000000000..4f4eb02de
--- /dev/null
+++ b/roms/u-boot/drivers/serial/usbtty.c
@@ -0,0 +1,1042 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2003
+ * Gerry Hamel, geh@ti.com, Texas Instruments
+ *
+ * (C) Copyright 2006
+ * Bryan O'Donoghue, bodonoghue@codehermit.ie
+ */
+
+#include <common.h>
+#include <config.h>
+#include <circbuf.h>
+#include <env.h>
+#include <serial.h>
+#include <stdio_dev.h>
+#include <asm/unaligned.h>
+#include "usbtty.h"
+#include "usb_cdc_acm.h"
+#include "usbdescriptors.h"
+
+#ifdef DEBUG
+#define TTYDBG(fmt,args...)\
+ serial_printf("[%s] %s %d: "fmt, __FILE__,__FUNCTION__,__LINE__,##args)
+#else
+#define TTYDBG(fmt,args...) do{}while(0)
+#endif
+
+#if 1
+#define TTYERR(fmt,args...)\
+ serial_printf("ERROR![%s] %s %d: "fmt, __FILE__,__FUNCTION__,\
+ __LINE__,##args)
+#else
+#define TTYERR(fmt,args...) do{}while(0)
+#endif
+
+/*
+ * Defines
+ */
+#define NUM_CONFIGS 1
+#define MAX_INTERFACES 2
+#define NUM_ENDPOINTS 3
+#define ACM_TX_ENDPOINT 3
+#define ACM_RX_ENDPOINT 2
+#define GSERIAL_TX_ENDPOINT 2
+#define GSERIAL_RX_ENDPOINT 1
+#define NUM_ACM_INTERFACES 2
+#define NUM_GSERIAL_INTERFACES 1
+#define CONFIG_USBD_DATA_INTERFACE_STR "Bulk Data Interface"
+#define CONFIG_USBD_CTRL_INTERFACE_STR "Control Interface"
+
+/*
+ * Buffers to hold input and output data
+ */
+#define USBTTY_BUFFER_SIZE 2048
+static circbuf_t usbtty_input;
+static circbuf_t usbtty_output;
+
+
+/*
+ * Instance variables
+ */
+static struct stdio_dev usbttydev;
+static struct usb_device_instance device_instance[1];
+static struct usb_bus_instance bus_instance[1];
+static struct usb_configuration_instance config_instance[NUM_CONFIGS];
+static struct usb_interface_instance interface_instance[MAX_INTERFACES];
+static struct usb_alternate_instance alternate_instance[MAX_INTERFACES];
+/* one extra for control endpoint */
+static struct usb_endpoint_instance endpoint_instance[NUM_ENDPOINTS+1];
+
+/*
+ * Global flag
+ */
+int usbtty_configured_flag = 0;
+
+/*
+ * Serial number
+ */
+static char serial_number[16];
+
+
+/*
+ * Descriptors, Strings, Local variables.
+ */
+
+/* defined and used by gadget/ep0.c */
+extern struct usb_string_descriptor **usb_strings;
+
+/* Indicies, References */
+static unsigned short rx_endpoint = 0;
+static unsigned short tx_endpoint = 0;
+static unsigned short interface_count = 0;
+static struct usb_string_descriptor *usbtty_string_table[STR_COUNT];
+
+/* USB Descriptor Strings */
+static u8 wstrLang[4] = {4,USB_DT_STRING,0x9,0x4};
+static u8 wstrManufacturer[2 + 2*(sizeof(CONFIG_USBD_MANUFACTURER)-1)];
+static u8 wstrProduct[2 + 2*(sizeof(CONFIG_USBD_PRODUCT_NAME)-1)];
+static u8 wstrSerial[2 + 2*(sizeof(serial_number) - 1)];
+static u8 wstrConfiguration[2 + 2*(sizeof(CONFIG_USBD_CONFIGURATION_STR)-1)];
+static u8 wstrDataInterface[2 + 2*(sizeof(CONFIG_USBD_DATA_INTERFACE_STR)-1)];
+static u8 wstrCtrlInterface[2 + 2*(sizeof(CONFIG_USBD_DATA_INTERFACE_STR)-1)];
+
+/* Standard USB Data Structures */
+static struct usb_interface_descriptor interface_descriptors[MAX_INTERFACES];
+static struct usb_endpoint_descriptor *ep_descriptor_ptrs[NUM_ENDPOINTS];
+static struct usb_configuration_descriptor *configuration_descriptor = 0;
+static struct usb_device_descriptor device_descriptor = {
+ .bLength = sizeof(struct usb_device_descriptor),
+ .bDescriptorType = USB_DT_DEVICE,
+ .bcdUSB = cpu_to_le16(USB_BCD_VERSION),
+ .bDeviceSubClass = 0x00,
+ .bDeviceProtocol = 0x00,
+ .bMaxPacketSize0 = EP0_MAX_PACKET_SIZE,
+ .idVendor = cpu_to_le16(CONFIG_USBD_VENDORID),
+ .bcdDevice = cpu_to_le16(USBTTY_BCD_DEVICE),
+ .iManufacturer = STR_MANUFACTURER,
+ .iProduct = STR_PRODUCT,
+ .iSerialNumber = STR_SERIAL,
+ .bNumConfigurations = NUM_CONFIGS
+};
+
+
+#if defined(CONFIG_USBD_HS)
+static struct usb_qualifier_descriptor qualifier_descriptor = {
+ .bLength = sizeof(struct usb_qualifier_descriptor),
+ .bDescriptorType = USB_DT_QUAL,
+ .bcdUSB = cpu_to_le16(USB_BCD_VERSION),
+ .bDeviceClass = COMMUNICATIONS_DEVICE_CLASS,
+ .bDeviceSubClass = 0x00,
+ .bDeviceProtocol = 0x00,
+ .bMaxPacketSize0 = EP0_MAX_PACKET_SIZE,
+ .bNumConfigurations = NUM_CONFIGS
+};
+#endif
+
+/*
+ * Static CDC ACM specific descriptors
+ */
+
+struct acm_config_desc {
+ struct usb_configuration_descriptor configuration_desc;
+
+ /* Master Interface */
+ struct usb_interface_descriptor interface_desc;
+
+ struct usb_class_header_function_descriptor usb_class_header;
+ struct usb_class_call_management_descriptor usb_class_call_mgt;
+ struct usb_class_abstract_control_descriptor usb_class_acm;
+ struct usb_class_union_function_descriptor usb_class_union;
+ struct usb_endpoint_descriptor notification_endpoint;
+
+ /* Slave Interface */
+ struct usb_interface_descriptor data_class_interface;
+ struct usb_endpoint_descriptor data_endpoints[NUM_ENDPOINTS-1];
+} __attribute__((packed));
+
+static struct acm_config_desc acm_configuration_descriptors[NUM_CONFIGS] = {
+ {
+ .configuration_desc ={
+ .bLength =
+ sizeof(struct usb_configuration_descriptor),
+ .bDescriptorType = USB_DT_CONFIG,
+ .wTotalLength =
+ cpu_to_le16(sizeof(struct acm_config_desc)),
+ .bNumInterfaces = NUM_ACM_INTERFACES,
+ .bConfigurationValue = 1,
+ .iConfiguration = STR_CONFIG,
+ .bmAttributes =
+ BMATTRIBUTE_SELF_POWERED|BMATTRIBUTE_RESERVED,
+ .bMaxPower = USBTTY_MAXPOWER
+ },
+ /* Interface 1 */
+ .interface_desc = {
+ .bLength = sizeof(struct usb_interface_descriptor),
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 0,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 0x01,
+ .bInterfaceClass =
+ COMMUNICATIONS_INTERFACE_CLASS_CONTROL,
+ .bInterfaceSubClass = COMMUNICATIONS_ACM_SUBCLASS,
+ .bInterfaceProtocol = COMMUNICATIONS_V25TER_PROTOCOL,
+ .iInterface = STR_CTRL_INTERFACE,
+ },
+ .usb_class_header = {
+ .bFunctionLength =
+ sizeof(struct usb_class_header_function_descriptor),
+ .bDescriptorType = CS_INTERFACE,
+ .bDescriptorSubtype = USB_ST_HEADER,
+ .bcdCDC = cpu_to_le16(110),
+ },
+ .usb_class_call_mgt = {
+ .bFunctionLength =
+ sizeof(struct usb_class_call_management_descriptor),
+ .bDescriptorType = CS_INTERFACE,
+ .bDescriptorSubtype = USB_ST_CMF,
+ .bmCapabilities = 0x00,
+ .bDataInterface = 0x01,
+ },
+ .usb_class_acm = {
+ .bFunctionLength =
+ sizeof(struct usb_class_abstract_control_descriptor),
+ .bDescriptorType = CS_INTERFACE,
+ .bDescriptorSubtype = USB_ST_ACMF,
+ .bmCapabilities = 0x00,
+ },
+ .usb_class_union = {
+ .bFunctionLength =
+ sizeof(struct usb_class_union_function_descriptor),
+ .bDescriptorType = CS_INTERFACE,
+ .bDescriptorSubtype = USB_ST_UF,
+ .bMasterInterface = 0x00,
+ .bSlaveInterface0 = 0x01,
+ },
+ .notification_endpoint = {
+ .bLength =
+ sizeof(struct usb_endpoint_descriptor),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = UDC_INT_ENDPOINT | USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize
+ = cpu_to_le16(CONFIG_USBD_SERIAL_INT_PKTSIZE),
+ .bInterval = 0xFF,
+ },
+
+ /* Interface 2 */
+ .data_class_interface = {
+ .bLength =
+ sizeof(struct usb_interface_descriptor),
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 0x01,
+ .bAlternateSetting = 0x00,
+ .bNumEndpoints = 0x02,
+ .bInterfaceClass =
+ COMMUNICATIONS_INTERFACE_CLASS_DATA,
+ .bInterfaceSubClass = DATA_INTERFACE_SUBCLASS_NONE,
+ .bInterfaceProtocol = DATA_INTERFACE_PROTOCOL_NONE,
+ .iInterface = STR_DATA_INTERFACE,
+ },
+ .data_endpoints = {
+ {
+ .bLength =
+ sizeof(struct usb_endpoint_descriptor),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = UDC_OUT_ENDPOINT | USB_DIR_OUT,
+ .bmAttributes =
+ USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize =
+ cpu_to_le16(CONFIG_USBD_SERIAL_BULK_PKTSIZE),
+ .bInterval = 0xFF,
+ },
+ {
+ .bLength =
+ sizeof(struct usb_endpoint_descriptor),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = UDC_IN_ENDPOINT | USB_DIR_IN,
+ .bmAttributes =
+ USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize =
+ cpu_to_le16(CONFIG_USBD_SERIAL_BULK_PKTSIZE),
+ .bInterval = 0xFF,
+ },
+ },
+ },
+};
+
+static struct rs232_emu rs232_desc={
+ .dter = 115200,
+ .stop_bits = 0x00,
+ .parity = 0x00,
+ .data_bits = 0x08
+};
+
+
+/*
+ * Static Generic Serial specific data
+ */
+
+
+struct gserial_config_desc {
+
+ struct usb_configuration_descriptor configuration_desc;
+ struct usb_interface_descriptor interface_desc[NUM_GSERIAL_INTERFACES];
+ struct usb_endpoint_descriptor data_endpoints[NUM_ENDPOINTS];
+
+} __attribute__((packed));
+
+static struct gserial_config_desc
+gserial_configuration_descriptors[NUM_CONFIGS] ={
+ {
+ .configuration_desc ={
+ .bLength = sizeof(struct usb_configuration_descriptor),
+ .bDescriptorType = USB_DT_CONFIG,
+ .wTotalLength =
+ cpu_to_le16(sizeof(struct gserial_config_desc)),
+ .bNumInterfaces = NUM_GSERIAL_INTERFACES,
+ .bConfigurationValue = 1,
+ .iConfiguration = STR_CONFIG,
+ .bmAttributes =
+ BMATTRIBUTE_SELF_POWERED|BMATTRIBUTE_RESERVED,
+ .bMaxPower = USBTTY_MAXPOWER
+ },
+ .interface_desc = {
+ {
+ .bLength =
+ sizeof(struct usb_interface_descriptor),
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 0,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = NUM_ENDPOINTS,
+ .bInterfaceClass =
+ COMMUNICATIONS_INTERFACE_CLASS_VENDOR,
+ .bInterfaceSubClass =
+ COMMUNICATIONS_NO_SUBCLASS,
+ .bInterfaceProtocol =
+ COMMUNICATIONS_NO_PROTOCOL,
+ .iInterface = STR_DATA_INTERFACE
+ },
+ },
+ .data_endpoints = {
+ {
+ .bLength =
+ sizeof(struct usb_endpoint_descriptor),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = UDC_OUT_ENDPOINT | USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize =
+ cpu_to_le16(CONFIG_USBD_SERIAL_OUT_PKTSIZE),
+ .bInterval= 0xFF,
+ },
+ {
+ .bLength =
+ sizeof(struct usb_endpoint_descriptor),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = UDC_IN_ENDPOINT | USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize =
+ cpu_to_le16(CONFIG_USBD_SERIAL_IN_PKTSIZE),
+ .bInterval = 0xFF,
+ },
+ {
+ .bLength =
+ sizeof(struct usb_endpoint_descriptor),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = UDC_INT_ENDPOINT | USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize =
+ cpu_to_le16(CONFIG_USBD_SERIAL_INT_PKTSIZE),
+ .bInterval = 0xFF,
+ },
+ },
+ },
+};
+
+/*
+ * Static Function Prototypes
+ */
+
+static void usbtty_init_strings (void);
+static void usbtty_init_instances (void);
+static void usbtty_init_endpoints (void);
+static void usbtty_init_terminal_type(short type);
+static void usbtty_event_handler (struct usb_device_instance *device,
+ usb_device_event_t event, int data);
+static int usbtty_cdc_setup(struct usb_device_request *request,
+ struct urb *urb);
+static int usbtty_configured (void);
+static int write_buffer (circbuf_t * buf);
+static int fill_buffer (circbuf_t * buf);
+
+void usbtty_poll (void);
+
+/* utility function for converting char* to wide string used by USB */
+static void str2wide (char *str, u16 * wide)
+{
+ int i;
+ for (i = 0; i < strlen (str) && str[i]; i++){
+ #if defined(__LITTLE_ENDIAN)
+ wide[i] = (u16) str[i];
+ #elif defined(__BIG_ENDIAN)
+ wide[i] = ((u16)(str[i])<<8);
+ #else
+ #error "__LITTLE_ENDIAN or __BIG_ENDIAN undefined"
+ #endif
+ }
+}
+
+/*
+ * Test whether a character is in the RX buffer
+ */
+
+int usbtty_tstc(struct stdio_dev *dev)
+{
+ struct usb_endpoint_instance *endpoint =
+ &endpoint_instance[rx_endpoint];
+
+ /* If no input data exists, allow more RX to be accepted */
+ if(usbtty_input.size <= 0){
+ udc_unset_nak(endpoint->endpoint_address&0x03);
+ }
+
+ usbtty_poll ();
+ return (usbtty_input.size > 0);
+}
+
+/*
+ * Read a single byte from the usb client port. Returns 1 on success, 0
+ * otherwise. When the function is succesfull, the character read is
+ * written into its argument c.
+ */
+
+int usbtty_getc(struct stdio_dev *dev)
+{
+ char c;
+ struct usb_endpoint_instance *endpoint =
+ &endpoint_instance[rx_endpoint];
+
+ while (usbtty_input.size <= 0) {
+ udc_unset_nak(endpoint->endpoint_address&0x03);
+ usbtty_poll ();
+ }
+
+ buf_pop (&usbtty_input, &c, 1);
+ udc_set_nak(endpoint->endpoint_address&0x03);
+
+ return c;
+}
+
+/*
+ * Output a single byte to the usb client port.
+ */
+void usbtty_putc(struct stdio_dev *dev, const char c)
+{
+ if (!usbtty_configured ())
+ return;
+
+ /* If \n, also do \r */
+ if (c == '\n')
+ buf_push (&usbtty_output, "\r", 1);
+
+ buf_push(&usbtty_output, &c, 1);
+
+ /* Poll at end to handle new data... */
+ if ((usbtty_output.size + 2) >= usbtty_output.totalsize) {
+ usbtty_poll ();
+ }
+}
+
+/* usbtty_puts() helper function for finding the next '\n' in a string */
+static int next_nl_pos (const char *s)
+{
+ int i;
+
+ for (i = 0; s[i] != '\0'; i++) {
+ if (s[i] == '\n')
+ return i;
+ }
+ return i;
+}
+
+/*
+ * Output a string to the usb client port - implementing flow control
+ */
+
+static void __usbtty_puts (const char *str, int len)
+{
+ int maxlen = usbtty_output.totalsize;
+ int space, n;
+
+ /* break str into chunks < buffer size, if needed */
+ while (len > 0) {
+ usbtty_poll ();
+
+ space = maxlen - usbtty_output.size;
+ /* Empty buffer here, if needed, to ensure space... */
+ if (space) {
+ write_buffer (&usbtty_output);
+
+ n = min(space, min(len, maxlen));
+ buf_push (&usbtty_output, str, n);
+
+ str += n;
+ len -= n;
+ }
+ }
+}
+
+void usbtty_puts(struct stdio_dev *dev, const char *str)
+{
+ int n;
+ int len;
+
+ if (!usbtty_configured ())
+ return;
+
+ len = strlen (str);
+ /* add '\r' for each '\n' */
+ while (len > 0) {
+ n = next_nl_pos (str);
+
+ if (str[n] == '\n') {
+ __usbtty_puts(str, n);
+ __usbtty_puts("\r\n", 2);
+ str += (n + 1);
+ len -= (n + 1);
+ } else {
+ /* No \n found. All done. */
+ __usbtty_puts (str, n);
+ break;
+ }
+ }
+
+ /* Poll at end to handle new data... */
+ usbtty_poll ();
+}
+
+/*
+ * Initialize the usb client port.
+ *
+ */
+int drv_usbtty_init (void)
+{
+ int rc;
+ char * sn;
+ char * tt;
+ int snlen;
+
+ /* Get serial number */
+ sn = env_get("serial#");
+ if (!sn)
+ sn = "000000000000";
+ snlen = strlen(sn);
+ if (snlen > sizeof(serial_number) - 1) {
+ printf ("Warning: serial number %s is too long (%d > %lu)\n",
+ sn, snlen, (ulong)(sizeof(serial_number) - 1));
+ snlen = sizeof(serial_number) - 1;
+ }
+ memcpy (serial_number, sn, snlen);
+ serial_number[snlen] = '\0';
+
+ /* Decide on which type of UDC device to be.
+ */
+ tt = env_get("usbtty");
+ if (!tt)
+ tt = "generic";
+ usbtty_init_terminal_type(strcmp(tt,"cdc_acm"));
+
+ /* prepare buffers... */
+ buf_init (&usbtty_input, USBTTY_BUFFER_SIZE);
+ buf_init (&usbtty_output, USBTTY_BUFFER_SIZE);
+
+ /* Now, set up USB controller and infrastructure */
+ udc_init (); /* Basic USB initialization */
+
+ usbtty_init_strings ();
+ usbtty_init_instances ();
+
+ usbtty_init_endpoints ();
+
+ udc_startup_events (device_instance);/* Enable dev, init udc pointers */
+ udc_connect (); /* Enable pullup for host detection */
+
+ /* Device initialization */
+ memset (&usbttydev, 0, sizeof (usbttydev));
+
+ strcpy (usbttydev.name, "usbtty");
+ usbttydev.ext = 0; /* No extensions */
+ usbttydev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_OUTPUT;
+ usbttydev.tstc = usbtty_tstc; /* 'tstc' function */
+ usbttydev.getc = usbtty_getc; /* 'getc' function */
+ usbttydev.putc = usbtty_putc; /* 'putc' function */
+ usbttydev.puts = usbtty_puts; /* 'puts' function */
+
+ rc = stdio_register (&usbttydev);
+
+ return (rc == 0) ? 1 : rc;
+}
+
+static void usbtty_init_strings (void)
+{
+ struct usb_string_descriptor *string;
+
+ usbtty_string_table[STR_LANG] =
+ (struct usb_string_descriptor*)wstrLang;
+
+ string = (struct usb_string_descriptor *) wstrManufacturer;
+ string->bLength = sizeof(wstrManufacturer);
+ string->bDescriptorType = USB_DT_STRING;
+ str2wide (CONFIG_USBD_MANUFACTURER, string->wData);
+ usbtty_string_table[STR_MANUFACTURER]=string;
+
+
+ string = (struct usb_string_descriptor *) wstrProduct;
+ string->bLength = sizeof(wstrProduct);
+ string->bDescriptorType = USB_DT_STRING;
+ str2wide (CONFIG_USBD_PRODUCT_NAME, string->wData);
+ usbtty_string_table[STR_PRODUCT]=string;
+
+
+ string = (struct usb_string_descriptor *) wstrSerial;
+ string->bLength = sizeof(serial_number);
+ string->bDescriptorType = USB_DT_STRING;
+ str2wide (serial_number, string->wData);
+ usbtty_string_table[STR_SERIAL]=string;
+
+
+ string = (struct usb_string_descriptor *) wstrConfiguration;
+ string->bLength = sizeof(wstrConfiguration);
+ string->bDescriptorType = USB_DT_STRING;
+ str2wide (CONFIG_USBD_CONFIGURATION_STR, string->wData);
+ usbtty_string_table[STR_CONFIG]=string;
+
+
+ string = (struct usb_string_descriptor *) wstrDataInterface;
+ string->bLength = sizeof(wstrDataInterface);
+ string->bDescriptorType = USB_DT_STRING;
+ str2wide (CONFIG_USBD_DATA_INTERFACE_STR, string->wData);
+ usbtty_string_table[STR_DATA_INTERFACE]=string;
+
+ string = (struct usb_string_descriptor *) wstrCtrlInterface;
+ string->bLength = sizeof(wstrCtrlInterface);
+ string->bDescriptorType = USB_DT_STRING;
+ str2wide (CONFIG_USBD_CTRL_INTERFACE_STR, string->wData);
+ usbtty_string_table[STR_CTRL_INTERFACE]=string;
+
+ /* Now, initialize the string table for ep0 handling */
+ usb_strings = usbtty_string_table;
+}
+
+#define init_wMaxPacketSize(x) le16_to_cpu(get_unaligned(\
+ &ep_descriptor_ptrs[(x) - 1]->wMaxPacketSize));
+
+static void usbtty_init_instances (void)
+{
+ int i;
+
+ /* initialize device instance */
+ memset (device_instance, 0, sizeof (struct usb_device_instance));
+ device_instance->device_state = STATE_INIT;
+ device_instance->device_descriptor = &device_descriptor;
+#if defined(CONFIG_USBD_HS)
+ device_instance->qualifier_descriptor = &qualifier_descriptor;
+#endif
+ device_instance->event = usbtty_event_handler;
+ device_instance->cdc_recv_setup = usbtty_cdc_setup;
+ device_instance->bus = bus_instance;
+ device_instance->configurations = NUM_CONFIGS;
+ device_instance->configuration_instance_array = config_instance;
+
+ /* initialize bus instance */
+ memset (bus_instance, 0, sizeof (struct usb_bus_instance));
+ bus_instance->device = device_instance;
+ bus_instance->endpoint_array = endpoint_instance;
+ bus_instance->max_endpoints = 1;
+ bus_instance->maxpacketsize = 64;
+ bus_instance->serial_number_str = serial_number;
+
+ /* configuration instance */
+ memset (config_instance, 0,
+ sizeof (struct usb_configuration_instance));
+ config_instance->interfaces = interface_count;
+ config_instance->configuration_descriptor = configuration_descriptor;
+ config_instance->interface_instance_array = interface_instance;
+
+ /* interface instance */
+ memset (interface_instance, 0,
+ sizeof (struct usb_interface_instance));
+ interface_instance->alternates = 1;
+ interface_instance->alternates_instance_array = alternate_instance;
+
+ /* alternates instance */
+ memset (alternate_instance, 0,
+ sizeof (struct usb_alternate_instance));
+ alternate_instance->interface_descriptor = interface_descriptors;
+ alternate_instance->endpoints = NUM_ENDPOINTS;
+ alternate_instance->endpoints_descriptor_array = ep_descriptor_ptrs;
+
+ /* endpoint instances */
+ memset (&endpoint_instance[0], 0,
+ sizeof (struct usb_endpoint_instance));
+ endpoint_instance[0].endpoint_address = 0;
+ endpoint_instance[0].rcv_packetSize = EP0_MAX_PACKET_SIZE;
+ endpoint_instance[0].rcv_attributes = USB_ENDPOINT_XFER_CONTROL;
+ endpoint_instance[0].tx_packetSize = EP0_MAX_PACKET_SIZE;
+ endpoint_instance[0].tx_attributes = USB_ENDPOINT_XFER_CONTROL;
+ udc_setup_ep (device_instance, 0, &endpoint_instance[0]);
+
+ for (i = 1; i <= NUM_ENDPOINTS; i++) {
+ memset (&endpoint_instance[i], 0,
+ sizeof (struct usb_endpoint_instance));
+
+ endpoint_instance[i].endpoint_address =
+ ep_descriptor_ptrs[i - 1]->bEndpointAddress;
+
+ endpoint_instance[i].rcv_attributes =
+ ep_descriptor_ptrs[i - 1]->bmAttributes;
+
+ endpoint_instance[i].rcv_packetSize = init_wMaxPacketSize(i);
+
+ endpoint_instance[i].tx_attributes =
+ ep_descriptor_ptrs[i - 1]->bmAttributes;
+
+ endpoint_instance[i].tx_packetSize = init_wMaxPacketSize(i);
+
+ endpoint_instance[i].tx_attributes =
+ ep_descriptor_ptrs[i - 1]->bmAttributes;
+
+ urb_link_init (&endpoint_instance[i].rcv);
+ urb_link_init (&endpoint_instance[i].rdy);
+ urb_link_init (&endpoint_instance[i].tx);
+ urb_link_init (&endpoint_instance[i].done);
+
+ if (endpoint_instance[i].endpoint_address & USB_DIR_IN)
+ endpoint_instance[i].tx_urb =
+ usbd_alloc_urb (device_instance,
+ &endpoint_instance[i]);
+ else
+ endpoint_instance[i].rcv_urb =
+ usbd_alloc_urb (device_instance,
+ &endpoint_instance[i]);
+ }
+}
+
+static void usbtty_init_endpoints (void)
+{
+ int i;
+
+ bus_instance->max_endpoints = NUM_ENDPOINTS + 1;
+ for (i = 1; i <= NUM_ENDPOINTS; i++) {
+ udc_setup_ep (device_instance, i, &endpoint_instance[i]);
+ }
+}
+
+/* usbtty_init_terminal_type
+ *
+ * Do some late binding for our device type.
+ */
+static void usbtty_init_terminal_type(short type)
+{
+ switch(type){
+ /* CDC ACM */
+ case 0:
+ /* Assign endpoint descriptors */
+ ep_descriptor_ptrs[0] =
+ &acm_configuration_descriptors[0].notification_endpoint;
+ ep_descriptor_ptrs[1] =
+ &acm_configuration_descriptors[0].data_endpoints[0];
+ ep_descriptor_ptrs[2] =
+ &acm_configuration_descriptors[0].data_endpoints[1];
+
+ /* Enumerate Device Descriptor */
+ device_descriptor.bDeviceClass =
+ COMMUNICATIONS_DEVICE_CLASS;
+ device_descriptor.idProduct =
+ cpu_to_le16(CONFIG_USBD_PRODUCTID_CDCACM);
+
+#if defined(CONFIG_USBD_HS)
+ qualifier_descriptor.bDeviceClass =
+ COMMUNICATIONS_DEVICE_CLASS;
+#endif
+ /* Assign endpoint indices */
+ tx_endpoint = ACM_TX_ENDPOINT;
+ rx_endpoint = ACM_RX_ENDPOINT;
+
+ /* Configuration Descriptor */
+ configuration_descriptor =
+ (struct usb_configuration_descriptor*)
+ &acm_configuration_descriptors;
+
+ /* Interface count */
+ interface_count = NUM_ACM_INTERFACES;
+ break;
+
+ /* BULK IN/OUT & Default */
+ case 1:
+ default:
+ /* Assign endpoint descriptors */
+ ep_descriptor_ptrs[0] =
+ &gserial_configuration_descriptors[0].data_endpoints[0];
+ ep_descriptor_ptrs[1] =
+ &gserial_configuration_descriptors[0].data_endpoints[1];
+ ep_descriptor_ptrs[2] =
+ &gserial_configuration_descriptors[0].data_endpoints[2];
+
+ /* Enumerate Device Descriptor */
+ device_descriptor.bDeviceClass = 0xFF;
+ device_descriptor.idProduct =
+ cpu_to_le16(CONFIG_USBD_PRODUCTID_GSERIAL);
+#if defined(CONFIG_USBD_HS)
+ qualifier_descriptor.bDeviceClass = 0xFF;
+#endif
+ /* Assign endpoint indices */
+ tx_endpoint = GSERIAL_TX_ENDPOINT;
+ rx_endpoint = GSERIAL_RX_ENDPOINT;
+
+ /* Configuration Descriptor */
+ configuration_descriptor =
+ (struct usb_configuration_descriptor*)
+ &gserial_configuration_descriptors;
+
+ /* Interface count */
+ interface_count = NUM_GSERIAL_INTERFACES;
+ break;
+ }
+}
+
+/******************************************************************************/
+
+static struct urb *next_urb (struct usb_device_instance *device,
+ struct usb_endpoint_instance *endpoint)
+{
+ struct urb *current_urb = NULL;
+ int space;
+
+ /* If there's a queue, then we should add to the last urb */
+ if (!endpoint->tx_queue) {
+ current_urb = endpoint->tx_urb;
+ } else {
+ /* Last urb from tx chain */
+ current_urb =
+ p2surround (struct urb, link, endpoint->tx.prev);
+ }
+
+ /* Make sure this one has enough room */
+ space = current_urb->buffer_length - current_urb->actual_length;
+ if (space > 0) {
+ return current_urb;
+ } else { /* No space here */
+ /* First look at done list */
+ current_urb = first_urb_detached (&endpoint->done);
+ if (!current_urb) {
+ current_urb = usbd_alloc_urb (device, endpoint);
+ }
+
+ urb_append (&endpoint->tx, current_urb);
+ endpoint->tx_queue++;
+ }
+ return current_urb;
+}
+
+static int write_buffer (circbuf_t * buf)
+{
+ if (!usbtty_configured ()) {
+ return 0;
+ }
+
+ struct usb_endpoint_instance *endpoint =
+ &endpoint_instance[tx_endpoint];
+ struct urb *current_urb = NULL;
+
+ /* TX data still exists - send it now
+ */
+ if(endpoint->sent < endpoint->tx_urb->actual_length){
+ if(udc_endpoint_write (endpoint)){
+ /* Write pre-empted by RX */
+ return -1;
+ }
+ }
+
+ if (buf->size) {
+ char *dest;
+
+ int space_avail;
+ int popnum, popped;
+ int total = 0;
+
+ /* Break buffer into urb sized pieces,
+ * and link each to the endpoint
+ */
+ while (buf->size > 0) {
+
+ current_urb = next_urb (device_instance, endpoint);
+
+ dest = (char*)current_urb->buffer +
+ current_urb->actual_length;
+
+ space_avail =
+ current_urb->buffer_length -
+ current_urb->actual_length;
+ popnum = min(space_avail, (int)buf->size);
+ if (popnum == 0)
+ break;
+
+ popped = buf_pop (buf, dest, popnum);
+ if (popped == 0)
+ break;
+ current_urb->actual_length += popped;
+ total += popped;
+
+ /* If endpoint->last == 0, then transfers have
+ * not started on this endpoint
+ */
+ if (endpoint->last == 0) {
+ if(udc_endpoint_write (endpoint)){
+ /* Write pre-empted by RX */
+ return -1;
+ }
+ }
+
+ }/* end while */
+ return total;
+ }
+
+ return 0;
+}
+
+static int fill_buffer (circbuf_t * buf)
+{
+ struct usb_endpoint_instance *endpoint =
+ &endpoint_instance[rx_endpoint];
+
+ if (endpoint->rcv_urb && endpoint->rcv_urb->actual_length) {
+ unsigned int nb = 0;
+ char *src = (char *) endpoint->rcv_urb->buffer;
+ unsigned int rx_avail = buf->totalsize - buf->size;
+
+ if(rx_avail >= endpoint->rcv_urb->actual_length){
+
+ nb = endpoint->rcv_urb->actual_length;
+ buf_push (buf, src, nb);
+ endpoint->rcv_urb->actual_length = 0;
+
+ }
+ return nb;
+ }
+ return 0;
+}
+
+static int usbtty_configured (void)
+{
+ return usbtty_configured_flag;
+}
+
+/******************************************************************************/
+
+static void usbtty_event_handler (struct usb_device_instance *device,
+ usb_device_event_t event, int data)
+{
+#if defined(CONFIG_USBD_HS)
+ int i;
+#endif
+ switch (event) {
+ case DEVICE_RESET:
+ case DEVICE_BUS_INACTIVE:
+ usbtty_configured_flag = 0;
+ break;
+ case DEVICE_CONFIGURED:
+ usbtty_configured_flag = 1;
+ break;
+
+ case DEVICE_ADDRESS_ASSIGNED:
+#if defined(CONFIG_USBD_HS)
+ /*
+ * is_usbd_high_speed routine needs to be defined by
+ * specific gadget driver
+ * It returns true if device enumerates at High speed
+ * Retuns false otherwise
+ */
+ for (i = 0; i < NUM_ENDPOINTS; i++) {
+ if (((ep_descriptor_ptrs[i]->bmAttributes &
+ USB_ENDPOINT_XFERTYPE_MASK) ==
+ USB_ENDPOINT_XFER_BULK)
+ && is_usbd_high_speed()) {
+
+ ep_descriptor_ptrs[i]->wMaxPacketSize =
+ CONFIG_USBD_SERIAL_BULK_HS_PKTSIZE;
+ }
+
+ endpoint_instance[i + 1].tx_packetSize =
+ ep_descriptor_ptrs[i]->wMaxPacketSize;
+ endpoint_instance[i + 1].rcv_packetSize =
+ ep_descriptor_ptrs[i]->wMaxPacketSize;
+ }
+#endif
+ usbtty_init_endpoints ();
+
+ default:
+ break;
+ }
+}
+
+/******************************************************************************/
+
+int usbtty_cdc_setup(struct usb_device_request *request, struct urb *urb)
+{
+ switch (request->bRequest){
+
+ case ACM_SET_CONTROL_LINE_STATE: /* Implies DTE ready */
+ break;
+ case ACM_SEND_ENCAPSULATED_COMMAND : /* Required */
+ break;
+ case ACM_SET_LINE_ENCODING : /* DTE stop/parity bits
+ * per character */
+ break;
+ case ACM_GET_ENCAPSULATED_RESPONSE : /* request response */
+ break;
+ case ACM_GET_LINE_ENCODING : /* request DTE rate,
+ * stop/parity bits */
+ memcpy (urb->buffer , &rs232_desc, sizeof(rs232_desc));
+ urb->actual_length = sizeof(rs232_desc);
+
+ break;
+ default:
+ return 1;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+
+/*
+ * Since interrupt handling has not yet been implemented, we use this function
+ * to handle polling. This is called by the tstc,getc,putc,puts routines to
+ * update the USB state.
+ */
+void usbtty_poll (void)
+{
+ /* New interrupts? */
+ udc_irq();
+
+ /* Write any output data to host buffer
+ * (do this before checking interrupts to avoid missing one)
+ */
+ if (usbtty_configured ()) {
+ write_buffer (&usbtty_output);
+ }
+
+ /* New interrupts? */
+ udc_irq();
+
+ /* Check for new data from host..
+ * (do this after checking interrupts to get latest data)
+ */
+ if (usbtty_configured ()) {
+ fill_buffer (&usbtty_input);
+ }
+
+ /* New interrupts? */
+ udc_irq();
+
+}
diff --git a/roms/u-boot/drivers/serial/usbtty.h b/roms/u-boot/drivers/serial/usbtty.h
new file mode 100644
index 000000000..05b3c01e5
--- /dev/null
+++ b/roms/u-boot/drivers/serial/usbtty.h
@@ -0,0 +1,76 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2003
+ * Gerry Hamel, geh@ti.com, Texas Instruments
+ *
+ * (C) Copyright 2006
+ * Bryan O'Donoghue, bodonoghue@codehermit.ie, CodeHermit
+ */
+
+#ifndef __USB_TTY_H__
+#define __USB_TTY_H__
+
+#include <usbdevice.h>
+#if defined(CONFIG_PPC)
+#include <usb/mpc8xx_udc.h>
+#elif defined(CONFIG_CPU_PXA27X)
+#include <usb/pxa27x_udc.h>
+#elif defined(CONFIG_DW_UDC)
+#include <usb/designware_udc.h>
+#elif defined(CONFIG_CI_UDC)
+#include <usb/ci_udc.h>
+#endif
+
+#include <usb/udc.h>
+#include <version.h>
+
+/* If no VendorID/ProductID is defined in config.h, pretend to be Linux
+ * DO NOT Reuse this Vendor/Product setup with protocol incompatible devices */
+
+#ifndef CONFIG_USBD_VENDORID
+#define CONFIG_USBD_VENDORID 0x0525 /* Linux/NetChip */
+#endif
+#ifndef CONFIG_USBD_PRODUCTID_GSERIAL
+#define CONFIG_USBD_PRODUCTID_GSERIAL 0xa4a6 /* gserial */
+#endif
+#ifndef CONFIG_USBD_PRODUCTID_CDCACM
+#define CONFIG_USBD_PRODUCTID_CDCACM 0xa4a7 /* CDC ACM */
+#endif
+#ifndef CONFIG_USBD_MANUFACTURER
+#define CONFIG_USBD_MANUFACTURER "Das U-Boot"
+#endif
+#ifndef CONFIG_USBD_PRODUCT_NAME
+#define CONFIG_USBD_PRODUCT_NAME U_BOOT_VERSION
+#endif
+
+#ifndef CONFIG_USBD_CONFIGURATION_STR
+#define CONFIG_USBD_CONFIGURATION_STR "TTY via USB"
+#endif
+
+#define CONFIG_USBD_SERIAL_OUT_ENDPOINT UDC_OUT_ENDPOINT
+#define CONFIG_USBD_SERIAL_OUT_PKTSIZE UDC_OUT_PACKET_SIZE
+#define CONFIG_USBD_SERIAL_IN_ENDPOINT UDC_IN_ENDPOINT
+#define CONFIG_USBD_SERIAL_IN_PKTSIZE UDC_IN_PACKET_SIZE
+#define CONFIG_USBD_SERIAL_INT_ENDPOINT UDC_INT_ENDPOINT
+#define CONFIG_USBD_SERIAL_INT_PKTSIZE UDC_INT_PACKET_SIZE
+#define CONFIG_USBD_SERIAL_BULK_PKTSIZE UDC_BULK_PACKET_SIZE
+
+#if defined(CONFIG_USBD_HS)
+#define CONFIG_USBD_SERIAL_BULK_HS_PKTSIZE UDC_BULK_HS_PACKET_SIZE
+#endif
+
+#define USBTTY_DEVICE_CLASS COMMUNICATIONS_DEVICE_CLASS
+
+#define USBTTY_BCD_DEVICE 0x00
+#define USBTTY_MAXPOWER 0x00
+
+#define STR_LANG 0x00
+#define STR_MANUFACTURER 0x01
+#define STR_PRODUCT 0x02
+#define STR_SERIAL 0x03
+#define STR_CONFIG 0x04
+#define STR_DATA_INTERFACE 0x05
+#define STR_CTRL_INTERFACE 0x06
+#define STR_COUNT 0x07
+
+#endif