Blame view
arch/powerpc/sysdev/mv64x60_udbg.c
2.97 KB
9b41fcb0e
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
/* * udbg serial input/output routines for the Marvell MV64x60 (Discovery). * * Author: Dale Farnsworth <dale@farnsworth.org> * * 2007 (c) MontaVista Software, Inc. This file is licensed under * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ #include <asm/io.h> #include <asm/prom.h> #include <asm/udbg.h> #include <sysdev/mv64x60.h> #define MPSC_0_CR1_OFFSET 0x000c #define MPSC_0_CR2_OFFSET 0x0010 #define MPSC_CHR_2_TCS (1 << 9) #define MPSC_0_CHR_10_OFFSET 0x0030 #define MPSC_INTR_CAUSE_OFF_0 0x0004 #define MPSC_INTR_CAUSE_OFF_1 0x000c #define MPSC_INTR_CAUSE_RCC (1<<6) static void __iomem *mpsc_base; static void __iomem *mpsc_intr_cause; static void mv64x60_udbg_putc(char c) { if (c == ' ') mv64x60_udbg_putc('\r'); while(in_le32(mpsc_base + MPSC_0_CR2_OFFSET) & MPSC_CHR_2_TCS) ; out_le32(mpsc_base + MPSC_0_CR1_OFFSET, c); out_le32(mpsc_base + MPSC_0_CR2_OFFSET, MPSC_CHR_2_TCS); } static int mv64x60_udbg_testc(void) { return (in_le32(mpsc_intr_cause) & MPSC_INTR_CAUSE_RCC) != 0; } static int mv64x60_udbg_getc(void) { int cause = 0; int c; while (!mv64x60_udbg_testc()) ; c = in_8(mpsc_base + MPSC_0_CHR_10_OFFSET + 2); out_8(mpsc_base + MPSC_0_CHR_10_OFFSET + 2, c); out_le32(mpsc_intr_cause, cause & ~MPSC_INTR_CAUSE_RCC); return c; } static int mv64x60_udbg_getc_poll(void) { if (!mv64x60_udbg_testc()) return -1; return mv64x60_udbg_getc(); } static void mv64x60_udbg_init(void) { struct device_node *np, *mpscintr, *stdout = NULL; const char *path; const phandle *ph; struct resource r[2]; const int *block_index; int intr_cause_offset; int err; path = of_get_property(of_chosen, "linux,stdout-path", NULL); if (!path) return; stdout = of_find_node_by_path(path); if (!stdout) return; |
482c43419
|
88 |
for_each_compatible_node(np, NULL, "marvell,mv64360-mpsc") { |
9b41fcb0e
|
89 90 |
if (np == stdout) break; |
26cb7d8bb
|
91 |
} |
9b41fcb0e
|
92 93 94 95 |
of_node_put(stdout); if (!np) return; |
df40a57ef
|
96 |
block_index = of_get_property(np, "cell-index", NULL); |
9b41fcb0e
|
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
if (!block_index) goto error; switch (*block_index) { case 0: intr_cause_offset = MPSC_INTR_CAUSE_OFF_0; break; case 1: intr_cause_offset = MPSC_INTR_CAUSE_OFF_1; break; default: goto error; } err = of_address_to_resource(np, 0, &r[0]); if (err) goto error; ph = of_get_property(np, "mpscintr", NULL); mpscintr = of_find_node_by_phandle(*ph); if (!mpscintr) goto error; err = of_address_to_resource(mpscintr, 0, &r[1]); of_node_put(mpscintr); if (err) goto error; of_node_put(np); |
28f65c11f
|
126 |
mpsc_base = ioremap(r[0].start, resource_size(&r[0])); |
9b41fcb0e
|
127 128 |
if (!mpsc_base) return; |
28f65c11f
|
129 |
mpsc_intr_cause = ioremap(r[1].start, resource_size(&r[1])); |
9b41fcb0e
|
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
if (!mpsc_intr_cause) { iounmap(mpsc_base); return; } mpsc_intr_cause += intr_cause_offset; udbg_putc = mv64x60_udbg_putc; udbg_getc = mv64x60_udbg_getc; udbg_getc_poll = mv64x60_udbg_getc_poll; return; error: of_node_put(np); } void mv64x60_init_early(void) { mv64x60_udbg_init(); } |