Received: by 10.223.185.116 with SMTP id b49csp2704051wrg; Mon, 5 Mar 2018 07:25:43 -0800 (PST) X-Google-Smtp-Source: AG47ELuu8p2mNiwS9tAmE6+Go7wn3pkw/RGlgiRAPNxmWPj6vmJ+OAv7t0qHAFsNukjuEJTBvOrU X-Received: by 2002:a17:902:b083:: with SMTP id p3-v6mr11539710plr.314.1520263543129; Mon, 05 Mar 2018 07:25:43 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1520263543; cv=none; d=google.com; s=arc-20160816; b=DrScbKTKPhZjoMG3YZTUkWeqaxWT+n3Noo7UPXzVbH+d/tpEOx9cA3SNMUp0Q4jNLv GR059f71Ty44/QgZQJ7jRM4nZgEBtHupb0l3XcWiDbUmL5VyIULjKh0UR4f3IFZwuFaq cPRoWMYZ8MTUDcTZ/Nl97biDxjR0SmmQy2XtcrFs7xcVpOwPGdo8befw0djDw6ce9hOU rD3ULCuYieEu/M0sFcnVKo/JNSs+vM7uIFewwjx/ClwktWlASEcPxRVm31vUayhKZf5A ZZ2KCvLV2M+GCDOWa+9I0LrQGCqb0KqedAY+V/SWTpYf5PAkJoLAqP014CDIDqtIcgLh 1tKg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:subject:cc:to:from :arc-authentication-results; bh=1jAz0XCn2aP4nzsh8KpSU8N/XRltw9EUxn2xIYgEGUA=; b=uOOvWORNsNp9o7NbCiu6YZzQ9rLUpayl+y2tJNgNdt/d7TXLSb5NFMjKl3l1crnO+S DuhkVcifX37jXNXDwNBo5V42rODBqFKJHl9DrW0N7bSQSnOOlFAICPpp4vVoSWxRAaRM dGElST8aGjXOkSM1nfyI/RrzwC4zBC/54bLqbn31vOSCXb+2AN7P6HBXyY96kBzV/uel uBWGljxTHzt3K32UHJ0uktaWMAJUk+98FTPjB605sX8DGiYTEN1zoCshSxLJrLUXBu1v ZAxIxk0EYYTweIMBLCm7/2OU3OAWOiFHKMc8OQfDY1QIq8kc+9fIjn742K8wZSsBQA5y ES+g== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id h186si8388255pge.814.2018.03.05.07.25.28; Mon, 05 Mar 2018 07:25:43 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752083AbeCEPYZ (ORCPT + 99 others); Mon, 5 Mar 2018 10:24:25 -0500 Received: from mx2.suse.de ([195.135.220.15]:36351 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751294AbeCEPYY (ORCPT ); Mon, 5 Mar 2018 10:24:24 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 45BB0ADFF; Mon, 5 Mar 2018 15:24:23 +0000 (UTC) From: Michael Moese To: Greg KH Cc: Linux Kernel Mailinglist , Johannes Thumshirn , Michael Moese , Andreas Geissler , Ben Turner , Andy Shevchenko Subject: [PATCH v3] 8250-men-mcb: add support for 16z025 and 16z057 Date: Mon, 5 Mar 2018 16:24:21 +0100 Message-Id: <20180305152421.29808-1-mmoese@suse.de> X-Mailer: git-send-email 2.13.6 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add support for two MEN UARTs (16z025 and 16z057) to the 8250_men_mcb driver. The 16z025 consists of up to four ports, the 16z057 has exactly four ports. Apart from that, all of them share the Port settings. Signed-off-by: Michael Moese Reported-by: Ben Turner Tested-by: Ben Turner --- Sorry for the resend, I messed up the previoius patch.. Changes to v2: Added include of linux/io.h due to finding of kbuild robot. Changes to v1: Deduplicated the two switch() blocks into a function returning the number of ports. Minor style corrections. --- drivers/tty/serial/8250/8250_men_mcb.c | 125 ++++++++++++++++++++++++--------- drivers/tty/serial/8250/Kconfig | 5 +- 2 files changed, 94 insertions(+), 36 deletions(-) diff --git a/drivers/tty/serial/8250/8250_men_mcb.c b/drivers/tty/serial/8250/8250_men_mcb.c index 308977807994..127017cc41d9 100644 --- a/drivers/tty/serial/8250/8250_men_mcb.c +++ b/drivers/tty/serial/8250/8250_men_mcb.c @@ -1,12 +1,19 @@ #include #include #include +#include #include #include #include #include #include +#define MEN_UART_ID_Z025 0x19 +#define MEN_UART_ID_Z057 0x39 +#define MEN_UART_ID_Z125 0x7d + +#define MEN_UART_MEM_SIZE 0x10 + struct serial_8250_men_mcb_data { struct uart_8250_port uart; int line; @@ -18,7 +25,7 @@ struct serial_8250_men_mcb_data { * parameter in order to really set the correct baudrate, and * do so if possible without user interaction */ -static u32 men_z125_lookup_uartclk(struct mcb_device *mdev) +static u32 men_lookup_uartclk(struct mcb_device *mdev) { /* use default value if board is not available below */ u32 clkval = 1041666; @@ -28,10 +35,12 @@ static u32 men_z125_lookup_uartclk(struct mcb_device *mdev) mdev->bus->name); if (strncmp(mdev->bus->name, "F075", 4) == 0) clkval = 1041666; - else if (strncmp(mdev->bus->name, "F216", 4) == 0) + else if (strncmp(mdev->bus->name, "F216", 4) == 0) clkval = 1843200; else if (strncmp(mdev->bus->name, "G215", 4) == 0) clkval = 1843200; + else if (strncmp(mdev->bus->name, "F210", 4) == 0) + clkval = 115200; else dev_info(&mdev->dev, "board not detected, using default uartclk\n"); @@ -41,62 +50,108 @@ static u32 men_z125_lookup_uartclk(struct mcb_device *mdev) return clkval; } +static unsigned int get_num_ports(struct mcb_device *mdev, + void __iomem *membase) +{ + switch (mdev->id) { + case MEN_UART_ID_Z125: + return 1U; + case MEN_UART_ID_Z025: + return readb(membase) >> 4; + case MEN_UART_ID_Z057: + return 4U; + default: + dev_err(&mdev->dev, "no supported device!\n"); + return -ENODEV; + } +} + static int serial_8250_men_mcb_probe(struct mcb_device *mdev, const struct mcb_device_id *id) { struct serial_8250_men_mcb_data *data; struct resource *mem; - - data = devm_kzalloc(&mdev->dev, - sizeof(struct serial_8250_men_mcb_data), - GFP_KERNEL); - if (!data) - return -ENOMEM; - - mcb_set_drvdata(mdev, data); - data->uart.port.dev = mdev->dma_dev; - spin_lock_init(&data->uart.port.lock); - - data->uart.port.type = PORT_16550; - data->uart.port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE; - data->uart.port.iotype = UPIO_MEM; - data->uart.port.uartclk = men_z125_lookup_uartclk(mdev); - data->uart.port.regshift = 0; - data->uart.port.fifosize = 60; + unsigned int num_ports; + unsigned int i; + void __iomem *membase; mem = mcb_get_resource(mdev, IORESOURCE_MEM); if (mem == NULL) return -ENXIO; + membase = devm_ioremap_resource(&mdev->dev, mem); + if (IS_ERR(membase)) + return PTR_ERR_OR_ZERO(membase); - data->uart.port.irq = mcb_get_irq(mdev); + num_ports = get_num_ports(mdev, membase); - data->uart.port.membase = devm_ioremap_resource(&mdev->dev, mem); - if (IS_ERR(data->uart.port.membase)) - return PTR_ERR_OR_ZERO(data->uart.port.membase); + dev_dbg(&mdev->dev, "found a 16z%03u with %u ports\n", + mdev->id, num_ports); - data->uart.port.mapbase = (unsigned long) mem->start; - data->uart.port.iobase = data->uart.port.mapbase; + if (num_ports == 0 || num_ports > 4) { + dev_err(&mdev->dev, "unexpected number of ports: %u\n", + num_ports); + return -ENODEV; + } - /* ok, register the port */ - data->line = serial8250_register_8250_port(&data->uart); - if (data->line < 0) - return data->line; + data = devm_kcalloc(&mdev->dev, num_ports, + sizeof(struct serial_8250_men_mcb_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; - dev_info(&mdev->dev, "found 16Z125 UART: ttyS%d\n", data->line); + mcb_set_drvdata(mdev, data); + + for (i = 0; i < num_ports; i++) { + data[i].uart.port.dev = mdev->dma_dev; + spin_lock_init(&data[i].uart.port.lock); + + data[i].uart.port.type = PORT_16550; + data[i].uart.port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ + | UPF_FIXED_TYPE; + data[i].uart.port.iotype = UPIO_MEM; + data[i].uart.port.uartclk = men_lookup_uartclk(mdev); + data[i].uart.port.regshift = 0; + data[i].uart.port.irq = mcb_get_irq(mdev); + data[i].uart.port.membase = membase; + data[i].uart.port.fifosize = 60; + data[i].uart.port.mapbase = (unsigned long) mem->start + + i * MEN_UART_MEM_SIZE; + data[i].uart.port.iobase = data[i].uart.port.mapbase; + + /* ok, register the port */ + data[i].line = serial8250_register_8250_port(&data[i].uart); + if (data[i].line < 0) { + dev_err(&mdev->dev, "unable to register UART port\n"); + return data[i].line; + } + dev_info(&mdev->dev, "found MCB UART: ttyS%d\n", data[i].line); + } return 0; } static void serial_8250_men_mcb_remove(struct mcb_device *mdev) { + unsigned int num_ports, i; struct serial_8250_men_mcb_data *data = mcb_get_drvdata(mdev); - if (data) - serial8250_unregister_port(data->line); + if (!data) + return; + + num_ports = get_num_ports(mdev, data[0].uart.port.membase); + if (num_ports < 0 || num_ports > 4) { + dev_err(&mdev->dev, "error retrieving number of ports!\n"); + return; + } + + for (i = 0; i < num_ports; i++) + serial8250_unregister_port(data[i].line); } static const struct mcb_device_id serial_8250_men_mcb_ids[] = { - { .device = 0x7d }, + { .device = MEN_UART_ID_Z025 }, + { .device = MEN_UART_ID_Z057 }, + { .device = MEN_UART_ID_Z125 }, { } }; MODULE_DEVICE_TABLE(mcb, serial_8250_men_mcb_ids); @@ -113,6 +168,8 @@ static struct mcb_driver mcb_driver = { module_mcb_driver(mcb_driver); MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("MEN 16z125 8250 UART driver"); +MODULE_DESCRIPTION("MEN 8250 UART driver"); MODULE_AUTHOR("Michael Moese