serial_uniphier.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /*
  2. * Copyright (C) 2012-2014 Panasonic Corporation
  3. * Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
  4. *
  5. * SPDX-License-Identifier: GPL-2.0+
  6. */
  7. #include <common.h>
  8. #include <asm/io.h>
  9. #include <asm/errno.h>
  10. #include <dm/device.h>
  11. #include <dm/platform_data/serial-uniphier.h>
  12. #include <serial.h>
  13. #define UART_REG(x) \
  14. u8 x; \
  15. u8 postpad_##x[3];
  16. /*
  17. * Note: Register map is slightly different from that of 16550.
  18. */
  19. struct uniphier_serial {
  20. UART_REG(rbr); /* 0x00 */
  21. UART_REG(ier); /* 0x04 */
  22. UART_REG(iir); /* 0x08 */
  23. UART_REG(fcr); /* 0x0c */
  24. u8 mcr; /* 0x10 */
  25. u8 lcr;
  26. u16 __postpad;
  27. UART_REG(lsr); /* 0x14 */
  28. UART_REG(msr); /* 0x18 */
  29. u32 __none1;
  30. u32 __none2;
  31. u16 dlr;
  32. u16 __postpad2;
  33. };
  34. #define thr rbr
  35. /*
  36. * These are the definitions for the Line Control Register
  37. */
  38. #define UART_LCR_WLS_8 0x03 /* 8 bit character length */
  39. /*
  40. * These are the definitions for the Line Status Register
  41. */
  42. #define UART_LSR_DR 0x01 /* Data ready */
  43. #define UART_LSR_THRE 0x20 /* Xmit holding register empty */
  44. struct uniphier_serial_private_data {
  45. struct uniphier_serial __iomem *membase;
  46. };
  47. #define uniphier_serial_port(dev) \
  48. ((struct uniphier_serial_private_data *)dev_get_priv(dev))->membase
  49. static int uniphier_serial_setbrg(struct udevice *dev, int baudrate)
  50. {
  51. struct uniphier_serial_platform_data *plat = dev_get_platdata(dev);
  52. struct uniphier_serial __iomem *port = uniphier_serial_port(dev);
  53. const unsigned int mode_x_div = 16;
  54. unsigned int divisor;
  55. writeb(UART_LCR_WLS_8, &port->lcr);
  56. divisor = DIV_ROUND_CLOSEST(plat->uartclk, mode_x_div * baudrate);
  57. writew(divisor, &port->dlr);
  58. return 0;
  59. }
  60. static int uniphier_serial_getc(struct udevice *dev)
  61. {
  62. struct uniphier_serial __iomem *port = uniphier_serial_port(dev);
  63. if (!(readb(&port->lsr) & UART_LSR_DR))
  64. return -EAGAIN;
  65. return readb(&port->rbr);
  66. }
  67. static int uniphier_serial_putc(struct udevice *dev, const char c)
  68. {
  69. struct uniphier_serial __iomem *port = uniphier_serial_port(dev);
  70. if (!(readb(&port->lsr) & UART_LSR_THRE))
  71. return -EAGAIN;
  72. writeb(c, &port->thr);
  73. return 0;
  74. }
  75. static int uniphier_serial_pending(struct udevice *dev, bool input)
  76. {
  77. struct uniphier_serial __iomem *port = uniphier_serial_port(dev);
  78. if (input)
  79. return readb(&port->lsr) & UART_LSR_DR;
  80. else
  81. return !(readb(&port->lsr) & UART_LSR_THRE);
  82. }
  83. static int uniphier_serial_probe(struct udevice *dev)
  84. {
  85. struct uniphier_serial_private_data *priv = dev_get_priv(dev);
  86. struct uniphier_serial_platform_data *plat = dev_get_platdata(dev);
  87. priv->membase = map_sysmem(plat->base, sizeof(struct uniphier_serial));
  88. if (!priv->membase)
  89. return -ENOMEM;
  90. return 0;
  91. }
  92. static int uniphier_serial_remove(struct udevice *dev)
  93. {
  94. unmap_sysmem(uniphier_serial_port(dev));
  95. return 0;
  96. }
  97. #ifdef CONFIG_OF_CONTROL
  98. static const struct udevice_id uniphier_uart_of_match = {
  99. { .compatible = "panasonic,uniphier-uart"},
  100. {},
  101. };
  102. static int uniphier_serial_ofdata_to_platdata(struct udevice *dev)
  103. {
  104. /*
  105. * TODO: Masahiro Yamada (yamada.m@jp.panasonic.com)
  106. *
  107. * Implement conversion code from DTB to platform data
  108. * when supporting CONFIG_OF_CONTROL on UniPhir platform.
  109. */
  110. }
  111. #endif
  112. static const struct dm_serial_ops uniphier_serial_ops = {
  113. .setbrg = uniphier_serial_setbrg,
  114. .getc = uniphier_serial_getc,
  115. .putc = uniphier_serial_putc,
  116. .pending = uniphier_serial_pending,
  117. };
  118. U_BOOT_DRIVER(uniphier_serial) = {
  119. .name = DRIVER_NAME,
  120. .id = UCLASS_SERIAL,
  121. .of_match = of_match_ptr(uniphier_uart_of_match),
  122. .ofdata_to_platdata = of_match_ptr(uniphier_serial_ofdata_to_platdata),
  123. .probe = uniphier_serial_probe,
  124. .remove = uniphier_serial_remove,
  125. .priv_auto_alloc_size = sizeof(struct uniphier_serial_private_data),
  126. .platdata_auto_alloc_size =
  127. sizeof(struct uniphier_serial_platform_data),
  128. .ops = &uniphier_serial_ops,
  129. .flags = DM_FLAG_PRE_RELOC,
  130. };