early_printk.c 3.3 KB

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