8250_dw.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. /*
  2. * Synopsys DesignWare specific 8250 operations.
  3. *
  4. * Copyright 2011 Picochip, Jamie Iles.
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * The Synopsys DesignWare 8250 has an extra feature whereby it detects if the
  12. * LCR is written whilst busy. If it is, then a busy detect interrupt is
  13. * raised, the LCR needs to be rewritten and the uart status register read.
  14. */
  15. #include <linux/io.h>
  16. #include <linux/serial_8250.h>
  17. #include <linux/serial_core.h>
  18. #include <linux/serial_reg.h>
  19. #include <linux/slab.h>
  20. struct dw8250_data {
  21. int last_lcr;
  22. };
  23. static void dw8250_serial_out(struct uart_port *p, int offset, int value)
  24. {
  25. struct dw8250_data *d = p->private_data;
  26. if (offset == UART_LCR)
  27. d->last_lcr = value;
  28. offset <<= p->regshift;
  29. writeb(value, p->membase + offset);
  30. }
  31. static unsigned int dw8250_serial_in(struct uart_port *p, int offset)
  32. {
  33. offset <<= p->regshift;
  34. return readb(p->membase + offset);
  35. }
  36. static void dw8250_serial_out32(struct uart_port *p, int offset,
  37. int value)
  38. {
  39. struct dw8250_data *d = p->private_data;
  40. if (offset == UART_LCR)
  41. d->last_lcr = value;
  42. offset <<= p->regshift;
  43. writel(value, p->membase + offset);
  44. }
  45. static unsigned int dw8250_serial_in32(struct uart_port *p, int offset)
  46. {
  47. offset <<= p->regshift;
  48. return readl(p->membase + offset);
  49. }
  50. /* Offset for the DesignWare's UART Status Register. */
  51. #define UART_USR 0x1f
  52. static int dw8250_handle_irq(struct uart_port *p)
  53. {
  54. struct dw8250_data *d = p->private_data;
  55. unsigned int iir = p->serial_in(p, UART_IIR);
  56. if (serial8250_handle_irq(p, iir)) {
  57. return 1;
  58. } else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) {
  59. /* Clear the USR and write the LCR again. */
  60. (void)p->serial_in(p, UART_USR);
  61. p->serial_out(p, d->last_lcr, UART_LCR);
  62. return 1;
  63. }
  64. return 0;
  65. }
  66. int serial8250_use_designware_io(struct uart_port *up)
  67. {
  68. up->private_data = kzalloc(sizeof(struct dw8250_data), GFP_KERNEL);
  69. if (!up->private_data)
  70. return -ENOMEM;
  71. if (up->iotype == UPIO_MEM32) {
  72. up->serial_out = dw8250_serial_out32;
  73. up->serial_in = dw8250_serial_in32;
  74. } else {
  75. up->serial_out = dw8250_serial_out;
  76. up->serial_in = dw8250_serial_in;
  77. }
  78. up->handle_irq = dw8250_handle_irq;
  79. return 0;
  80. }