root/drivers/tty/serial/8250/8250_uniphier.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. uniphier_early_console_setup
  2. uniphier_serial_in
  3. uniphier_serial_out
  4. uniphier_serial_dl_read
  5. uniphier_serial_dl_write
  6. uniphier_uart_probe
  7. uniphier_uart_remove
  8. uniphier_uart_suspend
  9. uniphier_uart_resume

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
   4  */
   5 
   6 #include <linux/clk.h>
   7 #include <linux/console.h>
   8 #include <linux/io.h>
   9 #include <linux/module.h>
  10 #include <linux/of.h>
  11 #include <linux/platform_device.h>
  12 
  13 #include "8250.h"
  14 
  15 /*
  16  * This hardware is similar to 8250, but its register map is a bit different:
  17  *   - MMIO32 (regshift = 2)
  18  *   - FCR is not at 2, but 3
  19  *   - LCR and MCR are not at 3 and 4, they share 4
  20  *   - No SCR (Instead, CHAR can be used as a scratch register)
  21  *   - Divisor latch at 9, no divisor latch access bit
  22  */
  23 
  24 #define UNIPHIER_UART_REGSHIFT          2
  25 
  26 /* bit[15:8] = CHAR, bit[7:0] = FCR */
  27 #define UNIPHIER_UART_CHAR_FCR          (3 << (UNIPHIER_UART_REGSHIFT))
  28 /* bit[15:8] = LCR, bit[7:0] = MCR */
  29 #define UNIPHIER_UART_LCR_MCR           (4 << (UNIPHIER_UART_REGSHIFT))
  30 /* Divisor Latch Register */
  31 #define UNIPHIER_UART_DLR               (9 << (UNIPHIER_UART_REGSHIFT))
  32 
  33 struct uniphier8250_priv {
  34         int line;
  35         struct clk *clk;
  36         spinlock_t atomic_write_lock;
  37 };
  38 
  39 #ifdef CONFIG_SERIAL_8250_CONSOLE
  40 static int __init uniphier_early_console_setup(struct earlycon_device *device,
  41                                                const char *options)
  42 {
  43         if (!device->port.membase)
  44                 return -ENODEV;
  45 
  46         /* This hardware always expects MMIO32 register interface. */
  47         device->port.iotype = UPIO_MEM32;
  48         device->port.regshift = UNIPHIER_UART_REGSHIFT;
  49 
  50         /*
  51          * Do not touch the divisor register in early_serial8250_setup();
  52          * we assume it has been initialized by a boot loader.
  53          */
  54         device->baud = 0;
  55 
  56         return early_serial8250_setup(device, options);
  57 }
  58 OF_EARLYCON_DECLARE(uniphier, "socionext,uniphier-uart",
  59                     uniphier_early_console_setup);
  60 #endif
  61 
  62 /*
  63  * The register map is slightly different from that of 8250.
  64  * IO callbacks must be overridden for correct access to FCR, LCR, MCR and SCR.
  65  */
  66 static unsigned int uniphier_serial_in(struct uart_port *p, int offset)
  67 {
  68         unsigned int valshift = 0;
  69 
  70         switch (offset) {
  71         case UART_SCR:
  72                 /* No SCR for this hardware.  Use CHAR as a scratch register */
  73                 valshift = 8;
  74                 offset = UNIPHIER_UART_CHAR_FCR;
  75                 break;
  76         case UART_LCR:
  77                 valshift = 8;
  78                 /* fall through */
  79         case UART_MCR:
  80                 offset = UNIPHIER_UART_LCR_MCR;
  81                 break;
  82         default:
  83                 offset <<= UNIPHIER_UART_REGSHIFT;
  84                 break;
  85         }
  86 
  87         /*
  88          * The return value must be masked with 0xff because some registers
  89          * share the same offset that must be accessed by 32-bit write/read.
  90          * 8 or 16 bit access to this hardware result in unexpected behavior.
  91          */
  92         return (readl(p->membase + offset) >> valshift) & 0xff;
  93 }
  94 
  95 static void uniphier_serial_out(struct uart_port *p, int offset, int value)
  96 {
  97         unsigned int valshift = 0;
  98         bool normal = false;
  99 
 100         switch (offset) {
 101         case UART_SCR:
 102                 /* No SCR for this hardware.  Use CHAR as a scratch register */
 103                 valshift = 8;
 104                 /* fall through */
 105         case UART_FCR:
 106                 offset = UNIPHIER_UART_CHAR_FCR;
 107                 break;
 108         case UART_LCR:
 109                 valshift = 8;
 110                 /* Divisor latch access bit does not exist. */
 111                 value &= ~UART_LCR_DLAB;
 112                 /* fall through */
 113         case UART_MCR:
 114                 offset = UNIPHIER_UART_LCR_MCR;
 115                 break;
 116         default:
 117                 offset <<= UNIPHIER_UART_REGSHIFT;
 118                 normal = true;
 119                 break;
 120         }
 121 
 122         if (normal) {
 123                 writel(value, p->membase + offset);
 124         } else {
 125                 /*
 126                  * Special case: two registers share the same address that
 127                  * must be 32-bit accessed.  As this is not longer atomic safe,
 128                  * take a lock just in case.
 129                  */
 130                 struct uniphier8250_priv *priv = p->private_data;
 131                 unsigned long flags;
 132                 u32 tmp;
 133 
 134                 spin_lock_irqsave(&priv->atomic_write_lock, flags);
 135                 tmp = readl(p->membase + offset);
 136                 tmp &= ~(0xff << valshift);
 137                 tmp |= value << valshift;
 138                 writel(tmp, p->membase + offset);
 139                 spin_unlock_irqrestore(&priv->atomic_write_lock, flags);
 140         }
 141 }
 142 
 143 /*
 144  * This hardware does not have the divisor latch access bit.
 145  * The divisor latch register exists at different address.
 146  * Override dl_read/write callbacks.
 147  */
 148 static int uniphier_serial_dl_read(struct uart_8250_port *up)
 149 {
 150         return readl(up->port.membase + UNIPHIER_UART_DLR);
 151 }
 152 
 153 static void uniphier_serial_dl_write(struct uart_8250_port *up, int value)
 154 {
 155         writel(value, up->port.membase + UNIPHIER_UART_DLR);
 156 }
 157 
 158 static int uniphier_uart_probe(struct platform_device *pdev)
 159 {
 160         struct device *dev = &pdev->dev;
 161         struct uart_8250_port up;
 162         struct uniphier8250_priv *priv;
 163         struct resource *regs;
 164         void __iomem *membase;
 165         int irq;
 166         int ret;
 167 
 168         regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 169         if (!regs) {
 170                 dev_err(dev, "failed to get memory resource\n");
 171                 return -EINVAL;
 172         }
 173 
 174         membase = devm_ioremap(dev, regs->start, resource_size(regs));
 175         if (!membase)
 176                 return -ENOMEM;
 177 
 178         irq = platform_get_irq(pdev, 0);
 179         if (irq < 0)
 180                 return irq;
 181 
 182         priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 183         if (!priv)
 184                 return -ENOMEM;
 185 
 186         memset(&up, 0, sizeof(up));
 187 
 188         ret = of_alias_get_id(dev->of_node, "serial");
 189         if (ret < 0) {
 190                 dev_err(dev, "failed to get alias id\n");
 191                 return ret;
 192         }
 193         up.port.line = ret;
 194 
 195         priv->clk = devm_clk_get(dev, NULL);
 196         if (IS_ERR(priv->clk)) {
 197                 dev_err(dev, "failed to get clock\n");
 198                 return PTR_ERR(priv->clk);
 199         }
 200 
 201         ret = clk_prepare_enable(priv->clk);
 202         if (ret)
 203                 return ret;
 204 
 205         up.port.uartclk = clk_get_rate(priv->clk);
 206 
 207         spin_lock_init(&priv->atomic_write_lock);
 208 
 209         up.port.dev = dev;
 210         up.port.private_data = priv;
 211         up.port.mapbase = regs->start;
 212         up.port.mapsize = resource_size(regs);
 213         up.port.membase = membase;
 214         up.port.irq = irq;
 215 
 216         up.port.type = PORT_16550A;
 217         up.port.iotype = UPIO_MEM32;
 218         up.port.fifosize = 64;
 219         up.port.regshift = UNIPHIER_UART_REGSHIFT;
 220         up.port.flags = UPF_FIXED_PORT | UPF_FIXED_TYPE;
 221         up.capabilities = UART_CAP_FIFO;
 222 
 223         if (of_property_read_bool(dev->of_node, "auto-flow-control"))
 224                 up.capabilities |= UART_CAP_AFE;
 225 
 226         up.port.serial_in = uniphier_serial_in;
 227         up.port.serial_out = uniphier_serial_out;
 228         up.dl_read = uniphier_serial_dl_read;
 229         up.dl_write = uniphier_serial_dl_write;
 230 
 231         ret = serial8250_register_8250_port(&up);
 232         if (ret < 0) {
 233                 dev_err(dev, "failed to register 8250 port\n");
 234                 clk_disable_unprepare(priv->clk);
 235                 return ret;
 236         }
 237         priv->line = ret;
 238 
 239         platform_set_drvdata(pdev, priv);
 240 
 241         return 0;
 242 }
 243 
 244 static int uniphier_uart_remove(struct platform_device *pdev)
 245 {
 246         struct uniphier8250_priv *priv = platform_get_drvdata(pdev);
 247 
 248         serial8250_unregister_port(priv->line);
 249         clk_disable_unprepare(priv->clk);
 250 
 251         return 0;
 252 }
 253 
 254 static int __maybe_unused uniphier_uart_suspend(struct device *dev)
 255 {
 256         struct uniphier8250_priv *priv = dev_get_drvdata(dev);
 257         struct uart_8250_port *up = serial8250_get_port(priv->line);
 258 
 259         serial8250_suspend_port(priv->line);
 260 
 261         if (!uart_console(&up->port) || console_suspend_enabled)
 262                 clk_disable_unprepare(priv->clk);
 263 
 264         return 0;
 265 }
 266 
 267 static int __maybe_unused uniphier_uart_resume(struct device *dev)
 268 {
 269         struct uniphier8250_priv *priv = dev_get_drvdata(dev);
 270         struct uart_8250_port *up = serial8250_get_port(priv->line);
 271         int ret;
 272 
 273         if (!uart_console(&up->port) || console_suspend_enabled) {
 274                 ret = clk_prepare_enable(priv->clk);
 275                 if (ret)
 276                         return ret;
 277         }
 278 
 279         serial8250_resume_port(priv->line);
 280 
 281         return 0;
 282 }
 283 
 284 static const struct dev_pm_ops uniphier_uart_pm_ops = {
 285         SET_SYSTEM_SLEEP_PM_OPS(uniphier_uart_suspend, uniphier_uart_resume)
 286 };
 287 
 288 static const struct of_device_id uniphier_uart_match[] = {
 289         { .compatible = "socionext,uniphier-uart" },
 290         { /* sentinel */ }
 291 };
 292 MODULE_DEVICE_TABLE(of, uniphier_uart_match);
 293 
 294 static struct platform_driver uniphier_uart_platform_driver = {
 295         .probe          = uniphier_uart_probe,
 296         .remove         = uniphier_uart_remove,
 297         .driver = {
 298                 .name   = "uniphier-uart",
 299                 .of_match_table = uniphier_uart_match,
 300                 .pm = &uniphier_uart_pm_ops,
 301         },
 302 };
 303 module_platform_driver(uniphier_uart_platform_driver);
 304 
 305 MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro@socionext.com>");
 306 MODULE_DESCRIPTION("UniPhier UART driver");
 307 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */