OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [arch/] [powerpc/] [sysdev/] [mv64x60_udbg.c] - Rev 3

Compare with Previous | Blame | View Log

/*
 * 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();
}
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.