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
;