Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/powerpc/platforms/powermac/udbg_scc.c
10818 views
1
/*
2
* udbg for zilog scc ports as found on Apple PowerMacs
3
*
4
* Copyright (C) 2001-2005 PPC 64 Team, IBM Corp
5
*
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU General Public License
8
* as published by the Free Software Foundation; either version
9
* 2 of the License, or (at your option) any later version.
10
*/
11
#include <linux/types.h>
12
#include <asm/udbg.h>
13
#include <asm/processor.h>
14
#include <asm/io.h>
15
#include <asm/prom.h>
16
#include <asm/pmac_feature.h>
17
18
extern u8 real_readb(volatile u8 __iomem *addr);
19
extern void real_writeb(u8 data, volatile u8 __iomem *addr);
20
21
#define SCC_TXRDY 4
22
#define SCC_RXRDY 1
23
24
static volatile u8 __iomem *sccc;
25
static volatile u8 __iomem *sccd;
26
27
static void udbg_scc_putc(char c)
28
{
29
if (sccc) {
30
while ((in_8(sccc) & SCC_TXRDY) == 0)
31
;
32
out_8(sccd, c);
33
if (c == '\n')
34
udbg_scc_putc('\r');
35
}
36
}
37
38
static int udbg_scc_getc_poll(void)
39
{
40
if (sccc) {
41
if ((in_8(sccc) & SCC_RXRDY) != 0)
42
return in_8(sccd);
43
else
44
return -1;
45
}
46
return -1;
47
}
48
49
static int udbg_scc_getc(void)
50
{
51
if (sccc) {
52
while ((in_8(sccc) & SCC_RXRDY) == 0)
53
;
54
return in_8(sccd);
55
}
56
return -1;
57
}
58
59
static unsigned char scc_inittab[] = {
60
13, 0, /* set baud rate divisor */
61
12, 0,
62
14, 1, /* baud rate gen enable, src=rtxc */
63
11, 0x50, /* clocks = br gen */
64
5, 0xea, /* tx 8 bits, assert DTR & RTS */
65
4, 0x46, /* x16 clock, 1 stop */
66
3, 0xc1, /* rx enable, 8 bits */
67
};
68
69
void udbg_scc_init(int force_scc)
70
{
71
const u32 *reg;
72
unsigned long addr;
73
struct device_node *stdout = NULL, *escc = NULL, *macio = NULL;
74
struct device_node *ch, *ch_def = NULL, *ch_a = NULL;
75
const char *path;
76
int i, x;
77
78
escc = of_find_node_by_name(NULL, "escc");
79
if (escc == NULL)
80
goto bail;
81
macio = of_get_parent(escc);
82
if (macio == NULL)
83
goto bail;
84
path = of_get_property(of_chosen, "linux,stdout-path", NULL);
85
if (path != NULL)
86
stdout = of_find_node_by_path(path);
87
for (ch = NULL; (ch = of_get_next_child(escc, ch)) != NULL;) {
88
if (ch == stdout)
89
ch_def = of_node_get(ch);
90
if (strcmp(ch->name, "ch-a") == 0)
91
ch_a = of_node_get(ch);
92
}
93
if (ch_def == NULL && !force_scc)
94
goto bail;
95
96
ch = ch_def ? ch_def : ch_a;
97
98
/* Get address within mac-io ASIC */
99
reg = of_get_property(escc, "reg", NULL);
100
if (reg == NULL)
101
goto bail;
102
addr = reg[0];
103
104
/* Get address of mac-io PCI itself */
105
reg = of_get_property(macio, "assigned-addresses", NULL);
106
if (reg == NULL)
107
goto bail;
108
addr += reg[2];
109
110
/* Lock the serial port */
111
pmac_call_feature(PMAC_FTR_SCC_ENABLE, ch,
112
PMAC_SCC_ASYNC | PMAC_SCC_FLAG_XMON, 1);
113
114
if (ch == ch_a)
115
addr += 0x20;
116
sccc = ioremap(addr & PAGE_MASK, PAGE_SIZE) ;
117
sccc += addr & ~PAGE_MASK;
118
sccd = sccc + 0x10;
119
120
mb();
121
122
for (i = 20000; i != 0; --i)
123
x = in_8(sccc);
124
out_8(sccc, 0x09); /* reset A or B side */
125
out_8(sccc, 0xc0);
126
127
/* If SCC was the OF output port, read the BRG value, else
128
* Setup for 38400 or 57600 8N1 depending on the machine
129
*/
130
if (ch_def != NULL) {
131
out_8(sccc, 13);
132
scc_inittab[1] = in_8(sccc);
133
out_8(sccc, 12);
134
scc_inittab[3] = in_8(sccc);
135
} else if (of_machine_is_compatible("RackMac1,1")
136
|| of_machine_is_compatible("RackMac1,2")
137
|| of_machine_is_compatible("MacRISC4")) {
138
/* Xserves and G5s default to 57600 */
139
scc_inittab[1] = 0;
140
scc_inittab[3] = 0;
141
} else {
142
/* Others default to 38400 */
143
scc_inittab[1] = 0;
144
scc_inittab[3] = 1;
145
}
146
147
for (i = 0; i < sizeof(scc_inittab); ++i)
148
out_8(sccc, scc_inittab[i]);
149
150
151
udbg_putc = udbg_scc_putc;
152
udbg_getc = udbg_scc_getc;
153
udbg_getc_poll = udbg_scc_getc_poll;
154
155
udbg_puts("Hello World !\n");
156
157
bail:
158
of_node_put(macio);
159
of_node_put(escc);
160
of_node_put(stdout);
161
of_node_put(ch_def);
162
of_node_put(ch_a);
163
}
164
165
#ifdef CONFIG_PPC64
166
static void udbg_real_scc_putc(char c)
167
{
168
while ((real_readb(sccc) & SCC_TXRDY) == 0)
169
;
170
real_writeb(c, sccd);
171
if (c == '\n')
172
udbg_real_scc_putc('\r');
173
}
174
175
void __init udbg_init_pmac_realmode(void)
176
{
177
sccc = (volatile u8 __iomem *)0x80013020ul;
178
sccd = (volatile u8 __iomem *)0x80013030ul;
179
180
udbg_putc = udbg_real_scc_putc;
181
udbg_getc = NULL;
182
udbg_getc_poll = NULL;
183
}
184
#endif /* CONFIG_PPC64 */
185
186