2 * udbg serial input/output routines for the Marvell MV64x60 (Discovery).
4 * Author: Dale Farnsworth <dale@farnsworth.org>
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
16 #include <sysdev/mv64x60.h>
18 #define MPSC_0_CR1_OFFSET 0x000c
20 #define MPSC_0_CR2_OFFSET 0x0010
21 #define MPSC_CHR_2_TCS (1 << 9)
23 #define MPSC_0_CHR_10_OFFSET 0x0030
25 #define MPSC_INTR_CAUSE_OFF_0 0x0004
26 #define MPSC_INTR_CAUSE_OFF_1 0x000c
27 #define MPSC_INTR_CAUSE_RCC (1<<6)
29 static void __iomem
*mpsc_base
;
30 static void __iomem
*mpsc_intr_cause
;
32 static void mv64x60_udbg_putc(char c
)
35 mv64x60_udbg_putc('\r');
37 while(in_le32(mpsc_base
+ MPSC_0_CR2_OFFSET
) & MPSC_CHR_2_TCS
)
39 out_le32(mpsc_base
+ MPSC_0_CR1_OFFSET
, c
);
40 out_le32(mpsc_base
+ MPSC_0_CR2_OFFSET
, MPSC_CHR_2_TCS
);
43 static int mv64x60_udbg_testc(void)
45 return (in_le32(mpsc_intr_cause
) & MPSC_INTR_CAUSE_RCC
) != 0;
48 static int mv64x60_udbg_getc(void)
53 while (!mv64x60_udbg_testc())
56 c
= in_8(mpsc_base
+ MPSC_0_CHR_10_OFFSET
+ 2);
57 out_8(mpsc_base
+ MPSC_0_CHR_10_OFFSET
+ 2, c
);
58 out_le32(mpsc_intr_cause
, cause
& ~MPSC_INTR_CAUSE_RCC
);
62 static int mv64x60_udbg_getc_poll(void)
64 if (!mv64x60_udbg_testc())
67 return mv64x60_udbg_getc();
70 static void mv64x60_udbg_init(void)
72 struct device_node
*np
, *mpscintr
, *stdout
= NULL
;
76 const int *block_index
;
77 int intr_cause_offset
;
80 path
= of_get_property(of_chosen
, "linux,stdout-path", NULL
);
84 stdout
= of_find_node_by_path(path
);
88 for_each_compatible_node(np
, "serial", "marvell,mv64360-mpsc") {
97 block_index
= of_get_property(np
, "cell-index", NULL
);
101 switch (*block_index
) {
103 intr_cause_offset
= MPSC_INTR_CAUSE_OFF_0
;
106 intr_cause_offset
= MPSC_INTR_CAUSE_OFF_1
;
112 err
= of_address_to_resource(np
, 0, &r
[0]);
116 ph
= of_get_property(np
, "mpscintr", NULL
);
117 mpscintr
= of_find_node_by_phandle(*ph
);
121 err
= of_address_to_resource(mpscintr
, 0, &r
[1]);
122 of_node_put(mpscintr
);
128 mpsc_base
= ioremap(r
[0].start
, r
[0].end
- r
[0].start
+ 1);
132 mpsc_intr_cause
= ioremap(r
[1].start
, r
[1].end
- r
[1].start
+ 1);
133 if (!mpsc_intr_cause
) {
137 mpsc_intr_cause
+= intr_cause_offset
;
139 udbg_putc
= mv64x60_udbg_putc
;
140 udbg_getc
= mv64x60_udbg_getc
;
141 udbg_getc_poll
= mv64x60_udbg_getc_poll
;
149 void mv64x60_init_early(void)