Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/powerpc/platforms/powermac/udbg_scc.c
26481 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* udbg for zilog scc ports as found on Apple PowerMacs
4
*
5
* Copyright (C) 2001-2005 PPC 64 Team, IBM Corp
6
*/
7
#include <linux/types.h>
8
#include <linux/of.h>
9
#include <asm/udbg.h>
10
#include <asm/processor.h>
11
#include <asm/io.h>
12
#include <asm/pmac_feature.h>
13
14
extern u8 real_readb(volatile u8 __iomem *addr);
15
extern void real_writeb(u8 data, volatile u8 __iomem *addr);
16
17
#define SCC_TXRDY 4
18
#define SCC_RXRDY 1
19
20
static volatile u8 __iomem *sccc;
21
static volatile u8 __iomem *sccd;
22
23
static void udbg_scc_putc(char c)
24
{
25
if (sccc) {
26
while ((in_8(sccc) & SCC_TXRDY) == 0)
27
;
28
out_8(sccd, c);
29
if (c == '\n')
30
udbg_scc_putc('\r');
31
}
32
}
33
34
static int udbg_scc_getc_poll(void)
35
{
36
if (sccc) {
37
if ((in_8(sccc) & SCC_RXRDY) != 0)
38
return in_8(sccd);
39
else
40
return -1;
41
}
42
return -1;
43
}
44
45
static int udbg_scc_getc(void)
46
{
47
if (sccc) {
48
while ((in_8(sccc) & SCC_RXRDY) == 0)
49
;
50
return in_8(sccd);
51
}
52
return -1;
53
}
54
55
static unsigned char scc_inittab[] = {
56
13, 0, /* set baud rate divisor */
57
12, 0,
58
14, 1, /* baud rate gen enable, src=rtxc */
59
11, 0x50, /* clocks = br gen */
60
5, 0xea, /* tx 8 bits, assert DTR & RTS */
61
4, 0x46, /* x16 clock, 1 stop */
62
3, 0xc1, /* rx enable, 8 bits */
63
};
64
65
void __init udbg_scc_init(int force_scc)
66
{
67
const u32 *reg;
68
unsigned long addr;
69
struct device_node *stdout = NULL, *escc = NULL, *macio = NULL;
70
struct device_node *ch, *ch_def = NULL, *ch_a = NULL;
71
const char *path;
72
int i;
73
74
escc = of_find_node_by_name(NULL, "escc");
75
if (escc == NULL)
76
goto bail;
77
macio = of_get_parent(escc);
78
if (macio == NULL)
79
goto bail;
80
path = of_get_property(of_chosen, "linux,stdout-path", NULL);
81
if (path != NULL)
82
stdout = of_find_node_by_path(path);
83
for_each_child_of_node(escc, ch) {
84
if (ch == stdout) {
85
of_node_put(ch_def);
86
ch_def = of_node_get(ch);
87
}
88
if (of_node_name_eq(ch, "ch-a")) {
89
of_node_put(ch_a);
90
ch_a = of_node_get(ch);
91
}
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
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