2 * MPSC/UART driver for the Marvell mv64360, mv64460, ...
4 * Author: Mark A. Greer <mgreer@mvista.com>
6 * 2007 (c) MontaVista Software, Inc. This file is licensed under
7 * the terms of the GNU General Public License version 2. This program
8 * is licensed "as is" without any warranty of any kind, whether express
20 extern void udelay(long delay);
22 #define MPSC_CHR_1 0x000c
24 #define MPSC_CHR_2 0x0010
25 #define MPSC_CHR_2_TA (1<<7)
26 #define MPSC_CHR_2_TCS (1<<9)
27 #define MPSC_CHR_2_RA (1<<23)
28 #define MPSC_CHR_2_CRD (1<<25)
29 #define MPSC_CHR_2_EH (1<<31)
31 #define MPSC_CHR_4 0x0018
32 #define MPSC_CHR_4_Z (1<<29)
34 #define MPSC_CHR_5 0x001c
35 #define MPSC_CHR_5_CTL1_INTR (1<<12)
36 #define MPSC_CHR_5_CTL1_VALID (1<<15)
38 #define MPSC_CHR_10 0x0030
40 #define MPSC_INTR_CAUSE 0x0000
41 #define MPSC_INTR_CAUSE_RCC (1<<6)
42 #define MPSC_INTR_MASK 0x0080
44 #define SDMA_SDCM 0x0008
45 #define SDMA_SDCM_AR (1<<15)
46 #define SDMA_SDCM_AT (1<<31)
48 static volatile char *mpsc_base;
49 static volatile char *mpscintr_base;
50 static u32 chr1, chr2;
52 static int mpsc_open(void)
54 chr1 = in_le32((u32 *)(mpsc_base + MPSC_CHR_1)) & 0x00ff0000;
55 chr2 = in_le32((u32 *)(mpsc_base + MPSC_CHR_2)) & ~(MPSC_CHR_2_TA
56 | MPSC_CHR_2_TCS | MPSC_CHR_2_RA | MPSC_CHR_2_CRD
58 out_le32((u32 *)(mpsc_base + MPSC_CHR_4), MPSC_CHR_4_Z);
59 out_le32((u32 *)(mpsc_base + MPSC_CHR_5),
60 MPSC_CHR_5_CTL1_INTR | MPSC_CHR_5_CTL1_VALID);
61 out_le32((u32 *)(mpsc_base + MPSC_CHR_2), chr2 | MPSC_CHR_2_EH);
65 static void mpsc_putc(unsigned char c)
67 while (in_le32((u32 *)(mpsc_base + MPSC_CHR_2)) & MPSC_CHR_2_TCS);
69 out_le32((u32 *)(mpsc_base + MPSC_CHR_1), chr1 | c);
70 out_le32((u32 *)(mpsc_base + MPSC_CHR_2), chr2 | MPSC_CHR_2_TCS);
73 static unsigned char mpsc_getc(void)
78 while (!(cause & MPSC_INTR_CAUSE_RCC))
79 cause = in_le32((u32 *)(mpscintr_base + MPSC_INTR_CAUSE));
81 c = in_8((u8 *)(mpsc_base + MPSC_CHR_10 + 2));
82 out_8((u8 *)(mpsc_base + MPSC_CHR_10 + 2), c);
83 out_le32((u32 *)(mpscintr_base + MPSC_INTR_CAUSE),
84 cause & ~MPSC_INTR_CAUSE_RCC);
89 static u8 mpsc_tstc(void)
91 return (u8)((in_le32((u32 *)(mpscintr_base + MPSC_INTR_CAUSE))
92 & MPSC_INTR_CAUSE_RCC) != 0);
95 static void mpsc_stop_dma(volatile char *sdma_base)
97 out_le32((u32 *)(mpsc_base + MPSC_CHR_2),MPSC_CHR_2_TA | MPSC_CHR_2_RA);
98 out_le32((u32 *)(sdma_base + SDMA_SDCM), SDMA_SDCM_AR | SDMA_SDCM_AT);
100 while ((in_le32((u32 *)(sdma_base + SDMA_SDCM))
101 & (SDMA_SDCM_AR | SDMA_SDCM_AT)) != 0)
105 static volatile char *mpsc_get_virtreg_of_phandle(void *devp, char *prop)
110 n = getprop(devp, prop, &v, sizeof(v));
114 devp = find_node_by_linuxphandle((u32)v);
118 n = getprop(devp, "virtual-reg", &v, sizeof(v));
126 int mpsc_console_init(void *devp, struct serial_console_data *scdp)
130 volatile char *sdma_base;
132 n = getprop(devp, "virtual-reg", &v, sizeof(v));
137 sdma_base = mpsc_get_virtreg_of_phandle(devp, "sdma");
138 if (sdma_base == NULL)
141 mpscintr_base = mpsc_get_virtreg_of_phandle(devp, "mpscintr");
142 if (mpscintr_base == NULL)
145 n = getprop(devp, "block-index", &v, sizeof(v));
150 mpscintr_base += (reg_set == 0) ? 0x4 : 0xc;
152 /* Make sure the mpsc ctlrs are shutdown */
153 out_le32((u32 *)(mpscintr_base + MPSC_INTR_CAUSE), 0);
154 out_le32((u32 *)(mpscintr_base + MPSC_INTR_CAUSE), 0);
155 out_le32((u32 *)(mpscintr_base + MPSC_INTR_MASK), 0);
156 out_le32((u32 *)(mpscintr_base + MPSC_INTR_MASK), 0);
158 mpsc_stop_dma(sdma_base);
160 scdp->open = mpsc_open;
161 scdp->putc = mpsc_putc;
162 scdp->getc = mpsc_getc;
163 scdp->tstc = mpsc_tstc;