Path: blob/master/arch/powerpc/sysdev/mv64x60_udbg.c
10817 views
/*1* udbg serial input/output routines for the Marvell MV64x60 (Discovery).2*3* Author: Dale Farnsworth <[email protected]>4*5* 2007 (c) MontaVista Software, Inc. This file is licensed under6* the terms of the GNU General Public License version 2. This program7* is licensed "as is" without any warranty of any kind, whether express8* or implied.9*/1011#include <asm/io.h>12#include <asm/prom.h>13#include <asm/udbg.h>1415#include <sysdev/mv64x60.h>1617#define MPSC_0_CR1_OFFSET 0x000c1819#define MPSC_0_CR2_OFFSET 0x001020#define MPSC_CHR_2_TCS (1 << 9)2122#define MPSC_0_CHR_10_OFFSET 0x00302324#define MPSC_INTR_CAUSE_OFF_0 0x000425#define MPSC_INTR_CAUSE_OFF_1 0x000c26#define MPSC_INTR_CAUSE_RCC (1<<6)2728static void __iomem *mpsc_base;29static void __iomem *mpsc_intr_cause;3031static void mv64x60_udbg_putc(char c)32{33if (c == '\n')34mv64x60_udbg_putc('\r');3536while(in_le32(mpsc_base + MPSC_0_CR2_OFFSET) & MPSC_CHR_2_TCS)37;38out_le32(mpsc_base + MPSC_0_CR1_OFFSET, c);39out_le32(mpsc_base + MPSC_0_CR2_OFFSET, MPSC_CHR_2_TCS);40}4142static int mv64x60_udbg_testc(void)43{44return (in_le32(mpsc_intr_cause) & MPSC_INTR_CAUSE_RCC) != 0;45}4647static int mv64x60_udbg_getc(void)48{49int cause = 0;50int c;5152while (!mv64x60_udbg_testc())53;5455c = in_8(mpsc_base + MPSC_0_CHR_10_OFFSET + 2);56out_8(mpsc_base + MPSC_0_CHR_10_OFFSET + 2, c);57out_le32(mpsc_intr_cause, cause & ~MPSC_INTR_CAUSE_RCC);58return c;59}6061static int mv64x60_udbg_getc_poll(void)62{63if (!mv64x60_udbg_testc())64return -1;6566return mv64x60_udbg_getc();67}6869static void mv64x60_udbg_init(void)70{71struct device_node *np, *mpscintr, *stdout = NULL;72const char *path;73const phandle *ph;74struct resource r[2];75const int *block_index;76int intr_cause_offset;77int err;7879path = of_get_property(of_chosen, "linux,stdout-path", NULL);80if (!path)81return;8283stdout = of_find_node_by_path(path);84if (!stdout)85return;8687for_each_compatible_node(np, "serial", "marvell,mv64360-mpsc") {88if (np == stdout)89break;90}9192of_node_put(stdout);93if (!np)94return;9596block_index = of_get_property(np, "cell-index", NULL);97if (!block_index)98goto error;99100switch (*block_index) {101case 0:102intr_cause_offset = MPSC_INTR_CAUSE_OFF_0;103break;104case 1:105intr_cause_offset = MPSC_INTR_CAUSE_OFF_1;106break;107default:108goto error;109}110111err = of_address_to_resource(np, 0, &r[0]);112if (err)113goto error;114115ph = of_get_property(np, "mpscintr", NULL);116mpscintr = of_find_node_by_phandle(*ph);117if (!mpscintr)118goto error;119120err = of_address_to_resource(mpscintr, 0, &r[1]);121of_node_put(mpscintr);122if (err)123goto error;124125of_node_put(np);126127mpsc_base = ioremap(r[0].start, r[0].end - r[0].start + 1);128if (!mpsc_base)129return;130131mpsc_intr_cause = ioremap(r[1].start, r[1].end - r[1].start + 1);132if (!mpsc_intr_cause) {133iounmap(mpsc_base);134return;135}136mpsc_intr_cause += intr_cause_offset;137138udbg_putc = mv64x60_udbg_putc;139udbg_getc = mv64x60_udbg_getc;140udbg_getc_poll = mv64x60_udbg_getc_poll;141142return;143144error:145of_node_put(np);146}147148void mv64x60_init_early(void)149{150mv64x60_udbg_init();151}152153154