diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-11 21:55:47 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-11 21:55:47 -0700 |
commit | e86908614f2c7fec401827e5cefd7a6ea9407f85 (patch) | |
tree | fcb5d9e52422b37bdaf0e647126ebdfc1680f162 /arch/powerpc/sysdev/mv64x60_udbg.c | |
parent | 547307420931344a868275bd7ea7a30f117a15a9 (diff) | |
parent | 9b4b8feb962f4b3e74768b7205f1f8f6cce87238 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
* 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: (408 commits)
[POWERPC] Add memchr() to the bootwrapper
[POWERPC] Implement logging of unhandled signals
[POWERPC] Add legacy serial support for OPB with flattened device tree
[POWERPC] Use 1TB segments
[POWERPC] XilinxFB: Allow fixed framebuffer base address
[POWERPC] XilinxFB: Add support for custom screen resolution
[POWERPC] XilinxFB: Use pdata to pass around framebuffer parameters
[POWERPC] PCI: Add 64-bit physical address support to setup_indirect_pci
[POWERPC] 4xx: Kilauea defconfig file
[POWERPC] 4xx: Kilauea DTS
[POWERPC] 4xx: Add AMCC Kilauea eval board support to platforms/40x
[POWERPC] 4xx: Add AMCC 405EX support to cputable.c
[POWERPC] Adjust TASK_SIZE on ppc32 systems to 3GB that are capable
[POWERPC] Use PAGE_OFFSET to tell if an address is user/kernel in SW TLB handlers
[POWERPC] 85xx: Enable FP emulation in MPC8560 ADS defconfig
[POWERPC] 85xx: Killed <asm/mpc85xx.h>
[POWERPC] 85xx: Add cpm nodes for 8541/8555 CDS
[POWERPC] 85xx: Convert mpc8560ads to the new CPM binding.
[POWERPC] mpc8272ads: Remove muram from the CPM reg property.
[POWERPC] Make clockevents work on PPC601 processors
...
Fixed up conflict in Documentation/powerpc/booting-without-of.txt manually.
Diffstat (limited to 'arch/powerpc/sysdev/mv64x60_udbg.c')
-rw-r--r-- | arch/powerpc/sysdev/mv64x60_udbg.c | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/arch/powerpc/sysdev/mv64x60_udbg.c b/arch/powerpc/sysdev/mv64x60_udbg.c new file mode 100644 index 00000000000..367e7b13ec0 --- /dev/null +++ b/arch/powerpc/sysdev/mv64x60_udbg.c @@ -0,0 +1,152 @@ +/* + * 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 == '\n') + 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; + + for (np = NULL; + (np = of_find_compatible_node(np, "serial", "marvell,mpsc")); ) + if (np == stdout) + break; + + of_node_put(stdout); + if (!np) + return; + + block_index = of_get_property(np, "block-index", NULL); + 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); + + mpsc_base = ioremap(r[0].start, r[0].end - r[0].start + 1); + if (!mpsc_base) + return; + + mpsc_intr_cause = ioremap(r[1].start, r[1].end - r[1].start + 1); + 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(); +} |