linux/drivers/tty/serial/8250/8250_dw.c
<<
>>
Prefs
   1/*
   2 * Synopsys DesignWare 8250 driver.
   3 *
   4 * Copyright 2011 Picochip, Jamie Iles.
   5 * Copyright 2013 Intel Corporation
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License as published by
   9 * the Free Software Foundation; either version 2 of the License, or
  10 * (at your option) any later version.
  11 *
  12 * The Synopsys DesignWare 8250 has an extra feature whereby it detects if the
  13 * LCR is written whilst busy.  If it is, then a busy detect interrupt is
  14 * raised, the LCR needs to be rewritten and the uart status register read.
  15 */
  16#include <linux/device.h>
  17#include <linux/init.h>
  18#include <linux/io.h>
  19#include <linux/module.h>
  20#include <linux/serial_8250.h>
  21#include <linux/serial_core.h>
  22#include <linux/serial_reg.h>
  23#include <linux/of.h>
  24#include <linux/of_irq.h>
  25#include <linux/of_platform.h>
  26#include <linux/platform_device.h>
  27#include <linux/slab.h>
  28#include <linux/acpi.h>
  29
  30#include "8250.h"
  31
  32/* Offsets for the DesignWare specific registers */
  33#define DW_UART_USR     0x1f /* UART Status Register */
  34#define DW_UART_CPR     0xf4 /* Component Parameter Register */
  35#define DW_UART_UCV     0xf8 /* UART Component Version */
  36
  37/* Intel Low Power Subsystem specific */
  38#define LPSS_PRV_CLOCK_PARAMS 0x800
  39
  40/* Component Parameter Register bits */
  41#define DW_UART_CPR_ABP_DATA_WIDTH      (3 << 0)
  42#define DW_UART_CPR_AFCE_MODE           (1 << 4)
  43#define DW_UART_CPR_THRE_MODE           (1 << 5)
  44#define DW_UART_CPR_SIR_MODE            (1 << 6)
  45#define DW_UART_CPR_SIR_LP_MODE         (1 << 7)
  46#define DW_UART_CPR_ADDITIONAL_FEATURES (1 << 8)
  47#define DW_UART_CPR_FIFO_ACCESS         (1 << 9)
  48#define DW_UART_CPR_FIFO_STAT           (1 << 10)
  49#define DW_UART_CPR_SHADOW              (1 << 11)
  50#define DW_UART_CPR_ENCODED_PARMS       (1 << 12)
  51#define DW_UART_CPR_DMA_EXTRA           (1 << 13)
  52#define DW_UART_CPR_FIFO_MODE           (0xff << 16)
  53/* Helper for fifo size calculation */
  54#define DW_UART_CPR_FIFO_SIZE(a)        (((a >> 16) & 0xff) * 16)
  55
  56
  57struct dw8250_data {
  58        int     last_lcr;
  59        int     line;
  60};
  61
  62static void dw8250_serial_out(struct uart_port *p, int offset, int value)
  63{
  64        struct dw8250_data *d = p->private_data;
  65
  66        if (offset == UART_LCR)
  67                d->last_lcr = value;
  68
  69        offset <<= p->regshift;
  70        writeb(value, p->membase + offset);
  71}
  72
  73static unsigned int dw8250_serial_in(struct uart_port *p, int offset)
  74{
  75        offset <<= p->regshift;
  76
  77        return readb(p->membase + offset);
  78}
  79
  80static void dw8250_serial_out32(struct uart_port *p, int offset, int value)
  81{
  82        struct dw8250_data *d = p->private_data;
  83
  84        if (offset == UART_LCR)
  85                d->last_lcr = value;
  86
  87        offset <<= p->regshift;
  88        writel(value, p->membase + offset);
  89}
  90
  91static unsigned int dw8250_serial_in32(struct uart_port *p, int offset)
  92{
  93        offset <<= p->regshift;
  94
  95        return readl(p->membase + offset);
  96}
  97
  98static int dw8250_handle_irq(struct uart_port *p)
  99{
 100        struct dw8250_data *d = p->private_data;
 101        unsigned int iir = p->serial_in(p, UART_IIR);
 102
 103        if (serial8250_handle_irq(p, iir)) {
 104                return 1;
 105        } else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) {
 106                /* Clear the USR and write the LCR again. */
 107                (void)p->serial_in(p, DW_UART_USR);
 108                p->serial_out(p, UART_LCR, d->last_lcr);
 109
 110                return 1;
 111        }
 112
 113        return 0;
 114}
 115
 116static int dw8250_probe_of(struct uart_port *p)
 117{
 118        struct device_node      *np = p->dev->of_node;
 119        u32                     val;
 120
 121        if (!of_property_read_u32(np, "reg-io-width", &val)) {
 122                switch (val) {
 123                case 1:
 124                        break;
 125                case 4:
 126                        p->iotype = UPIO_MEM32;
 127                        p->serial_in = dw8250_serial_in32;
 128                        p->serial_out = dw8250_serial_out32;
 129                        break;
 130                default:
 131                        dev_err(p->dev, "unsupported reg-io-width (%u)\n", val);
 132                        return -EINVAL;
 133                }
 134        }
 135
 136        if (!of_property_read_u32(np, "reg-shift", &val))
 137                p->regshift = val;
 138
 139        if (of_property_read_u32(np, "clock-frequency", &val)) {
 140                dev_err(p->dev, "no clock-frequency property set\n");
 141                return -EINVAL;
 142        }
 143        p->uartclk = val;
 144
 145        return 0;
 146}
 147
 148#ifdef CONFIG_ACPI
 149static bool dw8250_acpi_dma_filter(struct dma_chan *chan, void *parm)
 150{
 151        return chan->chan_id == *(int *)parm;
 152}
 153
 154static acpi_status
 155dw8250_acpi_walk_resource(struct acpi_resource *res, void *data)
 156{
 157        struct uart_port                *p = data;
 158        struct uart_8250_port           *port;
 159        struct uart_8250_dma            *dma;
 160        struct acpi_resource_fixed_dma  *fixed_dma;
 161        struct dma_slave_config         *slave;
 162
 163        port = container_of(p, struct uart_8250_port, port);
 164
 165        switch (res->type) {
 166        case ACPI_RESOURCE_TYPE_FIXED_DMA:
 167                fixed_dma = &res->data.fixed_dma;
 168
 169                /* TX comes first */
 170                if (!port->dma) {
 171                        dma = devm_kzalloc(p->dev, sizeof(*dma), GFP_KERNEL);
 172                        if (!dma)
 173                                return AE_NO_MEMORY;
 174
 175                        port->dma = dma;
 176                        slave = &dma->txconf;
 177
 178                        slave->direction        = DMA_MEM_TO_DEV;
 179                        slave->dst_addr_width   = DMA_SLAVE_BUSWIDTH_1_BYTE;
 180                        slave->slave_id         = fixed_dma->request_lines;
 181                        slave->dst_maxburst     = port->tx_loadsz / 4;
 182
 183                        dma->tx_chan_id         = fixed_dma->channels;
 184                        dma->tx_param           = &dma->tx_chan_id;
 185                        dma->fn                 = dw8250_acpi_dma_filter;
 186                } else {
 187                        dma = port->dma;
 188                        slave = &dma->rxconf;
 189
 190                        slave->direction        = DMA_DEV_TO_MEM;
 191                        slave->src_addr_width   = DMA_SLAVE_BUSWIDTH_1_BYTE;
 192                        slave->slave_id         = fixed_dma->request_lines;
 193                        slave->src_maxburst     = p->fifosize / 4;
 194
 195                        dma->rx_chan_id         = fixed_dma->channels;
 196                        dma->rx_param           = &dma->rx_chan_id;
 197                }
 198
 199                break;
 200        }
 201
 202        return AE_OK;
 203}
 204
 205static int dw8250_probe_acpi(struct uart_port *p)
 206{
 207        const struct acpi_device_id *id;
 208        acpi_status status;
 209        u32 reg;
 210
 211        id = acpi_match_device(p->dev->driver->acpi_match_table, p->dev);
 212        if (!id)
 213                return -ENODEV;
 214
 215        p->iotype = UPIO_MEM32;
 216        p->serial_in = dw8250_serial_in32;
 217        p->serial_out = dw8250_serial_out32;
 218        p->regshift = 2;
 219        p->uartclk = (unsigned int)id->driver_data;
 220
 221        status = acpi_walk_resources(ACPI_HANDLE(p->dev), METHOD_NAME__CRS,
 222                                     dw8250_acpi_walk_resource, p);
 223        if (ACPI_FAILURE(status)) {
 224                dev_err_ratelimited(p->dev, "%s failed \"%s\"\n", __func__,
 225                                    acpi_format_exception(status));
 226                return -ENODEV;
 227        }
 228
 229        /* Fix Haswell issue where the clocks do not get enabled */
 230        if (!strcmp(id->id, "INT33C4") || !strcmp(id->id, "INT33C5")) {
 231                reg = readl(p->membase + LPSS_PRV_CLOCK_PARAMS);
 232                writel(reg | 1, p->membase + LPSS_PRV_CLOCK_PARAMS);
 233        }
 234
 235        return 0;
 236}
 237#else
 238static inline int dw8250_probe_acpi(struct uart_port *p)
 239{
 240        return -ENODEV;
 241}
 242#endif /* CONFIG_ACPI */
 243
 244static void dw8250_setup_port(struct uart_8250_port *up)
 245{
 246        struct uart_port        *p = &up->port;
 247        u32                     reg = readl(p->membase + DW_UART_UCV);
 248
 249        /*
 250         * If the Component Version Register returns zero, we know that
 251         * ADDITIONAL_FEATURES are not enabled. No need to go any further.
 252         */
 253        if (!reg)
 254                return;
 255
 256        dev_dbg_ratelimited(p->dev, "Designware UART version %c.%c%c\n",
 257                (reg >> 24) & 0xff, (reg >> 16) & 0xff, (reg >> 8) & 0xff);
 258
 259        reg = readl(p->membase + DW_UART_CPR);
 260        if (!reg)
 261                return;
 262
 263        /* Select the type based on fifo */
 264        if (reg & DW_UART_CPR_FIFO_MODE) {
 265                p->type = PORT_16550A;
 266                p->flags |= UPF_FIXED_TYPE;
 267                p->fifosize = DW_UART_CPR_FIFO_SIZE(reg);
 268                up->tx_loadsz = p->fifosize;
 269        }
 270}
 271
 272static int dw8250_probe(struct platform_device *pdev)
 273{
 274        struct uart_8250_port uart = {};
 275        struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 276        struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 277        struct dw8250_data *data;
 278        int err;
 279
 280        if (!regs || !irq) {
 281                dev_err(&pdev->dev, "no registers/irq defined\n");
 282                return -EINVAL;
 283        }
 284
 285        spin_lock_init(&uart.port.lock);
 286        uart.port.mapbase = regs->start;
 287        uart.port.irq = irq->start;
 288        uart.port.handle_irq = dw8250_handle_irq;
 289        uart.port.type = PORT_8250;
 290        uart.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_FIXED_PORT;
 291        uart.port.dev = &pdev->dev;
 292
 293        uart.port.membase = ioremap(regs->start, resource_size(regs));
 294        if (!uart.port.membase)
 295                return -ENOMEM;
 296
 297        uart.port.iotype = UPIO_MEM;
 298        uart.port.serial_in = dw8250_serial_in;
 299        uart.port.serial_out = dw8250_serial_out;
 300
 301        dw8250_setup_port(&uart);
 302
 303        if (pdev->dev.of_node) {
 304                err = dw8250_probe_of(&uart.port);
 305                if (err)
 306                        return err;
 307        } else if (ACPI_HANDLE(&pdev->dev)) {
 308                err = dw8250_probe_acpi(&uart.port);
 309                if (err)
 310                        return err;
 311        } else {
 312                return -ENODEV;
 313        }
 314
 315        data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
 316        if (!data)
 317                return -ENOMEM;
 318
 319        uart.port.private_data = data;
 320
 321        data->line = serial8250_register_8250_port(&uart);
 322        if (data->line < 0)
 323                return data->line;
 324
 325        platform_set_drvdata(pdev, data);
 326
 327        return 0;
 328}
 329
 330static int dw8250_remove(struct platform_device *pdev)
 331{
 332        struct dw8250_data *data = platform_get_drvdata(pdev);
 333
 334        serial8250_unregister_port(data->line);
 335
 336        return 0;
 337}
 338
 339#ifdef CONFIG_PM
 340static int dw8250_suspend(struct platform_device *pdev, pm_message_t state)
 341{
 342        struct dw8250_data *data = platform_get_drvdata(pdev);
 343
 344        serial8250_suspend_port(data->line);
 345
 346        return 0;
 347}
 348
 349static int dw8250_resume(struct platform_device *pdev)
 350{
 351        struct dw8250_data *data = platform_get_drvdata(pdev);
 352
 353        serial8250_resume_port(data->line);
 354
 355        return 0;
 356}
 357#else
 358#define dw8250_suspend NULL
 359#define dw8250_resume NULL
 360#endif /* CONFIG_PM */
 361
 362static const struct of_device_id dw8250_of_match[] = {
 363        { .compatible = "snps,dw-apb-uart" },
 364        { /* Sentinel */ }
 365};
 366MODULE_DEVICE_TABLE(of, dw8250_of_match);
 367
 368static const struct acpi_device_id dw8250_acpi_match[] = {
 369        { "INT33C4", 100000000 },
 370        { "INT33C5", 100000000 },
 371        { },
 372};
 373MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match);
 374
 375static struct platform_driver dw8250_platform_driver = {
 376        .driver = {
 377                .name           = "dw-apb-uart",
 378                .owner          = THIS_MODULE,
 379                .of_match_table = dw8250_of_match,
 380                .acpi_match_table = ACPI_PTR(dw8250_acpi_match),
 381        },
 382        .probe                  = dw8250_probe,
 383        .remove                 = dw8250_remove,
 384        .suspend                = dw8250_suspend,
 385        .resume                 = dw8250_resume,
 386};
 387
 388module_platform_driver(dw8250_platform_driver);
 389
 390MODULE_AUTHOR("Jamie Iles");
 391MODULE_LICENSE("GPL");
 392MODULE_DESCRIPTION("Synopsys DesignWare 8250 serial port driver");
 393