early_printk.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Atheros AR7XXX/AR9XXX SoC early printk support
  4. *
  5. * Copyright (C) 2008-2011 Gabor Juhos <[email protected]>
  6. * Copyright (C) 2008 Imre Kaloz <[email protected]>
  7. */
  8. #include <linux/io.h>
  9. #include <linux/errno.h>
  10. #include <linux/serial.h>
  11. #include <linux/serial_reg.h>
  12. #include <asm/addrspace.h>
  13. #include <asm/setup.h>
  14. #include <asm/mach-ath79/ath79.h>
  15. #include <asm/mach-ath79/ar71xx_regs.h>
  16. #include <asm/mach-ath79/ar933x_uart.h>
  17. static void (*_prom_putchar)(char);
  18. static inline void prom_putchar_wait(void __iomem *reg, u32 val)
  19. {
  20. u32 t;
  21. do {
  22. t = __raw_readl(reg);
  23. if ((t & val) == val)
  24. break;
  25. } while (1);
  26. }
  27. static void prom_putchar_ar71xx(char ch)
  28. {
  29. void __iomem *base = (void __iomem *)(KSEG1ADDR(AR71XX_UART_BASE));
  30. prom_putchar_wait(base + UART_LSR * 4, UART_LSR_BOTH_EMPTY);
  31. __raw_writel((unsigned char)ch, base + UART_TX * 4);
  32. prom_putchar_wait(base + UART_LSR * 4, UART_LSR_BOTH_EMPTY);
  33. }
  34. static void prom_putchar_ar933x(char ch)
  35. {
  36. void __iomem *base = (void __iomem *)(KSEG1ADDR(AR933X_UART_BASE));
  37. prom_putchar_wait(base + AR933X_UART_DATA_REG, AR933X_UART_DATA_TX_CSR);
  38. __raw_writel(AR933X_UART_DATA_TX_CSR | (unsigned char)ch,
  39. base + AR933X_UART_DATA_REG);
  40. prom_putchar_wait(base + AR933X_UART_DATA_REG, AR933X_UART_DATA_TX_CSR);
  41. }
  42. static void prom_putchar_dummy(char ch)
  43. {
  44. /* nothing to do */
  45. }
  46. static void prom_enable_uart(u32 id)
  47. {
  48. void __iomem *gpio_base;
  49. u32 uart_en;
  50. u32 t;
  51. switch (id) {
  52. case REV_ID_MAJOR_AR71XX:
  53. uart_en = AR71XX_GPIO_FUNC_UART_EN;
  54. break;
  55. case REV_ID_MAJOR_AR7240:
  56. case REV_ID_MAJOR_AR7241:
  57. case REV_ID_MAJOR_AR7242:
  58. uart_en = AR724X_GPIO_FUNC_UART_EN;
  59. break;
  60. case REV_ID_MAJOR_AR913X:
  61. uart_en = AR913X_GPIO_FUNC_UART_EN;
  62. break;
  63. case REV_ID_MAJOR_AR9330:
  64. case REV_ID_MAJOR_AR9331:
  65. uart_en = AR933X_GPIO_FUNC_UART_EN;
  66. break;
  67. case REV_ID_MAJOR_AR9341:
  68. case REV_ID_MAJOR_AR9342:
  69. case REV_ID_MAJOR_AR9344:
  70. /* TODO */
  71. default:
  72. return;
  73. }
  74. gpio_base = (void __iomem *)KSEG1ADDR(AR71XX_GPIO_BASE);
  75. t = __raw_readl(gpio_base + AR71XX_GPIO_REG_FUNC);
  76. t |= uart_en;
  77. __raw_writel(t, gpio_base + AR71XX_GPIO_REG_FUNC);
  78. }
  79. static void prom_putchar_init(void)
  80. {
  81. void __iomem *base;
  82. u32 id;
  83. base = (void __iomem *)(KSEG1ADDR(AR71XX_RESET_BASE));
  84. id = __raw_readl(base + AR71XX_RESET_REG_REV_ID);
  85. id &= REV_ID_MAJOR_MASK;
  86. switch (id) {
  87. case REV_ID_MAJOR_AR71XX:
  88. case REV_ID_MAJOR_AR7240:
  89. case REV_ID_MAJOR_AR7241:
  90. case REV_ID_MAJOR_AR7242:
  91. case REV_ID_MAJOR_AR913X:
  92. case REV_ID_MAJOR_AR9341:
  93. case REV_ID_MAJOR_AR9342:
  94. case REV_ID_MAJOR_AR9344:
  95. case REV_ID_MAJOR_QCA9533:
  96. case REV_ID_MAJOR_QCA9533_V2:
  97. case REV_ID_MAJOR_QCA9556:
  98. case REV_ID_MAJOR_QCA9558:
  99. case REV_ID_MAJOR_TP9343:
  100. case REV_ID_MAJOR_QCA956X:
  101. case REV_ID_MAJOR_QCN550X:
  102. _prom_putchar = prom_putchar_ar71xx;
  103. break;
  104. case REV_ID_MAJOR_AR9330:
  105. case REV_ID_MAJOR_AR9331:
  106. _prom_putchar = prom_putchar_ar933x;
  107. break;
  108. default:
  109. _prom_putchar = prom_putchar_dummy;
  110. return;
  111. }
  112. prom_enable_uart(id);
  113. }
  114. void prom_putchar(char ch)
  115. {
  116. if (!_prom_putchar)
  117. prom_putchar_init();
  118. _prom_putchar(ch);
  119. }