0001
0002
0003
0004
0005
0006
0007 #include <linux/types.h>
0008 #include <linux/of.h>
0009 #include <asm/udbg.h>
0010 #include <asm/processor.h>
0011 #include <asm/io.h>
0012 #include <asm/pmac_feature.h>
0013
0014 extern u8 real_readb(volatile u8 __iomem *addr);
0015 extern void real_writeb(u8 data, volatile u8 __iomem *addr);
0016
0017 #define SCC_TXRDY 4
0018 #define SCC_RXRDY 1
0019
0020 static volatile u8 __iomem *sccc;
0021 static volatile u8 __iomem *sccd;
0022
0023 static void udbg_scc_putc(char c)
0024 {
0025 if (sccc) {
0026 while ((in_8(sccc) & SCC_TXRDY) == 0)
0027 ;
0028 out_8(sccd, c);
0029 if (c == '\n')
0030 udbg_scc_putc('\r');
0031 }
0032 }
0033
0034 static int udbg_scc_getc_poll(void)
0035 {
0036 if (sccc) {
0037 if ((in_8(sccc) & SCC_RXRDY) != 0)
0038 return in_8(sccd);
0039 else
0040 return -1;
0041 }
0042 return -1;
0043 }
0044
0045 static int udbg_scc_getc(void)
0046 {
0047 if (sccc) {
0048 while ((in_8(sccc) & SCC_RXRDY) == 0)
0049 ;
0050 return in_8(sccd);
0051 }
0052 return -1;
0053 }
0054
0055 static unsigned char scc_inittab[] = {
0056 13, 0,
0057 12, 0,
0058 14, 1,
0059 11, 0x50,
0060 5, 0xea,
0061 4, 0x46,
0062 3, 0xc1,
0063 };
0064
0065 void __init udbg_scc_init(int force_scc)
0066 {
0067 const u32 *reg;
0068 unsigned long addr;
0069 struct device_node *stdout = NULL, *escc = NULL, *macio = NULL;
0070 struct device_node *ch, *ch_def = NULL, *ch_a = NULL;
0071 const char *path;
0072 int i;
0073
0074 escc = of_find_node_by_name(NULL, "escc");
0075 if (escc == NULL)
0076 goto bail;
0077 macio = of_get_parent(escc);
0078 if (macio == NULL)
0079 goto bail;
0080 path = of_get_property(of_chosen, "linux,stdout-path", NULL);
0081 if (path != NULL)
0082 stdout = of_find_node_by_path(path);
0083 for_each_child_of_node(escc, ch) {
0084 if (ch == stdout)
0085 ch_def = of_node_get(ch);
0086 if (of_node_name_eq(ch, "ch-a"))
0087 ch_a = of_node_get(ch);
0088 }
0089 if (ch_def == NULL && !force_scc)
0090 goto bail;
0091
0092 ch = ch_def ? ch_def : ch_a;
0093
0094
0095 reg = of_get_property(escc, "reg", NULL);
0096 if (reg == NULL)
0097 goto bail;
0098 addr = reg[0];
0099
0100
0101 reg = of_get_property(macio, "assigned-addresses", NULL);
0102 if (reg == NULL)
0103 goto bail;
0104 addr += reg[2];
0105
0106
0107 pmac_call_feature(PMAC_FTR_SCC_ENABLE, ch,
0108 PMAC_SCC_ASYNC | PMAC_SCC_FLAG_XMON, 1);
0109
0110 if (ch == ch_a)
0111 addr += 0x20;
0112 sccc = ioremap(addr & PAGE_MASK, PAGE_SIZE) ;
0113 sccc += addr & ~PAGE_MASK;
0114 sccd = sccc + 0x10;
0115
0116 mb();
0117
0118 for (i = 20000; i != 0; --i)
0119 in_8(sccc);
0120 out_8(sccc, 0x09);
0121 out_8(sccc, 0xc0);
0122
0123
0124
0125
0126 if (ch_def != NULL) {
0127 out_8(sccc, 13);
0128 scc_inittab[1] = in_8(sccc);
0129 out_8(sccc, 12);
0130 scc_inittab[3] = in_8(sccc);
0131 } else if (of_machine_is_compatible("RackMac1,1")
0132 || of_machine_is_compatible("RackMac1,2")
0133 || of_machine_is_compatible("MacRISC4")) {
0134
0135 scc_inittab[1] = 0;
0136 scc_inittab[3] = 0;
0137 } else {
0138
0139 scc_inittab[1] = 0;
0140 scc_inittab[3] = 1;
0141 }
0142
0143 for (i = 0; i < sizeof(scc_inittab); ++i)
0144 out_8(sccc, scc_inittab[i]);
0145
0146
0147 udbg_putc = udbg_scc_putc;
0148 udbg_getc = udbg_scc_getc;
0149 udbg_getc_poll = udbg_scc_getc_poll;
0150
0151 udbg_puts("Hello World !\n");
0152
0153 bail:
0154 of_node_put(macio);
0155 of_node_put(escc);
0156 of_node_put(stdout);
0157 of_node_put(ch_def);
0158 of_node_put(ch_a);
0159 }
0160
0161 #ifdef CONFIG_PPC64
0162 static void udbg_real_scc_putc(char c)
0163 {
0164 while ((real_readb(sccc) & SCC_TXRDY) == 0)
0165 ;
0166 real_writeb(c, sccd);
0167 if (c == '\n')
0168 udbg_real_scc_putc('\r');
0169 }
0170
0171 void __init udbg_init_pmac_realmode(void)
0172 {
0173 sccc = (volatile u8 __iomem *)0x80013020ul;
0174 sccd = (volatile u8 __iomem *)0x80013030ul;
0175
0176 udbg_putc = udbg_real_scc_putc;
0177 udbg_getc = NULL;
0178 udbg_getc_poll = NULL;
0179 }
0180 #endif