mpc52xx_tty.c 3.8 KB

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