aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/boot/Makefile2
-rw-r--r--arch/powerpc/boot/mpsc.c170
-rw-r--r--arch/powerpc/boot/ops.h1
-rw-r--r--arch/powerpc/boot/serial.c2
4 files changed, 174 insertions, 1 deletions
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index 77ef7ee9cac6..71b284b2f179 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -43,7 +43,7 @@ $(addprefix $(obj)/,$(zlib) gunzip_util.o main.o): \
43src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \ 43src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \
44 ns16550.c serial.c simple_alloc.c div64.S util.S \ 44 ns16550.c serial.c simple_alloc.c div64.S util.S \
45 gunzip_util.c elf_util.c $(zlib) devtree.c \ 45 gunzip_util.c elf_util.c $(zlib) devtree.c \
46 44x.c ebony.c mv64x60.c 46 44x.c ebony.c mv64x60.c mpsc.c
47src-plat := of.c cuboot-83xx.c cuboot-85xx.c holly.c \ 47src-plat := of.c cuboot-83xx.c cuboot-85xx.c holly.c \
48 cuboot-ebony.c treeboot-ebony.c 48 cuboot-ebony.c treeboot-ebony.c
49src-boot := $(src-wlib) $(src-plat) empty.c 49src-boot := $(src-wlib) $(src-plat) empty.c
diff --git a/arch/powerpc/boot/mpsc.c b/arch/powerpc/boot/mpsc.c
new file mode 100644
index 000000000000..f1c0e965e5ce
--- /dev/null
+++ b/arch/powerpc/boot/mpsc.c
@@ -0,0 +1,170 @@
1/*
2 * MPSC/UART driver for the Marvell mv64360, mv64460, ...
3 *
4 * Author: Mark A. Greer <mgreer@mvista.com>
5 *
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
9 * or implied.
10 */
11
12#include <stdarg.h>
13#include <stddef.h>
14#include "types.h"
15#include "string.h"
16#include "stdio.h"
17#include "io.h"
18#include "ops.h"
19
20extern void udelay(long delay);
21
22#define MPSC_CHR_1 0x000c
23
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)
30
31#define MPSC_CHR_4 0x0018
32#define MPSC_CHR_4_Z (1<<29)
33
34#define MPSC_CHR_5 0x001c
35#define MPSC_CHR_5_CTL1_INTR (1<<12)
36#define MPSC_CHR_5_CTL1_VALID (1<<15)
37
38#define MPSC_CHR_10 0x0030
39
40#define MPSC_INTR_CAUSE 0x0000
41#define MPSC_INTR_CAUSE_RCC (1<<6)
42#define MPSC_INTR_MASK 0x0080
43
44#define SDMA_SDCM 0x0008
45#define SDMA_SDCM_AR (1<<15)
46#define SDMA_SDCM_AT (1<<31)
47
48static volatile char *mpsc_base;
49static volatile char *mpscintr_base;
50static u32 chr1, chr2;
51
52static int mpsc_open(void)
53{
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
57 | MPSC_CHR_2_EH);
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);
62 return 0;
63}
64
65static void mpsc_putc(unsigned char c)
66{
67 while (in_le32((u32 *)(mpsc_base + MPSC_CHR_2)) & MPSC_CHR_2_TCS);
68
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);
71}
72
73static unsigned char mpsc_getc(void)
74{
75 u32 cause = 0;
76 unsigned char c;
77
78 while (!(cause & MPSC_INTR_CAUSE_RCC))
79 cause = in_le32((u32 *)(mpscintr_base + MPSC_INTR_CAUSE));
80
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);
85
86 return c;
87}
88
89static u8 mpsc_tstc(void)
90{
91 return (u8)((in_le32((u32 *)(mpscintr_base + MPSC_INTR_CAUSE))
92 & MPSC_INTR_CAUSE_RCC) != 0);
93}
94
95static void mpsc_stop_dma(volatile char *sdma_base)
96{
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);
99
100 while ((in_le32((u32 *)(sdma_base + SDMA_SDCM))
101 & (SDMA_SDCM_AR | SDMA_SDCM_AT)) != 0)
102 udelay(100);
103}
104
105static volatile char *mpsc_get_virtreg_of_phandle(void *devp, char *prop)
106{
107 void *v;
108 int n;
109
110 n = getprop(devp, prop, &v, sizeof(v));
111 if (n != sizeof(v))
112 goto err_out;
113
114 devp = find_node_by_linuxphandle((u32)v);
115 if (devp == NULL)
116 goto err_out;
117
118 n = getprop(devp, "virtual-reg", &v, sizeof(v));
119 if (n == sizeof(v))
120 return v;
121
122err_out:
123 return NULL;
124}
125
126int mpsc_console_init(void *devp, struct serial_console_data *scdp)
127{
128 void *v;
129 int n, reg_set;
130 volatile char *sdma_base;
131
132 n = getprop(devp, "virtual-reg", &v, sizeof(v));
133 if (n != sizeof(v))
134 goto err_out;
135 mpsc_base = v;
136
137 sdma_base = mpsc_get_virtreg_of_phandle(devp, "sdma");
138 if (sdma_base == NULL)
139 goto err_out;
140
141 mpscintr_base = mpsc_get_virtreg_of_phandle(devp, "mpscintr");
142 if (mpscintr_base == NULL)
143 goto err_out;
144
145 n = getprop(devp, "block-index", &v, sizeof(v));
146 if (n != sizeof(v))
147 goto err_out;
148 reg_set = (int)v;
149
150 mpscintr_base += (reg_set == 0) ? 0x4 : 0xc;
151
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);
157
158 mpsc_stop_dma(sdma_base);
159
160 scdp->open = mpsc_open;
161 scdp->putc = mpsc_putc;
162 scdp->getc = mpsc_getc;
163 scdp->tstc = mpsc_tstc;
164 scdp->close = NULL;
165
166 return 0;
167
168err_out:
169 return -1;
170}
diff --git a/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h
index 73bd47a3a079..959124f3f9af 100644
--- a/arch/powerpc/boot/ops.h
+++ b/arch/powerpc/boot/ops.h
@@ -79,6 +79,7 @@ void start(void);
79int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device); 79int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device);
80int serial_console_init(void); 80int serial_console_init(void);
81int ns16550_console_init(void *devp, struct serial_console_data *scdp); 81int ns16550_console_init(void *devp, struct serial_console_data *scdp);
82int mpsc_console_init(void *devp, struct serial_console_data *scdp);
82void *simple_alloc_init(char *base, unsigned long heap_size, 83void *simple_alloc_init(char *base, unsigned long heap_size,
83 unsigned long granularity, unsigned long max_allocs); 84 unsigned long granularity, unsigned long max_allocs);
84extern void flush_cache(void *, unsigned long); 85extern void flush_cache(void *, unsigned long);
diff --git a/arch/powerpc/boot/serial.c b/arch/powerpc/boot/serial.c
index e8de4cf59be7..7fd32330a9a5 100644
--- a/arch/powerpc/boot/serial.c
+++ b/arch/powerpc/boot/serial.c
@@ -125,6 +125,8 @@ int serial_console_init(void)
125 125
126 if (!strcmp(compat, "ns16550")) 126 if (!strcmp(compat, "ns16550"))
127 rc = ns16550_console_init(devp, &serial_cd); 127 rc = ns16550_console_init(devp, &serial_cd);
128 else if (!strcmp(compat, "marvell,mpsc"))
129 rc = mpsc_console_init(devp, &serial_cd);
128 130
129 /* Add other serial console driver calls here */ 131 /* Add other serial console driver calls here */
130 132