linux/drivers/tty/serial/8250/8250_ioc3.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * SGI IOC3 8250 UART driver
   4 *
   5 * Copyright (C) 2019 Thomas Bogendoerfer <tbogendoerfer@suse.de>
   6 *
   7 * based on code Copyright (C) 2005 Stanislaw Skowronek <skylark@unaligned.org>
   8 *               Copyright (C) 2014 Joshua Kinard <kumba@gentoo.org>
   9 */
  10
  11#include <linux/module.h>
  12#include <linux/errno.h>
  13#include <linux/io.h>
  14#include <linux/platform_device.h>
  15
  16#include "8250.h"
  17
  18#define IOC3_UARTCLK (22000000 / 3)
  19
  20struct ioc3_8250_data {
  21        int line;
  22};
  23
  24static unsigned int ioc3_serial_in(struct uart_port *p, int offset)
  25{
  26        return readb(p->membase + (offset ^ 3));
  27}
  28
  29static void ioc3_serial_out(struct uart_port *p, int offset, int value)
  30{
  31        writeb(value, p->membase + (offset ^ 3));
  32}
  33
  34static int serial8250_ioc3_probe(struct platform_device *pdev)
  35{
  36        struct ioc3_8250_data *data;
  37        struct uart_8250_port up;
  38        struct resource *r;
  39        void __iomem *membase;
  40        int irq, line;
  41
  42        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  43        if (!r)
  44                return -ENODEV;
  45
  46        data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
  47        if (!data)
  48                return -ENOMEM;
  49
  50        membase = devm_ioremap(&pdev->dev, r->start, resource_size(r));
  51        if (!membase)
  52                return -ENOMEM;
  53
  54        irq = platform_get_irq(pdev, 0);
  55        if (irq < 0)
  56                irq = 0; /* no interrupt -> use polling */
  57
  58        /* Register serial ports with 8250.c */
  59        memset(&up, 0, sizeof(struct uart_8250_port));
  60        up.port.iotype = UPIO_MEM;
  61        up.port.uartclk = IOC3_UARTCLK;
  62        up.port.type = PORT_16550A;
  63        up.port.irq = irq;
  64        up.port.flags = (UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ);
  65        up.port.dev = &pdev->dev;
  66        up.port.membase = membase;
  67        up.port.mapbase = r->start;
  68        up.port.serial_in = ioc3_serial_in;
  69        up.port.serial_out = ioc3_serial_out;
  70        line = serial8250_register_8250_port(&up);
  71        if (line < 0)
  72                return line;
  73
  74        platform_set_drvdata(pdev, data);
  75        return 0;
  76}
  77
  78static int serial8250_ioc3_remove(struct platform_device *pdev)
  79{
  80        struct ioc3_8250_data *data = platform_get_drvdata(pdev);
  81
  82        serial8250_unregister_port(data->line);
  83        return 0;
  84}
  85
  86static struct platform_driver serial8250_ioc3_driver = {
  87        .probe  = serial8250_ioc3_probe,
  88        .remove = serial8250_ioc3_remove,
  89        .driver = {
  90                .name = "ioc3-serial8250",
  91        }
  92};
  93
  94module_platform_driver(serial8250_ioc3_driver);
  95
  96MODULE_AUTHOR("Thomas Bogendoerfer <tbogendoerfer@suse.de>");
  97MODULE_DESCRIPTION("SGI IOC3 8250 UART driver");
  98MODULE_LICENSE("GPL");
  99