aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/powermac
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2005-11-23 01:57:25 -0500
committerPaul Mackerras <paulus@samba.org>2006-01-08 22:49:54 -0500
commit51d3082fe6e55aecfa17113dbe98077c749f724c (patch)
tree9a1e2355d5988d8cc1ca511d53c1bb24b0baa17f /arch/powerpc/platforms/powermac
parent463ce0e103f419f51b1769111e73fe8bb305d0ec (diff)
[PATCH] powerpc: Unify udbg (#2)
This patch unifies udbg for both ppc32 and ppc64 when building the merged achitecture. xmon now has a single "back end". The powermac udbg stuff gets enriched with some ADB capabilities and btext output. In addition, the early_init callback is now called on ppc32 as well, approx. in the same order as ppc64 regarding device-tree manipulations. The init sequences of ppc32 and ppc64 are getting closer, I'll unify them in a later patch. For now, you can force udbg to the scc using "sccdbg" or to btext using "btextdbg" on powermacs. I'll implement a cleaner way of forcing udbg output to something else than the autodetected OF output device in a later patch. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/platforms/powermac')
-rw-r--r--arch/powerpc/platforms/powermac/Makefile1
-rw-r--r--arch/powerpc/platforms/powermac/feature.c68
-rw-r--r--arch/powerpc/platforms/powermac/low_i2c.c27
-rw-r--r--arch/powerpc/platforms/powermac/pic.c2
-rw-r--r--arch/powerpc/platforms/powermac/setup.c52
-rw-r--r--arch/powerpc/platforms/powermac/udbg_adb.c218
-rw-r--r--arch/powerpc/platforms/powermac/udbg_scc.c165
7 files changed, 470 insertions, 63 deletions
diff --git a/arch/powerpc/platforms/powermac/Makefile b/arch/powerpc/platforms/powermac/Makefile
index c9df44fcf571..3e5370eeb1b7 100644
--- a/arch/powerpc/platforms/powermac/Makefile
+++ b/arch/powerpc/platforms/powermac/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_NVRAM) += nvram.o
7# ppc64 pmac doesn't define CONFIG_NVRAM but needs nvram stuff 7# ppc64 pmac doesn't define CONFIG_NVRAM but needs nvram stuff
8obj-$(CONFIG_PPC64) += nvram.o 8obj-$(CONFIG_PPC64) += nvram.o
9obj-$(CONFIG_SMP) += smp.o 9obj-$(CONFIG_SMP) += smp.o
10obj-$(CONFIG_PPC_MERGE) += udbg_scc.o udbg_adb.o
diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c
index f6e22da2a5da..52a9d0c1b8b8 100644
--- a/arch/powerpc/platforms/powermac/feature.c
+++ b/arch/powerpc/platforms/powermac/feature.c
@@ -2607,6 +2607,8 @@ found:
2607 */ 2607 */
2608static void __init probe_uninorth(void) 2608static void __init probe_uninorth(void)
2609{ 2609{
2610 u32 *addrp;
2611 phys_addr_t address;
2610 unsigned long actrl; 2612 unsigned long actrl;
2611 2613
2612 /* Locate core99 Uni-N */ 2614 /* Locate core99 Uni-N */
@@ -2616,20 +2618,23 @@ static void __init probe_uninorth(void)
2616 uninorth_node = of_find_node_by_name(NULL, "u3"); 2618 uninorth_node = of_find_node_by_name(NULL, "u3");
2617 uninorth_u3 = 1; 2619 uninorth_u3 = 1;
2618 } 2620 }
2619 if (uninorth_node && uninorth_node->n_addrs > 0) { 2621 if (uninorth_node == NULL)
2620 unsigned long address = uninorth_node->addrs[0].address;
2621 uninorth_base = ioremap(address, 0x40000);
2622 uninorth_rev = in_be32(UN_REG(UNI_N_VERSION));
2623 if (uninorth_u3)
2624 u3_ht = ioremap(address + U3_HT_CONFIG_BASE, 0x1000);
2625 } else
2626 uninorth_node = NULL;
2627
2628 if (!uninorth_node)
2629 return; 2622 return;
2630 2623
2631 printk(KERN_INFO "Found %s memory controller & host bridge, revision: %d\n", 2624 addrp = (u32 *)get_property(uninorth_node, "reg", NULL);
2632 uninorth_u3 ? "U3" : "UniNorth", uninorth_rev); 2625 if (addrp == NULL)
2626 return;
2627 address = of_translate_address(uninorth_node, addrp);
2628 if (address == 0)
2629 return;
2630 uninorth_base = ioremap(address, 0x40000);
2631 uninorth_rev = in_be32(UN_REG(UNI_N_VERSION));
2632 if (uninorth_u3)
2633 u3_ht = ioremap(address + U3_HT_CONFIG_BASE, 0x1000);
2634
2635 printk(KERN_INFO "Found %s memory controller & host bridge,"
2636 " revision: %d\n", uninorth_u3 ? "U3" : "UniNorth",
2637 uninorth_rev);
2633 printk(KERN_INFO "Mapped at 0x%08lx\n", (unsigned long)uninorth_base); 2638 printk(KERN_INFO "Mapped at 0x%08lx\n", (unsigned long)uninorth_base);
2634 2639
2635 /* Set the arbitrer QAck delay according to what Apple does 2640 /* Set the arbitrer QAck delay according to what Apple does
@@ -2653,18 +2658,17 @@ static void __init probe_one_macio(const char *name, const char *compat, int typ
2653{ 2658{
2654 struct device_node* node; 2659 struct device_node* node;
2655 int i; 2660 int i;
2656 volatile u32 __iomem * base; 2661 volatile u32 __iomem *base;
2657 u32* revp; 2662 u32 *addrp, *revp;
2663 phys_addr_t addr;
2664 u64 size;
2658 2665
2659 node = find_devices(name); 2666 for (node = NULL; (node = of_find_node_by_name(node, name)) != NULL;) {
2660 if (!node || !node->n_addrs) 2667 if (!compat)
2661 return; 2668 break;
2662 if (compat) 2669 if (device_is_compatible(node, compat))
2663 do { 2670 break;
2664 if (device_is_compatible(node, compat)) 2671 }
2665 break;
2666 node = node->next;
2667 } while (node);
2668 if (!node) 2672 if (!node)
2669 return; 2673 return;
2670 for(i=0; i<MAX_MACIO_CHIPS; i++) { 2674 for(i=0; i<MAX_MACIO_CHIPS; i++) {
@@ -2673,14 +2677,28 @@ static void __init probe_one_macio(const char *name, const char *compat, int typ
2673 if (macio_chips[i].of_node == node) 2677 if (macio_chips[i].of_node == node)
2674 return; 2678 return;
2675 } 2679 }
2680
2676 if (i >= MAX_MACIO_CHIPS) { 2681 if (i >= MAX_MACIO_CHIPS) {
2677 printk(KERN_ERR "pmac_feature: Please increase MAX_MACIO_CHIPS !\n"); 2682 printk(KERN_ERR "pmac_feature: Please increase MAX_MACIO_CHIPS !\n");
2678 printk(KERN_ERR "pmac_feature: %s skipped\n", node->full_name); 2683 printk(KERN_ERR "pmac_feature: %s skipped\n", node->full_name);
2679 return; 2684 return;
2680 } 2685 }
2681 base = ioremap(node->addrs[0].address, node->addrs[0].size); 2686 addrp = of_get_pci_address(node, 0, &size);
2687 if (addrp == NULL) {
2688 printk(KERN_ERR "pmac_feature: %s: can't find base !\n",
2689 node->full_name);
2690 return;
2691 }
2692 addr = of_translate_address(node, addrp);
2693 if (addr == 0) {
2694 printk(KERN_ERR "pmac_feature: %s, can't translate base !\n",
2695 node->full_name);
2696 return;
2697 }
2698 base = ioremap(addr, (unsigned long)size);
2682 if (!base) { 2699 if (!base) {
2683 printk(KERN_ERR "pmac_feature: Can't map mac-io chip !\n"); 2700 printk(KERN_ERR "pmac_feature: %s, can't map mac-io chip !\n",
2701 node->full_name);
2684 return; 2702 return;
2685 } 2703 }
2686 if (type == macio_keylargo) { 2704 if (type == macio_keylargo) {
diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c
index f3f39e8e337a..606e0ed13731 100644
--- a/arch/powerpc/platforms/powermac/low_i2c.c
+++ b/arch/powerpc/platforms/powermac/low_i2c.c
@@ -36,7 +36,7 @@
36 36
37#ifdef DEBUG 37#ifdef DEBUG
38#define DBG(x...) do {\ 38#define DBG(x...) do {\
39 printk(KERN_DEBUG "KW:" x); \ 39 printk(KERN_DEBUG "low_i2c:" x); \
40 } while(0) 40 } while(0)
41#else 41#else
42#define DBG(x...) 42#define DBG(x...)
@@ -342,7 +342,7 @@ static int keywest_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 subaddr,
342static void keywest_low_i2c_add(struct device_node *np) 342static void keywest_low_i2c_add(struct device_node *np)
343{ 343{
344 struct low_i2c_host *host = find_low_i2c_host(NULL); 344 struct low_i2c_host *host = find_low_i2c_host(NULL);
345 u32 *psteps, *prate, steps, aoffset = 0; 345 u32 *psteps, *prate, *addrp, steps;
346 struct device_node *parent; 346 struct device_node *parent;
347 347
348 if (host == NULL) { 348 if (host == NULL) {
@@ -352,6 +352,16 @@ static void keywest_low_i2c_add(struct device_node *np)
352 } 352 }
353 memset(host, 0, sizeof(*host)); 353 memset(host, 0, sizeof(*host));
354 354
355 /* Apple is kind enough to provide a valid AAPL,address property
356 * on all i2c keywest nodes so far ... we would have to fallback
357 * to macio parsing if that wasn't the case
358 */
359 addrp = (u32 *)get_property(np, "AAPL,address", NULL);
360 if (addrp == NULL) {
361 printk(KERN_ERR "low_i2c: Can't find address for %s\n",
362 np->full_name);
363 return;
364 }
355 init_MUTEX(&host->mutex); 365 init_MUTEX(&host->mutex);
356 host->np = of_node_get(np); 366 host->np = of_node_get(np);
357 psteps = (u32 *)get_property(np, "AAPL,address-step", NULL); 367 psteps = (u32 *)get_property(np, "AAPL,address-step", NULL);
@@ -360,12 +370,10 @@ static void keywest_low_i2c_add(struct device_node *np)
360 steps >>= 1; 370 steps >>= 1;
361 parent = of_get_parent(np); 371 parent = of_get_parent(np);
362 host->num_channels = 1; 372 host->num_channels = 1;
363 if (parent && parent->name[0] == 'u') { 373 if (parent && parent->name[0] == 'u')
364 host->num_channels = 2; 374 host->num_channels = 2;
365 aoffset = 3;
366 }
367 /* Select interface rate */ 375 /* Select interface rate */
368 host->speed = KW_I2C_MODE_100KHZ; 376 host->speed = KW_I2C_MODE_25KHZ;
369 prate = (u32 *)get_property(np, "AAPL,i2c-rate", NULL); 377 prate = (u32 *)get_property(np, "AAPL,i2c-rate", NULL);
370 if (prate) switch(*prate) { 378 if (prate) switch(*prate) {
371 case 100: 379 case 100:
@@ -379,9 +387,12 @@ static void keywest_low_i2c_add(struct device_node *np)
379 break; 387 break;
380 } 388 }
381 389
390 printk(KERN_INFO "low_i2c: Bus %s found at 0x%08x, %d channels,"
391 " speed = %d KHz\n",
392 np->full_name, *addrp, host->num_channels, prate ? *prate : 25);
393
382 host->mode = pmac_low_i2c_mode_std; 394 host->mode = pmac_low_i2c_mode_std;
383 host->base = ioremap(np->addrs[0].address + aoffset, 395 host->base = ioremap((*addrp), 0x1000);
384 np->addrs[0].size);
385 host->func = keywest_low_i2c_func; 396 host->func = keywest_low_i2c_func;
386} 397}
387 398
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c
index 90040c49494d..ff78eeac10f2 100644
--- a/arch/powerpc/platforms/powermac/pic.c
+++ b/arch/powerpc/platforms/powermac/pic.c
@@ -459,7 +459,7 @@ void __init pmac_pic_init(void)
459 mpic_setup_cascade(irqctrler2->intrs[0].line, 459 mpic_setup_cascade(irqctrler2->intrs[0].line,
460 pmac_u3_cascade, mpic2); 460 pmac_u3_cascade, mpic2);
461 } 461 }
462#if defined(CONFIG_XMON) && defined(CONFIG_PPC32) 462#ifdef CONFIG_XMON
463 { 463 {
464 struct device_node* pswitch; 464 struct device_node* pswitch;
465 int nmi_irq; 465 int nmi_irq;
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index 3b7a492d9b68..6ee620fe5195 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -77,6 +77,7 @@
77#include <asm/pmc.h> 77#include <asm/pmc.h>
78#include <asm/mpic.h> 78#include <asm/mpic.h>
79#include <asm/lmb.h> 79#include <asm/lmb.h>
80#include <asm/udbg.h>
80 81
81#include "pmac.h" 82#include "pmac.h"
82 83
@@ -322,16 +323,6 @@ void __init pmac_setup_arch(void)
322 l2cr_init(); 323 l2cr_init();
323#endif /* CONFIG_PPC32 */ 324#endif /* CONFIG_PPC32 */
324 325
325#ifdef CONFIG_PPC64
326 /* Probe motherboard chipset */
327 /* this is done earlier in setup_arch for 32-bit */
328 pmac_feature_init();
329
330 /* We can NAP */
331 powersave_nap = 1;
332 printk(KERN_INFO "Using native/NAP idle loop\n");
333#endif
334
335#ifdef CONFIG_KGDB 326#ifdef CONFIG_KGDB
336 zs_kgdb_hook(0); 327 zs_kgdb_hook(0);
337#endif 328#endif
@@ -622,13 +613,26 @@ static void __init pmac_init_early(void)
622 * and call ioremap 613 * and call ioremap
623 */ 614 */
624 hpte_init_native(); 615 hpte_init_native();
616#endif
625 617
626 /* Init SCC */ 618 /* Enable early btext debug if requested */
627 if (strstr(cmd_line, "sccdbg")) { 619 if (strstr(cmd_line, "btextdbg")) {
628 sccdbg = 1; 620 udbg_adb_init_early();
629 udbg_init_scc(NULL); 621 register_early_udbg_console();
630 } 622 }
631 623
624 /* Probe motherboard chipset */
625 pmac_feature_init();
626
627 /* We can NAP */
628 powersave_nap = 1;
629 printk(KERN_INFO "Using native/NAP idle loop\n");
630
631 /* Initialize debug stuff */
632 udbg_scc_init(!!strstr(cmd_line, "sccdbg"));
633 udbg_adb_init(!!strstr(cmd_line, "btextdbg"));
634
635#ifdef CONFIG_PPC64
632 /* Setup interrupt mapping options */ 636 /* Setup interrupt mapping options */
633 ppc64_interrupt_controller = IC_OPEN_PIC; 637 ppc64_interrupt_controller = IC_OPEN_PIC;
634 638
@@ -638,19 +642,8 @@ static void __init pmac_init_early(void)
638 642
639static void __init pmac_progress(char *s, unsigned short hex) 643static void __init pmac_progress(char *s, unsigned short hex)
640{ 644{
641#ifdef CONFIG_PPC64 645 udbg_puts(s);
642 if (sccdbg) { 646 udbg_puts("\n");
643 udbg_puts(s);
644 udbg_puts("\n");
645 return;
646 }
647#endif
648#ifdef CONFIG_BOOTX_TEXT
649 if (boot_text_mapped) {
650 btext_drawstring(s);
651 btext_drawchar('\n');
652 }
653#endif /* CONFIG_BOOTX_TEXT */
654} 647}
655 648
656/* 649/*
@@ -735,7 +728,8 @@ static int __init pmac_probe(int platform)
735} 728}
736 729
737#ifdef CONFIG_PPC64 730#ifdef CONFIG_PPC64
738static int pmac_probe_mode(struct pci_bus *bus) 731/* Move that to pci.c */
732static int pmac_pci_probe_mode(struct pci_bus *bus)
739{ 733{
740 struct device_node *node = bus->sysdata; 734 struct device_node *node = bus->sysdata;
741 735
@@ -771,7 +765,7 @@ struct machdep_calls __initdata pmac_md = {
771 .check_legacy_ioport = pmac_check_legacy_ioport, 765 .check_legacy_ioport = pmac_check_legacy_ioport,
772 .progress = pmac_progress, 766 .progress = pmac_progress,
773#ifdef CONFIG_PPC64 767#ifdef CONFIG_PPC64
774 .pci_probe_mode = pmac_probe_mode, 768 .pci_probe_mode = pmac_pci_probe_mode,
775 .idle_loop = native_idle, 769 .idle_loop = native_idle,
776 .enable_pmcs = power4_enable_pmcs, 770 .enable_pmcs = power4_enable_pmcs,
777#ifdef CONFIG_KEXEC 771#ifdef CONFIG_KEXEC
diff --git a/arch/powerpc/platforms/powermac/udbg_adb.c b/arch/powerpc/platforms/powermac/udbg_adb.c
new file mode 100644
index 000000000000..e51de55b2d6e
--- /dev/null
+++ b/arch/powerpc/platforms/powermac/udbg_adb.c
@@ -0,0 +1,218 @@
1#include <linux/config.h>
2#include <linux/string.h>
3#include <linux/kernel.h>
4#include <linux/errno.h>
5#include <linux/bitops.h>
6#include <linux/ptrace.h>
7#include <linux/adb.h>
8#include <linux/pmu.h>
9#include <linux/cuda.h>
10#include <asm/machdep.h>
11#include <asm/io.h>
12#include <asm/page.h>
13#include <asm/xmon.h>
14#include <asm/prom.h>
15#include <asm/bootx.h>
16#include <asm/machdep.h>
17#include <asm/errno.h>
18#include <asm/pmac_feature.h>
19#include <asm/processor.h>
20#include <asm/delay.h>
21#include <asm/btext.h>
22#include <asm/time.h>
23#include <asm/udbg.h>
24
25/*
26 * This implementation is "special", it can "patch" the current
27 * udbg implementation and work on top of it. It must thus be
28 * initialized last
29 */
30
31static void (*udbg_adb_old_putc)(char c);
32static char (*udbg_adb_old_getc)(void);
33static int (*udbg_adb_old_getc_poll)(void);
34
35static enum {
36 input_adb_none,
37 input_adb_pmu,
38 input_adb_cuda,
39} input_type = input_adb_none;
40
41static int udbg_adb_use_btext;
42
43int xmon_wants_key, xmon_adb_keycode;
44
45static inline void udbg_adb_poll(void)
46{
47#ifdef CONFIG_ADB_PMU
48 if (input_type == input_adb_pmu)
49 pmu_poll_adb();
50#endif /* CONFIG_ADB_PMU */
51#ifdef CONFIG_ADB_CUDA
52 if (input_type == input_adb_cuda)
53 cuda_poll();
54#endif /* CONFIG_ADB_CUDA */
55}
56
57#ifdef CONFIG_BOOTX_TEXT
58static int xmon_adb_shiftstate;
59
60static unsigned char xmon_keytab[128] =
61 "asdfhgzxcv\000bqwer" /* 0x00 - 0x0f */
62 "yt123465=97-80]o" /* 0x10 - 0x1f */
63 "u[ip\rlj'k;\\,/nm." /* 0x20 - 0x2f */
64 "\t `\177\0\033\0\0\0\0\0\0\0\0\0\0" /* 0x30 - 0x3f */
65 "\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */
66 "\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */
67
68static unsigned char xmon_shift_keytab[128] =
69 "ASDFHGZXCV\000BQWER" /* 0x00 - 0x0f */
70 "YT!@#$^%+(&_*)}O" /* 0x10 - 0x1f */
71 "U{IP\rLJ\"K:|<?NM>" /* 0x20 - 0x2f */
72 "\t ~\177\0\033\0\0\0\0\0\0\0\0\0\0" /* 0x30 - 0x3f */
73 "\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */
74 "\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */
75
76static char udbg_adb_local_getc(void)
77{
78 int k, t, on;
79
80 xmon_wants_key = 1;
81 for (;;) {
82 xmon_adb_keycode = -1;
83 t = 0;
84 on = 0;
85 k = -1;
86 do {
87 if (--t < 0) {
88 on = 1 - on;
89 btext_drawchar(on? 0xdb: 0x20);
90 btext_drawchar('\b');
91 t = 200000;
92 }
93 udbg_adb_poll();
94 if (udbg_adb_old_getc_poll)
95 k = udbg_adb_old_getc_poll();
96 } while (k == -1 && xmon_adb_keycode == -1);
97 if (on)
98 btext_drawstring(" \b");
99 if (k != -1)
100 return k;
101 k = xmon_adb_keycode;
102
103 /* test for shift keys */
104 if ((k & 0x7f) == 0x38 || (k & 0x7f) == 0x7b) {
105 xmon_adb_shiftstate = (k & 0x80) == 0;
106 continue;
107 }
108 if (k >= 0x80)
109 continue; /* ignore up transitions */
110 k = (xmon_adb_shiftstate? xmon_shift_keytab: xmon_keytab)[k];
111 if (k != 0)
112 break;
113 }
114 xmon_wants_key = 0;
115 return k;
116}
117#endif /* CONFIG_BOOTX_TEXT */
118
119static char udbg_adb_getc(void)
120{
121#ifdef CONFIG_BOOTX_TEXT
122 if (udbg_adb_use_btext && input_type != input_adb_none)
123 return udbg_adb_local_getc();
124#endif
125 if (udbg_adb_old_getc)
126 return udbg_adb_old_getc();
127 return -1;
128}
129
130/* getc_poll() is not really used, unless you have the xmon-over modem
131 * hack that doesn't quite concern us here, thus we just poll the low level
132 * ADB driver to prevent it from timing out and call back the original poll
133 * routine.
134 */
135static int udbg_adb_getc_poll(void)
136{
137 udbg_adb_poll();
138
139 if (udbg_adb_old_getc_poll)
140 return udbg_adb_old_getc_poll();
141 return -1;
142}
143
144static void udbg_adb_putc(char c)
145{
146#ifdef CONFIG_BOOTX_TEXT
147 if (udbg_adb_use_btext)
148 btext_drawchar(c);
149#endif
150 if (udbg_adb_old_putc)
151 return udbg_adb_old_putc(c);
152}
153
154void udbg_adb_init_early(void)
155{
156#ifdef CONFIG_BOOTX_TEXT
157 if (btext_find_display(1) == 0) {
158 udbg_adb_use_btext = 1;
159 udbg_putc = udbg_adb_putc;
160 }
161#endif
162}
163
164int udbg_adb_init(int force_btext)
165{
166 struct device_node *np;
167
168 /* Capture existing callbacks */
169 udbg_adb_old_putc = udbg_putc;
170 udbg_adb_old_getc = udbg_getc;
171 udbg_adb_old_getc_poll = udbg_getc_poll;
172
173 /* Check if our early init was already called */
174 if (udbg_adb_old_putc == udbg_adb_putc ||
175 udbg_adb_old_putc == btext_drawchar)
176 udbg_adb_old_putc = NULL;
177
178 /* Set ours as output */
179 udbg_putc = udbg_adb_putc;
180 udbg_getc = udbg_adb_getc;
181 udbg_getc_poll = udbg_adb_getc_poll;
182
183#ifdef CONFIG_BOOTX_TEXT
184 /* Check if we should use btext output */
185 if (btext_find_display(force_btext) == 0)
186 udbg_adb_use_btext = 1;
187#endif
188
189 /* See if there is a keyboard in the device tree with a parent
190 * of type "adb". If not, we return a failure, but we keep the
191 * bext output set for now
192 */
193 for (np = NULL; (np = of_find_node_by_name(np, "keyboard")) != NULL;) {
194 struct device_node *parent = of_get_parent(np);
195 int found = (parent && !strcmp(parent->type, "adb") == 0);
196 of_node_put(parent);
197 if (found)
198 break;
199 }
200 if (np == NULL)
201 return -ENODEV;
202 of_node_put(np);
203
204#ifdef CONFIG_ADB_PMU
205 if (find_via_pmu())
206 input_type = input_adb_pmu;
207#endif
208#ifdef CONFIG_ADB_CUDA
209 if (find_via_cuda())
210 input_type = input_adb_cuda;
211#endif
212
213 /* Same as above: nothing found, keep btext set for output */
214 if (input_type == input_adb_none)
215 return -ENODEV;
216
217 return 0;
218}
diff --git a/arch/powerpc/platforms/powermac/udbg_scc.c b/arch/powerpc/platforms/powermac/udbg_scc.c
new file mode 100644
index 000000000000..df6dec49c4c7
--- /dev/null
+++ b/arch/powerpc/platforms/powermac/udbg_scc.c
@@ -0,0 +1,165 @@
1/*
2 * udbg for 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/config.h>
12#include <linux/types.h>
13#include <asm/udbg.h>
14#include <asm/processor.h>
15#include <asm/io.h>
16#include <asm/prom.h>
17#include <asm/pmac_feature.h>
18
19extern u8 real_readb(volatile u8 __iomem *addr);
20extern void real_writeb(u8 data, volatile u8 __iomem *addr);
21
22#define SCC_TXRDY 4
23#define SCC_RXRDY 1
24
25static volatile u8 __iomem *sccc;
26static volatile u8 __iomem *sccd;
27
28static void udbg_scc_putc(char c)
29{
30 if (sccc) {
31 while ((in_8(sccc) & SCC_TXRDY) == 0)
32 ;
33 out_8(sccd, c);
34 if (c == '\n')
35 udbg_scc_putc('\r');
36 }
37}
38
39static int udbg_scc_getc_poll(void)
40{
41 if (sccc) {
42 if ((in_8(sccc) & SCC_RXRDY) != 0)
43 return in_8(sccd);
44 else
45 return -1;
46 }
47 return -1;
48}
49
50static char udbg_scc_getc(void)
51{
52 if (sccc) {
53 while ((in_8(sccc) & SCC_RXRDY) == 0)
54 ;
55 return in_8(sccd);
56 }
57 return 0;
58}
59
60static unsigned char scc_inittab[] = {
61 13, 0, /* set baud rate divisor */
62 12, 0,
63 14, 1, /* baud rate gen enable, src=rtxc */
64 11, 0x50, /* clocks = br gen */
65 5, 0xea, /* tx 8 bits, assert DTR & RTS */
66 4, 0x46, /* x16 clock, 1 stop */
67 3, 0xc1, /* rx enable, 8 bits */
68};
69
70void udbg_scc_init(int force_scc)
71{
72 u32 *reg;
73 unsigned long addr;
74 struct device_node *stdout = NULL, *escc = NULL, *macio = NULL;
75 struct device_node *ch, *ch_def = NULL, *ch_a = NULL;
76 char *path;
77 int i, x;
78
79 escc = of_find_node_by_name(NULL, "escc");
80 if (escc == NULL)
81 goto bail;
82 macio = of_get_parent(escc);
83 if (macio == NULL)
84 goto bail;
85 path = (char *)get_property(of_chosen, "linux,stdout-path", NULL);
86 if (path != NULL)
87 stdout = of_find_node_by_path(path);
88 for (ch = NULL; (ch = of_get_next_child(escc, ch)) != NULL;) {
89 if (ch == stdout)
90 ch_def = of_node_get(ch);
91 if (strcmp(ch->name, "ch-a") == 0)
92 ch_a = of_node_get(ch);
93 }
94 if (ch_def == NULL && !force_scc)
95 goto bail;
96
97 ch = ch_def ? ch_def : ch_a;
98
99 /* Get address within mac-io ASIC */
100 reg = (u32 *)get_property(escc, "reg", NULL);
101 if (reg == NULL)
102 goto bail;
103 addr = reg[0];
104
105 /* Get address of mac-io PCI itself */
106 reg = (u32 *)get_property(macio, "assigned-addresses", NULL);
107 if (reg == NULL)
108 goto bail;
109 addr += reg[2];
110
111 /* Lock the serial port */
112 pmac_call_feature(PMAC_FTR_SCC_ENABLE, ch,
113 PMAC_SCC_ASYNC | PMAC_SCC_FLAG_XMON, 1);
114
115
116 /* Setup for 57600 8N1 */
117 if (ch == ch_a)
118 addr += 0x20;
119 sccc = (volatile u8 * __iomem) ioremap(addr & PAGE_MASK, PAGE_SIZE) ;
120 sccc += addr & ~PAGE_MASK;
121 sccd = sccc + 0x10;
122
123 mb();
124
125 for (i = 20000; i != 0; --i)
126 x = in_8(sccc);
127 out_8(sccc, 0x09); /* reset A or B side */
128 out_8(sccc, 0xc0);
129 for (i = 0; i < sizeof(scc_inittab); ++i)
130 out_8(sccc, scc_inittab[i]);
131
132 udbg_putc = udbg_scc_putc;
133 udbg_getc = udbg_scc_getc;
134 udbg_getc_poll = udbg_scc_getc_poll;
135
136 udbg_puts("Hello World !\n");
137
138 bail:
139 of_node_put(macio);
140 of_node_put(escc);
141 of_node_put(stdout);
142 of_node_put(ch_def);
143 of_node_put(ch_a);
144}
145
146#ifdef CONFIG_PPC64
147static void udbg_real_scc_putc(char c)
148{
149 while ((real_readb(sccc) & SCC_TXRDY) == 0)
150 ;
151 real_writeb(c, sccd);
152 if (c == '\n')
153 udbg_real_scc_putc('\r');
154}
155
156void udbg_init_pmac_realmode(void)
157{
158 sccc = (volatile u8 __iomem *)0x80013020ul;
159 sccd = (volatile u8 __iomem *)0x80013030ul;
160
161 udbg_putc = udbg_real_scc_putc;
162 udbg_getc = NULL;
163 udbg_getc_poll = NULL;
164}
165#endif /* CONFIG_PPC64 */