gaisler-uart.c 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. /*
  2. * SPDX-License-Identifier: BSD-2-Clause
  3. *
  4. * Copyright (c) 2021 Cobham Gaisler AB.
  5. *
  6. * Authors:
  7. * Daniel Cederman <cederman@gaisler.com>
  8. */
  9. #include <sbi/riscv_io.h>
  10. #include <sbi/sbi_console.h>
  11. #include <sbi_utils/serial/gaisler-uart.h>
  12. /* clang-format off */
  13. #define UART_REG_DATA 0
  14. #define UART_REG_STATUS 1
  15. #define UART_REG_CTRL 2
  16. #define UART_REG_SCALER 3
  17. #define UART_DATA_DATA 0x000000ff
  18. #define UART_STATUS_FIFOFULL 0x00000200
  19. #define UART_STATUS_DATAREADY 0x00000001
  20. #define UART_CTRL_DB (1<<11)
  21. #define UART_CTRL_FL (1<<6)
  22. #define UART_CTRL_TE (1<<1)
  23. #define UART_CTRL_RE (1<<0)
  24. /* clang-format on */
  25. static volatile char *uart_base;
  26. static u32 get_reg(u32 num)
  27. {
  28. return readl(uart_base + (num * 0x4));
  29. }
  30. static void set_reg(u32 num, u32 val)
  31. {
  32. writel(val, uart_base + (num * 0x4));
  33. }
  34. static void gaisler_uart_putc(char ch)
  35. {
  36. while (get_reg(UART_REG_STATUS) & UART_STATUS_FIFOFULL)
  37. ;
  38. set_reg(UART_REG_DATA, ch);
  39. }
  40. static int gaisler_uart_getc(void)
  41. {
  42. u32 ret = get_reg(UART_REG_STATUS);
  43. if (!(ret & UART_STATUS_DATAREADY))
  44. return -1;
  45. return get_reg(UART_REG_DATA) & UART_DATA_DATA;
  46. }
  47. static struct sbi_console_device gaisler_console = {
  48. .name = "gaisler_uart",
  49. .console_putc = gaisler_uart_putc,
  50. .console_getc = gaisler_uart_getc
  51. };
  52. int gaisler_uart_init(unsigned long base, u32 in_freq, u32 baudrate)
  53. {
  54. u32 ctrl;
  55. uart_base = (volatile char *)base;
  56. /* Configure baudrate */
  57. if (in_freq && baudrate)
  58. set_reg(UART_REG_SCALER, in_freq / (baudrate * 8 + 7));
  59. ctrl = get_reg(UART_REG_CTRL);
  60. /* Preserve debug mode and flow control */
  61. ctrl &= (UART_CTRL_DB | UART_CTRL_FL);
  62. /* Enable TX and RX */
  63. ctrl |= UART_CTRL_TE | UART_CTRL_RE;
  64. set_reg(UART_REG_CTRL, ctrl);
  65. sbi_console_set_device(&gaisler_console);
  66. return 0;
  67. }