From patchwork Sat Jan 9 13:07:33 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Sperl X-Patchwork-Id: 7992301 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 20D239F716 for ; Sat, 9 Jan 2016 13:09:50 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 14ABF20122 for ; Sat, 9 Jan 2016 13:09:49 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 1D77A20117 for ; Sat, 9 Jan 2016 13:09:48 +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 1aHtFq-0005Ew-JC; Sat, 09 Jan 2016 13:08:26 +0000 Received: from 212-186-180-163.dynamic.surfer.at ([212.186.180.163] helo=cgate.sperl.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1aHtFY-0005BV-Ms; Sat, 09 Jan 2016 13:08:10 +0000 Received: from raspcm.intern.sperl.org (account martin@sperl.org [10.10.10.41] verified) by sperl.org (CommuniGate Pro SMTP 6.1.2) with ESMTPSA id 6391325; Sat, 09 Jan 2016 13:07:41 +0000 From: kernel@martin.sperl.org To: Stephen Warren , Lee Jones , Eric Anholt , Greg Kroah-Hartman , Jiri Slaby , devicetree@vger.kernel.org, linux-rpi-kernel@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-serial@vger.kernel.org Subject: [PATCH V2 2/2] serial: bcm2835: add driver for bcm2835-aux-uart Date: Sat, 9 Jan 2016 13:07:33 +0000 Message-Id: <1452344854-2576-3-git-send-email-kernel@martin.sperl.org> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1452344854-2576-1-git-send-email-kernel@martin.sperl.org> References: <1452344854-2576-1-git-send-email-kernel@martin.sperl.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160109_050809_224621_CF8F09CA X-CRM114-Status: GOOD ( 18.47 ) X-Spam-Score: -0.9 (/) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Martin Sperl 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=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, 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 From: Martin Sperl The bcm2835 SOC contains an auxiliary uart, which is very close to the ns16550 with some differences. The big difference is that the uart HW is not using an internal divider of 16 but 8, which results in an effictive baud-rate being twice the requested baud-rate. This driver handles this device correctly and handles the difference in the HW divider by scaling up the clock ba a factor of 2. The approach to write a separate (wrapper) driver instead of using a multiplying clock and "ns16550" as compatibility in the device-tree has been recommended by Stephen Warren. Signed-off-by: Martin Sperl --- drivers/tty/serial/8250/8250_bcm2835aux.c | 143 +++++++++++++++++++++++++++++ drivers/tty/serial/8250/Kconfig | 8 ++ drivers/tty/serial/8250/Makefile | 1 + 3 files changed, 152 insertions(+) create mode 100644 drivers/tty/serial/8250/8250_bcm2835aux.c diff --git a/drivers/tty/serial/8250/8250_bcm2835aux.c b/drivers/tty/serial/8250/8250_bcm2835aux.c new file mode 100644 index 0000000..718c357 --- /dev/null +++ b/drivers/tty/serial/8250/8250_bcm2835aux.c @@ -0,0 +1,143 @@ +/* + * Serial port driver for BCM2835AUX UART + * + * Copyright (C) 2016 Martin Sperl + * + * Based on 8250_lpc18xx.c: + * Copyright (C) 2015 Joachim Eastwood + * + * 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 +#include +#include +#include +#include + +#include "8250.h" + +struct bcm2835aux_data { + struct uart_8250_port uart; + struct clk *clk; +}; + +static int bcm2835aux_serial_probe(struct platform_device *pdev) +{ + struct bcm2835aux_data *data; + struct resource *res; + int ret; + + /* allocate the custom structure */ + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + /* initialize data */ + spin_lock_init(&data->uart.port.lock); + data->uart.port.dev = &pdev->dev; + data->uart.port.regshift = 2; + data->uart.port.type = PORT_16550; + data->uart.port.iotype = UPIO_MEM; + data->uart.port.fifosize = 8; + data->uart.port.flags = UPF_SHARE_IRQ | + UPF_FIXED_PORT | + UPF_FIXED_TYPE | + UPF_SKIP_TEST; + + /* get the clock - this also enables the HW */ + data->clk = devm_clk_get(&pdev->dev, NULL); + ret = PTR_ERR_OR_ZERO(data->clk); + if (ret) { + dev_err(&pdev->dev, "could not get clk: %d\n", ret); + return ret; + } + + /* get the interrupt */ + data->uart.port.irq = platform_get_irq(pdev, 0); + if (data->uart.port.irq < 0) { + dev_err(&pdev->dev, "irq not found - %i", + data->uart.port.irq); + return data->uart.port.irq; + } + + /* map the main registers */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "memory resource not found"); + return -EINVAL; + } + data->uart.port.membase = devm_ioremap_resource(&pdev->dev, res); + ret = PTR_ERR_OR_ZERO(data->uart.port.membase); + if (ret) + return ret; + + /* Check for a fixed line number */ + ret = of_alias_get_id(pdev->dev.of_node, "serial"); + if (ret >= 0) + data->uart.port.line = ret; + + /* enable the clock as a last step */ + ret = clk_prepare_enable(data->clk); + if (ret) { + dev_err(&pdev->dev, "unable to enable uart clock\n"); + return ret; + } + + /* the HW-clock divider for bcm2835aux is 8, + * but 8250 expects a divider of 16, + * so we have to multiply the actual clock by 2 + * to get identical baudrates. + */ + data->uart.port.uartclk = clk_get_rate(data->clk) * 2; + + /* register the port */ + ret = serial8250_register_8250_port(&data->uart); + if (ret < 0) { + dev_err(&pdev->dev, + "unable to register 8250 port - %d\n", ret); + goto dis_clk; + } + data->uart.port.line = ret; + + platform_set_drvdata(pdev, data); + + return 0; + +dis_clk: + clk_disable_unprepare(data->clk); + return ret; +} + +static int bcm2835aux_serial_remove(struct platform_device *pdev) +{ + struct bcm2835aux_data *data = platform_get_drvdata(pdev); + + serial8250_unregister_port(data->uart.port.line); + clk_disable_unprepare(data->clk); + + return 0; +} + +static const struct of_device_id bcm2835aux_serial_match[] = { + { .compatible = "brcm,bcm2835-aux-uart" }, + { }, +}; +MODULE_DEVICE_TABLE(of, bcm2835aux_serial_match); + +static struct platform_driver bcm2835aux_serial_driver = { + .driver = { + .name = "bcm2835-aux-uart", + .of_match_table = bcm2835aux_serial_match, + }, + .probe = bcm2835aux_serial_probe, + .remove = bcm2835aux_serial_remove, +}; +module_platform_driver(bcm2835aux_serial_driver); + +MODULE_DESCRIPTION("BCM2835 auxiliar UART driver"); +MODULE_AUTHOR("Martin Sperl "); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index 6412f14..105aa19 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -272,6 +272,14 @@ config SERIAL_8250_ACORN system, say Y to this option. The driver can handle 1, 2, or 3 port cards. If unsure, say N. +config SERIAL_8250_BCM2835AUX + tristate "BCM2835 auxiliar uart support" + depends on ARCH_BCM2835 || COMPILE_TEST + depends on SERIAL_8250 && SERIAL_8250_SHARE_IRQ + help + support for the BCM2835 auxiliar uart. + If unsure, say N. + config SERIAL_8250_FSL bool depends on SERIAL_8250_CONSOLE diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile index e177f86..6327d0a 100644 --- a/drivers/tty/serial/8250/Makefile +++ b/drivers/tty/serial/8250/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_SERIAL_8250_PCI) += 8250_pci.o obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o obj-$(CONFIG_SERIAL_8250_CS) += serial_cs.o obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o +obj-$(CONFIG_SERIAL_8250_BCM2835AUX) += 8250_bcm2835aux.o obj-$(CONFIG_SERIAL_8250_CONSOLE) += 8250_early.o obj-$(CONFIG_SERIAL_8250_FOURPORT) += 8250_fourport.o obj-$(CONFIG_SERIAL_8250_ACCENT) += 8250_accent.o