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
21 #define MPSC_CHR_1 0x000c
23 #define MPSC_CHR_2 0x0010
24 #define MPSC_CHR_2_TA (1<<7)
25 #define MPSC_CHR_2_TCS (1<<9)
26 #define MPSC_CHR_2_RA (1<<23)
27 #define MPSC_CHR_2_CRD (1<<25)
28 #define MPSC_CHR_2_EH (1<<31)
30 #define MPSC_CHR_4 0x0018
31 #define MPSC_CHR_4_Z (1<<29)
33 #define MPSC_CHR_5 0x001c
34 #define MPSC_CHR_5_CTL1_INTR (1<<12)
35 #define MPSC_CHR_5_CTL1_VALID (1<<15)
37 #define MPSC_CHR_10 0x0030
39 #define MPSC_INTR_CAUSE 0x0000
40 #define MPSC_INTR_CAUSE_RCC (1<<6)
41 #define MPSC_INTR_MASK 0x0080
43 #define SDMA_SDCM 0x0008
44 #define SDMA_SDCM_AR (1<<15)
45 #define SDMA_SDCM_AT (1<<31)
47 static volatile char *mpsc_base
;
48 static volatile char *mpscintr_base
;
49 static u32 chr1
, chr2
;
51 static int mpsc_open(void)
53 chr1
= in_le32((u32
*)(mpsc_base
+ MPSC_CHR_1
)) & 0x00ff0000;
54 chr2
= in_le32((u32
*)(mpsc_base
+ MPSC_CHR_2
)) & ~(MPSC_CHR_2_TA
55 | MPSC_CHR_2_TCS
| MPSC_CHR_2_RA
| MPSC_CHR_2_CRD
57 out_le32((u32
*)(mpsc_base
+ MPSC_CHR_4
), MPSC_CHR_4_Z
);
58 out_le32((u32
*)(mpsc_base
+ MPSC_CHR_5
),
59 MPSC_CHR_5_CTL1_INTR
| MPSC_CHR_5_CTL1_VALID
);
60 out_le32((u32
*)(mpsc_base
+ MPSC_CHR_2
), chr2
| MPSC_CHR_2_EH
);
64 static void mpsc_putc(unsigned char c
)
66 while (in_le32((u32
*)(mpsc_base
+ MPSC_CHR_2
)) & MPSC_CHR_2_TCS
);
68 out_le32((u32
*)(mpsc_base
+ MPSC_CHR_1
), chr1
| c
);
69 out_le32((u32
*)(mpsc_base
+ MPSC_CHR_2
), chr2
| MPSC_CHR_2_TCS
);
72 static unsigned char mpsc_getc(void)
77 while (!(cause
& MPSC_INTR_CAUSE_RCC
))
78 cause
= in_le32((u32
*)(mpscintr_base
+ MPSC_INTR_CAUSE
));
80 c
= in_8((u8
*)(mpsc_base
+ MPSC_CHR_10
+ 2));
81 out_8((u8
*)(mpsc_base
+ MPSC_CHR_10
+ 2), c
);
82 out_le32((u32
*)(mpscintr_base
+ MPSC_INTR_CAUSE
),
83 cause
& ~MPSC_INTR_CAUSE_RCC
);
88 static u8
mpsc_tstc(void)
90 return (u8
)((in_le32((u32
*)(mpscintr_base
+ MPSC_INTR_CAUSE
))
91 & MPSC_INTR_CAUSE_RCC
) != 0);
94 static void mpsc_stop_dma(volatile char *sdma_base
)
96 out_le32((u32
*)(mpsc_base
+ MPSC_CHR_2
),MPSC_CHR_2_TA
| MPSC_CHR_2_RA
);
97 out_le32((u32
*)(sdma_base
+ SDMA_SDCM
), SDMA_SDCM_AR
| SDMA_SDCM_AT
);
99 while ((in_le32((u32
*)(sdma_base
+ SDMA_SDCM
))
100 & (SDMA_SDCM_AR
| SDMA_SDCM_AT
)) != 0)
104 static volatile char *mpsc_get_virtreg_of_phandle(void *devp
, char *prop
)
109 n
= getprop(devp
, prop
, &v
, sizeof(v
));
113 devp
= find_node_by_linuxphandle((u32
)v
);
117 n
= getprop(devp
, "virtual-reg", &v
, sizeof(v
));
125 int mpsc_console_init(void *devp
, struct serial_console_data
*scdp
)
129 volatile char *sdma_base
;
131 n
= getprop(devp
, "virtual-reg", &v
, sizeof(v
));
136 sdma_base
= mpsc_get_virtreg_of_phandle(devp
, "sdma");
137 if (sdma_base
== NULL
)
140 mpscintr_base
= mpsc_get_virtreg_of_phandle(devp
, "mpscintr");
141 if (mpscintr_base
== NULL
)
144 n
= getprop(devp
, "block-index", &v
, sizeof(v
));
149 mpscintr_base
+= (reg_set
== 0) ? 0x4 : 0xc;
151 /* Make sure the mpsc ctlrs are shutdown */
152 out_le32((u32
*)(mpscintr_base
+ MPSC_INTR_CAUSE
), 0);
153 out_le32((u32
*)(mpscintr_base
+ MPSC_INTR_CAUSE
), 0);
154 out_le32((u32
*)(mpscintr_base
+ MPSC_INTR_MASK
), 0);
155 out_le32((u32
*)(mpscintr_base
+ MPSC_INTR_MASK
), 0);
157 mpsc_stop_dma(sdma_base
);
159 scdp
->open
= mpsc_open
;
160 scdp
->putc
= mpsc_putc
;
161 scdp
->getc
= mpsc_getc
;
162 scdp
->tstc
= mpsc_tstc
;