Received: by 10.223.185.116 with SMTP id b49csp5914112wrg; Wed, 28 Feb 2018 00:29:22 -0800 (PST) X-Google-Smtp-Source: AG47ELsOPhe24n2fHL+MmLSoEiUAr8yhRTxEu4xofpG7+cFl/BK+JMLNBQhJa4IU1cqkmiB9Ygdc X-Received: by 2002:a17:902:526:: with SMTP id 35-v6mr2055289plf.276.1519806562548; Wed, 28 Feb 2018 00:29:22 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1519806562; cv=none; d=google.com; s=arc-20160816; b=ruvAc0XijGqFNvv9iMzW8hMQ3D7Mi74UyMv2q+4SoYDq8vAHhiuLFHZ5Me9JCvYFj2 v0K4oboYnlJoCI/B/U/KbwAzCPLnus7VBxKCS6L4OGFd6RZztR4CcV0Viq4e+lW2SfBG tMtUl4RwsPzi3YM3w9ZhpUrLjE/xG0P+PWM8wpXav6IFEQ+dciIfXGyCHjNW2PfxVM14 1hlAzMGaOGgo8kVmiBbhqicREID0D5zj8pt8cbkf0KXxAtb1I0UKVCRB+jAYYYnwriiG 2OgOK9ajRJ8GbnbkwkusMOys14zT0r0BcgT8BUduVPV9T6nx8XzMRCjZX8IoxkR2LVe9 ohpA== 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=NsvQ7BlUos2pZbp4U3FZYtmEJ5rhh/KAMSf+Ix8COZc=; b=rqKqqLFyz12zWd2IJdc7fEADy1UkJuxKdt31rIGRDDn3UtY5hjhZQSLPBRgF1FS+m7 i/B0qGjvQ/Xt3mJ/2Tg3AvgbsDEdrBamWFk+Xp+XkFo1jbvrXOfVu9lVnt5fHHUCYqqc 3IW1RTjVCjmjvvWRgklZXzBlFO79hS/P46Le+ZsxQK6mUjLWP5YijPsqXT96ehMUgSja 23SGIxZUmzofgeQs5BaArPv34ZXvaD++ibR66Jjf9znh6Tg7li1fgr/ZUJmLi5rhKekX ffviUx/3yVPNnBbuJMZAm/MOq6WTCwtMKThKrCfbCJIdeb01BZD5QQG/AHhcNbLcQDSp Qm0g== 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 h62si701760pgc.723.2018.02.28.00.29.05; Wed, 28 Feb 2018 00:29:22 -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 S1752174AbeB1I1g (ORCPT + 99 others); Wed, 28 Feb 2018 03:27:36 -0500 Received: from mx2.suse.de ([195.135.220.15]:42321 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751686AbeB1I1f (ORCPT ); Wed, 28 Feb 2018 03:27:35 -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 05A8CAC0D; Wed, 28 Feb 2018 08:27:34 +0000 (UTC) From: Michael Moese To: Greg KH Cc: Linux Kernel Mailinglist , Johannes Thumshirn , Michael Moese , Andreas Geissler , Ben Turner , Andy Shevchenko Subject: [PATCH v2] 8250-men-mcb: add support for 16z025 and 16z057 Date: Wed, 28 Feb 2018 09:27:26 +0100 Message-Id: <20180228082726.21535-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 --- 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 | 124 ++++++++++++++++++++++++--------- drivers/tty/serial/8250/Kconfig | 5 +- 2 files changed, 93 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..98b6b919bca6 100644 --- a/drivers/tty/serial/8250/8250_men_mcb.c +++ b/drivers/tty/serial/8250/8250_men_mcb.c @@ -7,6 +7,12 @@ #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 +24,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 +34,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 +49,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 +167,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