mpc52xx_tty.c 3.8 KB

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