avionic design with actual uboot and tooling
submodule of avionic design uboot bootloader and with included tools to get you started , read readme.md and readme-tk1-loader.md
This commit is contained in:
364
u-boot/drivers/serial/Kconfig
Normal file
364
u-boot/drivers/serial/Kconfig
Normal file
@@ -0,0 +1,364 @@
|
||||
#
|
||||
# Serial device configuration
|
||||
#
|
||||
|
||||
menu "Serial drivers"
|
||||
|
||||
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 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
|
||||
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 DM_SERIAL
|
||||
bool "Enable Driver Model for serial drivers"
|
||||
depends on DM
|
||||
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 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"
|
||||
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"
|
||||
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_UART_NS16550
|
||||
bool "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"
|
||||
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"
|
||||
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"
|
||||
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_UART_ZYNQ
|
||||
bool "Xilinx Zynq"
|
||||
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"
|
||||
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"
|
||||
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_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.
|
||||
|
||||
endchoice
|
||||
|
||||
config DEBUG_UART_BASE
|
||||
hex "Base address of UART"
|
||||
depends on DEBUG_UART
|
||||
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
|
||||
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"
|
||||
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 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 FSL_LPUART
|
||||
bool "Freescale LPUART support"
|
||||
help
|
||||
Select this to enable a Low Power UART for Freescale VF610 and
|
||||
QorIQ Layerscape devices.
|
||||
|
||||
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 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 UNIPHIER_SERIAL
|
||||
bool "Support for UniPhier on-chip UART"
|
||||
depends on ARCH_UNIPHIER
|
||||
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 && (MICROBLAZE || ARCH_ZYNQ || ARCH_ZYNQMP || 4xx)
|
||||
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).
|
||||
endmenu
|
||||
49
u-boot/drivers/serial/Makefile
Normal file
49
u-boot/drivers/serial/Makefile
Normal file
@@ -0,0 +1,49 @@
|
||||
#
|
||||
# (C) Copyright 2006-2009
|
||||
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
|
||||
ifdef CONFIG_DM_SERIAL
|
||||
obj-y += serial-uclass.o
|
||||
obj-$(CONFIG_PL01X_SERIAL) += serial_pl01x.o
|
||||
else
|
||||
obj-y += serial.o
|
||||
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_EFI_APP) += serial_efi.o
|
||||
obj-$(CONFIG_LPC32XX_HSUART) += lpc32xx_hsuart.o
|
||||
obj-$(CONFIG_MCFUART) += mcfuart.o
|
||||
obj-$(CONFIG_SYS_NS16550) += ns16550.o
|
||||
obj-$(CONFIG_S5P) += 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_S3C24X0_SERIAL) += serial_s3c24x0.o
|
||||
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_BFIN_SERIAL) += serial_bfin.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_PIC32_SERIAL) += serial_pic32.o
|
||||
obj-$(CONFIG_STM32X7_SERIAL) += serial_stm32x7.o
|
||||
obj-$(CONFIG_BCM283X_MU_SERIAL) += serial_bcm283x_mu.o
|
||||
obj-$(CONFIG_MSM_SERIAL) += serial_msm.o
|
||||
|
||||
ifndef CONFIG_SPL_BUILD
|
||||
obj-$(CONFIG_USB_TTY) += usbtty.o
|
||||
endif
|
||||
154
u-boot/drivers/serial/altera_jtag_uart.c
Normal file
154
u-boot/drivers/serial/altera_jtag_uart.c
Normal file
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* (C) Copyright 2004, Psyent Corporation <www.psyent.com>
|
||||
* Scott McNutt <smcnutt@psyent.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <serial.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
/* 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_platdata {
|
||||
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_platdata *plat = dev->platdata;
|
||||
struct altera_jtaguart_regs *const regs = plat->regs;
|
||||
u32 st = readl(®s->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, ®s->data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int altera_jtaguart_pending(struct udevice *dev, bool input)
|
||||
{
|
||||
struct altera_jtaguart_platdata *plat = dev->platdata;
|
||||
struct altera_jtaguart_regs *const regs = plat->regs;
|
||||
u32 st = readl(®s->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_platdata *plat = dev->platdata;
|
||||
struct altera_jtaguart_regs *const regs = plat->regs;
|
||||
u32 val;
|
||||
|
||||
val = readl(®s->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_platdata *plat = dev->platdata;
|
||||
struct altera_jtaguart_regs *const regs = plat->regs;
|
||||
|
||||
writel(ALTERA_JTAG_AC, ®s->control); /* clear AC flag */
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int altera_jtaguart_ofdata_to_platdata(struct udevice *dev)
|
||||
{
|
||||
struct altera_jtaguart_platdata *plat = dev_get_platdata(dev);
|
||||
|
||||
plat->regs = map_physmem(dev_get_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,
|
||||
.ofdata_to_platdata = altera_jtaguart_ofdata_to_platdata,
|
||||
.platdata_auto_alloc_size = sizeof(struct altera_jtaguart_platdata),
|
||||
.probe = altera_jtaguart_probe,
|
||||
.ops = &altera_jtaguart_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
|
||||
#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(®s->control);
|
||||
|
||||
if (ALTERA_JTAG_WSPACE(st))
|
||||
break;
|
||||
}
|
||||
|
||||
writel(ch, ®s->data);
|
||||
}
|
||||
|
||||
DEBUG_UART_FUNCS
|
||||
|
||||
#endif
|
||||
153
u-boot/drivers/serial/altera_uart.c
Normal file
153
u-boot/drivers/serial/altera_uart.c
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* (C) Copyright 2004, Psyent Corporation <www.psyent.com>
|
||||
* Scott McNutt <smcnutt@psyent.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <serial.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
/* 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_platdata {
|
||||
struct altera_uart_regs *regs;
|
||||
unsigned int uartclk;
|
||||
};
|
||||
|
||||
static int altera_uart_setbrg(struct udevice *dev, int baudrate)
|
||||
{
|
||||
struct altera_uart_platdata *plat = dev->platdata;
|
||||
struct altera_uart_regs *const regs = plat->regs;
|
||||
u32 div;
|
||||
|
||||
div = (plat->uartclk / baudrate) - 1;
|
||||
writel(div, ®s->divisor);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int altera_uart_putc(struct udevice *dev, const char ch)
|
||||
{
|
||||
struct altera_uart_platdata *plat = dev->platdata;
|
||||
struct altera_uart_regs *const regs = plat->regs;
|
||||
|
||||
if (!(readl(®s->status) & ALTERA_UART_TRDY))
|
||||
return -EAGAIN;
|
||||
|
||||
writel(ch, ®s->txdata);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int altera_uart_pending(struct udevice *dev, bool input)
|
||||
{
|
||||
struct altera_uart_platdata *plat = dev->platdata;
|
||||
struct altera_uart_regs *const regs = plat->regs;
|
||||
u32 st = readl(®s->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_platdata *plat = dev->platdata;
|
||||
struct altera_uart_regs *const regs = plat->regs;
|
||||
|
||||
if (!(readl(®s->status) & ALTERA_UART_RRDY))
|
||||
return -EAGAIN;
|
||||
|
||||
return readl(®s->rxdata) & 0xff;
|
||||
}
|
||||
|
||||
static int altera_uart_probe(struct udevice *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int altera_uart_ofdata_to_platdata(struct udevice *dev)
|
||||
{
|
||||
struct altera_uart_platdata *plat = dev_get_platdata(dev);
|
||||
|
||||
plat->regs = map_physmem(dev_get_addr(dev),
|
||||
sizeof(struct altera_uart_regs),
|
||||
MAP_NOCACHE);
|
||||
plat->uartclk = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
|
||||
"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,
|
||||
.ofdata_to_platdata = altera_uart_ofdata_to_platdata,
|
||||
.platdata_auto_alloc_size = sizeof(struct altera_uart_platdata),
|
||||
.probe = altera_uart_probe,
|
||||
.ops = &altera_uart_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
|
||||
#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, ®s->divisor);
|
||||
}
|
||||
|
||||
static inline void _debug_uart_putc(int ch)
|
||||
{
|
||||
struct altera_uart_regs *regs = (void *)CONFIG_DEBUG_UART_BASE;
|
||||
|
||||
while (1) {
|
||||
u32 st = readl(®s->status);
|
||||
|
||||
if (st & ALTERA_UART_TRDY)
|
||||
break;
|
||||
}
|
||||
|
||||
writel(ch, ®s->txdata);
|
||||
}
|
||||
|
||||
DEBUG_UART_FUNCS
|
||||
|
||||
#endif
|
||||
176
u-boot/drivers/serial/arm_dcc.c
Normal file
176
u-boot/drivers/serial/arm_dcc.c
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2007 ARM Limited.
|
||||
* Copyright (C) 2008 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
|
||||
* Copyright (C) 2015 - 2016 Xilinx, Inc, Michal Simek
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* 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_V7)
|
||||
/*
|
||||
* 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,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
|
||||
#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
|
||||
228
u-boot/drivers/serial/atmel_usart.c
Normal file
228
u-boot/drivers/serial/atmel_usart.c
Normal file
@@ -0,0 +1,228 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2006 Atmel Corporation
|
||||
*
|
||||
* Modified to support C structur SoC access by
|
||||
* Andreas Bießmann <biessmann@corscience.de>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <watchdog.h>
|
||||
#include <serial.h>
|
||||
#include <linux/compiler.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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_DM_SERIAL
|
||||
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
|
||||
|
||||
struct atmel_serial_priv {
|
||||
atmel_usart3_t *usart;
|
||||
};
|
||||
|
||||
int atmel_serial_setbrg(struct udevice *dev, int baudrate)
|
||||
{
|
||||
struct atmel_serial_priv *priv = dev_get_priv(dev);
|
||||
|
||||
atmel_serial_setbrg_internal(priv->usart, 0 /* ignored */, baudrate);
|
||||
atmel_serial_activate(priv->usart);
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
static int atmel_serial_probe(struct udevice *dev)
|
||||
{
|
||||
struct atmel_serial_platdata *plat = dev->platdata;
|
||||
struct atmel_serial_priv *priv = dev_get_priv(dev);
|
||||
#if CONFIG_IS_ENABLED(OF_CONTROL)
|
||||
fdt_addr_t addr_base;
|
||||
|
||||
addr_base = dev_get_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;
|
||||
atmel_serial_init_internal(priv->usart);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if CONFIG_IS_ENABLED(OF_CONTROL)
|
||||
static const struct udevice_id atmel_serial_ids[] = {
|
||||
{ .compatible = "atmel,at91sam9260-usart" },
|
||||
{ }
|
||||
};
|
||||
#endif
|
||||
|
||||
U_BOOT_DRIVER(serial_atmel) = {
|
||||
.name = "serial_atmel",
|
||||
.id = UCLASS_SERIAL,
|
||||
#if CONFIG_IS_ENABLED(OF_CONTROL)
|
||||
.of_match = atmel_serial_ids,
|
||||
.platdata_auto_alloc_size = sizeof(struct atmel_serial_platdata),
|
||||
#endif
|
||||
.probe = atmel_serial_probe,
|
||||
.ops = &atmel_serial_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
.priv_auto_alloc_size = sizeof(struct atmel_serial_priv),
|
||||
};
|
||||
#endif
|
||||
294
u-boot/drivers/serial/atmel_usart.h
Normal file
294
u-boot/drivers/serial/atmel_usart.h
Normal file
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
* 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>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
#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__ */
|
||||
114
u-boot/drivers/serial/lpc32xx_hsuart.c
Normal file
114
u-boot/drivers/serial/lpc32xx_hsuart.c
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2015 Vladimir Zapolskiy <vz@mleia.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <serial.h>
|
||||
#include <dm/platform_data/lpc32xx_hsuart.h>
|
||||
|
||||
#include <asm/arch/uart.h>
|
||||
#include <linux/compiler.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
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_platdata *platdata = dev_get_platdata(dev);
|
||||
struct lpc32xx_hsuart_priv *priv = dev_get_priv(dev);
|
||||
|
||||
priv->hsuart = (struct hsuart_regs *)platdata->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_alloc_size = sizeof(struct lpc32xx_hsuart_priv),
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
230
u-boot/drivers/serial/mcfuart.c
Normal file
230
u-boot/drivers/serial/mcfuart.c
Normal file
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* (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>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
/*
|
||||
* Minimal serial functions needed to use one of the uart ports
|
||||
* as serial console interface.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.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);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_DM_SERIAL
|
||||
|
||||
static int mcf_serial_init(void)
|
||||
{
|
||||
uart_t *uart_base;
|
||||
int port_idx;
|
||||
|
||||
uart_base = (uart_t *)CONFIG_SYS_UART_BASE;
|
||||
port_idx = CONFIG_SYS_UART_PORT;
|
||||
|
||||
return mcf_serial_init_common(uart_base, port_idx, gd->baudrate);
|
||||
}
|
||||
|
||||
static void mcf_serial_putc(const char c)
|
||||
{
|
||||
uart_t *uart = (uart_t *)CONFIG_SYS_UART_BASE;
|
||||
|
||||
if (c == '\n')
|
||||
serial_putc('\r');
|
||||
|
||||
/* Wait for last character to go. */
|
||||
while (!(readb(&uart->usr) & UART_USR_TXRDY))
|
||||
;
|
||||
|
||||
writeb(c, &uart->utb);
|
||||
}
|
||||
|
||||
static int mcf_serial_getc(void)
|
||||
{
|
||||
uart_t *uart = (uart_t *)CONFIG_SYS_UART_BASE;
|
||||
|
||||
/* Wait for a character to arrive. */
|
||||
while (!(readb(&uart->usr) & UART_USR_RXRDY))
|
||||
;
|
||||
|
||||
return readb(&uart->urb);
|
||||
}
|
||||
|
||||
static void mcf_serial_setbrg(void)
|
||||
{
|
||||
uart_t *uart = (uart_t *)CONFIG_SYS_UART_BASE;
|
||||
|
||||
mcf_serial_setbrg_common(uart, gd->baudrate);
|
||||
}
|
||||
|
||||
static int mcf_serial_tstc(void)
|
||||
{
|
||||
uart_t *uart = (uart_t *)CONFIG_SYS_UART_BASE;
|
||||
|
||||
return readb(&uart->usr) & UART_USR_RXRDY;
|
||||
}
|
||||
|
||||
static struct serial_device mcf_serial_drv = {
|
||||
.name = "mcf_serial",
|
||||
.start = mcf_serial_init,
|
||||
.stop = NULL,
|
||||
.setbrg = mcf_serial_setbrg,
|
||||
.putc = mcf_serial_putc,
|
||||
.puts = default_serial_puts,
|
||||
.getc = mcf_serial_getc,
|
||||
.tstc = mcf_serial_tstc,
|
||||
};
|
||||
|
||||
void mcf_serial_initialize(void)
|
||||
{
|
||||
serial_register(&mcf_serial_drv);
|
||||
}
|
||||
|
||||
__weak struct serial_device *default_serial_console(void)
|
||||
{
|
||||
return &mcf_serial_drv;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DM_SERIAL
|
||||
|
||||
static int coldfire_serial_probe(struct udevice *dev)
|
||||
{
|
||||
struct coldfire_serial_platdata *plat = dev->platdata;
|
||||
|
||||
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_platdata *plat = dev->platdata;
|
||||
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_platdata *plat = dev->platdata;
|
||||
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_platdata *plat = dev->platdata;
|
||||
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_platdata *plat = dev->platdata;
|
||||
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 const struct dm_serial_ops coldfire_serial_ops = {
|
||||
.putc = coldfire_serial_putc,
|
||||
.pending = coldfire_serial_pending,
|
||||
.getc = coldfire_serial_getc,
|
||||
.setbrg = coldfire_serial_setbrg,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(serial_coldfire) = {
|
||||
.name = "serial_coldfire",
|
||||
.id = UCLASS_SERIAL,
|
||||
.probe = coldfire_serial_probe,
|
||||
.ops = &coldfire_serial_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
#endif
|
||||
455
u-boot/drivers/serial/ns16550.c
Normal file
455
u-boot/drivers/serial/ns16550.c
Normal file
@@ -0,0 +1,455 @@
|
||||
/*
|
||||
* COM1 NS16550 support
|
||||
* originally from linux source (arch/powerpc/boot/ns16550.c)
|
||||
* modified to use CONFIG_SYS_ISA_MEM and new defines
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <fdtdec.h>
|
||||
#include <ns16550.h>
|
||||
#include <serial.h>
|
||||
#include <watchdog.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 */
|
||||
#define UART_FCRVAL (UART_FCR_FIFO_EN | \
|
||||
UART_FCR_RXSR | \
|
||||
UART_FCR_TXSR) /* Clear & enable FIFOs */
|
||||
|
||||
#ifndef CONFIG_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_BIG_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_BIG_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
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DM_SERIAL
|
||||
|
||||
#ifndef CONFIG_SYS_NS16550_CLK
|
||||
#define CONFIG_SYS_NS16550_CLK 0
|
||||
#endif
|
||||
|
||||
static void ns16550_writeb(NS16550_t port, int offset, int value)
|
||||
{
|
||||
struct ns16550_platdata *plat = port->plat;
|
||||
unsigned char *addr;
|
||||
|
||||
offset *= 1 << plat->reg_shift;
|
||||
addr = (unsigned char *)plat->base + offset;
|
||||
|
||||
/*
|
||||
* As far as we know it doesn't make sense to support selection of
|
||||
* these options at run-time, so use the existing CONFIG options.
|
||||
*/
|
||||
serial_out_shift(addr + plat->reg_offset, plat->reg_shift, value);
|
||||
}
|
||||
|
||||
static int ns16550_readb(NS16550_t port, int offset)
|
||||
{
|
||||
struct ns16550_platdata *plat = port->plat;
|
||||
unsigned char *addr;
|
||||
|
||||
offset *= 1 << plat->reg_shift;
|
||||
addr = (unsigned char *)plat->base + offset;
|
||||
|
||||
return serial_in_shift(addr + plat->reg_offset, plat->reg_shift);
|
||||
}
|
||||
|
||||
/* 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)
|
||||
#endif
|
||||
|
||||
int ns16550_calc_divisor(NS16550_t 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(NS16550_t com_port, int baud_divisor)
|
||||
{
|
||||
serial_out(UART_LCR_BKSE | UART_LCRVAL, &com_port->lcr);
|
||||
serial_out(baud_divisor & 0xff, &com_port->dll);
|
||||
serial_out((baud_divisor >> 8) & 0xff, &com_port->dlm);
|
||||
serial_out(UART_LCRVAL, &com_port->lcr);
|
||||
}
|
||||
|
||||
void NS16550_init(NS16550_t 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);
|
||||
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_OMAP) || defined(CONFIG_AM33XX) || \
|
||||
defined(CONFIG_TI81XX) || defined(CONFIG_AM43XX)
|
||||
serial_out(0x7, &com_port->mdr1); /* mode select reset TL16C750*/
|
||||
#endif
|
||||
serial_out(UART_MCRVAL, &com_port->mcr);
|
||||
serial_out(UART_FCRVAL, &com_port->fcr);
|
||||
if (baud_divisor != -1)
|
||||
NS16550_setbrg(com_port, baud_divisor);
|
||||
#if defined(CONFIG_OMAP) || \
|
||||
defined(CONFIG_AM33XX) || defined(CONFIG_SOC_DA8XX) || \
|
||||
defined(CONFIG_TI81XX) || defined(CONFIG_AM43XX)
|
||||
|
||||
/* /16 is proper to hit 115200 with 48MHz */
|
||||
serial_out(0, &com_port->mdr1);
|
||||
#endif /* CONFIG_OMAP */
|
||||
#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(NS16550_t 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(UART_FCRVAL, &com_port->fcr);
|
||||
NS16550_setbrg(com_port, baud_divisor);
|
||||
}
|
||||
#endif /* CONFIG_NS16550_MIN_FUNCTIONS */
|
||||
|
||||
void NS16550_putc(NS16550_t 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(NS16550_t 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(NS16550_t 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>
|
||||
|
||||
#define serial_dout(reg, value) \
|
||||
serial_out_shift((char *)com_port + \
|
||||
((char *)reg - (char *)com_port) * \
|
||||
(1 << CONFIG_DEBUG_UART_SHIFT), \
|
||||
CONFIG_DEBUG_UART_SHIFT, value)
|
||||
#define serial_din(reg) \
|
||||
serial_in_shift((char *)com_port + \
|
||||
((char *)reg - (char *)com_port) * \
|
||||
(1 << CONFIG_DEBUG_UART_SHIFT), \
|
||||
CONFIG_DEBUG_UART_SHIFT)
|
||||
|
||||
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_FCRVAL);
|
||||
|
||||
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 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
|
||||
|
||||
#ifdef CONFIG_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_platdata *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;
|
||||
}
|
||||
|
||||
int ns16550_serial_probe(struct udevice *dev)
|
||||
{
|
||||
struct NS16550 *const com_port = dev_get_priv(dev);
|
||||
|
||||
com_port->plat = dev_get_platdata(dev);
|
||||
NS16550_init(com_port, -1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if CONFIG_IS_ENABLED(OF_CONTROL)
|
||||
int ns16550_serial_ofdata_to_platdata(struct udevice *dev)
|
||||
{
|
||||
struct ns16550_platdata *plat = dev->platdata;
|
||||
fdt_addr_t addr;
|
||||
|
||||
/* try Processor Local Bus device first */
|
||||
addr = dev_get_addr(dev);
|
||||
#if defined(CONFIG_PCI) && defined(CONFIG_DM_PCI)
|
||||
if (addr == FDT_ADDR_T_NONE) {
|
||||
/* then try pci device */
|
||||
struct fdt_pci_addr pci_addr;
|
||||
u32 bar;
|
||||
int ret;
|
||||
|
||||
/* we prefer to use a memory-mapped register */
|
||||
ret = fdtdec_get_pci_addr(gd->fdt_blob, dev->of_offset,
|
||||
FDT_PCI_SPACE_MEM32, "reg",
|
||||
&pci_addr);
|
||||
if (ret) {
|
||||
/* try if there is any i/o-mapped register */
|
||||
ret = fdtdec_get_pci_addr(gd->fdt_blob,
|
||||
dev->of_offset,
|
||||
FDT_PCI_SPACE_IO,
|
||||
"reg", &pci_addr);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = fdtdec_get_pci_bar32(dev, &pci_addr, &bar);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
addr = bar;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (addr == FDT_ADDR_T_NONE)
|
||||
return -EINVAL;
|
||||
|
||||
#ifdef CONFIG_SYS_NS16550_PORT_MAPPED
|
||||
plat->base = addr;
|
||||
#else
|
||||
plat->base = (unsigned long)map_physmem(addr, 0, MAP_NOCACHE);
|
||||
#endif
|
||||
|
||||
plat->reg_offset = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
|
||||
"reg-offset", 0);
|
||||
plat->reg_shift = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
|
||||
"reg-shift", 0);
|
||||
plat->clock = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
|
||||
"clock-frequency",
|
||||
CONFIG_SYS_NS16550_CLK);
|
||||
if (!plat->clock) {
|
||||
debug("ns16550 clock not defined\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
#if CONFIG_IS_ENABLED(OF_CONTROL)
|
||||
/*
|
||||
* 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" },
|
||||
{ .compatible = "ns16550a" },
|
||||
{ .compatible = "nvidia,tegra20-uart" },
|
||||
{ .compatible = "snps,dw-apb-uart" },
|
||||
{ .compatible = "ti,omap2-uart" },
|
||||
{ .compatible = "ti,omap3-uart" },
|
||||
{ .compatible = "ti,omap4-uart" },
|
||||
{ .compatible = "ti,am3352-uart" },
|
||||
{ .compatible = "ti,am4372-uart" },
|
||||
{ .compatible = "ti,dra742-uart" },
|
||||
{}
|
||||
};
|
||||
#endif
|
||||
|
||||
#if CONFIG_IS_ENABLED(SERIAL_PRESENT)
|
||||
U_BOOT_DRIVER(ns16550_serial) = {
|
||||
.name = "ns16550_serial",
|
||||
.id = UCLASS_SERIAL,
|
||||
#if CONFIG_IS_ENABLED(OF_CONTROL)
|
||||
.of_match = ns16550_serial_ids,
|
||||
.ofdata_to_platdata = ns16550_serial_ofdata_to_platdata,
|
||||
.platdata_auto_alloc_size = sizeof(struct ns16550_platdata),
|
||||
#endif
|
||||
.priv_auto_alloc_size = sizeof(struct NS16550),
|
||||
.probe = ns16550_serial_probe,
|
||||
.ops = &ns16550_serial_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
#endif
|
||||
#endif /* CONFIG_DM_SERIAL */
|
||||
198
u-boot/drivers/serial/sandbox.c
Normal file
198
u-boot/drivers/serial/sandbox.c
Normal file
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The Chromium OS Authors.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 <dm.h>
|
||||
#include <fdtdec.h>
|
||||
#include <lcd.h>
|
||||
#include <os.h>
|
||||
#include <serial.h>
|
||||
#include <video.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <asm/state.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
/*
|
||||
*
|
||||
* serial_buf: A buffer that holds keyboard characters for the
|
||||
* Sandbox U-Boot.
|
||||
*
|
||||
* invariants:
|
||||
* serial_buf_write == serial_buf_read -> empty buffer
|
||||
* (serial_buf_write + 1) % 16 == serial_buf_read -> full buffer
|
||||
*/
|
||||
static char serial_buf[16];
|
||||
static unsigned int serial_buf_write;
|
||||
static unsigned int serial_buf_read;
|
||||
|
||||
struct sandbox_serial_platdata {
|
||||
int colour; /* Text colour to use for output, -1 for none */
|
||||
};
|
||||
|
||||
struct sandbox_serial_priv {
|
||||
bool start_of_line;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sandbox_serial_remove(struct udevice *dev)
|
||||
{
|
||||
struct sandbox_serial_platdata *plat = dev->platdata;
|
||||
|
||||
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_platdata *plat = dev->platdata;
|
||||
|
||||
if (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 unsigned int increment_buffer_index(unsigned int index)
|
||||
{
|
||||
return (index + 1) % ARRAY_SIZE(serial_buf);
|
||||
}
|
||||
|
||||
static int sandbox_serial_pending(struct udevice *dev, bool input)
|
||||
{
|
||||
const unsigned int next_index =
|
||||
increment_buffer_index(serial_buf_write);
|
||||
ssize_t count;
|
||||
|
||||
if (!input)
|
||||
return 0;
|
||||
|
||||
os_usleep(100);
|
||||
video_sync_all();
|
||||
if (next_index == serial_buf_read)
|
||||
return 1; /* buffer full */
|
||||
|
||||
count = os_read_no_block(0, &serial_buf[serial_buf_write], 1);
|
||||
if (count == 1)
|
||||
serial_buf_write = next_index;
|
||||
|
||||
return serial_buf_write != serial_buf_read;
|
||||
}
|
||||
|
||||
static int sandbox_serial_getc(struct udevice *dev)
|
||||
{
|
||||
int result;
|
||||
|
||||
if (!sandbox_serial_pending(dev, true))
|
||||
return -EAGAIN; /* buffer empty */
|
||||
|
||||
result = serial_buf[serial_buf_read];
|
||||
serial_buf_read = increment_buffer_index(serial_buf_read);
|
||||
return result;
|
||||
}
|
||||
|
||||
static const char * const ansi_colour[] = {
|
||||
"black", "red", "green", "yellow", "blue", "megenta", "cyan",
|
||||
"white",
|
||||
};
|
||||
|
||||
static int sandbox_serial_ofdata_to_platdata(struct udevice *dev)
|
||||
{
|
||||
struct sandbox_serial_platdata *plat = dev->platdata;
|
||||
const char *colour;
|
||||
int i;
|
||||
|
||||
plat->colour = -1;
|
||||
colour = fdt_getprop(gd->fdt_blob, dev->of_offset,
|
||||
"sandbox,text-colour", NULL);
|
||||
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,
|
||||
};
|
||||
|
||||
static const struct udevice_id sandbox_serial_ids[] = {
|
||||
{ .compatible = "sandbox,serial" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(serial_sandbox) = {
|
||||
.name = "serial_sandbox",
|
||||
.id = UCLASS_SERIAL,
|
||||
.of_match = sandbox_serial_ids,
|
||||
.ofdata_to_platdata = sandbox_serial_ofdata_to_platdata,
|
||||
.platdata_auto_alloc_size = sizeof(struct sandbox_serial_platdata),
|
||||
.priv_auto_alloc_size = sizeof(struct sandbox_serial_priv),
|
||||
.probe = sandbox_serial_probe,
|
||||
.remove = sandbox_serial_remove,
|
||||
.ops = &sandbox_serial_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
|
||||
static const struct sandbox_serial_platdata platdata_non_fdt = {
|
||||
.colour = -1,
|
||||
};
|
||||
|
||||
U_BOOT_DEVICE(serial_sandbox_non_fdt) = {
|
||||
.name = "serial_sandbox",
|
||||
.platdata = &platdata_non_fdt,
|
||||
};
|
||||
361
u-boot/drivers/serial/serial-uclass.c
Normal file
361
u-boot/drivers/serial/serial-uclass.c
Normal file
@@ -0,0 +1,361 @@
|
||||
/*
|
||||
* Copyright (c) 2014 The Chromium OS Authors.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <environment.h>
|
||||
#include <errno.h>
|
||||
#include <fdtdec.h>
|
||||
#include <os.h>
|
||||
#include <serial.h>
|
||||
#include <stdio_dev.h>
|
||||
#include <watchdog.h>
|
||||
#include <dm/lists.h>
|
||||
#include <dm/device-internal.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
/*
|
||||
* Table with supported baudrates (defined in config_xyz.h)
|
||||
*/
|
||||
static const unsigned long baudrate_table[] = CONFIG_SYS_BAUDRATE_TABLE;
|
||||
|
||||
#ifndef CONFIG_SYS_MALLOC_F_LEN
|
||||
#error "Serial is required before relocation - define CONFIG_SYS_MALLOC_F_LEN to make this work"
|
||||
#endif
|
||||
|
||||
static void serial_find_console_or_panic(void)
|
||||
{
|
||||
const void *blob = gd->fdt_blob;
|
||||
struct udevice *dev;
|
||||
int node;
|
||||
|
||||
if (CONFIG_IS_ENABLED(OF_CONTROL) && blob) {
|
||||
/* Check for a chosen console */
|
||||
node = fdtdec_get_chosen_node(blob, "stdout-path");
|
||||
if (node < 0) {
|
||||
const char *str, *p, *name;
|
||||
|
||||
/*
|
||||
* Deal with things like
|
||||
* stdout-path = "serial0:115200n8";
|
||||
*
|
||||
* We need to look up the alias and then follow it to
|
||||
* the correct node.
|
||||
*/
|
||||
str = fdtdec_get_chosen_prop(blob, "stdout-path");
|
||||
if (str) {
|
||||
p = strchr(str, ':');
|
||||
name = fdt_get_alias_namelen(blob, str,
|
||||
p ? p - str : strlen(str));
|
||||
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,
|
||||
&dev)) {
|
||||
gd->cur_serial_dev = dev;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the console is not marked to be bound before relocation,
|
||||
* bind it anyway.
|
||||
*/
|
||||
if (node > 0 &&
|
||||
!lists_bind_fdt(gd->dm_root, blob, node, &dev)) {
|
||||
if (!device_probe(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 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
|
||||
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;
|
||||
}
|
||||
#undef INDEX
|
||||
}
|
||||
|
||||
#ifdef CONFIG_REQUIRE_SERIAL_CONSOLE
|
||||
panic_str("No serial driver found");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Called prior to relocation */
|
||||
int serial_init(void)
|
||||
{
|
||||
serial_find_console_or_panic();
|
||||
gd->flags |= GD_FLG_SERIAL_READY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Called after relocation */
|
||||
void serial_initialize(void)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void serial_stdio_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DM_STDIO) && CONFIG_IS_ENABLED(SERIAL_PRESENT)
|
||||
static void serial_stub_putc(struct stdio_dev *sdev, const char ch)
|
||||
{
|
||||
_serial_putc(sdev->priv, ch);
|
||||
}
|
||||
#endif
|
||||
|
||||
void serial_stub_puts(struct stdio_dev *sdev, const char *str)
|
||||
{
|
||||
_serial_puts(sdev->priv, str);
|
||||
}
|
||||
|
||||
int serial_stub_getc(struct stdio_dev *sdev)
|
||||
{
|
||||
return _serial_getc(sdev->priv);
|
||||
}
|
||||
|
||||
int serial_stub_tstc(struct stdio_dev *sdev)
|
||||
{
|
||||
return _serial_tstc(sdev->priv);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 (getc() == '\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 CONFIG_POST & CONFIG_SYS_POST_UART
|
||||
if (ops->loop)
|
||||
ops->loop += gd->reloc_off
|
||||
#endif
|
||||
#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;
|
||||
sdev.priv = dev;
|
||||
sdev.putc = serial_stub_putc;
|
||||
sdev.puts = serial_stub_puts;
|
||||
sdev.getc = serial_stub_getc;
|
||||
sdev.tstc = serial_stub_tstc;
|
||||
stdio_register_dev(&sdev, &upriv->sdev);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int serial_pre_remove(struct udevice *dev)
|
||||
{
|
||||
#ifdef CONFIG_SYS_STDIO_DEREGISTER
|
||||
struct serial_dev_priv *upriv = dev_get_uclass_priv(dev);
|
||||
|
||||
if (stdio_deregister_dev(upriv->sdev, 0))
|
||||
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_alloc_size = sizeof(struct serial_dev_priv),
|
||||
};
|
||||
#endif
|
||||
617
u-boot/drivers/serial/serial.c
Normal file
617
u-boot/drivers/serial/serial.c
Normal file
@@ -0,0 +1,617 @@
|
||||
/*
|
||||
* (C) Copyright 2004
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <environment.h>
|
||||
#include <serial.h>
|
||||
#include <stdio_dev.h>
|
||||
#include <post.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <errno.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
|
||||
*
|
||||
* 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 (getc() == '\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(amirix_serial_initialize);
|
||||
serial_initfunc(arc_serial_initialize);
|
||||
serial_initfunc(arm_dcc_initialize);
|
||||
serial_initfunc(asc_serial_initialize);
|
||||
serial_initfunc(atmel_serial_initialize);
|
||||
serial_initfunc(au1x00_serial_initialize);
|
||||
serial_initfunc(bfin_jtag_initialize);
|
||||
serial_initfunc(bfin_serial_initialize);
|
||||
serial_initfunc(bmw_serial_initialize);
|
||||
serial_initfunc(clps7111_serial_initialize);
|
||||
serial_initfunc(cogent_serial_initialize);
|
||||
serial_initfunc(cpci750_serial_initialize);
|
||||
serial_initfunc(evb64260_serial_initialize);
|
||||
serial_initfunc(imx_serial_initialize);
|
||||
serial_initfunc(iop480_serial_initialize);
|
||||
serial_initfunc(jz_serial_initialize);
|
||||
serial_initfunc(leon2_serial_initialize);
|
||||
serial_initfunc(leon3_serial_initialize);
|
||||
serial_initfunc(lh7a40x_serial_initialize);
|
||||
serial_initfunc(lpc32xx_serial_initialize);
|
||||
serial_initfunc(marvell_serial_initialize);
|
||||
serial_initfunc(max3100_serial_initialize);
|
||||
serial_initfunc(mcf_serial_initialize);
|
||||
serial_initfunc(ml2_serial_initialize);
|
||||
serial_initfunc(mpc512x_serial_initialize);
|
||||
serial_initfunc(mpc5xx_serial_initialize);
|
||||
serial_initfunc(mpc8260_scc_serial_initialize);
|
||||
serial_initfunc(mpc8260_smc_serial_initialize);
|
||||
serial_initfunc(mpc85xx_serial_initialize);
|
||||
serial_initfunc(mpc8xx_serial_initialize);
|
||||
serial_initfunc(mxc_serial_initialize);
|
||||
serial_initfunc(mxs_auart_initialize);
|
||||
serial_initfunc(ns16550_serial_initialize);
|
||||
serial_initfunc(oc_serial_initialize);
|
||||
serial_initfunc(p3mx_serial_initialize);
|
||||
serial_initfunc(pl01x_serial_initialize);
|
||||
serial_initfunc(pxa_serial_initialize);
|
||||
serial_initfunc(s3c24xx_serial_initialize);
|
||||
serial_initfunc(s5p_serial_initialize);
|
||||
serial_initfunc(sa1100_serial_initialize);
|
||||
serial_initfunc(sandbox_serial_initialize);
|
||||
serial_initfunc(sconsole_serial_initialize);
|
||||
serial_initfunc(sh_serial_initialize);
|
||||
serial_initfunc(stm32_serial_initialize);
|
||||
serial_initfunc(uartlite_serial_initialize);
|
||||
serial_initfunc(zynq_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.
|
||||
*/
|
||||
void serial_initialize(void)
|
||||
{
|
||||
amirix_serial_initialize();
|
||||
arc_serial_initialize();
|
||||
arm_dcc_initialize();
|
||||
asc_serial_initialize();
|
||||
atmel_serial_initialize();
|
||||
au1x00_serial_initialize();
|
||||
bfin_jtag_initialize();
|
||||
bfin_serial_initialize();
|
||||
bmw_serial_initialize();
|
||||
clps7111_serial_initialize();
|
||||
cogent_serial_initialize();
|
||||
cpci750_serial_initialize();
|
||||
evb64260_serial_initialize();
|
||||
imx_serial_initialize();
|
||||
iop480_serial_initialize();
|
||||
jz_serial_initialize();
|
||||
leon2_serial_initialize();
|
||||
leon3_serial_initialize();
|
||||
lh7a40x_serial_initialize();
|
||||
lpc32xx_serial_initialize();
|
||||
marvell_serial_initialize();
|
||||
max3100_serial_initialize();
|
||||
mcf_serial_initialize();
|
||||
ml2_serial_initialize();
|
||||
mpc512x_serial_initialize();
|
||||
mpc5xx_serial_initialize();
|
||||
mpc8260_scc_serial_initialize();
|
||||
mpc8260_smc_serial_initialize();
|
||||
mpc85xx_serial_initialize();
|
||||
mpc8xx_serial_initialize();
|
||||
mxc_serial_initialize();
|
||||
mxs_auart_initialize();
|
||||
ns16550_serial_initialize();
|
||||
oc_serial_initialize();
|
||||
p3mx_serial_initialize();
|
||||
pl01x_serial_initialize();
|
||||
pxa_serial_initialize();
|
||||
s3c24xx_serial_initialize();
|
||||
s5p_serial_initialize();
|
||||
sa1100_serial_initialize();
|
||||
sandbox_serial_initialize();
|
||||
sconsole_serial_initialize();
|
||||
sh_serial_initialize();
|
||||
stm32_serial_initialize();
|
||||
uartlite_serial_initialize();
|
||||
zynq_serial_initialize();
|
||||
|
||||
serial_assign(default_serial_console()->name);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
int serial_stub_getc(struct stdio_dev *sdev)
|
||||
{
|
||||
struct serial_device *dev = sdev->priv;
|
||||
|
||||
return dev->getc();
|
||||
}
|
||||
|
||||
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
|
||||
243
u-boot/drivers/serial/serial_ar933x.c
Normal file
243
u-boot/drivers/serial/serial_ar933x.c
Normal file
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.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 <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_get_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_alloc_size = sizeof(struct ar933x_serial_priv),
|
||||
.probe = ar933x_serial_probe,
|
||||
.ops = &ar933x_serial_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
|
||||
#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
|
||||
132
u-boot/drivers/serial/serial_arc.c
Normal file
132
u-boot/drivers/serial/serial_arc.c
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* 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>
|
||||
|
||||
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_platdata {
|
||||
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_platdata *plat = dev->platdata;
|
||||
struct arc_serial_regs *const regs = plat->reg;
|
||||
int arc_console_baud = gd->cpu_clk / (baudrate * 4) - 1;
|
||||
|
||||
writeb(arc_console_baud & 0xff, ®s->baudl);
|
||||
writeb((arc_console_baud & 0xff00) >> 8, ®s->baudh);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int arc_serial_putc(struct udevice *dev, const char c)
|
||||
{
|
||||
struct arc_serial_platdata *plat = dev->platdata;
|
||||
struct arc_serial_regs *const regs = plat->reg;
|
||||
|
||||
while (!(readb(®s->status) & UART_TXEMPTY))
|
||||
;
|
||||
|
||||
writeb(c, ®s->data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int arc_serial_tstc(struct arc_serial_regs *const regs)
|
||||
{
|
||||
return !(readb(®s->status) & UART_RXEMPTY);
|
||||
}
|
||||
|
||||
static int arc_serial_pending(struct udevice *dev, bool input)
|
||||
{
|
||||
struct arc_serial_platdata *plat = dev->platdata;
|
||||
struct arc_serial_regs *const regs = plat->reg;
|
||||
uint32_t status = readb(®s->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_platdata *plat = dev->platdata;
|
||||
struct arc_serial_regs *const regs = plat->reg;
|
||||
|
||||
while (!arc_serial_tstc(regs))
|
||||
;
|
||||
|
||||
/* Check for overflow errors */
|
||||
if (readb(®s->status) & UART_OVERFLOW_ERR)
|
||||
return 0;
|
||||
|
||||
return readb(®s->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_ofdata_to_platdata(struct udevice *dev)
|
||||
{
|
||||
struct arc_serial_platdata *plat = dev_get_platdata(dev);
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
plat->reg = (struct arc_serial_regs *)dev_get_addr(dev);
|
||||
plat->uartclk = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
|
||||
"clock-frequency", 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
U_BOOT_DRIVER(serial_arc) = {
|
||||
.name = "serial_arc",
|
||||
.id = UCLASS_SERIAL,
|
||||
.of_match = arc_serial_ids,
|
||||
.ofdata_to_platdata = arc_serial_ofdata_to_platdata,
|
||||
.probe = arc_serial_probe,
|
||||
.ops = &arc_serial_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
140
u-boot/drivers/serial/serial_bcm283x_mu.c
Normal file
140
u-boot/drivers/serial/serial_bcm283x_mu.c
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* (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>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
/* Simple U-Boot driver for the BCM283x mini UART */
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <watchdog.h>
|
||||
#include <asm/io.h>
|
||||
#include <serial.h>
|
||||
#include <dm/platform_data/serial_bcm283x_mu.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <fdtdec.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_setbrg(struct udevice *dev, int baudrate)
|
||||
{
|
||||
struct bcm283x_mu_serial_platdata *plat = dev_get_platdata(dev);
|
||||
struct bcm283x_mu_priv *priv = dev_get_priv(dev);
|
||||
struct bcm283x_mu_regs *regs = priv->regs;
|
||||
u32 divider;
|
||||
|
||||
if (plat->skip_init)
|
||||
return 0;
|
||||
|
||||
divider = plat->clock / (baudrate * 8);
|
||||
|
||||
writel(BCM283X_MU_LCR_DATA_SIZE_8, ®s->lcr);
|
||||
writel(divider - 1, ®s->baud);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcm283x_mu_serial_probe(struct udevice *dev)
|
||||
{
|
||||
struct bcm283x_mu_serial_platdata *plat = dev_get_platdata(dev);
|
||||
struct bcm283x_mu_priv *priv = dev_get_priv(dev);
|
||||
|
||||
priv->regs = (struct bcm283x_mu_regs *)plat->base;
|
||||
|
||||
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(®s->lsr) & BCM283X_MU_LSR_RX_READY))
|
||||
return -EAGAIN;
|
||||
|
||||
data = readl(®s->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(®s->lsr) & BCM283X_MU_LSR_TX_EMPTY))
|
||||
return -EAGAIN;
|
||||
|
||||
/* Send the character */
|
||||
writel(data, ®s->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 = readl(®s->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,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(serial_bcm283x_mu) = {
|
||||
.name = "serial_bcm283x_mu",
|
||||
.id = UCLASS_SERIAL,
|
||||
.platdata_auto_alloc_size = sizeof(struct bcm283x_mu_serial_platdata),
|
||||
.probe = bcm283x_mu_serial_probe,
|
||||
.ops = &bcm283x_mu_serial_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
.priv_auto_alloc_size = sizeof(struct bcm283x_mu_priv),
|
||||
};
|
||||
411
u-boot/drivers/serial/serial_bfin.c
Normal file
411
u-boot/drivers/serial/serial_bfin.c
Normal file
@@ -0,0 +1,411 @@
|
||||
/*
|
||||
* U-Boot - serial.c Blackfin Serial Driver
|
||||
*
|
||||
* Copyright (c) 2005-2008 Analog Devices Inc.
|
||||
*
|
||||
* Copyright (c) 2003 Bas Vermeulen <bas@buyways.nl>,
|
||||
* BuyWays B.V. (www.buyways.nl)
|
||||
*
|
||||
* Based heavily on:
|
||||
* blkfinserial.c: Serial driver for BlackFin DSP internal USRTs.
|
||||
* Copyright(c) 2003 Metrowerks <mwaddel@metrowerks.com>
|
||||
* Copyright(c) 2001 Tony Z. Kou <tonyko@arcturusnetworks.com>
|
||||
* Copyright(c) 2001-2002 Arcturus Networks Inc. <www.arcturusnetworks.com>
|
||||
*
|
||||
* Based on code from 68328 version serial driver imlpementation which was:
|
||||
* Copyright (C) 1995 David S. Miller <davem@caip.rutgers.edu>
|
||||
* Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>
|
||||
* Copyright (C) 1998, 1999 D. Jeff Dionne <jeff@uclinux.org>
|
||||
* Copyright (C) 1999 Vladimir Gurevich <vgurevic@cisco.com>
|
||||
*
|
||||
* (C) Copyright 2000-2004
|
||||
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
|
||||
*
|
||||
* Licensed under the GPL-2 or later.
|
||||
*/
|
||||
|
||||
/* Anomaly notes:
|
||||
* 05000086 - we don't support autobaud
|
||||
* 05000099 - we only use DR bit, so losing others is not a problem
|
||||
* 05000100 - we don't use the UART_IIR register
|
||||
* 05000215 - we poll the uart (no dma/interrupts)
|
||||
* 05000225 - no workaround possible, but this shouldnt cause errors ...
|
||||
* 05000230 - we tweak the baud rate calculation slightly
|
||||
* 05000231 - we always use 1 stop bit
|
||||
* 05000309 - we always enable the uart before we modify it in anyway
|
||||
* 05000350 - we always enable the uart regardless of boot mode
|
||||
* 05000363 - we don't support break signals, so don't generate one
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <post.h>
|
||||
#include <watchdog.h>
|
||||
#include <serial.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <asm/blackfin.h>
|
||||
#include <asm/serial.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#ifdef CONFIG_UART_CONSOLE
|
||||
|
||||
#ifdef CONFIG_DEBUG_SERIAL
|
||||
static uart_lsr_t cached_lsr[256];
|
||||
static uart_lsr_t cached_rbr[256];
|
||||
static size_t cache_count;
|
||||
|
||||
/* The LSR is read-to-clear on some parts, so we have to make sure status
|
||||
* bits aren't inadvertently lost when doing various tests. This also
|
||||
* works around anomaly 05000099 at the same time by keeping a cumulative
|
||||
* tally of all the status bits.
|
||||
*/
|
||||
static uart_lsr_t uart_lsr_save;
|
||||
static uart_lsr_t uart_lsr_read(uint32_t uart_base)
|
||||
{
|
||||
uart_lsr_t lsr = _lsr_read(pUART);
|
||||
uart_lsr_save |= (lsr & (OE|PE|FE|BI));
|
||||
return lsr | uart_lsr_save;
|
||||
}
|
||||
/* Just do the clear for everyone since it can't hurt. */
|
||||
static void uart_lsr_clear(uint32_t uart_base)
|
||||
{
|
||||
uart_lsr_save = 0;
|
||||
_lsr_write(pUART, -1);
|
||||
}
|
||||
#else
|
||||
/* When debugging is disabled, we only care about the DR bit, so if other
|
||||
* bits get set/cleared, we don't really care since we don't read them
|
||||
* anyways (and thus anomaly 05000099 is irrelevant).
|
||||
*/
|
||||
static inline uart_lsr_t uart_lsr_read(uint32_t uart_base)
|
||||
{
|
||||
return _lsr_read(pUART);
|
||||
}
|
||||
static void uart_lsr_clear(uint32_t uart_base)
|
||||
{
|
||||
_lsr_write(pUART, -1);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void uart_putc(uint32_t uart_base, const char c)
|
||||
{
|
||||
/* send a \r for compatibility */
|
||||
if (c == '\n')
|
||||
serial_putc('\r');
|
||||
|
||||
WATCHDOG_RESET();
|
||||
|
||||
/* wait for the hardware fifo to clear up */
|
||||
while (!(uart_lsr_read(uart_base) & THRE))
|
||||
continue;
|
||||
|
||||
/* queue the character for transmission */
|
||||
bfin_write(&pUART->thr, c);
|
||||
SSYNC();
|
||||
|
||||
WATCHDOG_RESET();
|
||||
}
|
||||
|
||||
static int uart_tstc(uint32_t uart_base)
|
||||
{
|
||||
WATCHDOG_RESET();
|
||||
return (uart_lsr_read(uart_base) & DR) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int uart_getc(uint32_t uart_base)
|
||||
{
|
||||
uint16_t uart_rbr_val;
|
||||
|
||||
/* wait for data ! */
|
||||
while (!uart_tstc(uart_base))
|
||||
continue;
|
||||
|
||||
/* grab the new byte */
|
||||
uart_rbr_val = bfin_read(&pUART->rbr);
|
||||
|
||||
#ifdef CONFIG_DEBUG_SERIAL
|
||||
/* grab & clear the LSR */
|
||||
uart_lsr_t uart_lsr_val = uart_lsr_read(uart_base);
|
||||
|
||||
cached_lsr[cache_count] = uart_lsr_val;
|
||||
cached_rbr[cache_count] = uart_rbr_val;
|
||||
cache_count = (cache_count + 1) % ARRAY_SIZE(cached_lsr);
|
||||
|
||||
if (uart_lsr_val & (OE|PE|FE|BI)) {
|
||||
printf("\n[SERIAL ERROR]\n");
|
||||
do {
|
||||
--cache_count;
|
||||
printf("\t%3zu: RBR=0x%02x LSR=0x%02x\n", cache_count,
|
||||
cached_rbr[cache_count], cached_lsr[cache_count]);
|
||||
} while (cache_count > 0);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
uart_lsr_clear(uart_base);
|
||||
|
||||
return uart_rbr_val;
|
||||
}
|
||||
|
||||
#if CONFIG_POST & CONFIG_SYS_POST_UART
|
||||
# define LOOP(x) x
|
||||
#else
|
||||
# define LOOP(x)
|
||||
#endif
|
||||
|
||||
#if BFIN_UART_HW_VER < 4
|
||||
|
||||
LOOP(
|
||||
static void uart_loop(uint32_t uart_base, int state)
|
||||
{
|
||||
u16 mcr;
|
||||
|
||||
/* Drain the TX fifo first so bytes don't come back */
|
||||
while (!(uart_lsr_read(uart_base) & TEMT))
|
||||
continue;
|
||||
|
||||
mcr = bfin_read(&pUART->mcr);
|
||||
if (state)
|
||||
mcr |= LOOP_ENA | MRTS;
|
||||
else
|
||||
mcr &= ~(LOOP_ENA | MRTS);
|
||||
bfin_write(&pUART->mcr, mcr);
|
||||
}
|
||||
)
|
||||
|
||||
#else
|
||||
|
||||
LOOP(
|
||||
static void uart_loop(uint32_t uart_base, int state)
|
||||
{
|
||||
u32 control;
|
||||
|
||||
/* Drain the TX fifo first so bytes don't come back */
|
||||
while (!(uart_lsr_read(uart_base) & TEMT))
|
||||
continue;
|
||||
|
||||
control = bfin_read(&pUART->control);
|
||||
if (state)
|
||||
control |= LOOP_ENA | MRTS;
|
||||
else
|
||||
control &= ~(LOOP_ENA | MRTS);
|
||||
bfin_write(&pUART->control, control);
|
||||
}
|
||||
)
|
||||
|
||||
#endif
|
||||
|
||||
static inline void __serial_set_baud(uint32_t uart_base, uint32_t baud)
|
||||
{
|
||||
#ifdef CONFIG_DEBUG_EARLY_SERIAL
|
||||
serial_early_set_baud(uart_base, baud);
|
||||
#else
|
||||
uint16_t divisor = (get_uart_clk() + (baud * 8)) / (baud * 16)
|
||||
- ANOMALY_05000230;
|
||||
|
||||
/* Program the divisor to get the baud rate we want */
|
||||
serial_set_divisor(uart_base, divisor);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void uart_puts(uint32_t uart_base, const char *s)
|
||||
{
|
||||
while (*s)
|
||||
uart_putc(uart_base, *s++);
|
||||
}
|
||||
|
||||
#define DECL_BFIN_UART(n) \
|
||||
static int uart##n##_init(void) \
|
||||
{ \
|
||||
const unsigned short pins[] = { _P_UART(n, RX), _P_UART(n, TX), 0, }; \
|
||||
peripheral_request_list(pins, "bfin-uart"); \
|
||||
uart_init(MMR_UART(n)); \
|
||||
__serial_set_baud(MMR_UART(n), gd->baudrate); \
|
||||
uart_lsr_clear(MMR_UART(n)); \
|
||||
return 0; \
|
||||
} \
|
||||
\
|
||||
static int uart##n##_uninit(void) \
|
||||
{ \
|
||||
return serial_early_uninit(MMR_UART(n)); \
|
||||
} \
|
||||
\
|
||||
static void uart##n##_setbrg(void) \
|
||||
{ \
|
||||
__serial_set_baud(MMR_UART(n), gd->baudrate); \
|
||||
} \
|
||||
\
|
||||
static int uart##n##_getc(void) \
|
||||
{ \
|
||||
return uart_getc(MMR_UART(n)); \
|
||||
} \
|
||||
\
|
||||
static int uart##n##_tstc(void) \
|
||||
{ \
|
||||
return uart_tstc(MMR_UART(n)); \
|
||||
} \
|
||||
\
|
||||
static void uart##n##_putc(const char c) \
|
||||
{ \
|
||||
uart_putc(MMR_UART(n), c); \
|
||||
} \
|
||||
\
|
||||
static void uart##n##_puts(const char *s) \
|
||||
{ \
|
||||
uart_puts(MMR_UART(n), s); \
|
||||
} \
|
||||
\
|
||||
LOOP( \
|
||||
static void uart##n##_loop(int state) \
|
||||
{ \
|
||||
uart_loop(MMR_UART(n), state); \
|
||||
} \
|
||||
) \
|
||||
\
|
||||
struct serial_device bfin_serial##n##_device = { \
|
||||
.name = "bfin_uart"#n, \
|
||||
.start = uart##n##_init, \
|
||||
.stop = uart##n##_uninit, \
|
||||
.setbrg = uart##n##_setbrg, \
|
||||
.getc = uart##n##_getc, \
|
||||
.tstc = uart##n##_tstc, \
|
||||
.putc = uart##n##_putc, \
|
||||
.puts = uart##n##_puts, \
|
||||
LOOP(.loop = uart##n##_loop) \
|
||||
};
|
||||
|
||||
#ifdef UART0_RBR
|
||||
DECL_BFIN_UART(0)
|
||||
#endif
|
||||
#ifdef UART1_RBR
|
||||
DECL_BFIN_UART(1)
|
||||
#endif
|
||||
#ifdef UART2_RBR
|
||||
DECL_BFIN_UART(2)
|
||||
#endif
|
||||
#ifdef UART3_RBR
|
||||
DECL_BFIN_UART(3)
|
||||
#endif
|
||||
|
||||
__weak struct serial_device *default_serial_console(void)
|
||||
{
|
||||
#if CONFIG_UART_CONSOLE == 0
|
||||
return &bfin_serial0_device;
|
||||
#elif CONFIG_UART_CONSOLE == 1
|
||||
return &bfin_serial1_device;
|
||||
#elif CONFIG_UART_CONSOLE == 2
|
||||
return &bfin_serial2_device;
|
||||
#elif CONFIG_UART_CONSOLE == 3
|
||||
return &bfin_serial3_device;
|
||||
#endif
|
||||
}
|
||||
|
||||
void bfin_serial_initialize(void)
|
||||
{
|
||||
#ifdef UART0_RBR
|
||||
serial_register(&bfin_serial0_device);
|
||||
#endif
|
||||
#ifdef UART1_RBR
|
||||
serial_register(&bfin_serial1_device);
|
||||
#endif
|
||||
#ifdef UART2_RBR
|
||||
serial_register(&bfin_serial2_device);
|
||||
#endif
|
||||
#ifdef UART3_RBR
|
||||
serial_register(&bfin_serial3_device);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_EARLY_SERIAL
|
||||
inline void uart_early_putc(uint32_t uart_base, const char c)
|
||||
{
|
||||
/* send a \r for compatibility */
|
||||
if (c == '\n')
|
||||
uart_early_putc(uart_base, '\r');
|
||||
|
||||
/* wait for the hardware fifo to clear up */
|
||||
while (!(_lsr_read(pUART) & THRE))
|
||||
continue;
|
||||
|
||||
/* queue the character for transmission */
|
||||
bfin_write(&pUART->thr, c);
|
||||
SSYNC();
|
||||
}
|
||||
|
||||
void uart_early_puts(const char *s)
|
||||
{
|
||||
while (*s)
|
||||
uart_early_putc(UART_BASE, *s++);
|
||||
}
|
||||
|
||||
/* Symbol for our assembly to call. */
|
||||
void _serial_early_set_baud(uint32_t baud)
|
||||
{
|
||||
serial_early_set_baud(UART_BASE, baud);
|
||||
}
|
||||
|
||||
/* Symbol for our assembly to call. */
|
||||
void _serial_early_init(void)
|
||||
{
|
||||
serial_early_init(UART_BASE);
|
||||
}
|
||||
#endif
|
||||
|
||||
#elif defined(CONFIG_UART_MEM)
|
||||
|
||||
char serial_logbuf[CONFIG_UART_MEM];
|
||||
char *serial_logbuf_head = serial_logbuf;
|
||||
|
||||
int serial_mem_init(void)
|
||||
{
|
||||
serial_logbuf_head = serial_logbuf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void serial_mem_setbrg(void)
|
||||
{
|
||||
}
|
||||
|
||||
int serial_mem_tstc(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int serial_mem_getc(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void serial_mem_putc(const char c)
|
||||
{
|
||||
*serial_logbuf_head = c;
|
||||
if (++serial_logbuf_head == serial_logbuf + CONFIG_UART_MEM)
|
||||
serial_logbuf_head = serial_logbuf;
|
||||
}
|
||||
|
||||
void serial_mem_puts(const char *s)
|
||||
{
|
||||
while (*s)
|
||||
serial_putc(*s++);
|
||||
}
|
||||
|
||||
struct serial_device bfin_serial_mem_device = {
|
||||
.name = "bfin_uart_mem",
|
||||
.start = serial_mem_init,
|
||||
.setbrg = serial_mem_setbrg,
|
||||
.getc = serial_mem_getc,
|
||||
.tstc = serial_mem_tstc,
|
||||
.putc = serial_mem_putc,
|
||||
.puts = serial_mem_puts,
|
||||
};
|
||||
|
||||
|
||||
__weak struct serial_device *default_serial_console(void)
|
||||
{
|
||||
return &bfin_serial_mem_device;
|
||||
}
|
||||
|
||||
void bfin_serial_initialize(void)
|
||||
{
|
||||
serial_register(&bfin_serial_mem_device);
|
||||
}
|
||||
#endif /* CONFIG_UART_MEM */
|
||||
157
u-boot/drivers/serial/serial_efi.c
Normal file
157
u-boot/drivers/serial/serial_efi.c
Normal file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Google, Inc
|
||||
* Written by Simon Glass <sjg@chromium.org>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <debug_uart.h>
|
||||
#include <dm.h>
|
||||
#include <efi.h>
|
||||
#include <efi_api.h>
|
||||
#include <errno.h>
|
||||
#include <fdtdec.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <asm/io.h>
|
||||
#include <serial.h>
|
||||
|
||||
/* Information about the efi console */
|
||||
struct serial_efi_priv {
|
||||
struct efi_simple_input_interface *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_alloc_size = sizeof(struct serial_efi_priv),
|
||||
.probe = serial_efi_probe,
|
||||
.ops = &serial_efi_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
223
u-boot/drivers/serial/serial_linflexuart.c
Normal file
223
u-boot/drivers/serial/serial_linflexuart.c
Normal file
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
* (C) Copyright 2013-2016 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <watchdog.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;
|
||||
|
||||
#ifndef CONFIG_DM_SERIAL
|
||||
#error "The linflex serial driver does not have non-DM support."
|
||||
#endif
|
||||
|
||||
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_platdata {
|
||||
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_platdata *plat = dev->platdata;
|
||||
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_alloc_size = 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 */
|
||||
347
u-boot/drivers/serial/serial_lpuart.c
Normal file
347
u-boot/drivers/serial/serial_lpuart.c
Normal file
@@ -0,0 +1,347 @@
|
||||
/*
|
||||
* Copyright 2013 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <watchdog.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 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_TXFE 0x80
|
||||
#define FIFO_RXFE 0x40
|
||||
|
||||
#define WATER_TXWATER_OFF 1
|
||||
#define WATER_RXWATER_OFF 16
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
struct lpuart_serial_platdata {
|
||||
struct lpuart_fsl *reg;
|
||||
};
|
||||
|
||||
#ifndef CONFIG_LPUART_32B_REG
|
||||
static void _lpuart_serial_setbrg(struct lpuart_fsl *base, int baudrate)
|
||||
{
|
||||
u32 clk = mxc_get_clock(MXC_UART_CLK);
|
||||
u16 sbr;
|
||||
|
||||
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_fsl *base)
|
||||
{
|
||||
while (!(__raw_readb(&base->us1) & (US1_RDRF | US1_OR)))
|
||||
WATCHDOG_RESET();
|
||||
|
||||
barrier();
|
||||
|
||||
return __raw_readb(&base->ud);
|
||||
}
|
||||
|
||||
static void _lpuart_serial_putc(struct lpuart_fsl *base, const char c)
|
||||
{
|
||||
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_fsl *base)
|
||||
{
|
||||
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 lpuart_fsl *base)
|
||||
{
|
||||
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(base, gd->baudrate);
|
||||
|
||||
__raw_writeb(UC2_RE | UC2_TE, &base->uc2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lpuart_serial_setbrg(struct udevice *dev, int baudrate)
|
||||
{
|
||||
struct lpuart_serial_platdata *plat = dev->platdata;
|
||||
struct lpuart_fsl *reg = plat->reg;
|
||||
|
||||
_lpuart_serial_setbrg(reg, baudrate);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lpuart_serial_getc(struct udevice *dev)
|
||||
{
|
||||
struct lpuart_serial_platdata *plat = dev->platdata;
|
||||
struct lpuart_fsl *reg = plat->reg;
|
||||
|
||||
return _lpuart_serial_getc(reg);
|
||||
}
|
||||
|
||||
static int lpuart_serial_putc(struct udevice *dev, const char c)
|
||||
{
|
||||
struct lpuart_serial_platdata *plat = dev->platdata;
|
||||
struct lpuart_fsl *reg = plat->reg;
|
||||
|
||||
_lpuart_serial_putc(reg, c);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lpuart_serial_pending(struct udevice *dev, bool input)
|
||||
{
|
||||
struct lpuart_serial_platdata *plat = dev->platdata;
|
||||
struct lpuart_fsl *reg = plat->reg;
|
||||
|
||||
if (input)
|
||||
return _lpuart_serial_tstc(reg);
|
||||
else
|
||||
return __raw_readb(®->us1) & US1_TDRE ? 0 : 1;
|
||||
}
|
||||
|
||||
static int lpuart_serial_probe(struct udevice *dev)
|
||||
{
|
||||
struct lpuart_serial_platdata *plat = dev->platdata;
|
||||
struct lpuart_fsl *reg = plat->reg;
|
||||
|
||||
return _lpuart_serial_init(reg);
|
||||
}
|
||||
#else
|
||||
|
||||
static void _lpuart32_serial_setbrg(struct lpuart_fsl *base, int baudrate)
|
||||
{
|
||||
u32 clk = CONFIG_SYS_CLK_FREQ;
|
||||
u32 sbr;
|
||||
|
||||
sbr = (clk / (16 * baudrate));
|
||||
|
||||
/* place adjustment later - n/32 BRFA */
|
||||
out_be32(&base->baud, sbr);
|
||||
}
|
||||
|
||||
static int _lpuart32_serial_getc(struct lpuart_fsl *base)
|
||||
{
|
||||
u32 stat;
|
||||
|
||||
while (((stat = in_be32(&base->stat)) & STAT_RDRF) == 0) {
|
||||
out_be32(&base->stat, STAT_FLAGS);
|
||||
WATCHDOG_RESET();
|
||||
}
|
||||
|
||||
return in_be32(&base->data) & 0x3ff;
|
||||
}
|
||||
|
||||
static void _lpuart32_serial_putc(struct lpuart_fsl *base, const char c)
|
||||
{
|
||||
while (!(in_be32(&base->stat) & STAT_TDRE))
|
||||
WATCHDOG_RESET();
|
||||
|
||||
out_be32(&base->data, c);
|
||||
}
|
||||
|
||||
/* Test whether a character is in the RX buffer */
|
||||
static int _lpuart32_serial_tstc(struct lpuart_fsl *base)
|
||||
{
|
||||
if ((in_be32(&base->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 lpuart_fsl *base)
|
||||
{
|
||||
u8 ctrl;
|
||||
|
||||
ctrl = in_be32(&base->ctrl);
|
||||
ctrl &= ~CTRL_RE;
|
||||
ctrl &= ~CTRL_TE;
|
||||
out_be32(&base->ctrl, ctrl);
|
||||
|
||||
out_be32(&base->modir, 0);
|
||||
out_be32(&base->fifo, ~(FIFO_TXFE | FIFO_RXFE));
|
||||
|
||||
out_be32(&base->match, 0);
|
||||
|
||||
/* provide data bits, parity, stop bit, etc */
|
||||
_lpuart32_serial_setbrg(base, gd->baudrate);
|
||||
|
||||
out_be32(&base->ctrl, CTRL_RE | CTRL_TE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lpuart32_serial_setbrg(struct udevice *dev, int baudrate)
|
||||
{
|
||||
struct lpuart_serial_platdata *plat = dev->platdata;
|
||||
struct lpuart_fsl *reg = plat->reg;
|
||||
|
||||
_lpuart32_serial_setbrg(reg, baudrate);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lpuart32_serial_getc(struct udevice *dev)
|
||||
{
|
||||
struct lpuart_serial_platdata *plat = dev->platdata;
|
||||
struct lpuart_fsl *reg = plat->reg;
|
||||
|
||||
return _lpuart32_serial_getc(reg);
|
||||
}
|
||||
|
||||
static int lpuart32_serial_putc(struct udevice *dev, const char c)
|
||||
{
|
||||
struct lpuart_serial_platdata *plat = dev->platdata;
|
||||
struct lpuart_fsl *reg = plat->reg;
|
||||
|
||||
_lpuart32_serial_putc(reg, c);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lpuart32_serial_pending(struct udevice *dev, bool input)
|
||||
{
|
||||
struct lpuart_serial_platdata *plat = dev->platdata;
|
||||
struct lpuart_fsl *reg = plat->reg;
|
||||
|
||||
if (input)
|
||||
return _lpuart32_serial_tstc(reg);
|
||||
else
|
||||
return in_be32(®->stat) & STAT_TDRE ? 0 : 1;
|
||||
}
|
||||
|
||||
static int lpuart32_serial_probe(struct udevice *dev)
|
||||
{
|
||||
struct lpuart_serial_platdata *plat = dev->platdata;
|
||||
struct lpuart_fsl *reg = plat->reg;
|
||||
|
||||
return _lpuart32_serial_init(reg);
|
||||
}
|
||||
#endif /* CONFIG_LPUART_32B_REG */
|
||||
|
||||
static int lpuart_serial_ofdata_to_platdata(struct udevice *dev)
|
||||
{
|
||||
struct lpuart_serial_platdata *plat = dev->platdata;
|
||||
fdt_addr_t addr;
|
||||
|
||||
addr = dev_get_addr(dev);
|
||||
if (addr == FDT_ADDR_T_NONE)
|
||||
return -EINVAL;
|
||||
|
||||
plat->reg = (struct lpuart_fsl *)addr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_LPUART_32B_REG
|
||||
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,vf610-lpuart" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(serial_lpuart) = {
|
||||
.name = "serial_lpuart",
|
||||
.id = UCLASS_SERIAL,
|
||||
.of_match = lpuart_serial_ids,
|
||||
.ofdata_to_platdata = lpuart_serial_ofdata_to_platdata,
|
||||
.platdata_auto_alloc_size = sizeof(struct lpuart_serial_platdata),
|
||||
.probe = lpuart_serial_probe,
|
||||
.ops = &lpuart_serial_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
#else /* CONFIG_LPUART_32B_REG */
|
||||
static const struct dm_serial_ops lpuart32_serial_ops = {
|
||||
.putc = lpuart32_serial_putc,
|
||||
.pending = lpuart32_serial_pending,
|
||||
.getc = lpuart32_serial_getc,
|
||||
.setbrg = lpuart32_serial_setbrg,
|
||||
};
|
||||
|
||||
static const struct udevice_id lpuart32_serial_ids[] = {
|
||||
{ .compatible = "fsl,ls1021a-lpuart" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(serial_lpuart32) = {
|
||||
.name = "serial_lpuart32",
|
||||
.id = UCLASS_SERIAL,
|
||||
.of_match = lpuart32_serial_ids,
|
||||
.ofdata_to_platdata = lpuart_serial_ofdata_to_platdata,
|
||||
.platdata_auto_alloc_size = sizeof(struct lpuart_serial_platdata),
|
||||
.probe = lpuart32_serial_probe,
|
||||
.ops = &lpuart32_serial_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
#endif /* CONFIG_LPUART_32B_REG */
|
||||
162
u-boot/drivers/serial/serial_meson.c
Normal file
162
u-boot/drivers/serial/serial_meson.c
Normal file
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* (C) Copyright 2016 Beniamino Galvani <b.galvani@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <fdtdec.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <serial.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
struct meson_uart {
|
||||
u32 wfifo;
|
||||
u32 rfifo;
|
||||
u32 control;
|
||||
u32 status;
|
||||
u32 misc;
|
||||
};
|
||||
|
||||
struct meson_serial_platdata {
|
||||
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_platdata *plat = dev->platdata;
|
||||
struct meson_uart *const uart = plat->reg;
|
||||
|
||||
meson_serial_init(uart);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int meson_serial_getc(struct udevice *dev)
|
||||
{
|
||||
struct meson_serial_platdata *plat = dev->platdata;
|
||||
struct meson_uart *const uart = plat->reg;
|
||||
|
||||
if (readl(&uart->status) & AML_UART_RX_EMPTY)
|
||||
return -EAGAIN;
|
||||
|
||||
return readl(&uart->rfifo) & 0xff;
|
||||
}
|
||||
|
||||
static int meson_serial_putc(struct udevice *dev, const char ch)
|
||||
{
|
||||
struct meson_serial_platdata *plat = dev->platdata;
|
||||
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_platdata *plat = dev->platdata;
|
||||
struct meson_uart *const uart = plat->reg;
|
||||
uint32_t status = readl(&uart->status);
|
||||
|
||||
if (input)
|
||||
return !(status & AML_UART_RX_EMPTY);
|
||||
else
|
||||
return !(status & AML_UART_TX_FULL);
|
||||
}
|
||||
|
||||
static int meson_serial_ofdata_to_platdata(struct udevice *dev)
|
||||
{
|
||||
struct meson_serial_platdata *plat = dev->platdata;
|
||||
fdt_addr_t addr;
|
||||
|
||||
addr = dev_get_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" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(serial_meson) = {
|
||||
.name = "serial_meson",
|
||||
.id = UCLASS_SERIAL,
|
||||
.of_match = meson_serial_ids,
|
||||
.probe = meson_serial_probe,
|
||||
.ops = &meson_serial_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
.ofdata_to_platdata = meson_serial_ofdata_to_platdata,
|
||||
.platdata_auto_alloc_size = sizeof(struct meson_serial_platdata),
|
||||
};
|
||||
|
||||
#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(®s->status) & AML_UART_TX_FULL)
|
||||
;
|
||||
|
||||
writel(ch, ®s->wfifo);
|
||||
}
|
||||
|
||||
DEBUG_UART_FUNCS
|
||||
|
||||
#endif
|
||||
224
u-boot/drivers/serial/serial_msm.c
Normal file
224
u-boot/drivers/serial/serial_msm.c
Normal file
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* Qualcomm UART driver
|
||||
*
|
||||
* (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
|
||||
*
|
||||
* UART will work in Data Mover mode.
|
||||
* Based on Linux driver.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <clk.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <serial.h>
|
||||
#include <watchdog.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/compiler.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_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 */
|
||||
|
||||
|
||||
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 */
|
||||
};
|
||||
|
||||
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,
|
||||
"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, "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 int msm_serial_probe(struct udevice *dev)
|
||||
{
|
||||
struct msm_serial_data *priv = dev_get_priv(dev);
|
||||
|
||||
msm_uart_clk_init(dev); /* Ignore return value and hope clock was
|
||||
properly initialized by earlier loaders */
|
||||
|
||||
if (readl(priv->base + UARTDM_SR) & UARTDM_SR_UART_OVERRUN)
|
||||
writel(UARTDM_CR_CMD_RESET_ERR, priv->base + UARTDM_CR);
|
||||
|
||||
writel(0, priv->base + UARTDM_IMR);
|
||||
writel(UARTDM_CR_CMD_STALE_EVENT_DISABLE, priv->base + UARTDM_CR);
|
||||
msm_serial_fetch(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msm_serial_ofdata_to_platdata(struct udevice *dev)
|
||||
{
|
||||
struct msm_serial_data *priv = dev_get_priv(dev);
|
||||
|
||||
priv->base = dev_get_addr(dev);
|
||||
if (priv->base == FDT_ADDR_T_NONE)
|
||||
return -EINVAL;
|
||||
|
||||
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,
|
||||
.ofdata_to_platdata = msm_serial_ofdata_to_platdata,
|
||||
.priv_auto_alloc_size = sizeof(struct msm_serial_data),
|
||||
.probe = msm_serial_probe,
|
||||
.ops = &msm_serial_ops,
|
||||
};
|
||||
351
u-boot/drivers/serial/serial_mxc.c
Normal file
351
u-boot/drivers/serial/serial_mxc.c
Normal file
@@ -0,0 +1,351 @@
|
||||
/*
|
||||
* (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <watchdog.h>
|
||||
#include <asm/arch/imx-regs.h>
|
||||
#include <asm/arch/clock.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 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_SOFTRST (1<<0) /* Software reset */
|
||||
|
||||
#ifndef CONFIG_DM_SERIAL
|
||||
|
||||
#ifndef CONFIG_MXC_UART_BASE
|
||||
#error "define CONFIG_MXC_UART_BASE to use the MXC UART driver"
|
||||
#endif
|
||||
|
||||
#define UART_PHYS CONFIG_MXC_UART_BASE
|
||||
|
||||
#define __REG(x) (*((volatile u32 *)(x)))
|
||||
|
||||
/* Register definitions */
|
||||
#define URXD 0x0 /* Receiver Register */
|
||||
#define UTXD 0x40 /* Transmitter Register */
|
||||
#define UCR1 0x80 /* Control Register 1 */
|
||||
#define UCR2 0x84 /* Control Register 2 */
|
||||
#define UCR3 0x88 /* Control Register 3 */
|
||||
#define UCR4 0x8c /* Control Register 4 */
|
||||
#define UFCR 0x90 /* FIFO Control Register */
|
||||
#define USR1 0x94 /* Status Register 1 */
|
||||
#define USR2 0x98 /* Status Register 2 */
|
||||
#define UESC 0x9c /* Escape Character Register */
|
||||
#define UTIM 0xa0 /* Escape Timer Register */
|
||||
#define UBIR 0xa4 /* BRM Incremental Register */
|
||||
#define UBMR 0xa8 /* BRM Modulator Register */
|
||||
#define UBRC 0xac /* Baud Rate Count Register */
|
||||
#define UTS 0xb4 /* UART Test Register (mx31) */
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#define TXTL 2 /* reset default */
|
||||
#define RXTL 1 /* reset default */
|
||||
#define RFDIV 4 /* divide input clock by 2 */
|
||||
|
||||
static void mxc_serial_setbrg(void)
|
||||
{
|
||||
u32 clk = imx_get_uartclk();
|
||||
|
||||
if (!gd->baudrate)
|
||||
gd->baudrate = CONFIG_BAUDRATE;
|
||||
|
||||
__REG(UART_PHYS + UFCR) = (RFDIV << UFCR_RFDIV_SHF)
|
||||
| (TXTL << UFCR_TXTL_SHF)
|
||||
| (RXTL << UFCR_RXTL_SHF);
|
||||
__REG(UART_PHYS + UBIR) = 0xf;
|
||||
__REG(UART_PHYS + UBMR) = clk / (2 * gd->baudrate);
|
||||
|
||||
}
|
||||
|
||||
static int mxc_serial_getc(void)
|
||||
{
|
||||
while (__REG(UART_PHYS + UTS) & UTS_RXEMPTY)
|
||||
WATCHDOG_RESET();
|
||||
return (__REG(UART_PHYS + URXD) & 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');
|
||||
|
||||
__REG(UART_PHYS + UTXD) = c;
|
||||
|
||||
/* wait for transmitter to be ready */
|
||||
while (!(__REG(UART_PHYS + UTS) & 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 (__REG(UART_PHYS + UTS) & 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)
|
||||
{
|
||||
__REG(UART_PHYS + UCR1) = 0x0;
|
||||
__REG(UART_PHYS + UCR2) = 0x0;
|
||||
|
||||
while (!(__REG(UART_PHYS + UCR2) & UCR2_SRST));
|
||||
|
||||
__REG(UART_PHYS + UCR3) = 0x0704 | UCR3_ADNIMP;
|
||||
__REG(UART_PHYS + UCR4) = 0x8000;
|
||||
__REG(UART_PHYS + UESC) = 0x002b;
|
||||
__REG(UART_PHYS + UTIM) = 0x0;
|
||||
|
||||
__REG(UART_PHYS + UTS) = 0x0;
|
||||
|
||||
serial_setbrg();
|
||||
|
||||
__REG(UART_PHYS + UCR2) = UCR2_WS | UCR2_IRTS | UCR2_RXEN | UCR2_TXEN | UCR2_SRST;
|
||||
|
||||
__REG(UART_PHYS + UCR1) = UCR1_UARTEN;
|
||||
|
||||
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
|
||||
|
||||
#ifdef CONFIG_DM_SERIAL
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
int mxc_serial_setbrg(struct udevice *dev, int baudrate)
|
||||
{
|
||||
struct mxc_serial_platdata *plat = dev->platdata;
|
||||
struct mxc_uart *const uart = plat->reg;
|
||||
u32 clk = imx_get_uartclk();
|
||||
|
||||
writel(4 << 7, &uart->fcr); /* divide input clock by 2 */
|
||||
writel(0xf, &uart->bir);
|
||||
writel(clk / (2 * baudrate), &uart->bmr);
|
||||
|
||||
writel(UCR2_WS | UCR2_IRTS | UCR2_RXEN | UCR2_TXEN | UCR2_SRST,
|
||||
&uart->cr2);
|
||||
writel(UCR1_UARTEN, &uart->cr1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mxc_serial_probe(struct udevice *dev)
|
||||
{
|
||||
struct mxc_serial_platdata *plat = dev->platdata;
|
||||
struct mxc_uart *const uart = plat->reg;
|
||||
|
||||
writel(0, &uart->cr1);
|
||||
writel(0, &uart->cr2);
|
||||
while (!(readl(&uart->cr2) & UCR2_SRST));
|
||||
writel(0x704 | UCR3_ADNIMP, &uart->cr3);
|
||||
writel(0x8000, &uart->cr4);
|
||||
writel(0x2b, &uart->esc);
|
||||
writel(0, &uart->tim);
|
||||
writel(0, &uart->ts);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mxc_serial_getc(struct udevice *dev)
|
||||
{
|
||||
struct mxc_serial_platdata *plat = dev->platdata;
|
||||
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_platdata *plat = dev->platdata;
|
||||
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_platdata *plat = dev->platdata;
|
||||
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,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(serial_mxc) = {
|
||||
.name = "serial_mxc",
|
||||
.id = UCLASS_SERIAL,
|
||||
.probe = mxc_serial_probe,
|
||||
.ops = &mxc_serial_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
#endif
|
||||
258
u-boot/drivers/serial/serial_ns16550.c
Normal file
258
u-boot/drivers/serial/serial_ns16550.c
Normal file
@@ -0,0 +1,258 @@
|
||||
/*
|
||||
* (C) Copyright 2000
|
||||
* Rob Taylor, Flying Pig Systems. robt@flyingpig.com.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <linux/compiler.h>
|
||||
|
||||
#include <ns16550.h>
|
||||
#ifdef CONFIG_NS87308
|
||||
#include <ns87308.h>
|
||||
#endif
|
||||
|
||||
#include <serial.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 NS16550_t serial_ports[6] = {
|
||||
#ifdef CONFIG_SYS_NS16550_COM1
|
||||
(NS16550_t)CONFIG_SYS_NS16550_COM1,
|
||||
#else
|
||||
NULL,
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_NS16550_COM2
|
||||
(NS16550_t)CONFIG_SYS_NS16550_COM2,
|
||||
#else
|
||||
NULL,
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_NS16550_COM3
|
||||
(NS16550_t)CONFIG_SYS_NS16550_COM3,
|
||||
#else
|
||||
NULL,
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_NS16550_COM4
|
||||
(NS16550_t)CONFIG_SYS_NS16550_COM4,
|
||||
#else
|
||||
NULL,
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_NS16550_COM5
|
||||
(NS16550_t)CONFIG_SYS_NS16550_COM5,
|
||||
#else
|
||||
NULL,
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_NS16550_COM6
|
||||
(NS16550_t)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 */
|
||||
199
u-boot/drivers/serial/serial_pic32.c
Normal file
199
u-boot/drivers/serial/serial_pic32.c
Normal file
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* (c) 2015 Paul Thacker <paul.thacker@microchip.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <clk.h>
|
||||
#include <dm.h>
|
||||
#include <serial.h>
|
||||
#include <wait_bit.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(__func__, 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, "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,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
.priv_auto_alloc_size = 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
|
||||
403
u-boot/drivers/serial/serial_pl01x.c
Normal file
403
u-boot/drivers/serial/serial_pl01x.c
Normal file
@@ -0,0 +1,403 @@
|
||||
/*
|
||||
* (C) Copyright 2000
|
||||
* Rob Taylor, Flying Pig Systems. robt@flyingpig.com.
|
||||
*
|
||||
* (C) Copyright 2004
|
||||
* ARM Ltd.
|
||||
* Philippe Robin, <philippe.robin@arm.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
/* Simple U-Boot driver for the PrimeCell PL010/PL011 UARTs */
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <watchdog.h>
|
||||
#include <asm/io.h>
|
||||
#include <serial.h>
|
||||
#include <dm/platform_data/serial_pl01x.h>
|
||||
#include <linux/compiler.h>
|
||||
#include "serial_pl01x_internal.h"
|
||||
#include <fdtdec.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#ifndef CONFIG_DM_SERIAL
|
||||
|
||||
static volatile unsigned char *const port[] = CONFIG_PL01x_PORTS;
|
||||
static enum pl01x_type pl01x_type __attribute__ ((section(".data")));
|
||||
static struct pl01x_regs *base_regs __attribute__ ((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(®s->fr) & UART_PL01x_FR_TXFF)
|
||||
return -EAGAIN;
|
||||
|
||||
/* Send the character */
|
||||
writel(c, ®s->dr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pl01x_getc(struct pl01x_regs *regs)
|
||||
{
|
||||
unsigned int data;
|
||||
|
||||
/* Wait until there is data in the FIFO */
|
||||
if (readl(®s->fr) & UART_PL01x_FR_RXFE)
|
||||
return -EAGAIN;
|
||||
|
||||
data = readl(®s->dr);
|
||||
|
||||
/* Check for an error flag */
|
||||
if (data & 0xFFFFFF00) {
|
||||
/* Clear the error */
|
||||
writel(0xFFFFFFFF, ®s->ecr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (int) data;
|
||||
}
|
||||
|
||||
static int pl01x_tstc(struct pl01x_regs *regs)
|
||||
{
|
||||
WATCHDOG_RESET();
|
||||
return !(readl(®s->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, ®s->pl010_cr);
|
||||
break;
|
||||
case TYPE_PL011:
|
||||
/* disable everything */
|
||||
writel(0, ®s->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, ®s->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, ®s->pl010_cr);
|
||||
|
||||
switch (baudrate) {
|
||||
case 9600:
|
||||
divisor = UART_PL010_BAUD_9600;
|
||||
break;
|
||||
case 19200:
|
||||
divisor = UART_PL010_BAUD_9600;
|
||||
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, ®s->pl010_lcrm);
|
||||
writel(divisor & 0xff, ®s->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,
|
||||
®s->pl010_lcrh);
|
||||
/* Finally, enable the UART */
|
||||
writel(UART_PL010_CR_UARTEN, ®s->pl010_cr);
|
||||
break;
|
||||
}
|
||||
case TYPE_PL011: {
|
||||
unsigned int temp;
|
||||
unsigned int divider;
|
||||
unsigned int remainder;
|
||||
unsigned int fraction;
|
||||
|
||||
/*
|
||||
* 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, ®s->pl011_ibrd);
|
||||
writel(fraction, ®s->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, ®s->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
|
||||
|
||||
struct pl01x_priv {
|
||||
struct pl01x_regs *regs;
|
||||
enum pl01x_type type;
|
||||
};
|
||||
|
||||
static int pl01x_serial_setbrg(struct udevice *dev, int baudrate)
|
||||
{
|
||||
struct pl01x_serial_platdata *plat = dev_get_platdata(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;
|
||||
}
|
||||
|
||||
static int pl01x_serial_probe(struct udevice *dev)
|
||||
{
|
||||
struct pl01x_serial_platdata *plat = dev_get_platdata(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;
|
||||
}
|
||||
|
||||
static int pl01x_serial_getc(struct udevice *dev)
|
||||
{
|
||||
struct pl01x_priv *priv = dev_get_priv(dev);
|
||||
|
||||
return pl01x_getc(priv->regs);
|
||||
}
|
||||
|
||||
static int pl01x_serial_putc(struct udevice *dev, const char ch)
|
||||
{
|
||||
struct pl01x_priv *priv = dev_get_priv(dev);
|
||||
|
||||
return pl01x_putc(priv->regs, ch);
|
||||
}
|
||||
|
||||
static 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},
|
||||
{}
|
||||
};
|
||||
|
||||
static int pl01x_serial_ofdata_to_platdata(struct udevice *dev)
|
||||
{
|
||||
struct pl01x_serial_platdata *plat = dev_get_platdata(dev);
|
||||
fdt_addr_t addr;
|
||||
|
||||
addr = dev_get_addr(dev);
|
||||
if (addr == FDT_ADDR_T_NONE)
|
||||
return -EINVAL;
|
||||
|
||||
plat->base = addr;
|
||||
plat->clock = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "clock", 1);
|
||||
plat->type = dev_get_driver_data(dev);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
U_BOOT_DRIVER(serial_pl01x) = {
|
||||
.name = "serial_pl01x",
|
||||
.id = UCLASS_SERIAL,
|
||||
.of_match = of_match_ptr(pl01x_serial_id),
|
||||
.ofdata_to_platdata = of_match_ptr(pl01x_serial_ofdata_to_platdata),
|
||||
.platdata_auto_alloc_size = sizeof(struct pl01x_serial_platdata),
|
||||
.probe = pl01x_serial_probe,
|
||||
.ops = &pl01x_serial_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
.priv_auto_alloc_size = 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
|
||||
128
u-boot/drivers/serial/serial_pl01x_internal.h
Normal file
128
u-boot/drivers/serial/serial_pl01x_internal.h
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* (C) Copyright 2003, 2004
|
||||
* ARM Ltd.
|
||||
* Philippe Robin, <philippe.robin@arm.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
};
|
||||
#endif
|
||||
|
||||
#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)
|
||||
299
u-boot/drivers/serial/serial_pxa.c
Normal file
299
u-boot/drivers/serial/serial_pxa.c
Normal file
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
* 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)
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/arch/pxa-regs.h>
|
||||
#include <asm/arch/regs-uart.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <serial.h>
|
||||
#include <watchdog.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
/*
|
||||
* The numbering scheme differs here for PXA25x, PXA27x and PXA3xx so we can
|
||||
* easily handle enabling of clock.
|
||||
*/
|
||||
#ifdef CONFIG_CPU_MONAHANS
|
||||
#define UART_CLK_BASE CKENA_21_BTUART
|
||||
#define UART_CLK_REG CKENA
|
||||
#define BTUART_INDEX 0
|
||||
#define FFUART_INDEX 1
|
||||
#define STUART_INDEX 2
|
||||
#elif CONFIG_CPU_PXA25X
|
||||
#define UART_CLK_BASE (1 << 4) /* HWUART */
|
||||
#define UART_CLK_REG CKEN
|
||||
#define HWUART_INDEX 0
|
||||
#define STUART_INDEX 1
|
||||
#define FFUART_INDEX 2
|
||||
#define BTUART_INDEX 3
|
||||
#else /* PXA27x */
|
||||
#define UART_CLK_BASE CKEN5_STUART
|
||||
#define UART_CLK_REG CKEN
|
||||
#define STUART_INDEX 0
|
||||
#define FFUART_INDEX 1
|
||||
#define BTUART_INDEX 2
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Only PXA250 has HWUART, to avoid poluting the code with more macros,
|
||||
* artificially introduce this.
|
||||
*/
|
||||
#ifndef CONFIG_CPU_PXA25X
|
||||
#define HWUART_INDEX 0xff
|
||||
#endif
|
||||
|
||||
static uint32_t pxa_uart_get_baud_divider(void)
|
||||
{
|
||||
if (gd->baudrate == 1200)
|
||||
return 768;
|
||||
else if (gd->baudrate == 9600)
|
||||
return 96;
|
||||
else if (gd->baudrate == 19200)
|
||||
return 48;
|
||||
else if (gd->baudrate == 38400)
|
||||
return 24;
|
||||
else if (gd->baudrate == 57600)
|
||||
return 16;
|
||||
else if (gd->baudrate == 115200)
|
||||
return 8;
|
||||
else /* Unsupported baudrate */
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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_dev(uint32_t uart_index)
|
||||
{
|
||||
uint32_t divider = 0;
|
||||
struct pxa_uart_regs *uart_regs;
|
||||
|
||||
divider = pxa_uart_get_baud_divider();
|
||||
if (!divider)
|
||||
hang();
|
||||
|
||||
uart_regs = pxa_uart_index_to_regs(uart_index);
|
||||
if (!uart_regs)
|
||||
hang();
|
||||
|
||||
pxa_uart_toggle_clock(uart_index, 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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
}
|
||||
208
u-boot/drivers/serial/serial_s3c24x0.c
Normal file
208
u-boot/drivers/serial/serial_s3c24x0.c
Normal file
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
* (C) Copyright 2002
|
||||
* Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <asm/arch/s3c24x0_cpu.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#ifdef CONFIG_SERIAL1
|
||||
#define UART_NR S3C24X0_UART0
|
||||
|
||||
#elif defined(CONFIG_SERIAL2)
|
||||
#define UART_NR S3C24X0_UART1
|
||||
|
||||
#elif defined(CONFIG_SERIAL3)
|
||||
#define UART_NR S3C24X0_UART2
|
||||
|
||||
#else
|
||||
#error "Bad: you didn't configure serial ..."
|
||||
#endif
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <serial.h>
|
||||
|
||||
/* Multi serial device functions */
|
||||
#define DECLARE_S3C_SERIAL_FUNCTIONS(port) \
|
||||
int s3serial##port##_init(void) \
|
||||
{ \
|
||||
return serial_init_dev(port); \
|
||||
} \
|
||||
void s3serial##port##_setbrg(void) \
|
||||
{ \
|
||||
serial_setbrg_dev(port); \
|
||||
} \
|
||||
int s3serial##port##_getc(void) \
|
||||
{ \
|
||||
return serial_getc_dev(port); \
|
||||
} \
|
||||
int s3serial##port##_tstc(void) \
|
||||
{ \
|
||||
return serial_tstc_dev(port); \
|
||||
} \
|
||||
void s3serial##port##_putc(const char c) \
|
||||
{ \
|
||||
serial_putc_dev(port, c); \
|
||||
} \
|
||||
void s3serial##port##_puts(const char *s) \
|
||||
{ \
|
||||
serial_puts_dev(port, s); \
|
||||
}
|
||||
|
||||
#define INIT_S3C_SERIAL_STRUCTURE(port, __name) { \
|
||||
.name = __name, \
|
||||
.start = s3serial##port##_init, \
|
||||
.stop = NULL, \
|
||||
.setbrg = s3serial##port##_setbrg, \
|
||||
.getc = s3serial##port##_getc, \
|
||||
.tstc = s3serial##port##_tstc, \
|
||||
.putc = s3serial##port##_putc, \
|
||||
.puts = s3serial##port##_puts, \
|
||||
}
|
||||
|
||||
static void _serial_setbrg(const int dev_index)
|
||||
{
|
||||
struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index);
|
||||
unsigned int reg = 0;
|
||||
int i;
|
||||
|
||||
/* value is calculated so : (int)(PCLK/16./baudrate) -1 */
|
||||
reg = get_PCLK() / (16 * gd->baudrate) - 1;
|
||||
|
||||
writel(reg, &uart->ubrdiv);
|
||||
for (i = 0; i < 100; i++)
|
||||
/* Delay */ ;
|
||||
}
|
||||
|
||||
static inline void serial_setbrg_dev(unsigned int dev_index)
|
||||
{
|
||||
_serial_setbrg(dev_index);
|
||||
}
|
||||
|
||||
/* Initialise the serial port. The settings are always 8 data bits, no parity,
|
||||
* 1 stop bit, no start bits.
|
||||
*/
|
||||
static int serial_init_dev(const int dev_index)
|
||||
{
|
||||
struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index);
|
||||
|
||||
/* FIFO enable, Tx/Rx FIFO clear */
|
||||
writel(0x07, &uart->ufcon);
|
||||
writel(0x0, &uart->umcon);
|
||||
|
||||
/* Normal,No parity,1 stop,8 bit */
|
||||
writel(0x3, &uart->ulcon);
|
||||
/*
|
||||
* tx=level,rx=edge,disable timeout int.,enable rx error int.,
|
||||
* normal,interrupt or polling
|
||||
*/
|
||||
writel(0x245, &uart->ucon);
|
||||
|
||||
_serial_setbrg(dev_index);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
static int _serial_getc(const int dev_index)
|
||||
{
|
||||
struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index);
|
||||
|
||||
while (!(readl(&uart->utrstat) & 0x1))
|
||||
/* wait for character to arrive */ ;
|
||||
|
||||
return readb(&uart->urxh) & 0xff;
|
||||
}
|
||||
|
||||
static inline int serial_getc_dev(unsigned int dev_index)
|
||||
{
|
||||
return _serial_getc(dev_index);
|
||||
}
|
||||
|
||||
/*
|
||||
* Output a single byte to the serial port.
|
||||
*/
|
||||
static void _serial_putc(const char c, const int dev_index)
|
||||
{
|
||||
struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index);
|
||||
|
||||
/* If \n, also do \r */
|
||||
if (c == '\n')
|
||||
serial_putc('\r');
|
||||
|
||||
while (!(readl(&uart->utrstat) & 0x2))
|
||||
/* wait for room in the tx FIFO */ ;
|
||||
|
||||
writeb(c, &uart->utxh);
|
||||
}
|
||||
|
||||
static inline void serial_putc_dev(unsigned int dev_index, const char c)
|
||||
{
|
||||
_serial_putc(c, dev_index);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test whether a character is in the RX buffer
|
||||
*/
|
||||
static int _serial_tstc(const int dev_index)
|
||||
{
|
||||
struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index);
|
||||
|
||||
return readl(&uart->utrstat) & 0x1;
|
||||
}
|
||||
|
||||
static inline int serial_tstc_dev(unsigned int dev_index)
|
||||
{
|
||||
return _serial_tstc(dev_index);
|
||||
}
|
||||
|
||||
static void _serial_puts(const char *s, const int dev_index)
|
||||
{
|
||||
while (*s) {
|
||||
_serial_putc(*s++, dev_index);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void serial_puts_dev(int dev_index, const char *s)
|
||||
{
|
||||
_serial_puts(s, dev_index);
|
||||
}
|
||||
|
||||
DECLARE_S3C_SERIAL_FUNCTIONS(0);
|
||||
struct serial_device s3c24xx_serial0_device =
|
||||
INIT_S3C_SERIAL_STRUCTURE(0, "s3ser0");
|
||||
DECLARE_S3C_SERIAL_FUNCTIONS(1);
|
||||
struct serial_device s3c24xx_serial1_device =
|
||||
INIT_S3C_SERIAL_STRUCTURE(1, "s3ser1");
|
||||
DECLARE_S3C_SERIAL_FUNCTIONS(2);
|
||||
struct serial_device s3c24xx_serial2_device =
|
||||
INIT_S3C_SERIAL_STRUCTURE(2, "s3ser2");
|
||||
|
||||
__weak struct serial_device *default_serial_console(void)
|
||||
{
|
||||
#if defined(CONFIG_SERIAL1)
|
||||
return &s3c24xx_serial0_device;
|
||||
#elif defined(CONFIG_SERIAL2)
|
||||
return &s3c24xx_serial1_device;
|
||||
#elif defined(CONFIG_SERIAL3)
|
||||
return &s3c24xx_serial2_device;
|
||||
#else
|
||||
#error "CONFIG_SERIAL? missing."
|
||||
#endif
|
||||
}
|
||||
|
||||
void s3c24xx_serial_initialize(void)
|
||||
{
|
||||
serial_register(&s3c24xx_serial0_device);
|
||||
serial_register(&s3c24xx_serial1_device);
|
||||
serial_register(&s3c24xx_serial2_device);
|
||||
}
|
||||
242
u-boot/drivers/serial/serial_s5p.c
Normal file
242
u-boot/drivers/serial/serial_s5p.c
Normal file
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
* (C) Copyright 2009 SAMSUNG Electronics
|
||||
* Minkyu Kang <mk7.kang@samsung.com>
|
||||
* Heungjun Kim <riverful.kim@samsung.com>
|
||||
*
|
||||
* based on drivers/serial/s3c64xx.c
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <fdtdec.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_platdata {
|
||||
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_platdata *plat = dev->platdata;
|
||||
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_platdata *plat = dev->platdata;
|
||||
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_platdata *plat = dev->platdata;
|
||||
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_platdata *plat = dev->platdata;
|
||||
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_platdata *plat = dev->platdata;
|
||||
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_ofdata_to_platdata(struct udevice *dev)
|
||||
{
|
||||
struct s5p_serial_platdata *plat = dev->platdata;
|
||||
fdt_addr_t addr;
|
||||
|
||||
addr = dev_get_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,
|
||||
"id", dev->seq);
|
||||
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,
|
||||
.ofdata_to_platdata = s5p_serial_ofdata_to_platdata,
|
||||
.platdata_auto_alloc_size = sizeof(struct s5p_serial_platdata),
|
||||
.probe = s5p_serial_probe,
|
||||
.ops = &s5p_serial_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
#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
|
||||
325
u-boot/drivers/serial/serial_sh.c
Normal file
325
u-boot/drivers/serial/serial_sh.c
Normal file
@@ -0,0 +1,325 @@
|
||||
/*
|
||||
* SuperH SCIF device driver.
|
||||
* Copyright (C) 2013 Renesas Electronics Corporation
|
||||
* Copyright (C) 2007,2008,2010, 2014 Nobuhiro Iwamatsu
|
||||
* Copyright (C) 2002 - 2008 Paul Mundt
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <errno.h>
|
||||
#include <dm.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/processor.h>
|
||||
#include <serial.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <dm/platform_data/serial_sh.h>
|
||||
#include "serial_sh.h"
|
||||
|
||||
#if defined(CONFIG_CPU_SH7760) || \
|
||||
defined(CONFIG_CPU_SH7780) || \
|
||||
defined(CONFIG_CPU_SH7785) || \
|
||||
defined(CONFIG_CPU_SH7786)
|
||||
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;
|
||||
}
|
||||
}
|
||||
#elif defined(CONFIG_ARCH_SH7372)
|
||||
static int scif_rxfill(struct uart_port *port)
|
||||
{
|
||||
if (port->type == PORT_SCIFA)
|
||||
return sci_in(port, SCFDR) & SCIF_RFDC_MASK;
|
||||
else
|
||||
return sci_in(port, SCRFDR);
|
||||
}
|
||||
#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);
|
||||
}
|
||||
|
||||
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);
|
||||
return status & (SCIF_DR | SCxSR_RDxF(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;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_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_platdata *plat = dev_get_platdata(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_platdata *plat = dev_get_platdata(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,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(serial_sh) = {
|
||||
.name = "serial_sh",
|
||||
.id = UCLASS_SERIAL,
|
||||
.probe = sh_serial_probe,
|
||||
.ops = &sh_serial_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
.priv_auto_alloc_size = 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
|
||||
#else
|
||||
# error "Default SCIF doesn't set....."
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SCIF_A)
|
||||
#define SCIF_BASE_PORT PORT_SCIFA
|
||||
#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 */
|
||||
778
u-boot/drivers/serial/serial_sh.h
Normal file
778
u-boot/drivers/serial/serial_sh.h
Normal file
@@ -0,0 +1,778 @@
|
||||
/*
|
||||
* 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_H83007) || defined(CONFIG_H83068)
|
||||
#include <asm/regs306x.h>
|
||||
#endif
|
||||
#if defined(CONFIG_H8S2678)
|
||||
#include <asm/regs267x.h>
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CPU_SH7706) || \
|
||||
defined(CONFIG_CPU_SH7707) || \
|
||||
defined(CONFIG_CPU_SH7708) || \
|
||||
defined(CONFIG_CPU_SH7709)
|
||||
# define SCPCR 0xA4000116 /* 16 bit SCI and SCIF */
|
||||
# define SCPDR 0xA4000136 /* 8 bit SCI and SCIF */
|
||||
# define SCSCR_INIT(port) 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */
|
||||
#elif defined(CONFIG_CPU_SH7705)
|
||||
# define SCIF0 0xA4400000
|
||||
# define SCIF2 0xA4410000
|
||||
# define SCSMR_Ir 0xA44A0000
|
||||
# define IRDA_SCIF SCIF0
|
||||
# define SCPCR 0xA4000116
|
||||
# define SCPDR 0xA4000136
|
||||
|
||||
/* Set the clock source,
|
||||
* SCIF2 (0xA4410000) -> External clock, SCK pin used as clock input
|
||||
* SCIF0 (0xA4400000) -> Internal clock, SCK pin as serial clock output
|
||||
*/
|
||||
# define SCSCR_INIT(port) (port->mapbase == SCIF2) ? 0xF3 : 0xF0
|
||||
#elif defined(CONFIG_CPU_SH7720) || \
|
||||
defined(CONFIG_CPU_SH7721) || \
|
||||
defined(CONFIG_ARCH_SH7367) || \
|
||||
defined(CONFIG_ARCH_SH7377) || \
|
||||
defined(CONFIG_ARCH_SH7372) || \
|
||||
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_SH_RTS7751R2D)
|
||||
# define SCSPTR1 0xFFE0001C /* 8 bit SCIF */
|
||||
# define SCSPTR2 0xFFE80020 /* 16 bit SCIF */
|
||||
# define SCIF_ORER 0x0001 /* overrun error bit */
|
||||
# define SCSCR_INIT(port) 0x3a /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
|
||||
#elif defined(CONFIG_CPU_SH7750) || \
|
||||
defined(CONFIG_CPU_SH7750R) || \
|
||||
defined(CONFIG_CPU_SH7750S) || \
|
||||
defined(CONFIG_CPU_SH7091) || \
|
||||
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_SH7760)
|
||||
# define SCSPTR0 0xfe600024 /* 16 bit SCIF */
|
||||
# define SCSPTR1 0xfe610024 /* 16 bit SCIF */
|
||||
# define SCSPTR2 0xfe620024 /* 16 bit SCIF */
|
||||
# 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_SH7710) || defined(CONFIG_CPU_SH7712)
|
||||
# define SCSPTR0 0xA4400000 /* 16 bit SCIF */
|
||||
# define SCIF_ORER 0x0001 /* overrun error bit */
|
||||
# define PACR 0xa4050100
|
||||
# define PBCR 0xa4050102
|
||||
# define SCSCR_INIT(port) 0x3B
|
||||
#elif defined(CONFIG_CPU_SH7343)
|
||||
# define SCSPTR0 0xffe00010 /* 16 bit SCIF */
|
||||
# define SCSPTR1 0xffe10010 /* 16 bit SCIF */
|
||||
# define SCSPTR2 0xffe20010 /* 16 bit SCIF */
|
||||
# define SCSPTR3 0xffe30010 /* 16 bit SCIF */
|
||||
# define SCSCR_INIT(port) 0x32 /* TIE=0,RIE=0,TE=1,RE=1,REIE=0,CKE=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_SH7366)
|
||||
# define SCPDR0 0xA405013E /* 16 bit SCIF0 PSDR */
|
||||
# define SCSPTR0 SCPDR0
|
||||
# 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_SH7724)
|
||||
# define SCIF_ORER 0x0001 /* overrun error bit */
|
||||
# define SCSCR_INIT(port) ((port)->type == PORT_SCIFA ? \
|
||||
0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ : \
|
||||
0x38 /* 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_SH4_202)
|
||||
# define SCSPTR2 0xffe80020 /* 16 bit SCIF */
|
||||
# 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_SH5_101) || defined(CONFIG_CPU_SH5_103)
|
||||
# define SCIF_BASE_ADDR 0x01030000
|
||||
# define SCIF_ADDR_SH5 (PHYS_PERIPHERAL_BLOCK+SCIF_BASE_ADDR)
|
||||
# define SCIF_PTR2_OFFS 0x0000020
|
||||
# define SCIF_LSR2_OFFS 0x0000024
|
||||
# define SCSPTR\
|
||||
((port->mapbase)+SCIF_PTR2_OFFS) /* 16 bit SCIF */
|
||||
# define SCLSR2\
|
||||
((port->mapbase)+SCIF_LSR2_OFFS) /* 16 bit SCIF */
|
||||
# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0, TE=1,RE=1,REIE=1 */
|
||||
#elif defined(CONFIG_H83007) || defined(CONFIG_H83068)
|
||||
# define SCSCR_INIT(port) 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */
|
||||
# define H8300_SCI_DR(ch) (*(volatile char *)(P1DR + h8300_sci_pins[ch].port))
|
||||
#elif defined(CONFIG_H8S2678)
|
||||
# define SCSCR_INIT(port) 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */
|
||||
# define H8300_SCI_DR(ch) (*(volatile char *)(P1DR + h8300_sci_pins[ch].port))
|
||||
#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_SH7770)
|
||||
# define SCSPTR0 0xff923020 /* 16 bit SCIF */
|
||||
# define SCSPTR1 0xff924020 /* 16 bit SCIF */
|
||||
# define SCSPTR2 0xff925020 /* 16 bit SCIF */
|
||||
# define SCIF_ORER 0x0001 /* overrun error bit */
|
||||
# define SCSCR_INIT(port) 0x3c /* TIE=0,RIE=0,TE=1,RE=1,REIE=1,cke=2 */
|
||||
#elif defined(CONFIG_CPU_SH7780)
|
||||
# define SCSPTR0 0xffe00024 /* 16 bit SCIF */
|
||||
# define SCSPTR1 0xffe10024 /* 16 bit SCIF */
|
||||
# define SCIF_ORER 0x0001 /* Overrun error bit */
|
||||
|
||||
#if defined(CONFIG_SH_SH2007)
|
||||
/* TIE=0,RIE=0,TE=1,RE=1,REIE=1,CKE1=0 */
|
||||
# define SCSCR_INIT(port) 0x38
|
||||
#else
|
||||
/* TIE=0,RIE=0,TE=1,RE=1,REIE=1,CKE1=1 */
|
||||
# define SCSCR_INIT(port) 0x3a
|
||||
#endif
|
||||
|
||||
#elif defined(CONFIG_CPU_SH7785) || \
|
||||
defined(CONFIG_CPU_SH7786)
|
||||
# define SCSPTR0 0xffea0024 /* 16 bit SCIF */
|
||||
# define SCSPTR1 0xffeb0024 /* 16 bit SCIF */
|
||||
# define SCSPTR2 0xffec0024 /* 16 bit SCIF */
|
||||
# define SCSPTR3 0xffed0024 /* 16 bit SCIF */
|
||||
# define SCSPTR4 0xffee0024 /* 16 bit SCIF */
|
||||
# define SCSPTR5 0xffef0024 /* 16 bit SCIF */
|
||||
# define SCIF_ORER 0x0001 /* Overrun error bit */
|
||||
# define SCSCR_INIT(port) 0x3a /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
|
||||
#elif defined(CONFIG_CPU_SH7201) || \
|
||||
defined(CONFIG_CPU_SH7203) || \
|
||||
defined(CONFIG_CPU_SH7206) || \
|
||||
defined(CONFIG_CPU_SH7263) || \
|
||||
defined(CONFIG_CPU_SH7264)
|
||||
# define SCSPTR0 0xfffe8020 /* 16 bit SCIF */
|
||||
# define SCSPTR1 0xfffe8820 /* 16 bit SCIF */
|
||||
# define SCSPTR2 0xfffe9020 /* 16 bit SCIF */
|
||||
# define SCSPTR3 0xfffe9820 /* 16 bit SCIF */
|
||||
# if defined(CONFIG_CPU_SH7201)
|
||||
# define SCSPTR4 0xfffeA020 /* 16 bit SCIF */
|
||||
# define SCSPTR5 0xfffeA820 /* 16 bit SCIF */
|
||||
# define SCSPTR6 0xfffeB020 /* 16 bit SCIF */
|
||||
# define SCSPTR7 0xfffeB820 /* 16 bit SCIF */
|
||||
# endif
|
||||
# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
|
||||
#elif defined(CONFIG_CPU_SH7269)
|
||||
# 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 */
|
||||
#elif defined(CONFIG_CPU_SH7619)
|
||||
# define SCSPTR0 0xf8400020 /* 16 bit SCIF */
|
||||
# define SCSPTR1 0xf8410020 /* 16 bit SCIF */
|
||||
# define SCSPTR2 0xf8420020 /* 16 bit SCIF */
|
||||
# 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_SHX3)
|
||||
# define SCSPTR0 0xffc30020 /* 16 bit SCIF */
|
||||
# define SCSPTR1 0xffc40020 /* 16 bit SCIF */
|
||||
# define SCSPTR2 0xffc50020 /* 16 bit SCIF */
|
||||
# define SCSPTR3 0xffc60020 /* 16 bit SCIF */
|
||||
# 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_R8A7790) || defined(CONFIG_R8A7791) || \
|
||||
defined(CONFIG_R8A7793) || defined(CONFIG_R8A7794)
|
||||
# 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_SH7091) || \
|
||||
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) || \
|
||||
defined(CONFIG_CPU_SH7785) || \
|
||||
defined(CONFIG_CPU_SH7786) || \
|
||||
defined(CONFIG_CPU_SHX3)
|
||||
#define SCI_CTRL_FLAGS_REIE 0x08 /* 7750 SCIF */
|
||||
#elif defined(CONFIG_CPU_SH7724)
|
||||
#define SCI_CTRL_FLAGS_REIE ((port)->type == PORT_SCIFA ? 0 : 8)
|
||||
#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_SH7705) || \
|
||||
defined(CONFIG_CPU_SH7720) || \
|
||||
defined(CONFIG_CPU_SH7721) || \
|
||||
defined(CONFIG_ARCH_SH7367) || \
|
||||
defined(CONFIG_ARCH_SH7377) || \
|
||||
defined(CONFIG_ARCH_SH7372) || \
|
||||
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_R8A7790) || defined(CONFIG_R8A7791) || \
|
||||
defined(CONFIG_R8A7793) || defined(CONFIG_R8A7794)
|
||||
# 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_SH7705) || \
|
||||
defined(CONFIG_CPU_SH7720) || \
|
||||
defined(CONFIG_CPU_SH7721) || \
|
||||
defined(CONFIG_ARCH_SH7367) || \
|
||||
defined(CONFIG_ARCH_SH7377) || \
|
||||
defined(CONFIG_ARCH_SH7372) || \
|
||||
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);\
|
||||
}\
|
||||
}
|
||||
|
||||
#ifdef CONFIG_H8300
|
||||
/* h8300 don't have SCIF */
|
||||
#define CPU_SCIF_FNS(name) \
|
||||
static inline unsigned int sci_##name##_in(struct uart_port *port) {\
|
||||
return 0;\
|
||||
}\
|
||||
static inline void sci_##name##_out(struct uart_port *port,\
|
||||
unsigned int value) {\
|
||||
}
|
||||
#else
|
||||
#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);\
|
||||
}
|
||||
#endif
|
||||
|
||||
#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_CPU_SH3) || \
|
||||
defined(CONFIG_ARCH_SH7367) || \
|
||||
defined(CONFIG_ARCH_SH7377) || \
|
||||
defined(CONFIG_ARCH_SH7372) || \
|
||||
defined(CONFIG_SH73A0) || \
|
||||
defined(CONFIG_R8A7740)
|
||||
#if defined(CONFIG_CPU_SH7710) || defined(CONFIG_CPU_SH7712)
|
||||
#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)
|
||||
#elif defined(CONFIG_CPU_SH7705) || \
|
||||
defined(CONFIG_CPU_SH7720) || \
|
||||
defined(CONFIG_CPU_SH7721) || \
|
||||
defined(CONFIG_ARCH_SH7367) || \
|
||||
defined(CONFIG_ARCH_SH7377) || \
|
||||
defined(CONFIG_SH73A0)
|
||||
#define SCIF_FNS(name, scif_offset, scif_size) \
|
||||
CPU_SCIF_FNS(name, scif_offset, scif_size)
|
||||
#elif defined(CONFIG_ARCH_SH7372) || \
|
||||
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(__H8300H__) || defined(__H8300S__)
|
||||
#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_SCI_FNS(name, h8_sci_offset, h8_sci_size)
|
||||
#define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size,\
|
||||
sh4_scif_offset, sh4_scif_size) \
|
||||
CPU_SCIF_FNS(name)
|
||||
#elif defined(CONFIG_CPU_SH7723) || defined(CONFIG_CPU_SH7724)
|
||||
#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_SH7705) || \
|
||||
defined(CONFIG_CPU_SH7720) || \
|
||||
defined(CONFIG_CPU_SH7721) || \
|
||||
defined(CONFIG_ARCH_SH7367) || \
|
||||
defined(CONFIG_ARCH_SH7377) || \
|
||||
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_ARCH_SH7372) || \
|
||||
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) ||\
|
||||
defined(CONFIG_CPU_SH7724)
|
||||
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_R8A7790) || defined(CONFIG_R8A7791) || \
|
||||
defined(CONFIG_R8A7793) || defined(CONFIG_R8A7794)
|
||||
/* 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_SH7760) || \
|
||||
defined(CONFIG_CPU_SH7780) || \
|
||||
defined(CONFIG_CPU_SH7785) || \
|
||||
defined(CONFIG_CPU_SH7786)
|
||||
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)
|
||||
|
||||
/* H8/300 series SCI pins assignment */
|
||||
#if defined(__H8300H__) || defined(__H8300S__)
|
||||
static const struct __attribute__((packed)) {
|
||||
int port; /* GPIO port no */
|
||||
unsigned short rx, tx; /* GPIO bit no */
|
||||
} h8300_sci_pins[] = {
|
||||
#if defined(CONFIG_H83007) || defined(CONFIG_H83068)
|
||||
{ /* SCI0 */
|
||||
.port = H8300_GPIO_P9,
|
||||
.rx = H8300_GPIO_B2,
|
||||
.tx = H8300_GPIO_B0,
|
||||
},
|
||||
{ /* SCI1 */
|
||||
.port = H8300_GPIO_P9,
|
||||
.rx = H8300_GPIO_B3,
|
||||
.tx = H8300_GPIO_B1,
|
||||
},
|
||||
{ /* SCI2 */
|
||||
.port = H8300_GPIO_PB,
|
||||
.rx = H8300_GPIO_B7,
|
||||
.tx = H8300_GPIO_B6,
|
||||
}
|
||||
#elif defined(CONFIG_H8S2678)
|
||||
{ /* SCI0 */
|
||||
.port = H8300_GPIO_P3,
|
||||
.rx = H8300_GPIO_B2,
|
||||
.tx = H8300_GPIO_B0,
|
||||
},
|
||||
{ /* SCI1 */
|
||||
.port = H8300_GPIO_P3,
|
||||
.rx = H8300_GPIO_B3,
|
||||
.tx = H8300_GPIO_B1,
|
||||
},
|
||||
{ /* SCI2 */
|
||||
.port = H8300_GPIO_P5,
|
||||
.rx = H8300_GPIO_B1,
|
||||
.tx = H8300_GPIO_B0,
|
||||
}
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CPU_SH7706) || \
|
||||
defined(CONFIG_CPU_SH7707) || \
|
||||
defined(CONFIG_CPU_SH7708) || \
|
||||
defined(CONFIG_CPU_SH7709)
|
||||
static inline int sci_rxd_in(struct uart_port *port)
|
||||
{
|
||||
if (port->mapbase == 0xfffffe80)
|
||||
return __raw_readb(SCPDR)&0x01 ? 1 : 0; /* SCI */
|
||||
return 1;
|
||||
}
|
||||
#elif defined(CONFIG_CPU_SH7750) || \
|
||||
defined(CONFIG_CPU_SH7751) || \
|
||||
defined(CONFIG_CPU_SH7751R) || \
|
||||
defined(CONFIG_CPU_SH7750R) || \
|
||||
defined(CONFIG_CPU_SH7750S) || \
|
||||
defined(CONFIG_CPU_SH7091)
|
||||
static inline int sci_rxd_in(struct uart_port *port)
|
||||
{
|
||||
if (port->mapbase == 0xffe00000)
|
||||
return __raw_readb(SCSPTR1)&0x01 ? 1 : 0; /* SCI */
|
||||
return 1;
|
||||
}
|
||||
#elif defined(__H8300H__) || defined(__H8300S__)
|
||||
static inline int sci_rxd_in(struct uart_port *port)
|
||||
{
|
||||
int ch = (port->mapbase - SMR0) >> 3;
|
||||
return (H8300_SCI_DR(ch) & h8300_sci_pins[ch].rx) ? 1 : 0;
|
||||
}
|
||||
#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) || \
|
||||
defined(CONFIG_CPU_SH7785) || \
|
||||
defined(CONFIG_CPU_SH7786)) && \
|
||||
!defined(CONFIG_SH_SH2007)
|
||||
#define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(16*bps)-1)
|
||||
#elif defined(CONFIG_CPU_SH7705) || \
|
||||
defined(CONFIG_CPU_SH7720) || \
|
||||
defined(CONFIG_CPU_SH7721) || \
|
||||
defined(CONFIG_ARCH_SH7367) || \
|
||||
defined(CONFIG_ARCH_SH7377) || \
|
||||
defined(CONFIG_ARCH_SH7372) || \
|
||||
defined(CONFIG_SH73A0) || \
|
||||
defined(CONFIG_R8A7740)
|
||||
#define SCBRR_VALUE(bps, clk) (((clk*2)+16*bps)/(32*bps)-1)
|
||||
#elif defined(CONFIG_CPU_SH7723) ||\
|
||||
defined(CONFIG_CPU_SH7724)
|
||||
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(__H8300H__) || defined(__H8300S__)
|
||||
#define SCBRR_VALUE(bps, clk) (((clk*1000/32)/bps)-1)
|
||||
#elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) || \
|
||||
defined(CONFIG_R8A7793) || defined(CONFIG_R8A7794)
|
||||
#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
|
||||
117
u-boot/drivers/serial/serial_stm32.c
Normal file
117
u-boot/drivers/serial/serial_stm32.c
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* (C) Copyright 2015
|
||||
* Kamil Lulko, <kamil.lulko@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <asm/io.h>
|
||||
#include <serial.h>
|
||||
#include <asm/arch/stm32.h>
|
||||
#include <dm/platform_data/serial_stm32.h>
|
||||
|
||||
struct stm32_usart {
|
||||
u32 sr;
|
||||
u32 dr;
|
||||
u32 brr;
|
||||
u32 cr1;
|
||||
u32 cr2;
|
||||
u32 cr3;
|
||||
u32 gtpr;
|
||||
};
|
||||
|
||||
#define USART_CR1_RE (1 << 2)
|
||||
#define USART_CR1_TE (1 << 3)
|
||||
#define USART_CR1_UE (1 << 13)
|
||||
|
||||
#define USART_SR_FLAG_RXNE (1 << 5)
|
||||
#define USART_SR_FLAG_TXE (1 << 7)
|
||||
|
||||
#define USART_BRR_F_MASK 0xF
|
||||
#define USART_BRR_M_SHIFT 4
|
||||
#define USART_BRR_M_MASK 0xFFF0
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
static int stm32_serial_setbrg(struct udevice *dev, int baudrate)
|
||||
{
|
||||
struct stm32_serial_platdata *plat = dev->platdata;
|
||||
struct stm32_usart *const usart = plat->base;
|
||||
u32 clock, int_div, frac_div, tmp;
|
||||
|
||||
if (((u32)usart & STM32_BUS_MASK) == STM32_APB1PERIPH_BASE)
|
||||
clock = clock_get(CLOCK_APB1);
|
||||
else if (((u32)usart & STM32_BUS_MASK) == STM32_APB2PERIPH_BASE)
|
||||
clock = clock_get(CLOCK_APB2);
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
int_div = (25 * clock) / (4 * baudrate);
|
||||
tmp = ((int_div / 100) << USART_BRR_M_SHIFT) & USART_BRR_M_MASK;
|
||||
frac_div = int_div - (100 * (tmp >> USART_BRR_M_SHIFT));
|
||||
tmp |= (((frac_div * 16) + 50) / 100) & USART_BRR_F_MASK;
|
||||
writel(tmp, &usart->brr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stm32_serial_getc(struct udevice *dev)
|
||||
{
|
||||
struct stm32_serial_platdata *plat = dev->platdata;
|
||||
struct stm32_usart *const usart = plat->base;
|
||||
|
||||
if ((readl(&usart->sr) & USART_SR_FLAG_RXNE) == 0)
|
||||
return -EAGAIN;
|
||||
|
||||
return readl(&usart->dr);
|
||||
}
|
||||
|
||||
static int stm32_serial_putc(struct udevice *dev, const char c)
|
||||
{
|
||||
struct stm32_serial_platdata *plat = dev->platdata;
|
||||
struct stm32_usart *const usart = plat->base;
|
||||
|
||||
if ((readl(&usart->sr) & USART_SR_FLAG_TXE) == 0)
|
||||
return -EAGAIN;
|
||||
|
||||
writel(c, &usart->dr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stm32_serial_pending(struct udevice *dev, bool input)
|
||||
{
|
||||
struct stm32_serial_platdata *plat = dev->platdata;
|
||||
struct stm32_usart *const usart = plat->base;
|
||||
|
||||
if (input)
|
||||
return readl(&usart->sr) & USART_SR_FLAG_RXNE ? 1 : 0;
|
||||
else
|
||||
return readl(&usart->sr) & USART_SR_FLAG_TXE ? 0 : 1;
|
||||
}
|
||||
|
||||
static int stm32_serial_probe(struct udevice *dev)
|
||||
{
|
||||
struct stm32_serial_platdata *plat = dev->platdata;
|
||||
struct stm32_usart *const usart = plat->base;
|
||||
setbits_le32(&usart->cr1, USART_CR1_RE | USART_CR1_TE | USART_CR1_UE);
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(serial_stm32) = {
|
||||
.name = "serial_stm32",
|
||||
.id = UCLASS_SERIAL,
|
||||
.ops = &stm32_serial_ops,
|
||||
.probe = stm32_serial_probe,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
83
u-boot/drivers/serial/serial_stm32x7.c
Normal file
83
u-boot/drivers/serial/serial_stm32x7.c
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* (C) Copyright 2016
|
||||
* Vikas Manocha, <vikas.manocha@st.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <asm/io.h>
|
||||
#include <serial.h>
|
||||
#include <dm/platform_data/serial_stm32x7.h>
|
||||
#include "serial_stm32x7.h"
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
static int stm32_serial_setbrg(struct udevice *dev, int baudrate)
|
||||
{
|
||||
struct stm32x7_serial_platdata *plat = dev->platdata;
|
||||
struct stm32_usart *const usart = plat->base;
|
||||
writel(plat->clock/baudrate, &usart->brr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stm32_serial_getc(struct udevice *dev)
|
||||
{
|
||||
struct stm32x7_serial_platdata *plat = dev->platdata;
|
||||
struct stm32_usart *const usart = plat->base;
|
||||
|
||||
if ((readl(&usart->sr) & USART_SR_FLAG_RXNE) == 0)
|
||||
return -EAGAIN;
|
||||
|
||||
return readl(&usart->rd_dr);
|
||||
}
|
||||
|
||||
static int stm32_serial_putc(struct udevice *dev, const char c)
|
||||
{
|
||||
struct stm32x7_serial_platdata *plat = dev->platdata;
|
||||
struct stm32_usart *const usart = plat->base;
|
||||
|
||||
if ((readl(&usart->sr) & USART_SR_FLAG_TXE) == 0)
|
||||
return -EAGAIN;
|
||||
|
||||
writel(c, &usart->tx_dr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stm32_serial_pending(struct udevice *dev, bool input)
|
||||
{
|
||||
struct stm32x7_serial_platdata *plat = dev->platdata;
|
||||
struct stm32_usart *const usart = plat->base;
|
||||
|
||||
if (input)
|
||||
return readl(&usart->sr) & USART_SR_FLAG_RXNE ? 1 : 0;
|
||||
else
|
||||
return readl(&usart->sr) & USART_SR_FLAG_TXE ? 0 : 1;
|
||||
}
|
||||
|
||||
static int stm32_serial_probe(struct udevice *dev)
|
||||
{
|
||||
struct stm32x7_serial_platdata *plat = dev->platdata;
|
||||
struct stm32_usart *const usart = plat->base;
|
||||
setbits_le32(&usart->cr1, USART_CR1_RE | USART_CR1_TE | USART_CR1_UE);
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(serial_stm32) = {
|
||||
.name = "serial_stm32x7",
|
||||
.id = UCLASS_SERIAL,
|
||||
.ops = &stm32_serial_ops,
|
||||
.probe = stm32_serial_probe,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
37
u-boot/drivers/serial/serial_stm32x7.h
Normal file
37
u-boot/drivers/serial/serial_stm32x7.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* (C) Copyright 2016
|
||||
* Vikas Manocha, <vikas.manocha@st.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _SERIAL_STM32_X7_
|
||||
#define _SERIAL_STM32_X7_
|
||||
|
||||
struct stm32_usart {
|
||||
u32 cr1;
|
||||
u32 cr2;
|
||||
u32 cr3;
|
||||
u32 brr;
|
||||
u32 gtpr;
|
||||
u32 rtor;
|
||||
u32 rqr;
|
||||
u32 sr;
|
||||
u32 icr;
|
||||
u32 rd_dr;
|
||||
u32 tx_dr;
|
||||
};
|
||||
|
||||
|
||||
#define USART_CR1_RE (1 << 2)
|
||||
#define USART_CR1_TE (1 << 3)
|
||||
#define USART_CR1_UE (1 << 0)
|
||||
|
||||
#define USART_SR_FLAG_RXNE (1 << 5)
|
||||
#define USART_SR_FLAG_TXE (1 << 7)
|
||||
|
||||
#define USART_BRR_F_MASK 0xFF
|
||||
#define USART_BRR_M_SHIFT 4
|
||||
#define USART_BRR_M_MASK 0xFFF0
|
||||
|
||||
#endif
|
||||
145
u-boot/drivers/serial/serial_uniphier.c
Normal file
145
u-boot/drivers/serial/serial_uniphier.c
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2015 Masahiro Yamada <yamada.masahiro@socionext.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/serial_reg.h>
|
||||
#include <linux/sizes.h>
|
||||
#include <asm/errno.h>
|
||||
#include <dm/device.h>
|
||||
#include <mapmem.h>
|
||||
#include <serial.h>
|
||||
#include <fdtdec.h>
|
||||
|
||||
/*
|
||||
* Note: Register map is slightly different from that of 16550.
|
||||
*/
|
||||
struct uniphier_serial {
|
||||
u32 rx; /* In: Receive buffer */
|
||||
#define tx rx /* Out: Transmit buffer */
|
||||
u32 ier; /* Interrupt Enable Register */
|
||||
u32 iir; /* In: Interrupt ID Register */
|
||||
u32 char_fcr; /* Charactor / FIFO Control Register */
|
||||
u32 lcr_mcr; /* Line/Modem Control Register */
|
||||
#define LCR_SHIFT 8
|
||||
#define LCR_MASK (0xff << (LCR_SHIFT))
|
||||
u32 lsr; /* In: Line Status Register */
|
||||
u32 msr; /* In: Modem Status Register */
|
||||
u32 __rsv0;
|
||||
u32 __rsv1;
|
||||
u32 dlr; /* Divisor Latch Register */
|
||||
};
|
||||
|
||||
struct uniphier_serial_private_data {
|
||||
struct uniphier_serial __iomem *membase;
|
||||
unsigned int uartclk;
|
||||
};
|
||||
|
||||
#define uniphier_serial_port(dev) \
|
||||
((struct uniphier_serial_private_data *)dev_get_priv(dev))->membase
|
||||
|
||||
static int uniphier_serial_setbrg(struct udevice *dev, int baudrate)
|
||||
{
|
||||
struct uniphier_serial_private_data *priv = dev_get_priv(dev);
|
||||
struct uniphier_serial __iomem *port = uniphier_serial_port(dev);
|
||||
const unsigned int mode_x_div = 16;
|
||||
unsigned int divisor;
|
||||
|
||||
divisor = DIV_ROUND_CLOSEST(priv->uartclk, mode_x_div * baudrate);
|
||||
|
||||
writel(divisor, &port->dlr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uniphier_serial_getc(struct udevice *dev)
|
||||
{
|
||||
struct uniphier_serial __iomem *port = uniphier_serial_port(dev);
|
||||
|
||||
if (!(readl(&port->lsr) & UART_LSR_DR))
|
||||
return -EAGAIN;
|
||||
|
||||
return readl(&port->rx);
|
||||
}
|
||||
|
||||
static int uniphier_serial_putc(struct udevice *dev, const char c)
|
||||
{
|
||||
struct uniphier_serial __iomem *port = uniphier_serial_port(dev);
|
||||
|
||||
if (!(readl(&port->lsr) & UART_LSR_THRE))
|
||||
return -EAGAIN;
|
||||
|
||||
writel(c, &port->tx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uniphier_serial_pending(struct udevice *dev, bool input)
|
||||
{
|
||||
struct uniphier_serial __iomem *port = uniphier_serial_port(dev);
|
||||
|
||||
if (input)
|
||||
return readl(&port->lsr) & UART_LSR_DR;
|
||||
else
|
||||
return !(readl(&port->lsr) & UART_LSR_THRE);
|
||||
}
|
||||
|
||||
static int uniphier_serial_probe(struct udevice *dev)
|
||||
{
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
struct uniphier_serial_private_data *priv = dev_get_priv(dev);
|
||||
struct uniphier_serial __iomem *port;
|
||||
fdt_addr_t base;
|
||||
u32 tmp;
|
||||
|
||||
base = dev_get_addr(dev);
|
||||
if (base == FDT_ADDR_T_NONE)
|
||||
return -EINVAL;
|
||||
|
||||
port = map_sysmem(base, SZ_64);
|
||||
if (!port)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->membase = port;
|
||||
|
||||
priv->uartclk = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
|
||||
"clock-frequency", 0);
|
||||
|
||||
tmp = readl(&port->lcr_mcr);
|
||||
tmp &= ~LCR_MASK;
|
||||
tmp |= UART_LCR_WLEN8 << LCR_SHIFT;
|
||||
writel(tmp, &port->lcr_mcr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uniphier_serial_remove(struct udevice *dev)
|
||||
{
|
||||
unmap_sysmem(uniphier_serial_port(dev));
|
||||
|
||||
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,
|
||||
.remove = uniphier_serial_remove,
|
||||
.priv_auto_alloc_size = sizeof(struct uniphier_serial_private_data),
|
||||
.ops = &uniphier_serial_ops,
|
||||
};
|
||||
142
u-boot/drivers/serial/serial_xuartlite.c
Normal file
142
u-boot/drivers/serial/serial_xuartlite.c
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* (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>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <serial.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#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
|
||||
|
||||
struct uartlite {
|
||||
unsigned int rx_fifo;
|
||||
unsigned int tx_fifo;
|
||||
unsigned int status;
|
||||
unsigned int control;
|
||||
};
|
||||
|
||||
struct uartlite_platdata {
|
||||
struct uartlite *regs;
|
||||
};
|
||||
|
||||
static int uartlite_serial_putc(struct udevice *dev, const char ch)
|
||||
{
|
||||
struct uartlite_platdata *plat = dev_get_platdata(dev);
|
||||
struct uartlite *regs = plat->regs;
|
||||
|
||||
if (in_be32(®s->status) & SR_TX_FIFO_FULL)
|
||||
return -EAGAIN;
|
||||
|
||||
out_be32(®s->tx_fifo, ch & 0xff);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uartlite_serial_getc(struct udevice *dev)
|
||||
{
|
||||
struct uartlite_platdata *plat = dev_get_platdata(dev);
|
||||
struct uartlite *regs = plat->regs;
|
||||
|
||||
if (!(in_be32(®s->status) & SR_RX_FIFO_VALID_DATA))
|
||||
return -EAGAIN;
|
||||
|
||||
return in_be32(®s->rx_fifo) & 0xff;
|
||||
}
|
||||
|
||||
static int uartlite_serial_pending(struct udevice *dev, bool input)
|
||||
{
|
||||
struct uartlite_platdata *plat = dev_get_platdata(dev);
|
||||
struct uartlite *regs = plat->regs;
|
||||
|
||||
if (input)
|
||||
return in_be32(®s->status) & SR_RX_FIFO_VALID_DATA;
|
||||
|
||||
return !(in_be32(®s->status) & SR_TX_FIFO_EMPTY);
|
||||
}
|
||||
|
||||
static int uartlite_serial_probe(struct udevice *dev)
|
||||
{
|
||||
struct uartlite_platdata *plat = dev_get_platdata(dev);
|
||||
struct uartlite *regs = plat->regs;
|
||||
|
||||
out_be32(®s->control, 0);
|
||||
out_be32(®s->control, ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX);
|
||||
in_be32(®s->control);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uartlite_serial_ofdata_to_platdata(struct udevice *dev)
|
||||
{
|
||||
struct uartlite_platdata *plat = dev_get_platdata(dev);
|
||||
|
||||
plat->regs = (struct uartlite *)dev_get_addr(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,
|
||||
.ofdata_to_platdata = uartlite_serial_ofdata_to_platdata,
|
||||
.platdata_auto_alloc_size = sizeof(struct uartlite_platdata),
|
||||
.probe = uartlite_serial_probe,
|
||||
.ops = &uartlite_serial_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
|
||||
#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;
|
||||
|
||||
out_be32(®s->control, 0);
|
||||
out_be32(®s->control, ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX);
|
||||
in_be32(®s->control);
|
||||
}
|
||||
|
||||
static inline void _debug_uart_putc(int ch)
|
||||
{
|
||||
struct uartlite *regs = (struct uartlite *)CONFIG_DEBUG_UART_BASE;
|
||||
|
||||
while (in_be32(®s->status) & SR_TX_FIFO_FULL)
|
||||
;
|
||||
|
||||
out_be32(®s->tx_fifo, ch & 0xff);
|
||||
}
|
||||
|
||||
DEBUG_UART_FUNCS
|
||||
#endif
|
||||
210
u-boot/drivers/serial/serial_zynq.c
Normal file
210
u-boot/drivers/serial/serial_zynq.c
Normal file
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Michal Simek <monstr@monstr.eu>
|
||||
* Copyright (C) 2011-2012 Xilinx, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <debug_uart.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <fdtdec.h>
|
||||
#include <watchdog.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <serial.h>
|
||||
#include <asm/arch/clk.h>
|
||||
#include <asm/arch/hardware.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#define ZYNQ_UART_SR_TXEMPTY (1 << 3) /* TX FIFO empty */
|
||||
#define ZYNQ_UART_SR_TXACTIVE (1 << 11) /* TX active */
|
||||
#define ZYNQ_UART_SR_RXEMPTY 0x00000002 /* RX FIFO empty */
|
||||
|
||||
#define ZYNQ_UART_CR_TX_EN 0x00000010 /* TX enabled */
|
||||
#define ZYNQ_UART_CR_RX_EN 0x00000004 /* RX enabled */
|
||||
#define ZYNQ_UART_CR_TXRST 0x00000002 /* TX logic reset */
|
||||
#define ZYNQ_UART_CR_RXRST 0x00000001 /* 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_priv {
|
||||
struct uart_zynq *regs;
|
||||
};
|
||||
|
||||
/* Set up the baud rate in gd struct */
|
||||
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, ®s->baud_rate_divider);
|
||||
writel(bgen, ®s->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, ®s->control);
|
||||
writel(ZYNQ_UART_MR_PARITY_NONE, ®s->mode); /* 8 bit, no parity */
|
||||
}
|
||||
|
||||
static int _uart_zynq_serial_putc(struct uart_zynq *regs, const char c)
|
||||
{
|
||||
if (!(readl(®s->channel_sts) & ZYNQ_UART_SR_TXEMPTY))
|
||||
return -EAGAIN;
|
||||
|
||||
writel(c, ®s->tx_rx_fifo);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int zynq_serial_setbrg(struct udevice *dev, int baudrate)
|
||||
{
|
||||
struct zynq_uart_priv *priv = dev_get_priv(dev);
|
||||
unsigned long clock = get_uart_clk(0);
|
||||
|
||||
_uart_zynq_serial_setbrg(priv->regs, clock, baudrate);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int zynq_serial_probe(struct udevice *dev)
|
||||
{
|
||||
struct zynq_uart_priv *priv = dev_get_priv(dev);
|
||||
|
||||
_uart_zynq_serial_init(priv->regs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int zynq_serial_getc(struct udevice *dev)
|
||||
{
|
||||
struct zynq_uart_priv *priv = dev_get_priv(dev);
|
||||
struct uart_zynq *regs = priv->regs;
|
||||
|
||||
if (readl(®s->channel_sts) & ZYNQ_UART_SR_RXEMPTY)
|
||||
return -EAGAIN;
|
||||
|
||||
return readl(®s->tx_rx_fifo);
|
||||
}
|
||||
|
||||
static int zynq_serial_putc(struct udevice *dev, const char ch)
|
||||
{
|
||||
struct zynq_uart_priv *priv = dev_get_priv(dev);
|
||||
|
||||
return _uart_zynq_serial_putc(priv->regs, ch);
|
||||
}
|
||||
|
||||
static int zynq_serial_pending(struct udevice *dev, bool input)
|
||||
{
|
||||
struct zynq_uart_priv *priv = dev_get_priv(dev);
|
||||
struct uart_zynq *regs = priv->regs;
|
||||
|
||||
if (input)
|
||||
return !(readl(®s->channel_sts) & ZYNQ_UART_SR_RXEMPTY);
|
||||
else
|
||||
return !!(readl(®s->channel_sts) & ZYNQ_UART_SR_TXACTIVE);
|
||||
}
|
||||
|
||||
static int zynq_serial_ofdata_to_platdata(struct udevice *dev)
|
||||
{
|
||||
struct zynq_uart_priv *priv = dev_get_priv(dev);
|
||||
|
||||
priv->regs = (struct uart_zynq *)dev_get_addr(dev);
|
||||
|
||||
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,
|
||||
.ofdata_to_platdata = zynq_serial_ofdata_to_platdata,
|
||||
.priv_auto_alloc_size = sizeof(struct zynq_uart_priv),
|
||||
.probe = zynq_serial_probe,
|
||||
.ops = &zynq_serial_ops,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
|
||||
#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
|
||||
1047
u-boot/drivers/serial/usbtty.c
Normal file
1047
u-boot/drivers/serial/usbtty.c
Normal file
File diff suppressed because it is too large
Load Diff
77
u-boot/drivers/serial/usbtty.h
Normal file
77
u-boot/drivers/serial/usbtty.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* (C) Copyright 2003
|
||||
* Gerry Hamel, geh@ti.com, Texas Instruments
|
||||
*
|
||||
* (C) Copyright 2006
|
||||
* Bryan O'Donoghue, bodonoghue@codehermit.ie, CodeHermit
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#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
|
||||
Reference in New Issue
Block a user