Received: by 10.223.185.116 with SMTP id b49csp5083974wrg; Tue, 27 Feb 2018 07:33:16 -0800 (PST) X-Google-Smtp-Source: AH8x2252HGOFQyiJZtGiRovEu5Zy+MqyHamZcKAXUpLHTkLpv34Gzp7XW7OJR0PpNyTifQM9fMKO X-Received: by 10.101.101.204 with SMTP id y12mr11793893pgv.450.1519745596775; Tue, 27 Feb 2018 07:33:16 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1519745596; cv=none; d=google.com; s=arc-20160816; b=h7TrByLye/KGzFJq4l9ucUCSWpIjyK0542h76u2GXvccYngX7p/KFzk+Z5dsKUDzN6 Eq5D+52PsUv/iZ6D82Yqt3tSeMouhkIERG9Lv5CmoEzmlU1gMEJNYboNfyKwlzc17CRT eglocylTCf+HvwXL0J432ycolgyL2SY//ZnVe2J3gybxv0Tz0k1Qjj86Ho1Y9a28hVZL dGyHTk6UHE0GGRpR5mCJn5d24xwZyG4fpuR38cMQqVatb94VwXuSq1nmu72LRWiwqxWG CDgSw0DDccx89RsqDfB1+cQPdWr3DQFWk6y69TWUChbgKrR65a706RYYnokfJaEMg8v8 b/hg== 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=/rzYIdUwNgCQMUPGFdx4Jo4TH1w1UqNZZleh9KVIxms=; b=lZU2XNtAhLYi77Bt/zBPict71sUB49tlNBywr4OYP183NpZ64wf2od39TPcF4NWqU6 13tqf/BTY48K6Nd1xwLKSuzOL6aHD2CURfMthwymMpfnwbuSt5QV+tFFaGNpShnGMHR0 4pTsY/FY85ypqX/JbPXbF3ZsBXKyD/nQJwndZGRLcHsGpDDblgV5dVluNiVj5kV9TIn0 VAiItWAsc7Nyb/HJzZcHYj8+wa/gTboIi91yOyf4e+wRc5rikcq0VemyB1ymZAqnK74Z yCIrLOtWtoUgcBi7+mSSZ6wEzt4MWiu+7K/0MyV9fXfeygYqyon7orlWz9WUo2psnx68 OKxw== 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 o1-v6si8742496pld.546.2018.02.27.07.33.01; Tue, 27 Feb 2018 07:33:16 -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 S1753496AbeB0Pb2 (ORCPT + 99 others); Tue, 27 Feb 2018 10:31:28 -0500 Received: from mx2.suse.de ([195.135.220.15]:38994 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752798AbeB0Pb1 (ORCPT ); Tue, 27 Feb 2018 10:31:27 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 935A8AEB3; Tue, 27 Feb 2018 15:31:25 +0000 (UTC) From: Michael Moese To: Greg KH Cc: Linux Kernel Mailinglist , Johannes Thumshirn , Michael Moese , Andreas Geissler , Ben Turner Subject: [PATCH] 8250-men-mcb: add support for 16z025 and 16z057 Date: Tue, 27 Feb 2018 16:31:06 +0100 Message-Id: <20180227153106.3224-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 --- drivers/tty/serial/8250/8250_men_mcb.c | 132 ++++++++++++++++++++++++--------- drivers/tty/serial/8250/Kconfig | 5 +- 2 files changed, 100 insertions(+), 37 deletions(-) diff --git a/drivers/tty/serial/8250/8250_men_mcb.c b/drivers/tty/serial/8250/8250_men_mcb.c index 308977807994..47abcb8d834f 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"); @@ -46,57 +54,109 @@ static int serial_8250_men_mcb_probe(struct mcb_device *mdev, { struct serial_8250_men_mcb_data *data; struct resource *mem; + unsigned int num_ports; + unsigned int i; + void __iomem *membase; + + mem = mcb_get_resource(mdev, IORESOURCE_MEM); + if (mem == NULL) + return -ENXIO; - data = devm_kzalloc(&mdev->dev, + membase = devm_ioremap_resource(&mdev->dev, mem); + if (IS_ERR(membase)) + return PTR_ERR_OR_ZERO(membase); + + switch (mdev->id) { + case MEN_UART_ID_Z125: + num_ports = 1U; + break; + case MEN_UART_ID_Z025: + num_ports = readb(membase) >> 4; + break; + case MEN_UART_ID_Z057: + num_ports = 4U; + break; + default: + dev_err(&mdev->dev, "no supported device!\n"); + return -ENODEV; + } + dev_dbg(&mdev->dev, "found a 16z%03u with %u ports\n", + mdev->id, num_ports); + + if (num_ports == 0 || num_ports > 4) { + dev_err(&mdev->dev, "unexpected number of ports: %u\n", + num_ports); + return -ENODEV; + } + + data = devm_kcalloc(&mdev->dev, num_ports, 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; - - mem = mcb_get_resource(mdev, IORESOURCE_MEM); - if (mem == NULL) - return -ENXIO; - - data->uart.port.irq = mcb_get_irq(mdev); - 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); - - data->uart.port.mapbase = (unsigned long) mem->start; - data->uart.port.iobase = data->uart.port.mapbase; - - /* ok, register the port */ - data->line = serial8250_register_8250_port(&data->uart); - if (data->line < 0) - return data->line; - - dev_info(&mdev->dev, "found 16Z125 UART: ttyS%d\n", data->line); + 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; + + switch (mdev->id) { + case MEN_UART_ID_Z125: + num_ports = 1U; + break; + case MEN_UART_ID_Z025: + num_ports = readb(data[0].uart.port.membase) >> 4; + break; + case MEN_UART_ID_Z057: + num_ports = 4U; + break; + default: + dev_err(&mdev->dev, "no supported device!\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 +173,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