From patchwork Tue May 21 09:56:52 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yuriy Kolerov X-Patchwork-Id: 90568 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 07D9E38449C1 for ; Tue, 21 May 2024 10:00:31 +0000 (GMT) X-Original-To: newlib@sourceware.org Delivered-To: newlib@sourceware.org Received: from mail-wm1-x329.google.com (mail-wm1-x329.google.com [IPv6:2a00:1450:4864:20::329]) by sourceware.org (Postfix) with ESMTPS id 89F923858C98 for ; Tue, 21 May 2024 09:58:20 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 89F923858C98 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 89F923858C98 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2a00:1450:4864:20::329 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1716285507; cv=none; b=mBOx8pxtv/SYBL5sSheoN8diqVMeIV7WsmIcGosPDBbEmVYTYl711qCXHJCGq9E7pWcR+LlhJJtjdwRivZ3yJYJhLRP8dg6CUFg2C/1aVpl22llDCvNLmj8xGImcZBCz6tjCi7UouD9KHMgSZ72o2cw9jyPwjrZacVj5heKHwvE= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1716285507; c=relaxed/simple; bh=pmU4wPQ40PaW6syPZCRiP4wkw3n7pfUXO1VP5lSEi/k=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=c5/jtkmxQQBteUEFfBXVTLAGLO+/g1mMI20mMAQw7WJxkeJrH1lwdcJiQZQLzKrWKK1LFilgx9P0XjdQ38oP5iZ65kyXqGni49W4qkw4kF4GKu5rdZ+teJRS03Jxs3PZClcB413zCJ7bGwXkxRfZ/tizg7DVFaLJwbHv81/c21s= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-wm1-x329.google.com with SMTP id 5b1f17b1804b1-4202cea9a2fso29233455e9.3 for ; Tue, 21 May 2024 02:58:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1716285499; x=1716890299; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=SXFBXDZRnqxGCU0zZNdzl76Hv3sRx9ehPZWAP1HGqjU=; b=Jt6xiKB5+8pgePWI4SDDkg0oyCV44woKKwCovOFywjEQ0G9rG9dQ7xjsO/gq8SA6nf yYgGYYurkL7y7xVqgXMg4qMBwfTE+dzjb9+z2bRNkPBaZJviVmy2sWDui1ujuTDsm09B MxrOqM/ZoKb1rPVUXxYv2xDMaQNbMxwuXYCdPXtJjziIv/g8Xw6/S9Yp6tUU0e4JgGF5 qv50UdbbBCbi4tSjyCcjPszbbzJsKeW5BUovr9e9lLCXvNELQVXA1yjKAQfsPSJwz4jS aBFhWOsLabLKE3CrJroMS6nIwMoiC9MoQYd//QRHao6Kn7Ptt/CKs+uVOamEkrnSvpTo Exsg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1716285499; x=1716890299; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=SXFBXDZRnqxGCU0zZNdzl76Hv3sRx9ehPZWAP1HGqjU=; b=bw7N0GD8Oe9sglpqyqU46YYVjw67PPuXZeBoqfwJlIE4QCU85nMMm5KVO4ItHcbA9d moDtvH5nLNTggNvBaOe0jzg70oy2HWkXqIkZbm3oBLuLQWR6CdEqZXwZA5Mc5WE5N3LR 150HPWjn44+RPuu9s4E1LdYdRFmZOUDu84B1Ql89nqGADJ0Xgy3p2QvdoK3b/LRTlILL YgD4oRkqXGiRDLF7NPpT7mFsq21L33gFe4lwnJziev4z5sm6sppp6MPgHLAK1am0QM5f qJR+snU1CQmbuCfM0Zt1ZOe+6ANx20XUevP2GAgBlgbjM4L0EZXSv0S5JR25F9Yb7HCf ks2w== X-Gm-Message-State: AOJu0Yw2LBcQsUZzAxLQEY+K/lziZp4X5GQ9/0Du5vTO7FUvp0ShkyiE 1FuCKoPYmqF04yaWjIKLALV/RbGB+2oa2jkhGCC0BGXC1rml2/n8vWW6b1ZqecA= X-Google-Smtp-Source: AGHT+IGdmnewwquX9it6N+kMzBWwn3+HEai5xhYIAHXlvZxCg+WfYHJd313k07MYuJi/otE/5olq4Q== X-Received: by 2002:a05:600c:5685:b0:418:f991:713f with SMTP id 5b1f17b1804b1-41feab42b13mr256652995e9.23.1716285498827; Tue, 21 May 2024 02:58:18 -0700 (PDT) Received: from localhost.localdomain ([2a00:a041:e626:f00:a285:867a:5e98:7729]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-41f87b2653bsm490773635e9.4.2024.05.21.02.58.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 May 2024 02:58:18 -0700 (PDT) From: kolerov93@gmail.com To: newlib@sourceware.org Cc: shahab@synopsys.com, claziss@gmail.com, Yuriy Kolerov , Vladimir Isaev Subject: [PATCH 09/15] arc: libgloss: Add UART 8250 library Date: Tue, 21 May 2024 10:56:52 +0100 Message-Id: <20240521095658.10311-10-kolerov93@gmail.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20240521095658.10311-1-kolerov93@gmail.com> References: <20240521095658.10311-1-kolerov93@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-12.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: newlib@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Newlib mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: newlib-bounces+patchwork=sourceware.org@sourceware.org From: Yuriy Kolerov This library implements libgloss input/output and setup routines for UART 8250 devices of ARC development boards: * EM Starter Kit * HS Development Kit * EM Software Development Platform * IoT Development Kit _uart_8250_setup function with proper parameteres must be called to setup UART 8250 device for a particular board (refer to a board's documentation). Signed-off-by: Vladimir Isaev Signed-off-by: Yuriy Kolerov --- libgloss/arc/uart-8250-stub.c | 116 +++++++++++++ libgloss/arc/uart-8250.c | 316 ++++++++++++++++++++++++++++++++++ libgloss/arc/uart-8250.h | 25 +++ 3 files changed, 457 insertions(+) create mode 100644 libgloss/arc/uart-8250-stub.c create mode 100644 libgloss/arc/uart-8250.c create mode 100644 libgloss/arc/uart-8250.h diff --git a/libgloss/arc/uart-8250-stub.c b/libgloss/arc/uart-8250-stub.c new file mode 100644 index 000000000..ab69d6354 --- /dev/null +++ b/libgloss/arc/uart-8250-stub.c @@ -0,0 +1,116 @@ +/* + * uart-8250-stub.c -- various stubs for 8250 UART libgloss. + * + * Copyright (c) 2024 Synopsys Inc. + * + * The authors hereby grant permission to use, copy, modify, distribute, + * and license this software and its documentation for any purpose, provided + * that existing copyright notices are retained in all copies and that this + * notice is included verbatim in any distributions. No written agreement, + * license, or royalty fee is required for any of the authorized uses. + * Modifications to this software may be copyrighted by their authors + * and need not follow the licensing terms described here, provided that + * the new terms are clearly indicated on the first page of each file where + * they apply. + */ +#include +#include +#include +#include + +#include "glue.h" + + +/* Always return character device with 1024 bytes block. */ +int +_fstat (int fd __attribute__ ((unused)), struct stat *buf) +{ + memset (buf, 0, sizeof (*buf)); + buf->st_mode = S_IFCHR; + buf->st_blksize = 1024; + + return 0; +} + +/* ARC UART is actually console so just return 1. */ +int +_isatty (int fildes __attribute__ ((unused))) +{ + return 1; +} + +/* Should be provided by crt0.S. */ +extern void __attribute__((noreturn)) _exit_halt (int ret); + +void +__attribute__((noreturn)) +_exit (int ret) +{ + _exit_halt (ret); +} + +/* Not implemented. */ +off_t +_lseek (int fd __attribute__ ((unused)), + off_t offset __attribute__ ((unused)), + int whence __attribute__ ((unused))) +{ + errno = ENOSYS; + return -1; +} + +/* Not implemented. */ +int +_close (int fd __attribute__ ((unused))) +{ + errno = ENOSYS; + return -1; +} + +/* Not implemented. */ +int +_open (const char *path __attribute__ ((unused)), + int flags __attribute__ ((unused)), ...) +{ + errno = ENOSYS; + return -1; +} + +/* If PID is equal to __MYPID, exit with sig as retcode. */ +int +_kill (int pid, int sig) +{ + if (pid == __MYPID) + _exit (sig); + + errno = ENOSYS; + return -1; +} + +/* Return __MYPID. */ +int +_getpid (void) +{ + return __MYPID; +} + +/* No arguments. */ +int +_argc (void) +{ + return 0; +} + +/* No arguments. */ +uint32_t +_argvlen (int a __attribute__ ((unused))) +{ + return 0; +} + +/* No arguments. */ +int +_argv (int a __attribute__ ((unused)), char *arg __attribute__ ((unused))) +{ + return -1; +} diff --git a/libgloss/arc/uart-8250.c b/libgloss/arc/uart-8250.c new file mode 100644 index 000000000..6f4e9f3d6 --- /dev/null +++ b/libgloss/arc/uart-8250.c @@ -0,0 +1,316 @@ +/* + * uart-8250.c -- polling driver for 32-bit 8250 UART. + * Provides _uart_8250_setup(), _read() and _write(). Please note that + * _read() and _write() from this file can only be used for console access. + * + * Copyright (c) 2024 Synopsys Inc. + * + * The authors hereby grant permission to use, copy, modify, distribute, + * and license this software and its documentation for any purpose, provided + * that existing copyright notices are retained in all copies and that this + * notice is included verbatim in any distributions. No written agreement, + * license, or royalty fee is required for any of the authorized uses. + * Modifications to this software may be copyrighted by their authors + * and need not follow the licensing terms described here, provided that + * the new terms are clearly indicated on the first page of each file where + * they apply. + */ + +#include +#include +#include +#include + +/* + * List of UART 8250 registers with offsets: + * + * 0x00 - Transmit Holding Register, WO, LCR_DLAB == 0 + * 0x00 - Receive Buffer Register, RO, LCR_DLAB == 0 + * 0x00 - Divisor Latch Low, RW, LCR_DLAB == 1 + * 0x04 - Divisor Latch High, RW, LCR_DLAB == 1 + * 0x04 - Interrupt Enable Register, RW, LCR_DLAB == 0 + * 0x08 - FIFO Control Register, WO + * 0x08 - Interrupt Identification Register, RO + * 0x0C - Line Control Register, RW + * 0x10 - Modem Control Register, RW + * 0x14 - Line Status Register, RO + * 0x18 - Modem Status Register, RO + */ + +#define THR_OFFSET 0x00 +#define RBR_OFFSET 0x00 +#define DLL_OFFSET 0x00 +#define DLH_OFFSET 0x04 +#define IER_OFFSET 0x04 +#define FCR_OFFSET 0x08 +#define IIR_OFFSET 0x08 +#define LCR_OFFSET 0x0C +#define MCR_OFFSET 0x10 +#define LSR_OFFSET 0x14 +#define MSR_OFFSET 0x18 + +/* + * LCR (Line Control Register) fields: + * + * [7] - Divisor Latch Access Bit + * [6] - Set Break + * [5] - Stick Parity + * [4] - Even Parity Select + * [3] - Parity Enable + * [2] - Number of Stop Bits + * [1:0] - Data Length Select. Values: + * 0b11 - 8 data bits per character (default) + * 0b10 - 7 data bits per character + * 0b01 - 6 data bits per character + * 0b00 - 5 data bits per character + */ + +#define LCR_DLAB_SHIFT 7 +#define LCR_SB_SHIFT 6 +#define LCR_SP_SHIFT 5 +#define LCR_EPS_SHIFT 4 +#define LCR_PEN_SHIFT 3 +#define LCR_STB_SHIFT 2 +#define LCR_DLS_SHIFT 0 +/* + * MCR (Modem Control Register) fields: + * + * [4] - LoopBack Bit + * [3] - Auxiliary Output 2 + * [2] - Auxiliary Output 1 + * [1] - Request To Send (ON by default) + * [0] - Data Terminal Ready (ON by default) + */ + +#define MCR_LB_SHIFT 4 +#define MCR_OUT2_SHIFT 3 +#define MCR_OUT1_SHIFT 2 +#define MCR_RTS_SHIFT 1 +#define MCR_DTR_SHIFT 0 + +/* + * LSR (Line Status Register) fields: + * + * [7] - Receiver FIFO Error + * [6] - Transmitter Empty + * [5] - Transmit Holding Register Empty + * [4] - Break Interrupt + * [3] - Framing Error + * [2] - Parity Error + * [1] - Overrun Error + * [0] - Data Ready + */ + +#define LSR_RFE_SHIFT 7 +#define LSR_TEMT_SHIFT 6 +#define LSR_THRE_SHIFT 5 +#define LSR_BI_SHIFT 4 +#define LSR_FE_SHIFT 3 +#define LSR_PE_SHIFT 2 +#define LSR_OE_SHIFT 1 +#define LSR_DR_SHIFT 0 + +/* + * Default initial values for configuration registers. + */ + +#define FCR_DEFAULT 0x0 +#define IER_DEFAULT 0x0 +#define LCR_DLS_DEFAULT 0x3 +#define LCR_DEFAULT (LCR_DLS_DEFAULT << LCR_DLS_SHIFT) +#define MCR_RTS_DEFAULT 0x1 +#define MCR_DTR_DEFAULT 0x1 +#define MCR_DEFAULT ((MCR_RTS_DEFAULT << MCR_RTS_SHIFT) | \ + (MCR_DTR_DEFAULT << MCR_DTR_SHIFT)) + +#define LCR_MODE_SETUP (0x1 << LCR_DLAB_SHIFT) +#define LSR_MODE_GETC (0x1 << LSR_DR_SHIFT) +#define LSR_MODE_PUTC ((0x1 << LSR_TEMT_SHIFT) | (0x1 << LSR_THRE_SHIFT)) + +/* Main UART control structure. */ +struct _uart_8250 { + volatile char *base; /* Start of UART registers. */ + uint32_t clk; /* UART clock. */ + uint32_t baud; /* Baud rate. */ + int aux_mapped; /* If UART registers are mapped to AUX or memory. */ + int ready; /* If UART is ready to use or not. */ +}; + +static struct _uart_8250 _uart_8250; + +/* Write 32-bit value to the UART register. */ +static inline void +_uart_8250_write_reg (const struct _uart_8250 *uart, uint32_t reg, + uint32_t value) +{ + if (uart->aux_mapped) + __builtin_arc_sr (value, (uint32_t) uart->base + reg); + else + *(volatile uint32_t *)(uart->base + reg) = value; +} + +/* Read 32-bit value from the UART register. */ +static inline uint32_t +_uart_8250_read_reg (const struct _uart_8250 *uart, uint32_t reg) +{ + if (uart->aux_mapped) + return __builtin_arc_lr ((uint32_t) uart->base + reg); + else + return *(volatile uint32_t *)(uart->base + reg); +} + +/* Wait until all flags are set. */ +static inline void +_uart_8250_wait (const struct _uart_8250 *uart, uint32_t reg, uint32_t flags) +{ + while (1) + { + if ((_uart_8250_read_reg (uart, reg) & flags) == flags) + break; + } +} + +/* Get one character from UART. CR is converted to NL. */ +static int +_uart_8250_getc (const struct _uart_8250 *uart) +{ + char c; + + _uart_8250_wait (uart, LSR_OFFSET, LSR_MODE_GETC); + + c = _uart_8250_read_reg (uart, RBR_OFFSET); + + if (c == '\r') + c = '\n'; + + return c; +} + +/* Put one character to UART. CR is placed before NL. */ +static void +_uart_8250_putc (const struct _uart_8250 *uart, char c) +{ + if (c == '\n') + _uart_8250_putc (uart, '\r'); + + _uart_8250_wait (uart, LSR_OFFSET, LSR_MODE_PUTC); + + _uart_8250_write_reg (uart, THR_OFFSET, c); +} + +/* + * Setup UART control structure and following parameters: + * + * - baudrate if clock and baudrate are passed to function + * - 8n1 (8 data bits, no parity bit, one stop bit) + * - disable interrupts + * - disable FIFO + * - set Request To Send and Data Terminal Ready + * + * Arguments: + * + * - base - start address of UART registers + * - aux_mapped - set if UART registers are mapped to ARC AUX + * - clk - UART clock frequency + * - baud - UART baudrate to setup + * + * The function returns 0 on success. + */ +int +_uart_8250_setup (void *base, int aux_mapped, uint32_t clk, uint32_t baud) +{ + struct _uart_8250 *uart = &_uart_8250; + + uart->base = base; + uart->aux_mapped = aux_mapped; + uart->clk = clk; + uart->baud = baud; + + if (clk && baud) + { + uint32_t div; + + div = ((clk + 8 * baud) / baud) / 16; + _uart_8250_write_reg (uart, LCR_OFFSET, LCR_MODE_SETUP); + _uart_8250_write_reg (uart, DLL_OFFSET, div & 0xFF); + _uart_8250_write_reg (uart, DLH_OFFSET, div >> 8); + } + + _uart_8250_write_reg (uart, FCR_OFFSET, FCR_DEFAULT); + _uart_8250_write_reg (uart, IER_OFFSET, IER_DEFAULT); + _uart_8250_write_reg (uart, LCR_OFFSET, LCR_DEFAULT); + _uart_8250_write_reg (uart, MCR_OFFSET, MCR_DEFAULT); + + uart->ready = 1; + + return 0; +} + +/* _read() is implemented only for stdin. Each read character is echoed. */ +ssize_t +_read (int fd, void *buf, size_t count) +{ + struct _uart_8250 *uart = &_uart_8250; + size_t bytes_read; + char *buf_char = buf; + int c; + + if (fd != STDIN_FILENO) + { + errno = ENOSYS; + return -1; + } + + if (!uart->ready) + { + errno = EIO; + return -1; + } + + bytes_read = 0; + c = EOF; + /* Break on '\n' to simulate readline behavior. */ + while (bytes_read != count && c != '\n') + { + c = _uart_8250_getc (uart); + if (c == EOF) + break; + + /* Echo character to the console. */ + _uart_8250_putc (uart, c); + + buf_char[bytes_read] = c; + bytes_read++; + } + + return bytes_read; +} + +/* _write() is implemented only for stdout and stderr. */ +ssize_t +_write (int fd, const char *buf, size_t nbyte) +{ + struct _uart_8250 *uart = &_uart_8250; + uint32_t bytes_written; + + if (fd != STDOUT_FILENO && fd != STDERR_FILENO) + { + errno = ENOSYS; + return -1; + } + + if (!uart->ready) + { + errno = EIO; + return -1; + } + + bytes_written = 0; + while (bytes_written != nbyte) + { + _uart_8250_putc (uart, buf[bytes_written]); + bytes_written++; + } + + return bytes_written; +} diff --git a/libgloss/arc/uart-8250.h b/libgloss/arc/uart-8250.h new file mode 100644 index 000000000..dc6062334 --- /dev/null +++ b/libgloss/arc/uart-8250.h @@ -0,0 +1,25 @@ +/* + * uart-8250.h -- polling driver for 32-bit 8250 UART. + * Header defines _uart_8250_setup(). + * + * Copyright (c) 2024 Synopsys Inc. + * + * The authors hereby grant permission to use, copy, modify, distribute, + * and license this software and its documentation for any purpose, provided + * that existing copyright notices are retained in all copies and that this + * notice is included verbatim in any distributions. No written agreement, + * license, or royalty fee is required for any of the authorized uses. + * Modifications to this software may be copyrighted by their authors + * and need not follow the licensing terms described here, provided that + * the new terms are clearly indicated on the first page of each file where + * they apply. + */ + +#ifndef _UART_8250_H +#define _UART_8250_H + +#include + +int _uart_8250_setup (void *base, int aux_mapped, uint32_t clk, uint32_t baud); + +#endif /* ! _UART_8250_H */