npcm845x_serial_port.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /*
  2. * Copyright (c) 2015-2023, ARM Limited and Contributors. All rights reserved.
  3. *
  4. * Copyright (C) 2017-2023 Nuvoton Ltd.
  5. *
  6. * SPDX-License-Identifier: BSD-3-Clause
  7. */
  8. #include <stdbool.h>
  9. #include <arch.h>
  10. #include <arch_helpers.h>
  11. #include <common/debug.h>
  12. #include <drivers/arm/gicv2.h>
  13. #include <drivers/delay_timer.h>
  14. #include <drivers/generic_delay_timer.h>
  15. #include <lib/mmio.h>
  16. #include <lib/psci/psci.h>
  17. #include <npcm845x_clock.h>
  18. #include <npcm845x_gcr.h>
  19. #include <npcm845x_lpuart.h>
  20. #include <plat_npcm845x.h>
  21. uintptr_t npcm845x_get_base_uart(UART_DEV_T devNum)
  22. {
  23. return 0xF0000000 + devNum * 0x1000;
  24. }
  25. uintptr_t npcm845x_get_base_clk(void)
  26. {
  27. return 0xF0801000;
  28. }
  29. uintptr_t npcm845x_get_base_gcr(void)
  30. {
  31. return 0xF0800000;
  32. }
  33. void npcm845x_wait_for_empty(int uart_n)
  34. {
  35. volatile struct npcmX50_uart *uart = (struct npcmX50_uart *)npcm845x_get_base_uart(uart_n);
  36. while ((*(uint8_t *)(uintptr_t)(&uart->lsr) & 0x40) == 0x00) {
  37. /*
  38. * wait for THRE (Transmitter Holding Register Empty)
  39. * and TSR (Transmitter Shift Register) to be empty.
  40. * Some delay. notice needed some delay so UartUpdateTool
  41. * will pass w/o error log
  42. */
  43. }
  44. volatile int delay;
  45. for (delay = 0; delay < 10000; delay++) {
  46. ;
  47. }
  48. }
  49. int UART_Init(UART_DEV_T devNum, UART_BAUDRATE_T baudRate)
  50. {
  51. uint32_t val = 0;
  52. uintptr_t clk_base = npcm845x_get_base_clk();
  53. uintptr_t gcr_base = npcm845x_get_base_gcr();
  54. uintptr_t uart_base = npcm845x_get_base_uart(devNum);
  55. volatile struct npcmX50_uart *uart = (struct npcmX50_uart *)uart_base;
  56. /* Use CLKREF to be independent of CPU frequency */
  57. volatile struct clk_ctl *clk_ctl_obj = (struct clk_ctl *)clk_base;
  58. volatile struct npcm845x_gcr *gcr_ctl_obj =
  59. (struct npcm845x_gcr *)gcr_base;
  60. clk_ctl_obj->clksel = clk_ctl_obj->clksel & ~(0x3 << 8);
  61. clk_ctl_obj->clksel = clk_ctl_obj->clksel | (0x2 << 8);
  62. /* Set devider according to baudrate */
  63. clk_ctl_obj->clkdiv1 =
  64. (unsigned int)(clk_ctl_obj->clkdiv1 & ~(0x1F << 16));
  65. /* clear bits 11-15 - set value 0 */
  66. if (devNum == UART3_DEV) {
  67. clk_ctl_obj->clkdiv2 =
  68. (unsigned int)(clk_ctl_obj->clkdiv2 & ~(0x1F << 11));
  69. }
  70. npcm845x_wait_for_empty(devNum);
  71. val = (uint32_t)LCR_WLS_8bit;
  72. mmio_write_8((uintptr_t)&uart->lcr, (uint8_t)val);
  73. /* disable all interrupts */
  74. mmio_write_8((uintptr_t)&uart->ier, 0);
  75. /*
  76. * Set the RX FIFO trigger level, reset RX, TX FIFO
  77. */
  78. val = (uint32_t)(FCR_FME | FCR_RFR | FCR_TFR | FCR_RFITL_4B);
  79. /* reset TX and RX FIFO */
  80. mmio_write_8((uintptr_t)(&uart->fcr), (uint8_t)val);
  81. /* Set port for 8 bit, 1 stop, no parity */
  82. val = (uint32_t)LCR_WLS_8bit;
  83. /* Set DLAB bit; Accesses the Divisor Latch Registers (DLL, DLM). */
  84. val |= 0x80;
  85. mmio_write_8((uintptr_t)(&uart->lcr), (uint8_t)val);
  86. /* Baud Rate = UART Clock 24MHz / (16 * (11+2)) = 115384 */
  87. mmio_write_8((uintptr_t)(&uart->dll), 11);
  88. mmio_write_8((uintptr_t)(&uart->dlm), 0x00);
  89. val = mmio_read_8((uintptr_t)&uart->lcr);
  90. /* Clear DLAB bit; Accesses RBR, THR or IER registers. */
  91. val &= 0x7F;
  92. mmio_write_8((uintptr_t)(&uart->lcr), (uint8_t)val);
  93. if (devNum == UART0_DEV) {
  94. gcr_ctl_obj->mfsel4 &= ~(1 << 1);
  95. gcr_ctl_obj->mfsel1 |= 1 << 9;
  96. } else if (devNum == UART3_DEV) {
  97. /* Pin Mux */
  98. gcr_ctl_obj->mfsel4 &= ~(1 << 1);
  99. gcr_ctl_obj->mfsel1 |= 1 << 11;
  100. gcr_ctl_obj->spswc &= (7 << 0);
  101. gcr_ctl_obj->spswc |= (2 << 0);
  102. } else {
  103. /* halt */
  104. while (1) {
  105. ;
  106. }
  107. }
  108. return 0;
  109. }