ppc64: Add support for z85c30 SCCs for low level console (PowerMac G5)

This is only used with the "sccdbg" kernel command line option, as
you need a special adapter (www.geethree.com) to get access to the
serial port on those machines.
parent da8106ad
...@@ -22,6 +22,9 @@ ...@@ -22,6 +22,9 @@
#include <asm/naca.h> #include <asm/naca.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/machdep.h> #include <asm/machdep.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/pmac_feature.h>
struct NS16550 { struct NS16550 {
/* this struct must be packed */ /* this struct must be packed */
...@@ -69,6 +72,61 @@ udbg_init_uart(void *comport) ...@@ -69,6 +72,61 @@ udbg_init_uart(void *comport)
} }
} }
#ifdef CONFIG_PPC_PMAC
#define SCC_TXRDY 4
#define SCC_RXRDY 1
static volatile u8 *sccc, *sccd;
static unsigned char scc_inittab[] = {
13, 0, /* set baud rate divisor */
12, 0,
14, 1, /* baud rate gen enable, src=rtxc */
11, 0x50, /* clocks = br gen */
5, 0xea, /* tx 8 bits, assert DTR & RTS */
4, 0x46, /* x16 clock, 1 stop */
3, 0xc1, /* rx enable, 8 bits */
};
void
udbg_init_scc(struct device_node *np)
{
unsigned long addr;
int i, x;
if (np == NULL)
np = of_find_node_by_name(NULL, "escc");
if (np == NULL)
return;
/* Lock-enable the SCC channel */
pmac_call_feature(PMAC_FTR_SCC_ENABLE, np, PMAC_SCC_ASYNC | PMAC_SCC_FLAG_XMON, 1);
/* Setup for 57600 8N1 */
addr = np->addrs[0].address + 0x20;
sccc = (volatile u8 *) ioremap(addr & PAGE_MASK, PAGE_SIZE) ;
sccc += addr & ~PAGE_MASK;
sccd = sccc + 0x10;
for (i = 20000; i != 0; --i)
x = *sccc; eieio();
*sccc = 9; eieio(); /* reset A or B side */
*sccc = 0xc0; eieio();
for (i = 0; i < sizeof(scc_inittab); ++i) {
*sccc = scc_inittab[i];
eieio();
}
ppc_md.udbg_putc = udbg_putc;
ppc_md.udbg_getc = udbg_getc;
ppc_md.udbg_getc_poll = udbg_getc_poll;
udbg_puts("Hello World !\n");
}
#endif /* CONFIG_PPC_PMAC */
void void
udbg_putc(unsigned char c) udbg_putc(unsigned char c)
{ {
...@@ -83,6 +141,16 @@ udbg_putc(unsigned char c) ...@@ -83,6 +141,16 @@ udbg_putc(unsigned char c)
udbg_comport->thr = '\r'; eieio(); udbg_comport->thr = '\r'; eieio();
} }
} }
#ifdef CONFIG_PPC_PMAC
else if (sccc) {
while ((*sccc & SCC_TXRDY) == 0)
eieio();
*sccd = c;
eieio();
if (c == '\n')
udbg_putc('\r');
}
#endif /* CONFIG_PPC_PMAC */
} }
int udbg_getc_poll(void) int udbg_getc_poll(void)
...@@ -93,6 +161,15 @@ int udbg_getc_poll(void) ...@@ -93,6 +161,15 @@ int udbg_getc_poll(void)
else else
return -1; return -1;
} }
#ifdef CONFIG_PPC_PMAC
else if (sccc) {
eieio();
if ((*sccc & SCC_RXRDY) != 0)
return *sccd;
else
return -1;
}
#endif /* CONFIG_PPC_PMAC */
return -1; return -1;
} }
...@@ -104,6 +181,14 @@ udbg_getc(void) ...@@ -104,6 +181,14 @@ udbg_getc(void)
/* wait for char */; /* wait for char */;
return udbg_comport->rbr; return udbg_comport->rbr;
} }
#ifdef CONFIG_PPC_PMAC
else if (sccc) {
eieio();
while ((*sccc & SCC_RXRDY) == 0)
eieio();
return *sccd;
}
#endif /* CONFIG_PPC_PMAC */
return 0; return 0;
} }
...@@ -149,6 +234,8 @@ udbg_read(char *buf, int buflen) { ...@@ -149,6 +234,8 @@ udbg_read(char *buf, int buflen) {
do { do {
c = ppc_md.udbg_getc(); c = ppc_md.udbg_getc();
} while (c == 0x11 || c == 0x13); } while (c == 0x11 || c == 0x13);
if (c == 0)
break;
*p++ = c; *p++ = c;
} }
return i; return i;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment