17f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller/* 2411c94038594b2a3fd123d09bdec3fe2500e383dAnand Gadiyar * udbg for zilog scc ports as found on Apple PowerMacs 37f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller * 47f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller * Copyright (C) 2001-2005 PPC 64 Team, IBM Corp 57f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller * 67f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller * This program is free software; you can redistribute it and/or 77f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller * modify it under the terms of the GNU General Public License 87f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller * as published by the Free Software Foundation; either version 97f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller * 2 of the License, or (at your option) any later version. 107f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller */ 117f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller#include <linux/types.h> 12188d2ce78feac67e41e41808acda7951810f677bMilton Miller#include <asm/udbg.h> 137f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller#include <asm/processor.h> 147f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller#include <asm/io.h> 157f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller#include <asm/prom.h> 167f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller#include <asm/pmac_feature.h> 177f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller 187f853352e79bf57c4ee279b7458ed0c072e2be76Milton Millerextern u8 real_readb(volatile u8 __iomem *addr); 197f853352e79bf57c4ee279b7458ed0c072e2be76Milton Millerextern void real_writeb(u8 data, volatile u8 __iomem *addr); 207f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller 217f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller#define SCC_TXRDY 4 227f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller#define SCC_RXRDY 1 237f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller 247f853352e79bf57c4ee279b7458ed0c072e2be76Milton Millerstatic volatile u8 __iomem *sccc; 257f853352e79bf57c4ee279b7458ed0c072e2be76Milton Millerstatic volatile u8 __iomem *sccd; 267f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller 2751d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidtstatic void udbg_scc_putc(char c) 287f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller{ 297f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller if (sccc) { 307f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller while ((in_8(sccc) & SCC_TXRDY) == 0) 317f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller ; 327f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller out_8(sccd, c); 337f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller if (c == '\n') 347f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller udbg_scc_putc('\r'); 357f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller } 367f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller} 377f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller 387f853352e79bf57c4ee279b7458ed0c072e2be76Milton Millerstatic int udbg_scc_getc_poll(void) 397f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller{ 407f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller if (sccc) { 417f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller if ((in_8(sccc) & SCC_RXRDY) != 0) 427f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller return in_8(sccd); 437f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller else 447f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller return -1; 457f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller } 467f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller return -1; 477f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller} 487f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller 49bb6b9b28d6847bc71f910e2e82c9040ff4b97ec0Benjamin Herrenschmidtstatic int udbg_scc_getc(void) 507f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller{ 517f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller if (sccc) { 527f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller while ((in_8(sccc) & SCC_RXRDY) == 0) 537f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller ; 547f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller return in_8(sccd); 557f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller } 56bb6b9b28d6847bc71f910e2e82c9040ff4b97ec0Benjamin Herrenschmidt return -1; 577f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller} 587f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller 597f853352e79bf57c4ee279b7458ed0c072e2be76Milton Millerstatic unsigned char scc_inittab[] = { 607f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller 13, 0, /* set baud rate divisor */ 617f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller 12, 0, 627f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller 14, 1, /* baud rate gen enable, src=rtxc */ 637f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller 11, 0x50, /* clocks = br gen */ 647f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller 5, 0xea, /* tx 8 bits, assert DTR & RTS */ 657f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller 4, 0x46, /* x16 clock, 1 stop */ 667f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller 3, 0xc1, /* rx enable, 8 bits */ 677f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller}; 687f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller 6951d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidtvoid udbg_scc_init(int force_scc) 707f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller{ 71018a3d1db7cdb6127656c1622ee1d2302e16436dJeremy Kerr const u32 *reg; 727f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller unsigned long addr; 7351d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidt struct device_node *stdout = NULL, *escc = NULL, *macio = NULL; 7451d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidt struct device_node *ch, *ch_def = NULL, *ch_a = NULL; 75018a3d1db7cdb6127656c1622ee1d2302e16436dJeremy Kerr const char *path; 767f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller int i, x; 777f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller 7851d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidt escc = of_find_node_by_name(NULL, "escc"); 7951d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidt if (escc == NULL) 8051d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidt goto bail; 8151d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidt macio = of_get_parent(escc); 8251d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidt if (macio == NULL) 8351d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidt goto bail; 84e2eb63927bfcb54232163bfec32440246fd44457Stephen Rothwell path = of_get_property(of_chosen, "linux,stdout-path", NULL); 8551d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidt if (path != NULL) 8651d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidt stdout = of_find_node_by_path(path); 8751d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidt for (ch = NULL; (ch = of_get_next_child(escc, ch)) != NULL;) { 8851d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidt if (ch == stdout) 8951d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidt ch_def = of_node_get(ch); 9051d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidt if (strcmp(ch->name, "ch-a") == 0) 9151d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidt ch_a = of_node_get(ch); 9251d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidt } 9351d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidt if (ch_def == NULL && !force_scc) 9451d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidt goto bail; 9551d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidt 9651d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidt ch = ch_def ? ch_def : ch_a; 977f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller 987f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller /* Get address within mac-io ASIC */ 99e2eb63927bfcb54232163bfec32440246fd44457Stephen Rothwell reg = of_get_property(escc, "reg", NULL); 1007f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller if (reg == NULL) 10151d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidt goto bail; 1027f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller addr = reg[0]; 10351d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidt 1047f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller /* Get address of mac-io PCI itself */ 105e2eb63927bfcb54232163bfec32440246fd44457Stephen Rothwell reg = of_get_property(macio, "assigned-addresses", NULL); 1067f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller if (reg == NULL) 10751d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidt goto bail; 1087f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller addr += reg[2]; 10951d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidt 11051d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidt /* Lock the serial port */ 11151d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidt pmac_call_feature(PMAC_FTR_SCC_ENABLE, ch, 11251d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidt PMAC_SCC_ASYNC | PMAC_SCC_FLAG_XMON, 1); 11351d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidt 11451d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidt if (ch == ch_a) 11551d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidt addr += 0x20; 116af308377e204e25f1f58627d05fe0f483703b514Stephen Rothwell sccc = ioremap(addr & PAGE_MASK, PAGE_SIZE) ; 1177f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller sccc += addr & ~PAGE_MASK; 1187f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller sccd = sccc + 0x10; 1197f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller 1207f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller mb(); 1217f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller 1227f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller for (i = 20000; i != 0; --i) 1237f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller x = in_8(sccc); 1247f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller out_8(sccc, 0x09); /* reset A or B side */ 1257f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller out_8(sccc, 0xc0); 1262ec6ef1034632c67896955d52bf8efb99195b742Benjamin Herrenschmidt 1272ec6ef1034632c67896955d52bf8efb99195b742Benjamin Herrenschmidt /* If SCC was the OF output port, read the BRG value, else 128f023bf0f91f1f1b926ec8f5cf0ee24be134bf024Benjamin Herrenschmidt * Setup for 38400 or 57600 8N1 depending on the machine 1292ec6ef1034632c67896955d52bf8efb99195b742Benjamin Herrenschmidt */ 1302ec6ef1034632c67896955d52bf8efb99195b742Benjamin Herrenschmidt if (ch_def != NULL) { 1312ec6ef1034632c67896955d52bf8efb99195b742Benjamin Herrenschmidt out_8(sccc, 13); 1322ec6ef1034632c67896955d52bf8efb99195b742Benjamin Herrenschmidt scc_inittab[1] = in_8(sccc); 1332ec6ef1034632c67896955d52bf8efb99195b742Benjamin Herrenschmidt out_8(sccc, 12); 1342ec6ef1034632c67896955d52bf8efb99195b742Benjamin Herrenschmidt scc_inittab[3] = in_8(sccc); 13571a157e8edca55198e808f8561dd49017a54ee34Grant Likely } else if (of_machine_is_compatible("RackMac1,1") 13671a157e8edca55198e808f8561dd49017a54ee34Grant Likely || of_machine_is_compatible("RackMac1,2") 13771a157e8edca55198e808f8561dd49017a54ee34Grant Likely || of_machine_is_compatible("MacRISC4")) { 138f023bf0f91f1f1b926ec8f5cf0ee24be134bf024Benjamin Herrenschmidt /* Xserves and G5s default to 57600 */ 139f023bf0f91f1f1b926ec8f5cf0ee24be134bf024Benjamin Herrenschmidt scc_inittab[1] = 0; 140f023bf0f91f1f1b926ec8f5cf0ee24be134bf024Benjamin Herrenschmidt scc_inittab[3] = 0; 141f023bf0f91f1f1b926ec8f5cf0ee24be134bf024Benjamin Herrenschmidt } else { 142f023bf0f91f1f1b926ec8f5cf0ee24be134bf024Benjamin Herrenschmidt /* Others default to 38400 */ 143f023bf0f91f1f1b926ec8f5cf0ee24be134bf024Benjamin Herrenschmidt scc_inittab[1] = 0; 144f023bf0f91f1f1b926ec8f5cf0ee24be134bf024Benjamin Herrenschmidt scc_inittab[3] = 1; 1452ec6ef1034632c67896955d52bf8efb99195b742Benjamin Herrenschmidt } 1462ec6ef1034632c67896955d52bf8efb99195b742Benjamin Herrenschmidt 1477f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller for (i = 0; i < sizeof(scc_inittab); ++i) 1487f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller out_8(sccc, scc_inittab[i]); 1497f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller 1502ec6ef1034632c67896955d52bf8efb99195b742Benjamin Herrenschmidt 151c8f1c8be629ee34991fdba8bfe46a5c455393209Milton Miller udbg_putc = udbg_scc_putc; 152c8f1c8be629ee34991fdba8bfe46a5c455393209Milton Miller udbg_getc = udbg_scc_getc; 153c8f1c8be629ee34991fdba8bfe46a5c455393209Milton Miller udbg_getc_poll = udbg_scc_getc_poll; 1547f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller 1557f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller udbg_puts("Hello World !\n"); 15651d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidt 15751d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidt bail: 15851d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidt of_node_put(macio); 15951d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidt of_node_put(escc); 16051d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidt of_node_put(stdout); 16151d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidt of_node_put(ch_def); 16251d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidt of_node_put(ch_a); 1637f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller} 1647f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller 16551d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidt#ifdef CONFIG_PPC64 16651d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidtstatic void udbg_real_scc_putc(char c) 1677f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller{ 1687f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller while ((real_readb(sccc) & SCC_TXRDY) == 0) 1697f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller ; 1707f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller real_writeb(c, sccd); 1717f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller if (c == '\n') 1727f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller udbg_real_scc_putc('\r'); 1737f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller} 1747f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller 175296167ae1799815b9ed2d135a847436502f2ee91Michael Ellermanvoid __init udbg_init_pmac_realmode(void) 1767f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller{ 1777f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller sccc = (volatile u8 __iomem *)0x80013020ul; 1787f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller sccd = (volatile u8 __iomem *)0x80013030ul; 1797f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller 180c8f1c8be629ee34991fdba8bfe46a5c455393209Milton Miller udbg_putc = udbg_real_scc_putc; 181c8f1c8be629ee34991fdba8bfe46a5c455393209Milton Miller udbg_getc = NULL; 182c8f1c8be629ee34991fdba8bfe46a5c455393209Milton Miller udbg_getc_poll = NULL; 1837f853352e79bf57c4ee279b7458ed0c072e2be76Milton Miller} 18451d3082fe6e55aecfa17113dbe98077c749f724cBenjamin Herrenschmidt#endif /* CONFIG_PPC64 */ 185