Merge patch series "xtensa: Enable qemu-xtensa board"

Jiaxun Yang <jiaxun.yang@flygoat.com> says:

Hi all,

This series enabled qemu-xtensa board.

For dc232b CPU it needs to be built with toolchain[1].

This is a side product of me investigating architectures
physical address != virtual address in U-Boot. Now we can
get it covered under CI and regular tests.

VirtIO devices are not working as expected, due to U-Boot's
assumption on VA == PA everywhere, I'm going to get this fixed
later.

My Xtensa knowledge is pretty limited, Xtensa people please
feel free to point out if I got anything wrong.

Thanks
[1]: https://github.com/foss-xtensa/toolchain/releases/download/2020.07/x86_64-2020.07-xtensa-dc232b-elf.tar.gz
This commit is contained in:
Tom Rini 2024-07-04 16:11:08 -06:00
commit 7c9c5c0562
29 changed files with 789 additions and 8 deletions

View file

@ -237,7 +237,7 @@ stages:
# the below corresponds to .gitlab-ci.yml "before_script"
cd \${WORK_DIR}
git config --global --add safe.directory \${WORK_DIR}
git clone --depth=1 https://source.denx.de/u-boot/u-boot-test-hooks /tmp/uboot-test-hooks
git clone --depth=1 https://github.com/FlyGoat/u-boot-test-hooks.git /tmp/uboot-test-hooks
ln -s travis-ci /tmp/uboot-test-hooks/bin/\`hostname\`
ln -s travis-ci /tmp/uboot-test-hooks/py/\`hostname\`
grub-mkimage --prefix=\"\" -o ~/grub_x86.efi -O i386-efi normal echo lsefimmap lsefi lsefisystab efinet tftp minicmd
@ -457,6 +457,9 @@ stages:
qemu_x86_64:
TEST_PY_BD: "qemu-x86_64"
TEST_PY_TEST_SPEC: "not sleep"
qemu_xtensa_dc233c:
TEST_PY_BD: "qemu-xtensa-dc233c"
TEST_PY_TEST_SPEC: "not sleep and not efi"
r2dplus_i82557c:
TEST_PY_BD: "r2dplus"
TEST_PY_ID: "--id i82557c_qemu"

View file

@ -422,6 +422,12 @@ qemu-x86_64 test.py:
TEST_PY_TEST_SPEC: "not sleep"
<<: *buildman_and_testpy_dfn
qemu-xtensa-dc233c test.py:
variables:
TEST_PY_BD: "qemu-xtensa-dc233c"
TEST_PY_TEST_SPEC: "not sleep and not efi"
<<: *buildman_and_testpy_dfn
r2dplus_i82557c test.py:
variables:
TEST_PY_BD: "r2dplus"

View file

@ -15,6 +15,10 @@ config TARGET_XTFPGA
bool "Support XTFPGA"
select BOARD_POSTCLK_INIT
config TARGET_QEMU_XTENSA
bool "Support QEMU Xtensa Virt Board"
select BOARD_LATE_INIT
endchoice
config SYS_ICACHE_OFF
@ -41,6 +45,34 @@ config SPL_SYS_DCACHE_OFF
help
Do not enable data cache in SPL.
config XTENSA_SEMIHOSTING
bool "Support semihosting"
help
Enable Xtensa semihosting debugging support.
choice
prompt "Semihosting interface"
default XTENSA_SIMCALL_ISS
depends on XTENSA_SEMIHOSTING
help
Choose semihosting interface that will be used for serial port,
block device and networking.
config XTENSA_SIMCALL_ISS
bool "simcall"
help
Use simcall instruction. simcall is only available on simulators,
it does nothing on hardware.
config XTENSA_SIMCALL_GDBIO
bool "GDBIO"
help
Use break instruction. It is available on real hardware when GDB
is attached to it via JTAG.
endchoice
source "board/cadence/xtfpga/Kconfig"
source "board/emulation/qemu-xtensa/Kconfig"
endmenu

View file

@ -7,3 +7,9 @@ PLATFORM_CPPFLAGS += -D__XTENSA__ -mlongcalls -mforce-no-pic \
-ffunction-sections -fdata-sections
LDFLAGS_FINAL += --gc-sections
ifeq ($(CONFIG_SYS_BIG_ENDIAN),y)
PLATFORM_CPPFLAGS += -B xtensa -O elf32-xtensa-be
else
PLATFORM_ELFFLAGS += -B xtensa -O elf32-xtensa-le
endif

View file

@ -48,8 +48,3 @@ int arch_cpu_init(void)
gd->ram_size = CFG_SYS_SDRAM_SIZE;
return 0;
}
int dram_init(void)
{
return 0;
}

View file

@ -82,6 +82,8 @@ SECTIONS
__reloc_end = .;
__init_end = .;
/* Calculation to get end address in ROM */
_end = LOADADDR(.data) + (_data_end - _data_start);
SECTION_bss(__init_end (OVERLAY),)

View file

@ -0,0 +1,17 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2024 Jiaxun Yang <jiaxun.yang@flygoat.com>
*/
#include <config.h>
/ {
memory@0 {
device_type = "memory";
#if XCHAL_HAVE_PTP_MMU
reg = <0x00000000 CFG_SYS_SDRAM_SIZE>;
#else
reg = <CFG_SYS_MEMORY_BASE CFG_SYS_SDRAM_SIZE>;
#endif
};
};

View file

@ -7,6 +7,8 @@
#ifndef _XTENSA_ADDRSPACE_H
#define _XTENSA_ADDRSPACE_H
#include <config.h>
#include <asm/arch/core.h>
/*

View file

@ -12,6 +12,8 @@
#include <linux/types.h>
#include <asm/byteorder.h>
#include <asm/addrspace.h>
/*
* swap functions to change byte order from little-endian to big-endian and
* vice versa.
@ -127,6 +129,36 @@ static inline void sync(void)
{
}
#if XCHAL_HAVE_PTP_MMU
static inline void *phys_to_virt(phys_addr_t paddr)
{
if (paddr >= CFG_SYS_IO_BASE)
return (void *)(unsigned long)paddr;
if (paddr < CFG_MAX_MEM_MAPPED)
return (void *)(unsigned long)MEMADDR(paddr);
return NULL;
}
#define phys_to_virt phys_to_virt
static inline phys_addr_t virt_to_phys(void *vaddr)
{
unsigned long addr = (unsigned long)vaddr;
if (addr >= CFG_SYS_IO_BASE)
return addr;
if (addr >= CFG_SYS_SDRAM_BASE && addr < MEMADDR(CFG_MAX_MEM_MAPPED))
return PHYSADDR(addr);
return 0;
}
#define virt_to_phys virt_to_phys
#endif /* XCHAL_HAVE_PTP_MMU */
#include <asm-generic/io.h>
#endif /* _XTENSA_IO_H */

View file

@ -165,7 +165,6 @@
. = ALIGN(8); \
_bss_end = ABSOLUTE(.); \
__bss_end = ABSOLUTE(.); \
_end = ALIGN(0x8); \
PROVIDE(end = ALIGN(0x8)); \
_stack_sentry = ALIGN(0x8); \
}

View file

@ -0,0 +1,34 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (C) 2021 Cadence Design Systems Inc. */
#ifndef _XTENSA_PLATFORM_ISS_SIMCALL_GDBIO_H
#define _XTENSA_PLATFORM_ISS_SIMCALL_GDBIO_H
/*
* System call like services offered by the GDBIO host.
*/
#define SYS_open -2
#define SYS_close -3
#define SYS_read -4
#define SYS_write -5
#define SYS_lseek -6
static int errno;
static inline int __simc(int a, int b, int c, int d)
{
register int a1 asm("a2") = a;
register int b1 asm("a6") = b;
register int c1 asm("a3") = c;
register int d1 asm("a4") = d;
__asm__ __volatile__ (
"break 1, 14\n"
: "+r"(a1), "+r"(c1)
: "r"(b1), "r"(d1)
: "memory");
errno = c1;
return a1;
}
#endif /* _XTENSA_PLATFORM_ISS_SIMCALL_GDBIO_H */

View file

@ -0,0 +1,73 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (C) 2021 Cadence Design Systems Inc. */
#ifndef _XTENSA_PLATFORM_ISS_SIMCALL_ISS_H
#define _XTENSA_PLATFORM_ISS_SIMCALL_ISS_H
/*
* System call like services offered by the simulator host.
*/
#define SYS_nop 0 /* unused */
#define SYS_exit 1 /*x*/
#define SYS_fork 2
#define SYS_read 3 /*x*/
#define SYS_write 4 /*x*/
#define SYS_open 5 /*x*/
#define SYS_close 6 /*x*/
#define SYS_rename 7 /*x 38 - waitpid */
#define SYS_creat 8 /*x*/
#define SYS_link 9 /*x (not implemented on WIN32) */
#define SYS_unlink 10 /*x*/
#define SYS_execv 11 /* n/a - execve */
#define SYS_execve 12 /* 11 - chdir */
#define SYS_pipe 13 /* 42 - time */
#define SYS_stat 14 /* 106 - mknod */
#define SYS_chmod 15
#define SYS_chown 16 /* 202 - lchown */
#define SYS_utime 17 /* 30 - break */
#define SYS_wait 18 /* n/a - oldstat */
#define SYS_lseek 19 /*x*/
#define SYS_getpid 20
#define SYS_isatty 21 /* n/a - mount */
#define SYS_fstat 22 /* 108 - oldumount */
#define SYS_time 23 /* 13 - setuid */
#define SYS_gettimeofday 24 /*x 78 - getuid (not implemented on WIN32) */
#define SYS_times 25 /*X 43 - stime (Xtensa-specific implementation) */
#define SYS_socket 26
#define SYS_sendto 27
#define SYS_recvfrom 28
#define SYS_select_one 29 /* not compatible select, one file descriptor at the time */
#define SYS_bind 30
#define SYS_ioctl 31
#define SYS_iss_argc 1000 /* returns value of argc */
#define SYS_iss_argv_size 1001 /* bytes needed for argv & arg strings */
#define SYS_iss_set_argv 1002 /* saves argv & arg strings at given addr */
/*
* SYS_select_one specifiers
*/
#define XTISS_SELECT_ONE_READ 1
#define XTISS_SELECT_ONE_WRITE 2
#define XTISS_SELECT_ONE_EXCEPT 3
static int errno;
static inline int __simc(int a, int b, int c, int d)
{
register int a1 asm("a2") = a;
register int b1 asm("a3") = b;
register int c1 asm("a4") = c;
register int d1 asm("a5") = d;
__asm__ __volatile__ (
"simcall\n"
: "+r"(a1), "+r"(b1)
: "r"(c1), "r"(d1)
: "memory");
errno = b1;
return a1;
}
#endif /* _XTENSA_PLATFORM_ISS_SIMCALL_ISS_H */

View file

@ -0,0 +1,110 @@
/*
* include/asm-xtensa/platform-iss/simcall.h
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2001 Tensilica Inc.
* Copyright (C) 2017 - 2021 Cadence Design Systems Inc.
*/
#ifndef _XTENSA_PLATFORM_ISS_SIMCALL_H
#define _XTENSA_PLATFORM_ISS_SIMCALL_H
#include <linux/bug.h>
#ifdef CONFIG_XTENSA_SIMCALL_ISS
#include <asm/platform/simcall-iss.h>
#endif
#ifdef CONFIG_XTENSA_SIMCALL_GDBIO
#include <asm/platform/simcall-gdbio.h>
#endif
static inline int simc_exit(int exit_code)
{
#ifdef SYS_exit
return __simc(SYS_exit, exit_code, 0, 0);
#else
WARN_ONCE(1, "%s: not implemented\n", __func__);
return -1;
#endif
}
static inline int simc_open(const char *file, int flags, int mode)
{
return __simc(SYS_open, (int) file, flags, mode);
}
static inline int simc_close(int fd)
{
return __simc(SYS_close, fd, 0, 0);
}
static inline int simc_ioctl(int fd, int request, void *arg)
{
#ifdef SYS_ioctl
return __simc(SYS_ioctl, fd, request, (int) arg);
#else
WARN_ONCE(1, "%s: not implemented\n", __func__);
return -1;
#endif
}
static inline int simc_read(int fd, void *buf, size_t count)
{
return __simc(SYS_read, fd, (int) buf, count);
}
static inline int simc_write(int fd, const void *buf, size_t count)
{
return __simc(SYS_write, fd, (int) buf, count);
}
static inline int simc_poll(int fd)
{
#ifdef SYS_select_one
long timeval[2] = { 0, 0 };
return __simc(SYS_select_one, fd, XTISS_SELECT_ONE_READ, (int)&timeval);
#else
WARN_ONCE(1, "%s: not implemented\n", __func__);
return -1;
#endif
}
static inline int simc_lseek(int fd, uint32_t off, int whence)
{
return __simc(SYS_lseek, fd, off, whence);
}
static inline int simc_argc(void)
{
#ifdef SYS_iss_argc
return __simc(SYS_iss_argc, 0, 0, 0);
#else
WARN_ONCE(1, "%s: not implemented\n", __func__);
return 0;
#endif
}
static inline int simc_argv_size(void)
{
#ifdef SYS_iss_argv_size
return __simc(SYS_iss_argv_size, 0, 0, 0);
#else
WARN_ONCE(1, "%s: not implemented\n", __func__);
return 0;
#endif
}
static inline void simc_argv(void *buf)
{
#ifdef SYS_iss_set_argv
__simc(SYS_iss_set_argv, (int)buf, 0, 0);
#else
WARN_ONCE(1, "%s: not implemented\n", __func__);
#endif
}
#endif /* _XTENSA_PLATFORM_ISS_SIMCALL_H */

View file

@ -66,6 +66,11 @@ unsigned long get_board_sys_clk(void)
#endif
}
int dram_init(void)
{
return 0;
}
int board_postclk_init(void)
{
gd->cpu_clk = get_board_sys_clk();

View file

@ -0,0 +1,43 @@
if TARGET_QEMU_XTENSA
config SYS_BOARD
default "qemu-xtensa"
config SYS_VENDOR
default "emulation"
config SYS_CONFIG_NAME
default "qemu-xtensa"
config TEXT_BASE
default 0x50000000 if (SYS_CPU = de212)
default 0xfe000000
config BOARD_SPECIFIC_OPTIONS # dummy
def_bool y
select BOARD_EARLY_INIT_F
select DM
select CPU
select CPU_XTENSA
select CLK
select DM_SERIAL
select XTENSA_SEMIHOSTING
select XTENSA_SEMIHOSTING_SERIAL
imply BLK
imply VIRTIO
imply VIRTIO_PCI
imply VIRTIO_NET
imply VIRTIO_BLK
imply E1000
imply PCI
imply PCI_INIT_R
imply NVME_PCI
imply PCIE_ECAM_GENERIC
imply SCSI
imply REMAKE_ELF
select OF_CONTROL
select OF_UPSTREAM
imply CMD_DM
imply CMD_PCI
endif

View file

@ -0,0 +1,8 @@
QEMU XTENSA 'VIRT' BOARD
M: Jiaxun Yang <jiaxun.yang@flygoat.com>
M: Max Filippov <jcmvbkbc@gmail.com>
S: Maintained
F: board/emulation/qemu-xtensa/
F: board/emulation/common/
F: include/configs/qemu-xtensa.h
F: configs/qemu-xtensa-dc233c_defconfig

View file

@ -0,0 +1,5 @@
# SPDX-License-Identifier: GPL-2.0+
#
# Copyright (C) 2024, Jiaxun Yang <jiaxun.yang@flygoat.com>
obj-y += qemu-xtensa.o

View file

@ -0,0 +1,60 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
*/
#include <dm.h>
#include <cpu.h>
#include <log.h>
#include <init.h>
#include <usb.h>
#include <virtio_types.h>
#include <virtio.h>
DECLARE_GLOBAL_DATA_PTR;
int board_init(void)
{
return 0;
}
unsigned long get_board_sys_clk(void)
{
return gd->cpu_clk ? gd->cpu_clk : 40000000;
}
int dram_init(void)
{
return fdtdec_setup_mem_size_base();
}
int board_early_init_f(void)
{
struct cpu_plat *cpu_plat;
struct udevice *cpu = cpu_get_current_dev();
if (!cpu)
return -ENODEV;
cpu_plat = dev_get_parent_plat(cpu);
if (!cpu_plat)
return -ENODEV;
gd->cpu_clk = cpu_plat->timebase_freq;
return 0;
}
int board_late_init(void)
{
/* start usb so that usb keyboard can be used as input device */
if (CONFIG_IS_ENABLED(USB_KEYBOARD))
usb_init();
/*
* Make sure virtio bus is enumerated so that peripherals
* on the virtio bus can be discovered by their drivers
*/
virtio_init();
return 0;
}

View file

@ -0,0 +1,32 @@
CONFIG_XTENSA=y
CONFIG_SYS_CPU="dc233c"
CONFIG_SYS_MALLOC_LEN=0x40000
CONFIG_SYS_MALLOC_F_LEN=0x400
CONFIG_ENV_SIZE=0x20000
CONFIG_DEFAULT_DEVICE_TREE="virt"
CONFIG_SYS_MONITOR_LEN=262144
CONFIG_SYS_LOAD_ADDR=0x02000000
CONFIG_TARGET_QEMU_XTENSA=y
CONFIG_REMAKE_ELF=y
CONFIG_SYS_MONITOR_BASE=0xF6000000
CONFIG_DYNAMIC_SYS_CLK_FREQ=y
CONFIG_SHOW_BOOT_PROGRESS=y
CONFIG_BOOTDELAY=10
CONFIG_AUTOBOOT_KEYED=y
CONFIG_AUTOBOOT_PROMPT="Autobooting in %d seconds, press <SPACE> to stop\n"
CONFIG_AUTOBOOT_STOP_STR=" "
CONFIG_SYS_PBSIZE=1049
CONFIG_SYS_MALLOC_BOOTPARAMS=y
CONFIG_HUSH_PARSER=y
CONFIG_SYS_PROMPT="U-Boot> "
CONFIG_CMD_ASKENV=y
CONFIG_CRC32_VERIFY=y
CONFIG_CMD_MX_CYCLIC=y
CONFIG_CMD_SAVES=y
CONFIG_CMD_DHCP=y
CONFIG_CMD_PING=y
CONFIG_CMD_DIAG=y
CONFIG_USE_BOOTFILE=y
CONFIG_BOOTFILE="uImage"
CONFIG_VERSION_VARIABLE=y
CONFIG_SYSRESET=y

View file

@ -14,3 +14,4 @@ Emulation
qemu-ppce500
qemu-riscv
qemu-x86
qemu-xtensa

View file

@ -0,0 +1,33 @@
.. SPDX-License-Identifier: GPL-2.0+
.. Copyright (C) 2024 Jiaxun Yang <jiaxun.yang@flygoat.com>
QEMU Xtensa
===========
QEMU for Xtensa supports a special 'virt' machine designed for emulation and
virtualization purposes. This document describes how to run U-Boot under it.
The QEMU virt machine models a generic Xtensa virtual machine with PCI Bus
and Xtensa ISS simcall semihosting support. It supports many different Xtensa
CPU configuration. Currently, only dc233c variant is tested against U-Boot.
Building U-Boot
---------------
Set the CROSS_COMPILE environment variable as usual, and run:
make qemu-xtensa-dc233c_defconfig
make
Note that Xtensa's toolchain is bounded to CPU configuration, you must use
the toolchain built for exactly the same CPU configuration as you selected
in U-Boot.
Running U-Boot
--------------
The minimal QEMU command line to get U-Boot up and running is:
qemu-system-xtensa -nographic -machine virt -cpu dc233c -semihosting -kernel ./u-boot.elf
You many change cpu option to match your U-Boot CPU type configuration.
semihosting option is mandatory because this is the only way to interact
with U-Boot in command line.

View file

@ -33,3 +33,9 @@ config CPU_MICROBLAZE
select XILINX_MICROBLAZE0_PVR
help
Support CPU cores for Microblaze architecture.
config CPU_XTENSA
bool "Enable Xtensa CPU driver"
depends on CPU && XTENSA
help
Support CPU cores for Xtensa architecture.

View file

@ -14,4 +14,5 @@ obj-$(CONFIG_CPU_IMX) += imx8_cpu.o
obj-$(CONFIG_CPU_MPC83XX) += mpc83xx_cpu.o
obj-$(CONFIG_CPU_RISCV) += riscv_cpu.o
obj-$(CONFIG_CPU_MICROBLAZE) += microblaze_cpu.o
obj-$(CONFIG_CPU_XTENSA) += xtensa_cpu.o
obj-$(CONFIG_SANDBOX) += cpu_sandbox.o

117
drivers/cpu/xtensa_cpu.c Normal file
View file

@ -0,0 +1,117 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2024 Jiaxun Yang <jiaxun.yang@flygoat.com>
*/
#include <clk.h>
#include <cpu.h>
#include <dm.h>
#include <errno.h>
#include <linux/bitops.h>
#include <linux/err.h>
#include <asm/arch/core.h>
static int xtensa_cpu_get_desc(const struct udevice *dev, char *buf, int size)
{
const char *cpu = XCHAL_CORE_ID;
if (!cpu || size < (strlen(cpu) + 1))
return -ENOSPC;
strcpy(buf, cpu);
return 0;
}
static int xtensa_cpu_get_info(const struct udevice *dev, struct cpu_info *info)
{
struct cpu_plat *plat = dev_get_parent_plat(dev);
info->cpu_freq = plat->timebase_freq;
#if XCHAL_HAVE_PTP_MMU
info->features |= BIT(CPU_FEAT_MMU);
#endif
#if XCHAL_ICACHE_SIZE || XCHAL_DCACHE_SIZE
info->features |= BIT(CPU_FEAT_L1_CACHE);
#endif
return 0;
}
static int xtensa_cpu_get_count(const struct udevice *dev)
{
ofnode node;
int num = 0;
ofnode_for_each_subnode(node, dev_ofnode(dev->parent)) {
const char *device_type;
/* skip if hart is marked as not available in the device tree */
if (!ofnode_is_enabled(node))
continue;
device_type = ofnode_read_string(node, "device_type");
if (!device_type)
continue;
if (strcmp(device_type, "cpu") == 0)
num++;
}
return num;
}
static int xtensa_cpu_bind(struct udevice *dev)
{
struct cpu_plat *plat = dev_get_parent_plat(dev);
plat->cpu_id = dev_read_addr(dev);
return 0;
}
static int xtensa_cpu_probe(struct udevice *dev)
{
int ret = 0;
struct clk clk;
struct cpu_plat *plat = dev_get_parent_plat(dev);
asm volatile ("rsr %0, 176\n"
"rsr %1, 208\n"
: "=r"(plat->id[0]), "=r"(plat->id[1]));
/* Get a clock if it exists */
ret = clk_get_by_index(dev, 0, &clk);
if (!ret) {
ret = clk_enable(&clk);
if (ret && (ret != -ENOSYS || ret != -ENOTSUPP))
return ret;
ret = clk_get_rate(&clk);
if (!IS_ERR_VALUE(ret))
plat->timebase_freq = ret;
}
return 0;
}
static const struct cpu_ops xtensa_cpu_ops = {
.get_desc = xtensa_cpu_get_desc,
.get_info = xtensa_cpu_get_info,
.get_count = xtensa_cpu_get_count,
};
static const struct udevice_id xtensa_cpu_ids[] = {
{ .compatible = "cdns,xtensa-cpu" },
{ }
};
U_BOOT_DRIVER(xtensa_cpu) = {
.name = "xtensa_cpu",
.id = UCLASS_CPU,
.of_match = xtensa_cpu_ids,
.bind = xtensa_cpu_bind,
.probe = xtensa_cpu_probe,
.ops = &xtensa_cpu_ops,
.flags = DM_FLAG_PRE_RELOC,
};

View file

@ -501,6 +501,15 @@ config DEBUG_UART_MT7620
driver will be available until the real driver model serial is
running.
config DEBUG_UART_XTENSA_SEMIHOSTING
bool "Xtensa semihosting"
depends on XTENSA_SEMIHOSTING_SERIAL
help
Select this to enable the debug UART using the Xtensa semihosting driver.
This provides basic serial output from the console without needing to
start up driver model. The driver will be available until the real
driver model serial is running.
endchoice
config DEBUG_UART_BASE
@ -936,7 +945,6 @@ config SH_SCIF_CLK_FREQ
config SEMIHOSTING_SERIAL
bool "Semihosting UART support"
depends on SEMIHOSTING && !SERIAL_RX_BUFFER
imply SERIAL_PUTS
help
Select this to enable a serial UART using semihosting. Special halt
instructions will be issued which an external debugger (such as a
@ -1115,6 +1123,14 @@ config XEN_SERIAL
If built without DM support, then requires Xen
to be built with CONFIG_VERBOSE_DEBUG.
config XTENSA_SEMIHOSTING_SERIAL
bool "Xtensa Semihosting UART support"
depends on DM_SERIAL
depends on XTENSA_SEMIHOSTING
imply SERIAL_PUTS
help
Select this to enable a serial UART using Xtensa semihosting.
choice
prompt "Console port"
default 8xx_CONS_SMC1

View file

@ -60,6 +60,7 @@ obj-$(CONFIG_MT7620_SERIAL) += serial_mt7620.o
obj-$(CONFIG_HTIF_CONSOLE) += serial_htif.o
obj-$(CONFIG_SIFIVE_SERIAL) += serial_sifive.o
obj-$(CONFIG_XEN_SERIAL) += serial_xen.o
obj-$(CONFIG_XTENSA_SEMIHOSTING_SERIAL) += serial_xtensa_semihosting.o
obj-$(CONFIG_S5P4418_PL011_SERIAL) += serial_s5p4418_pl011.o
ifndef CONFIG_SPL_BUILD

View file

@ -0,0 +1,92 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2024 Jiaxun Yang <jiaxun.yang@flygoat.com>
*/
#include <dm.h>
#include <malloc.h>
#include <serial.h>
#include <asm/platform/simcall.h>
/**
* struct simc_serial_priv - Semihosting serial private data
* @counter: Counter used to fake pending every other call
*/
struct simc_serial_priv {
unsigned int counter;
};
static int simc_serial_getc(struct udevice *dev)
{
char ch = 0;
simc_read(0, &ch, sizeof(ch));
return ch;
}
static int simc_serial_putc(struct udevice *dev, const char ch)
{
char str[2] = {0};
str[0] = ch;
simc_write(1, str, 1);
return 0;
}
static int simc_serial_pending(struct udevice *dev, bool input)
{
struct simc_serial_priv *priv = dev_get_priv(dev);
if (input) {
int res = simc_poll(0);
return res < 0 ? priv->counter++ & 1 : res;
}
return false;
}
static ssize_t smh_serial_puts(struct udevice *dev, const char *s, size_t len)
{
int ret;
ret = simc_write(1, s, len);
return ret;
}
static const struct dm_serial_ops simc_serial_ops = {
.putc = simc_serial_putc,
.puts = smh_serial_puts,
.getc = simc_serial_getc,
.pending = simc_serial_pending,
};
U_BOOT_DRIVER(simc_serial) = {
.name = "serial_xtensa_semihosting",
.id = UCLASS_SERIAL,
.priv_auto = sizeof(struct simc_serial_priv),
.ops = &simc_serial_ops,
.flags = DM_FLAG_PRE_RELOC,
};
U_BOOT_DRVINFO(simc_serial) = {
.name = "serial_xtensa_semihosting",
};
#if CONFIG_IS_ENABLED(DEBUG_UART_XTENSA_SEMIHOSTING)
#include <debug_uart.h>
static inline void _debug_uart_init(void)
{
}
static inline void _debug_uart_putc(int c)
{
simc_serial_putc(NULL, c);
}
DEBUG_UART_FUNCS
#endif

View file

@ -0,0 +1,14 @@
# SPDX-License-Identifier: GPL-2.0+
include $(srctree)/scripts/Makefile.dts
targets += $(dtb-y)
# Add any required device tree compiler flags here
DTC_FLAGS += -a 0x8
PHONY += dtbs
dtbs: $(addprefix $(obj)/, $(dtb-y))
@:
clean-files := *.dtb *.dtbo */*.dtb */*.dtbo

View file

@ -0,0 +1,36 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (C) 2007-2013 Tensilica, Inc.
* Copyright (C) 2014 - 2016 Cadence Design Systems Inc.
* Copyright (C) 2024 Jiaxun Yang <jiaxun.yang@flygoat.com>
*/
#ifndef __CONFIG_H
#define __CONFIG_H
#include <asm/arch/core.h>
#include <asm/addrspace.h>
#include <asm/config.h>
#if XCHAL_HAVE_PTP_MMU
#define CFG_SYS_MEMORY_BASE \
(XCHAL_VECBASE_RESET_VADDR - XCHAL_VECBASE_RESET_PADDR)
#define CFG_SYS_IO_BASE 0xf0000000
#define CFG_SYS_SDRAM_SIZE 0x80000000 /* xtensa.sysram0 */
#else
#define CFG_SYS_MEMORY_BASE 0x60000000
#define CFG_SYS_SDRAM_SIZE 0x08000000 /* xtensa.sysram0 */
#endif
#define CFG_SYS_SDRAM_BASE MEMADDR(0x00000000)
#if defined(CFG_MAX_MEM_MAPPED) && \
CFG_MAX_MEM_MAPPED < CFG_SYS_SDRAM_SIZE
#define XTENSA_SYS_TEXT_ADDR \
(MEMADDR(CFG_MAX_MEM_MAPPED) - CONFIG_SYS_MONITOR_LEN)
#else
#define XTENSA_SYS_TEXT_ADDR \
(MEMADDR(CFG_SYS_SDRAM_SIZE) - CONFIG_SYS_MONITOR_LEN)
#endif
#endif /* __CONFIG_H */