Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.9-rc8 392 lines 9.7 kB view raw
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");