From patchwork Tue Feb 21 08:55:09 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrice CHOTARD X-Patchwork-Id: 730375 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 3vSDqf3Kx8z9s1y for ; Tue, 21 Feb 2017 19:55:58 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id B14804B5A8; Tue, 21 Feb 2017 09:55:56 +0100 (CET) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id ELQlIKwbZg9s; Tue, 21 Feb 2017 09:55:56 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 0D1354B5B7; Tue, 21 Feb 2017 09:55:51 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id C055A4B4E9 for ; Tue, 21 Feb 2017 09:55:27 +0100 (CET) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 6rXFYetYKJOv for ; Tue, 21 Feb 2017 09:55:27 +0100 (CET) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mx07-00178001.pphosted.com (mx07-00178001.pphosted.com [62.209.51.94]) by theia.denx.de (Postfix) with ESMTPS id 3B7EE4B252 for ; Tue, 21 Feb 2017 09:55:24 +0100 (CET) Received: from pps.filterd (m0046668.ppops.net [127.0.0.1]) by mx07-00178001.pphosted.com (8.16.0.11/8.16.0.11) with SMTP id v1L8qQni007413; Tue, 21 Feb 2017 09:55:23 +0100 Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-.pphosted.com with ESMTP id 28pcm2946q-1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT); Tue, 21 Feb 2017 09:55:23 +0100 Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 1DDA142; Tue, 21 Feb 2017 08:55:22 +0000 (GMT) Received: from Webmail-eu.st.com (sfhdag6node3.st.com [10.75.127.18]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id A98EE2659; Tue, 21 Feb 2017 08:55:22 +0000 (GMT) Received: from localhost (10.75.127.45) by SFHDAG6NODE3.st.com (10.75.127.18) with Microsoft SMTP Server (TLS) id 15.0.1178.4; Tue, 21 Feb 2017 09:55:22 +0100 From: To: , , , Date: Tue, 21 Feb 2017 09:55:09 +0100 Message-ID: <1487667314-29957-5-git-send-email-patrice.chotard@st.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1487667314-29957-1-git-send-email-patrice.chotard@st.com> References: <1487667314-29957-1-git-send-email-patrice.chotard@st.com> MIME-Version: 1.0 X-Originating-IP: [10.75.127.45] X-ClientProxiedBy: SFHDAG6NODE2.st.com (10.75.127.17) To SFHDAG6NODE3.st.com (10.75.127.18) X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2017-02-21_07:, , signatures=0 Cc: christophe.kerello@st.com, patrick.delaunay@st.com Subject: [U-Boot] [PATCH v6 4/9] STiH410: Add STi serial driver X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.15 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" From: Patrice Chotard This patch adds support to ASC (asynchronous serial controller) driver, which is basically a standard serial driver. This IP is common across other STMicroelectronics SoCs Signed-off-by: Patrice Chotard Reviewed-by: Simon Glass --- arch/arm/Kconfig | 2 + drivers/serial/Kconfig | 8 ++ drivers/serial/Makefile | 1 + drivers/serial/serial_sti_asc.c | 211 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 222 insertions(+) create mode 100644 drivers/serial/serial_sti_asc.c diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 4aa5eb9..b91a5b7 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -985,6 +985,8 @@ config STM32 config ARCH_STI bool "Support STMicrolectronics SoCs" select CPU_V7 + select DM + select DM_SERIAL help Support for STMicroelectronics STiH407/10 SoC family. This SoC is used on Linaro 96Board STiH410-B2260 diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index b11f3ff..7cb0eaa 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -413,4 +413,12 @@ config PXA_SERIAL If you have a machine based on a Marvell XScale PXA2xx CPU you can enable its onboard serial ports by enabling this option. +config STI_ASC_SERIAL + bool "STMicroelectronics on-chip UART" + depends on DM_SERIAL && ARCH_STI + help + Select this to enable Asynchronous Serial Controller available + on STiH410 SoC. This is a basic implementation, it supports + following baudrate 9600, 19200, 38400, 57600 and 115200. + endmenu diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 8430668..84a22ce 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -41,6 +41,7 @@ obj-$(CONFIG_FSL_LINFLEXUART) += serial_linflexuart.o obj-$(CONFIG_ARC_SERIAL) += serial_arc.o obj-$(CONFIG_UNIPHIER_SERIAL) += serial_uniphier.o obj-$(CONFIG_STM32_SERIAL) += serial_stm32.o +obj-$(CONFIG_STI_ASC_SERIAL) += serial_sti_asc.o obj-$(CONFIG_PIC32_SERIAL) += serial_pic32.o obj-$(CONFIG_STM32X7_SERIAL) += serial_stm32x7.o obj-$(CONFIG_BCM283X_MU_SERIAL) += serial_bcm283x_mu.o diff --git a/drivers/serial/serial_sti_asc.c b/drivers/serial/serial_sti_asc.c new file mode 100644 index 0000000..ce26c94 --- /dev/null +++ b/drivers/serial/serial_sti_asc.c @@ -0,0 +1,211 @@ +/* + * Support for Serial I/O using STMicroelectronics' on-chip ASC. + * + * Copyright (c) 2017 + * Patrice Chotard + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +#define BAUDMODE 0x00001000 +#define RXENABLE 0x00000100 +#define RUN 0x00000080 +#define MODE 0x00000001 +#define MODE_8BIT 0x0001 +#define STOP_1BIT 0x0008 +#define PARITYODD 0x0020 + +#define STA_TF BIT(9) +#define STA_RBF BIT(0) + +struct sti_asc_uart { + u32 baudrate; + u32 txbuf; + u32 rxbuf; + u32 control; + u32 inten; + u32 status; + u32 guardtime; + u32 timeout; + u32 txreset; + u32 rxreset; +}; + +struct sti_asc_serial { + /* address of registers in physical memory */ + struct sti_asc_uart *regs; +}; + +/* Values for the BAUDRATE Register */ +#define PCLK (200ul * 1000000ul) +#define BAUDRATE_VAL_M0(bps) (PCLK / (16 * (bps))) +#define BAUDRATE_VAL_M1(bps) ((bps * (1 << 14)) + (1<<13)) / (PCLK/(1 << 6)) + +/* + * MODE 0 + * ICCLK + * ASCBaudRate = ---------------- + * baudrate * 16 + * + * MODE 1 + * baudrate * 16 * 2^16 + * ASCBaudRate = ------------------------ + * ICCLK + * + * NOTE: + * Mode 1 should be used for baudrates of 19200, and above, as it + * has a lower deviation error than Mode 0 for higher frequencies. + * Mode 0 should be used for all baudrates below 19200. + */ + +static int sti_asc_pending(struct udevice *dev, bool input) +{ + struct sti_asc_serial *priv = dev_get_priv(dev); + struct sti_asc_uart *const uart = priv->regs; + unsigned long status; + + status = readl(&uart->status); + if (input) + return status & STA_RBF; + else + return status & STA_TF; +} + +static int _sti_asc_serial_setbrg(struct sti_asc_uart *uart, int baudrate) +{ + unsigned long val; + int t, mode = 1; + + switch (baudrate) { + case 9600: + t = BAUDRATE_VAL_M0(9600); + mode = 0; + break; + case 19200: + t = BAUDRATE_VAL_M1(19200); + break; + case 38400: + t = BAUDRATE_VAL_M1(38400); + break; + case 57600: + t = BAUDRATE_VAL_M1(57600); + break; + default: + debug("ASC: unsupported baud rate: %d, using 115200 instead.\n", + baudrate); + case 115200: + t = BAUDRATE_VAL_M1(115200); + break; + } + + /* disable the baudrate generator */ + val = readl(&uart->control); + writel(val & ~RUN, &uart->control); + + /* set baud generator reload value */ + writel(t, &uart->baudrate); + /* reset the RX & TX buffers */ + writel(1, &uart->txreset); + writel(1, &uart->rxreset); + + /* set baud generator mode */ + if (mode) + val |= BAUDMODE; + + /* finally, write value and enable ASC */ + writel(val, &uart->control); + + return 0; +} + +/* called to adjust baud-rate */ +static int sti_asc_serial_setbrg(struct udevice *dev, int baudrate) +{ + struct sti_asc_serial *priv = dev_get_priv(dev); + struct sti_asc_uart *const uart = priv->regs; + + return _sti_asc_serial_setbrg(uart, baudrate); +} + +/* blocking function, that returns next char */ +static int sti_asc_serial_getc(struct udevice *dev) +{ + struct sti_asc_serial *priv = dev_get_priv(dev); + struct sti_asc_uart *const uart = priv->regs; + + /* polling wait: for a char to be read */ + if (!sti_asc_pending(dev, true)) + return -EAGAIN; + + return readl(&uart->rxbuf); +} + +/* write write out a single char */ +static int sti_asc_serial_putc(struct udevice *dev, const char c) +{ + struct sti_asc_serial *priv = dev_get_priv(dev); + struct sti_asc_uart *const uart = priv->regs; + + /* wait till safe to write next char */ + if (sti_asc_pending(dev, false)) + return -EAGAIN; + + /* finally, write next char */ + writel(c, &uart->txbuf); + + return 0; +} + +/* initialize the ASC */ +static int sti_asc_serial_probe(struct udevice *dev) +{ + struct sti_asc_serial *priv = dev_get_priv(dev); + unsigned long val; + fdt_addr_t base; + + base = dev_get_addr(dev); + if (base == FDT_ADDR_T_NONE) + return -EINVAL; + + priv->regs = (struct sti_asc_uart *)base; + sti_asc_serial_setbrg(dev, gd->baudrate); + + /* + * build up the value to be written to CONTROL + * set character length, bit stop number, odd parity + */ + val = RXENABLE | RUN | MODE_8BIT | STOP_1BIT | PARITYODD; + writel(val, &priv->regs->control); + + return 0; +} + +static const struct dm_serial_ops sti_asc_serial_ops = { + .putc = sti_asc_serial_putc, + .pending = sti_asc_pending, + .getc = sti_asc_serial_getc, + .setbrg = sti_asc_serial_setbrg, +}; + +static const struct udevice_id sti_serial_of_match[] = { + { .compatible = "st,asc" }, + { } +}; + +U_BOOT_DRIVER(serial_sti_asc) = { + .name = "serial_sti_asc", + .id = UCLASS_SERIAL, + .of_match = sti_serial_of_match, + .ops = &sti_asc_serial_ops, + .probe = sti_asc_serial_probe, + .priv_auto_alloc_size = sizeof(struct sti_asc_serial), + .flags = DM_FLAG_PRE_RELOC, +}; +