Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.25-rc2 137 lines 3.9 kB view raw
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 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 20 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 28static struct mpc52xx_psc __iomem *psc = 29 (struct mpc52xx_psc __iomem *) MPC52xx_PA(MPC52xx_CONSOLE); 30 31/* The decrementer counts at the system bus clock frequency 32 * divided by four. The most accurate time base is connected to the 33 * rtc. We read the decrementer change during one rtc tick 34 * and multiply by 4 to get the system bus clock frequency. Since a 35 * rtc tick is one seconds, and that's pretty long, we change the rtc 36 * dividers temporarily to set them 64x faster ;) 37 */ 38static int 39mpc52xx_ipbfreq(void) 40{ 41 struct mpc52xx_rtc __iomem *rtc = 42 (struct mpc52xx_rtc __iomem *) MPC52xx_PA(MPC52xx_RTC_OFFSET); 43 struct mpc52xx_cdm __iomem *cdm = 44 (struct mpc52xx_cdm __iomem *) MPC52xx_PA(MPC52xx_CDM_OFFSET); 45 int current_time, previous_time; 46 int tbl_start, tbl_end; 47 int xlbfreq, ipbfreq; 48 49 out_be32(&rtc->dividers, 0x8f1f0000); /* Set RTC 64x faster */ 50 previous_time = in_be32(&rtc->time); 51 while ((current_time = in_be32(&rtc->time)) == previous_time) ; 52 tbl_start = get_tbl(); 53 previous_time = current_time; 54 while ((current_time = in_be32(&rtc->time)) == previous_time) ; 55 tbl_end = get_tbl(); 56 out_be32(&rtc->dividers, 0xffff0000); /* Restore RTC */ 57 58 xlbfreq = (tbl_end - tbl_start) << 8; 59 ipbfreq = (in_8(&cdm->ipb_clk_sel) & 1) ? xlbfreq / 2 : xlbfreq; 60 61 return ipbfreq; 62} 63 64unsigned long 65serial_init(int ignored, void *ignored2) 66{ 67 struct mpc52xx_gpio __iomem *gpio = 68 (struct mpc52xx_gpio __iomem *) MPC52xx_PA(MPC52xx_GPIO_OFFSET); 69 int divisor; 70 int mode1; 71 int mode2; 72 u32 val32; 73 74 static int been_here = 0; 75 76 if (been_here) 77 return 0; 78 79 been_here = 1; 80 81 val32 = in_be32(&gpio->port_config); 82 val32 &= ~(0x7 << MPC52xx_PSC_CONFIG_SHIFT); 83 val32 |= MPC52xx_GPIO_PSC_CONFIG_UART_WITHOUT_CD 84 << MPC52xx_PSC_CONFIG_SHIFT; 85 out_be32(&gpio->port_config, val32); 86 87 out_8(&psc->command, MPC52xx_PSC_RST_TX 88 | MPC52xx_PSC_RX_DISABLE | MPC52xx_PSC_TX_ENABLE); 89 out_8(&psc->command, MPC52xx_PSC_RST_RX); 90 91 out_be32(&psc->sicr, 0x0); 92 out_be16(&psc->mpc52xx_psc_clock_select, 0xdd00); 93 out_be16(&psc->tfalarm, 0xf8); 94 95 out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1 96 | MPC52xx_PSC_RX_ENABLE 97 | MPC52xx_PSC_TX_ENABLE); 98 99 divisor = ((mpc52xx_ipbfreq() 100 / (CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD * 16)) + 1) >> 1; 101 102 mode1 = MPC52xx_PSC_MODE_8_BITS | MPC52xx_PSC_MODE_PARNONE 103 | MPC52xx_PSC_MODE_ERR; 104 mode2 = MPC52xx_PSC_MODE_ONE_STOP; 105 106 out_8(&psc->ctur, divisor>>8); 107 out_8(&psc->ctlr, divisor); 108 out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1); 109 out_8(&psc->mode, mode1); 110 out_8(&psc->mode, mode2); 111 112 return 0; /* ignored */ 113} 114 115void 116serial_putc(void *ignored, const char c) 117{ 118 serial_init(0, NULL); 119 120 while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXEMP)) ; 121 out_8(&psc->mpc52xx_psc_buffer_8, c); 122 while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXEMP)) ; 123} 124 125char 126serial_getc(void *ignored) 127{ 128 while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_RXRDY)) ; 129 130 return in_8(&psc->mpc52xx_psc_buffer_8); 131} 132 133int 134serial_tstc(void *ignored) 135{ 136 return (in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_RXRDY) != 0; 137}