From patchwork Sat Sep 6 17:21:14 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexey Charkov X-Patchwork-Id: 4857911 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 6C68BC033A for ; Sat, 6 Sep 2014 17:24:45 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 88A4C20121 for ; Sat, 6 Sep 2014 17:24:44 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id ACBB82013A for ; Sat, 6 Sep 2014 17:24:43 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1XQJhJ-00019p-3E; Sat, 06 Sep 2014 17:22:49 +0000 Received: from mail-la0-x231.google.com ([2a00:1450:4010:c03::231]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1XQJhF-00011d-L7 for linux-arm-kernel@lists.infradead.org; Sat, 06 Sep 2014 17:22:46 +0000 Received: by mail-la0-f49.google.com with SMTP id b17so15361159lan.22 for ; Sat, 06 Sep 2014 10:22:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=8+vjnxDQ1lywJxOZiYY/M0ZwRnkker6x9VKwEPcRIao=; b=tICxsr5A0L5dbDO2XDXgxT7FgrboKGtLNaZXF8MOBTh/QI58lwuOh8sbu7bASymvKZ Lz7lqvTm/sEuRTYL+auzhAYj8XKDs3t3vByBoev6CJycvhnTuhabh38mQw9b4ASiwzt/ Md1RMgUgc/WeGevgWhjV5YX+b/k9QiWRKrPjE3UcOhtDdapg71Nd1D/i6w5bMXQ9K8l4 +nfEXin+lHVxGtby/ZWXRRJNEESyi5zOI31fSG9ZzGHxZ6DObarg/1VZ3/2d4s4yrk9X AajCLnQfN3lGnfYh7AgpYmcbdXe71tzgiMkYflvcjBV9VNkxXK0fht4DvjGUq188t5bn MHIQ== X-Received: by 10.112.156.138 with SMTP id we10mr2403369lbb.68.1410024143156; Sat, 06 Sep 2014 10:22:23 -0700 (PDT) Received: from localhost.localdomain ([83.149.9.109]) by mx.google.com with ESMTPSA id vr9sm1883449lbb.36.2014.09.06.10.22.20 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sat, 06 Sep 2014 10:22:22 -0700 (PDT) From: Alexey Charkov To: Rob Herring , Pawel Moll , Mark Rutland , Ian Campbell , Kumar Gala , Tony Prisk , Greg Kroah-Hartman , Jiri Slaby , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-serial@vger.kernel.org Subject: [PATCH 3/4] tty: vt8500_serial: explicitly calculate base baud rate Date: Sat, 6 Sep 2014 21:21:14 +0400 Message-Id: <1410024075-1354-4-git-send-email-alchark@gmail.com> X-Mailer: git-send-email 2.0.0 In-Reply-To: <1410024075-1354-1-git-send-email-alchark@gmail.com> References: <1410024075-1354-1-git-send-email-alchark@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140906_102245_874552_65211894 X-CRM114-Status: GOOD ( 13.99 ) X-Spam-Score: -0.2 (/) Cc: Alexey Charkov X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-2.7 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE,RCVD_IN_SORBS_WEB, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Current code relies on the UART clock pre-divisor to be already configured in the baud rate register. Calculate it in the driver and set explicitly instead, also return the "real" effective baud rate, which is generally slightly different from the requested value. While at this, also ensure that break signal timing is updated when baud rate changes. Signed-off-by: Alexey Charkov --- drivers/tty/serial/vt8500_serial.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c index 47e74f9..bfcebfd 100644 --- a/drivers/tty/serial/vt8500_serial.c +++ b/drivers/tty/serial/vt8500_serial.c @@ -101,12 +101,15 @@ #define VT8500_HAS_SWRTSCTS_SWITCH (1 << 1) +#define VT8500_RECOMMENDED_CLK 12000000 +#define VT8500_OVERSAMPLING_DIVISOR 13 #define VT8500_MAX_PORTS 6 struct vt8500_port { struct uart_port uart; char name[16]; struct clk *clk; + unsigned int clk_predivisor; unsigned int ier; unsigned int vt8500_uart_flags; }; @@ -311,20 +314,25 @@ static void vt8500_break_ctl(struct uart_port *port, int break_ctl) static int vt8500_set_baud_rate(struct uart_port *port, unsigned int baud) { + struct vt8500_port *vt8500_port = + container_of(port, struct vt8500_port, uart); unsigned long div; unsigned int loops = 1000; - div = vt8500_read(port, VT8500_URDIV) & ~(0x3ff); + div = ((vt8500_port->clk_predivisor - 1) & 0xf) << 16; + div |= (uart_get_divisor(port, baud) - 1) & 0x3ff; - if (unlikely((baud < 900) || (baud > 921600))) - div |= 7; - else - div |= (921600 / baud) - 1; + /* Effective baud rate */ + baud = port->uartclk / 16 / ((div & 0x3ff) + 1); while ((vt8500_read(port, VT8500_URUSR) & (1 << 5)) && --loops) cpu_relax(); + vt8500_write(port, div, VT8500_URDIV); + /* Break signal timing depends on baud rate, update accordingly */ + vt8500_write(port, mult_frac(baud, 4096, 1000000), VT8500_URBKR); + return baud; } @@ -660,6 +668,10 @@ static int vt8500_serial_probe(struct platform_device *pdev) } vt8500_port->vt8500_uart_flags = *flags; + vt8500_port->clk_predivisor = DIV_ROUND_CLOSEST( + clk_get_rate(vt8500_port->clk), + VT8500_RECOMMENDED_CLK + ); vt8500_port->uart.type = PORT_VT8500; vt8500_port->uart.iotype = UPIO_MEM; vt8500_port->uart.mapbase = mmres->start; @@ -670,7 +682,10 @@ static int vt8500_serial_probe(struct platform_device *pdev) vt8500_port->uart.dev = &pdev->dev; vt8500_port->uart.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF; - vt8500_port->uart.uartclk = clk_get_rate(vt8500_port->clk); + /* Serial core uses the magic "16" everywhere - adjust for it */ + vt8500_port->uart.uartclk = 16 * clk_get_rate(vt8500_port->clk) / + vt8500_port->clk_predivisor / + VT8500_OVERSAMPLING_DIVISOR; snprintf(vt8500_port->name, sizeof(vt8500_port->name), "VT8500 UART%d", pdev->id);