2 * Minimal serial functions needed to send messages out a MPC52xx
3 * Programmable Serial Controller (PSC).
5 * Author: Dale Farnsworth <dfarnsworth@mvista.com>
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.
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>
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)
25 #error "MPC52xx_PF_CONSOLE_PORT not defined"
28 static struct mpc52xx_psc __iomem
*psc
=
29 (struct mpc52xx_psc __iomem
*) MPC52xx_PA(MPC52xx_CONSOLE
);
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 temporarly to set them 64x faster ;)
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
;
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
) ;
56 out_be32(&rtc
->dividers
, 0xffff0000); /* Restore RTC */
58 xlbfreq
= (tbl_end
- tbl_start
) << 8;
59 ipbfreq
= (in_8(&cdm
->ipb_clk_sel
) & 1) ? xlbfreq
/ 2 : xlbfreq
;
65 serial_init(int ignored
, void *ignored2
)
67 struct mpc52xx_gpio __iomem
*gpio
=
68 (struct mpc52xx_gpio __iomem
*) MPC52xx_PA(MPC52xx_GPIO_OFFSET
);
74 static int been_here
= 0;
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
);
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
);
91 out_be32(&psc
->sicr
, 0x0);
92 out_be16(&psc
->mpc52xx_psc_clock_select
, 0xdd00);
93 out_be16(&psc
->tfalarm
, 0xf8);
95 out_8(&psc
->command
, MPC52xx_PSC_SEL_MODE_REG_1
96 | MPC52xx_PSC_RX_ENABLE
97 | MPC52xx_PSC_TX_ENABLE
);
99 divisor
= ((mpc52xx_ipbfreq()
100 / (CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD
* 16)) + 1) >> 1;
102 mode1
= MPC52xx_PSC_MODE_8_BITS
| MPC52xx_PSC_MODE_PARNONE
103 | MPC52xx_PSC_MODE_ERR
;
104 mode2
= MPC52xx_PSC_MODE_ONE_STOP
;
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
);
112 return 0; /* ignored */
116 serial_putc(void *ignored
, const char c
)
118 serial_init(0, NULL
);
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
)) ;
126 serial_getc(void *ignored
)
128 while (!(in_be16(&psc
->mpc52xx_psc_status
) & MPC52xx_PSC_SR_RXRDY
)) ;
130 return in_8(&psc
->mpc52xx_psc_buffer_8
);
134 serial_tstc(void *ignored
)
136 return (in_be16(&psc
->mpc52xx_psc_status
) & MPC52xx_PSC_SR_RXRDY
) != 0;