mpc52xx_tty.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /*
  2. * arch/ppc/boot/simple/mpc52xx_tty.c
  3. *
  4. * Minimal serial functions needed to send messages out a MPC52xx
  5. * Programmable Serial Controller (PSC).
  6. *
  7. * Author: Dale Farnsworth <dfarnsworth@mvista.com>
  8. *
  9. * 2003-2004 (c) MontaVista, Software, Inc. This file is licensed under the
  10. * terms of the GNU General Public License version 2. This program is licensed
  11. * "as is" without any warranty of any kind, whether express or implied.
  12. */
  13. #include <linux/config.h>
  14. #include <linux/types.h>
  15. #include <asm/uaccess.h>
  16. #include <asm/mpc52xx.h>
  17. #include <asm/mpc52xx_psc.h>
  18. #include <asm/serial.h>
  19. #include <asm/io.h>
  20. #include <asm/time.h>
  21. #ifdef MPC52xx_PF_CONSOLE_PORT
  22. #define MPC52xx_CONSOLE MPC52xx_PSCx_OFFSET(MPC52xx_PF_CONSOLE_PORT)
  23. #define MPC52xx_PSC_CONFIG_SHIFT ((MPC52xx_PF_CONSOLE_PORT-1)<<2)
  24. #else
  25. #error "MPC52xx_PF_CONSOLE_PORT not defined"
  26. #endif
  27. static struct mpc52xx_psc __iomem *psc =
  28. (struct mpc52xx_psc __iomem *) MPC52xx_PA(MPC52xx_CONSOLE);
  29. /* The decrementer counts at the system bus clock frequency
  30. * divided by four. The most accurate time base is connected to the
  31. * rtc. We read the decrementer change during one rtc tick
  32. * and multiply by 4 to get the system bus clock frequency. Since a
  33. * rtc tick is one seconds, and that's pretty long, we change the rtc
  34. * dividers temporarly to set them 64x faster ;)
  35. */
  36. static int
  37. mpc52xx_ipbfreq(void)
  38. {
  39. struct mpc52xx_rtc __iomem *rtc =
  40. (struct mpc52xx_rtc __iomem *) MPC52xx_PA(MPC52xx_RTC_OFFSET);
  41. struct mpc52xx_cdm __iomem *cdm =
  42. (struct mpc52xx_cdm __iomem *) MPC52xx_PA(MPC52xx_CDM_OFFSET);
  43. int current_time, previous_time;
  44. int tbl_start, tbl_end;
  45. int xlbfreq, ipbfreq;
  46. out_be32(&rtc->dividers, 0x8f1f0000); /* Set RTC 64x faster */
  47. previous_time = in_be32(&rtc->time);
  48. while ((current_time = in_be32(&rtc->time)) == previous_time) ;
  49. tbl_start = get_tbl();
  50. previous_time = current_time;
  51. while ((current_time = in_be32(&rtc->time)) == previous_time) ;
  52. tbl_end = get_tbl();
  53. out_be32(&rtc->dividers, 0xffff0000); /* Restore RTC */
  54. xlbfreq = (tbl_end - tbl_start) << 8;
  55. ipbfreq = (in_8(&cdm->ipb_clk_sel) & 1) ? xlbfreq / 2 : xlbfreq;
  56. return ipbfreq;
  57. }
  58. unsigned long
  59. serial_init(int ignored, void *ignored2)
  60. {
  61. struct mpc52xx_gpio __iomem *gpio =
  62. (struct mpc52xx_gpio __iomem *) MPC52xx_PA(MPC52xx_GPIO_OFFSET);
  63. int divisor;
  64. int mode1;
  65. int mode2;
  66. u32 val32;
  67. static int been_here = 0;
  68. if (been_here)
  69. return 0;
  70. been_here = 1;
  71. val32 = in_be32(&gpio->port_config);
  72. val32 &= ~(0x7 << MPC52xx_PSC_CONFIG_SHIFT);
  73. val32 |= MPC52xx_GPIO_PSC_CONFIG_UART_WITHOUT_CD
  74. << MPC52xx_PSC_CONFIG_SHIFT;
  75. out_be32(&gpio->port_config, val32);
  76. out_8(&psc->command, MPC52xx_PSC_RST_TX
  77. | MPC52xx_PSC_RX_DISABLE | MPC52xx_PSC_TX_ENABLE);
  78. out_8(&psc->command, MPC52xx_PSC_RST_RX);
  79. out_be32(&psc->sicr, 0x0);
  80. out_be16(&psc->mpc52xx_psc_clock_select, 0xdd00);
  81. out_be16(&psc->tfalarm, 0xf8);
  82. out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1
  83. | MPC52xx_PSC_RX_ENABLE
  84. | MPC52xx_PSC_TX_ENABLE);
  85. divisor = ((mpc52xx_ipbfreq()
  86. / (CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD * 16)) + 1) >> 1;
  87. mode1 = MPC52xx_PSC_MODE_8_BITS | MPC52xx_PSC_MODE_PARNONE
  88. | MPC52xx_PSC_MODE_ERR;
  89. mode2 = MPC52xx_PSC_MODE_ONE_STOP;
  90. out_8(&psc->ctur, divisor>>8);
  91. out_8(&psc->ctlr, divisor);
  92. out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1);
  93. out_8(&psc->mode, mode1);
  94. out_8(&psc->mode, mode2);
  95. return 0; /* ignored */
  96. }
  97. void
  98. serial_putc(void *ignored, const char c)
  99. {
  100. serial_init(0, NULL);
  101. while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXEMP)) ;
  102. out_8(&psc->mpc52xx_psc_buffer_8, c);
  103. while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXEMP)) ;
  104. }
  105. char
  106. serial_getc(void *ignored)
  107. {
  108. while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_RXRDY)) ;
  109. return in_8(&psc->mpc52xx_psc_buffer_8);
  110. }
  111. int
  112. serial_tstc(void *ignored)
  113. {
  114. return (in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_RXRDY) != 0;
  115. }